26 #ifndef EDELSBRUNNER96_INDUCED_SUBCOMPLEX_HPP_
27 #define EDELSBRUNNER96_INDUCED_SUBCOMPLEX_HPP_
38 namespace edelsbrunner96 {
40 template<
typename Traits>
50 std::set_union(s0.V.begin(), s0.V.end(), s1.V.begin(), s1.V.end(),
57 s1.V.end(), e.begin() + 1, e.begin(),
66 template <
typename Traits>
68 const std::array<SimplexRef, 2>&
s) {
69 Init(storage, s[0], s[1]);
72 template<
class Traits>
74 typedef Eigen::Matrix<Scalar, Traits::NDim, 1> VectorN;
79 for (
int i = 0; i < 2; i++) {
80 VectorN v = storage[e[i]] - storage[
s[i]].c;
81 isRegular[i] = v.squaredNorm() > storage[
s[i]].r2;
84 return isRegular[0] && isRegular[1];
87 template<
typename Traits>
90 for (
int i = 0; i < Traits::NDim + 2; i++) {
91 S[i] = storage.NullSimplex();
95 std::list<BreadthFirstNode> bfs_queue;
99 std::list<SimplexRef> evaluated_list;
101 for (
int i = 0; i < 2; i++) {
105 uint8_t i_of_missing =
106 std::lower_bound(V.begin(), V.end(), v_missing) - V.begin();
107 assert(i_of_missing < Traits::NDim + 2);
109 evaluated_list.push_back(s_ref);
110 bfs_queue.emplace_back(s_ref, v_missing);
111 S[i_of_missing] = s_ref;
114 while (bfs_queue.size() > 0) {
116 bfs_queue.pop_front();
118 for (
int i = 0; i < Traits::NDim + 1; i++) {
133 Simplex& s_neighbor = storage[neighbor];
136 evaluated_list.push_back(neighbor);
140 if (std::binary_search(s_neighbor.V.begin(), s_neighbor.V.end(),
144 uint8_t i_of_missing =
145 std::lower_bound(V.begin(), V.end(), v_missing) - V.begin();
146 assert(i_of_missing < Traits::NDim + 2);
147 S[i_of_missing] = neighbor;
148 bfs_queue.emplace_back(neighbor, v_missing);
160 template <
typename T>
int signum(T val) {
161 return (T(0) < val) - (val < T(0));
164 template<
typename Traits>
166 typedef typename Traits::Scalar
Scalar;
167 typedef Eigen::Matrix<Scalar, Traits::NDim, Traits::NDim>
Matrix;
168 typedef Eigen::Matrix<Scalar, Traits::NDim, 1> Vector;
172 for (
int i = 0; i < Traits::NDim; i++) {
173 A.row(i) = storage[f[i]];
185 for (
int i = 0; i < Traits::NDim; i++) {
192 A.row(i) = storage[e[0]];
196 for(
int j=0; j < Traits::NDim; j++) {
197 B.row(j) = storage[f[i]];
202 Vector n = (A-B).fullPivLu().solve(b).normalized();
203 Scalar o = (storage[e[0]] - storage[f[i]]).
dot(n);
210 A.row(i) = storage[f[i]];
215 if (n.dot(storage[e[1]] - storage[f[i]]) < o) {
225 for (
int j = 0; j < 2; j++) {
226 neighbors[j] = storage[
s[j]].NeighborAcross(f[i]);
231 if (neighbors[0] != neighbors[1]) {
246 template<
typename Traits>
248 typename Traits::Simplex&
s) {
252 while (i < Traits::NDim + 1 && j < Traits::NDim + 2) {
253 while (V[j] < s.V[i]) {
291 template<
typename Traits>
300 Eigen::Array<SimplexRef, Traits::NDim + 2, Traits::NDim + 2> neighborhood;
301 neighborhood.fill(storage.NullSimplex());
303 for (
int i = 0; i < Traits::NDim + 2; i++) {
304 if (S[i] == storage.NullSimplex()) {
309 for (
int j = 0; j < Traits::NDim + 2; j++) {
317 if (S[j] == storage.NullSimplex()) {
318 SimplexRef neighbor = storage[S[i]].NeighborAcross(V[j]);
319 neighborhood(i, j) = neighbor;
320 neighborhood(j, i) = neighbor;
326 for (
int i = 0; i < Traits::NDim + 2; i++) {
328 if (S[i] == storage.NullSimplex()) {
330 S[i] = storage.Promote();
334 std::remove_copy_if(V.begin(), V.end(), storage[S[i]].V.begin(),
339 storage[S[i]].ComputeCenter(storage);
343 storage.Retire(S[i]);
344 S[i] = storage.NullSimplex();
350 for (
int i = 0; i < Traits::NDim + 2; i++) {
351 if (S[i] == storage.NullSimplex()) {
354 for (
int j = 0; j < Traits::NDim + 2; j++) {
360 if (S[j] == storage.NullSimplex()) {
362 Simplex& s_neighbor = storage[neighbor];
363 storage[S[i]].SetNeighborAcross(V[j], neighborhood(i, j));
365 uint8_t k = FindIndexOfPeakVertex(s_neighbor);
366 storage[neighbor].N[k] = S[i];
368 storage[S[i]].SetNeighborAcross(V[j], S[j]);
376 #endif // EDELSBRUNNER96_INDUCED_SUBCOMPLEX_HPP_
void IntersectionAndDifference(InputIt1 first1, InputIt1 last1, InputIt2 first2, InputIt2 last2, OutputIt1 out1, OutputIt2 out2, OutputIt3 intersect)
Collect in out1 elements from the first set not found in the second, and collect in out2 elements fro...
bool IsFlippable(Storage &storage)
Return true if the facet is flippable.
uint8_t FindIndexOfPeakVertex(Simplex &s)
Given a simplex s which borders the hull of V (i.e. s shares a facet with hull(V)), then find the vertex of s which is not in V, and return it's index in S.V;.
Traits::SimplexRef SimplexRef
bool IsLocallyRegular(Storage &storage)
Return true if the facet is locally regular.
__device__ __host__ Scalar dot(const RValue< Scalar, ROWS, 1, ExpA > &A, const RValue< Scalar, ROWS, 1, ExpB > &B)
compute the DOT
void Build(Storage &storage)
Fill the induced simplex by breadth-first search of the neighborhood about s[0] and s[1]...
queued in induced subcomplex search
void Init(Storage &storage, SimplexRef s0_ref, SimplexRef s1_ref)
Initialize the data structure with the two simplices and build the vertex set for the common facet...
Traits::PointRef PointRef
We do a breadthfirst search for simplices in the induced subcomplex. This data structure is what we q...
void Flip(Storage &storage)
Flip the subcomplex.