26 #ifndef MPBLOCKS_EDELSBRUNNER96_TRIANGULATION_HPP_
27 #define MPBLOCKS_EDELSBRUNNER96_TRIANGULATION_HPP_
37 namespace edelsbrunner96 {
39 template <
class Traits>
41 typename Traits::Storage& storage,
42 std::initializer_list<typename Traits::PointRef> refs) {
43 typedef typename Traits::SimplexRef SimplexRef;
44 typedef typename Traits::Simplex Simplex;
48 assert(refs.size() == Traits::NDim + 1);
50 SimplexRef simplex_refs[Traits::NDim + 1];
51 SimplexRef center_ref = storage.Promote();
55 for (
int i = 0; i < Traits::NDim + 1; i++) {
56 simplex_refs[i] = storage.Promote();
62 Simplex& center_simplex = storage[center_ref];
63 std::copy(refs.begin(), refs.end(), center_simplex.V.begin());
65 for (
int i = 0; i < Traits::NDim + 1; i++) {
66 auto pr = storage[simplex_refs[i]].V.begin();
67 auto sr = storage[simplex_refs[i]].N.begin();
69 *pr++ = storage.NullPoint();
72 for (
int j = 0; j < Traits::NDim + 1; j++) {
76 *pr++ = center_simplex.V[j];
77 *sr++ = simplex_refs[j];
80 center_simplex.N[i] = simplex_refs[i];
86 template <
class Traits>
87 typename Traits::SimplexRef
Maintain(
typename Traits::Storage& storage,
88 typename Traits::PointRef point_ref,
89 typename Traits::SimplexRef return_ref,
91 typedef typename Traits::SimplexRef SimplexRef;
95 while (!link_facets.empty()) {
96 Facet facet = link_facets.back();
97 link_facets.pop_back();
108 induced_subcomplex.
Init(storage, facet.
s);
117 induced_subcomplex.
Build(storage);
123 induced_subcomplex.
Flip(storage);
124 for (SimplexRef s_ref : induced_subcomplex.
S) {
125 if (s_ref != storage.NullSimplex()) {
142 typedef std::pair<SimplexRef, SimplexRef> SimplexPair;
143 std::set<SimplexPair> facet_pairs;
144 for (
int i = 0; i < Traits::NDim + 2; i++) {
149 if (induced_subcomplex.
V[i] == point_ref) {
154 SimplexRef link_simplex = induced_subcomplex.
S[i];
155 if (link_simplex == storage.NullSimplex()) {
160 SimplexRef neighbor = storage[link_simplex].NeighborAcross(point_ref);
162 if (storage[neighbor].V[0] == storage.NullPoint()) {
165 link_facets.emplace_back();
166 link_facets.back().Construct(storage, link_simplex, neighbor);
176 template <
class Traits,
class Container>
178 Container& visible_hull,
179 typename Traits::PointRef point_ref) {
180 typedef typename Traits::Simplex Simplex;
181 typedef typename Traits::SimplexRef SimplexRef;
186 for (SimplexRef s_ref : visible_hull) {
188 Simplex&
s = storage[s_ref];
189 assert(s.V.end() - s.V.begin() > 1);
191 SimplexRef neighbor_across = s.N[0];
193 auto N = s.N.begin();
194 auto V = s.V.begin();
201 for (; V != s.V.end()-1 && *(V + 1) < point_ref; ++V, ++N) {
207 *N = neighbor_across;
208 s.ComputeCenter(storage);
222 template <
class Traits,
class Container>
223 std::list<std::pair<typename Traits::SimplexRef, typename Traits::SimplexRef>>
225 typedef typename Traits::Simplex Simplex;
226 typedef typename Traits::SimplexRef SimplexRef;
227 typedef std::pair<SimplexRef, SimplexRef> Edge;
229 std::list<Edge> horizon_ridge;
230 for (SimplexRef s_ref : visible_hull) {
231 Simplex&
s = storage[s_ref];
232 for (
int i = 0; i < Traits::NDim + 1; i++) {
233 SimplexRef neighbor_ref = s.N[i];
234 if (storage[neighbor_ref].V[0] == storage.NullPoint() &&
236 horizon_ridge.emplace_back(s_ref, neighbor_ref);
240 return horizon_ridge;
245 template <
class Traits,
class Container>
247 typename Traits::Storage& storage, Container& horizon_ridge,
248 typename Traits::PointRef point_ref) {
249 typedef typename Traits::Simplex Simplex;
250 typedef typename Traits::SimplexRef SimplexRef;
251 typedef typename Traits::PointRef PointRef;
253 std::list<SimplexRef> horizon_wedges;
254 for (
auto& pair : horizon_ridge) {
258 SimplexRef wedge_ref = storage.Promote();
259 horizon_wedges.push_back(wedge_ref);
260 Simplex& wedge_simplex = storage[wedge_ref];
264 wedge_simplex.V[0] = storage.NullPoint();
265 std::set_intersection(
266 storage[pair.first].V.begin(), storage[pair.first].V.end(),
267 storage[pair.second].V.begin(), storage[pair.second].V.end(),
268 wedge_simplex.V.begin() + 1);
269 wedge_simplex.V[Traits::NDim] = point_ref;
276 std::sort(wedge_simplex.V.begin(), wedge_simplex.V.end());
279 for (
int i = 0; i < Traits::NDim + 1; i++) {
280 wedge_simplex.N[i] = storage.NullSimplex();
283 Simplex& s_a = storage[pair.first];
284 Simplex& s_b = storage[pair.second];
285 PointRef v_a[2] = {storage.NullPoint(), storage.NullPoint()};
286 PointRef v_b[2] = {storage.NullPoint(), storage.NullPoint()};
289 s_b.V.end(), v_a, v_b);
290 assert(v_a[0] == point_ref || v_a[1] == point_ref);
291 assert(v_b[0] == storage.NullPoint() || v_b[1] == storage.NullPoint());
293 PointRef v_a_across_b = v_a[0] == point_ref ? v_a[1] : v_a[0];
294 PointRef v_b_across_a = v_b[0] == storage.NullPoint() ? v_b[1] : v_b[0];
295 assert(v_a_across_b != point_ref);
296 assert(v_a_across_b != storage.NullPoint());
297 assert(v_b_across_a != storage.NullPoint());
298 assert(s_a.NeighborAcross(v_a_across_b) == pair.second);
299 assert(s_b.NeighborAcross(v_b_across_a) == pair.first);
303 wedge_simplex.SetNeighborAcross(point_ref, pair.second);
304 wedge_simplex.SetNeighborAcross(storage.NullPoint(), pair.first);
305 int i_first = s_a.IndexOf(v_a_across_b);
306 assert(s_a.N[i_first] == pair.second);
307 s_a.N[i_first] = wedge_ref;
308 int i_second = s_b.IndexOf(v_b_across_a);
309 assert(s_b.N[i_second] == pair.first);
310 s_b.N[i_second] = wedge_ref;
313 return horizon_wedges;
367 template <
class Traits>
369 typename Traits::SimplexRef wedge_ref,
int i) {
370 typedef typename Traits::SimplexRef SimplexRef;
371 typedef typename Traits::PointRef PointRef;
374 PointRef V_edge[Traits::NDim - 1];
376 PointRef* V = V_edge;
377 for (
int j = 1; j < Traits::NDim + 1; j++) {
381 *V++ = storage[wedge_ref].V[j];
386 SimplexRef prev_ref = wedge_ref;
387 SimplexRef next_ref = storage[wedge_ref].N[0];
389 while (next_ref != storage.NullSimplex()) {
391 PointRef V_common[Traits::NDim];
392 std::set_intersection(
393 storage[prev_ref].V.begin(), storage[prev_ref].V.end(),
394 storage[next_ref].V.begin(), storage[next_ref].V.end(), V_common);
397 std::set_difference(V_common, V_common + Traits::NDim, V_edge,
398 V_edge + Traits::NDim - 1, &V_diff);
402 next_ref = storage[prev_ref].NeighborAcross(V_diff);
405 SimplexRef neighbor_ref = prev_ref;
406 storage[wedge_ref].N[i] = neighbor_ref;
407 storage[neighbor_ref].SetNeighborAcross(V_diff, wedge_ref);
410 template <
class Traits>
412 typename Traits::Storage& storage,
typename Traits::SimplexRef simplex_ref,
413 typename Traits::PointRef point_ref) {
414 typedef typename Traits::SimplexRef SimplexRef;
417 SimplexRef return_ref = storage.NullSimplex();
419 std::list<SimplexRef> visible_hull;
420 GetVisibleHull<Traits>(storage, simplex_ref, storage[point_ref],
421 std::back_inserter(visible_hull));
424 for (SimplexRef s_ref : visible_hull) {
425 assert(storage[s_ref].V[0] == storage.NullPoint());
431 DemoteHullSimplices<Traits>(storage, visible_hull, point_ref);
435 auto horizon_ridge = BuildHorizonRidge<Traits>(storage, visible_hull);
439 auto horizon_wedges =
440 FillHorizonWedges<Traits>(storage, horizon_ridge, point_ref);
458 for (SimplexRef wedge_ref : horizon_wedges) {
460 for (
int i = 1; i < Traits::NDim + 1; i++) {
462 if (storage[wedge_ref].N[i] != storage.NullSimplex()) {
466 FindWedgeNeighbor<Traits>(storage, wedge_ref, i);
484 std::list<Facet> link_facets;
487 for (SimplexRef s_ref : visible_hull) {
489 link_facets.emplace_back();
490 link_facets.back().Construct(storage, s_ref,
491 storage[s_ref].NeighborAcross(point_ref));
494 return Maintain(storage, point_ref, return_ref, link_facets);
497 template <
class Traits>
499 typename Traits::Storage& storage,
typename Traits::SimplexRef simplex_ref,
500 typename Traits::PointRef point_ref) {
501 typedef typename Traits::Simplex Simplex;
502 typedef typename Traits::SimplexRef SimplexRef;
505 SimplexRef return_ref = storage.NullSimplex();
513 Simplex& simplex = storage[simplex_ref];
516 for (; i < Traits::NDim + 1 && simplex.V[i] < point_ref; ++i) {
517 induced_subcomplex.
V[i] = simplex.V[i];
518 induced_subcomplex.
S[i] = storage.NullSimplex();
520 induced_subcomplex.
V[i] = point_ref;
521 induced_subcomplex.
S[i] = simplex_ref;
523 for (; i < Traits::NDim + 2; ++i) {
524 induced_subcomplex.
V[i] = simplex.V[i - 1];
525 induced_subcomplex.
S[i] = storage.NullSimplex();
531 induced_subcomplex.
Flip(storage);
532 for (SimplexRef s_ref : induced_subcomplex.
S) {
533 if (s_ref != storage.NullSimplex()) {
557 std::list<Facet> link_facets;
560 for (
int i = 0; i < Traits::NDim + 2; i++) {
561 SimplexRef link_simplex = induced_subcomplex.
S[i];
562 if (link_simplex == storage.NullSimplex()) {
565 SimplexRef neighbor = storage[link_simplex].NeighborAcross(point_ref);
567 if (storage[neighbor].V[0] == storage.NullPoint()) {
570 link_facets.emplace_back();
571 link_facets.back().Construct(storage, link_simplex, neighbor);
574 return Maintain(storage, point_ref, return_ref, link_facets);
578 template <
class Traits>
580 typename Traits::SimplexRef s_ref,
581 typename Traits::PointRef v_ref,
582 typename Traits::PointRef peak_ref) {
583 typedef typename Traits::SimplexRef SimplexRef;
584 typedef typename Traits::PointRef PointRef;
587 std::array<PointRef, Traits::NDim - 1> V_edge;
588 std::array<PointRef, 2> V_missing = {v_ref, peak_ref};
589 std::sort(V_missing.begin(), V_missing.end());
590 std::set_difference(storage[s_ref].V.begin(), storage[s_ref].V.end(),
591 V_missing.begin(), V_missing.end(), V_edge.begin());
593 SimplexRef prev_ref = s_ref;
594 SimplexRef next_ref = storage[s_ref].NeighborAcross(peak_ref);
596 while (next_ref != storage.NullSimplex()) {
598 std::array<PointRef, Traits::NDim> V_common;
599 std::set_intersection(storage[prev_ref].V.begin(),
600 storage[prev_ref].V.end(),
601 storage[next_ref].V.begin(),
602 storage[next_ref].V.end(), V_common.begin());
605 std::set_difference(V_common.begin(), V_common.end(), V_edge.begin(),
606 V_edge.end(), &V_diff);
610 next_ref = storage[prev_ref].NeighborAcross(V_diff);
613 SimplexRef neighbor_ref = prev_ref;
614 storage[s_ref].SetNeighborAcross(v_ref, neighbor_ref);
615 storage[neighbor_ref].SetNeighborAcross(V_diff, s_ref);
618 template <
class Traits,
class Iterator>
620 typename Traits::Storage& storage,
621 typename Traits::PointRef point_ref,
622 Iterator S_begin, Iterator S_end) {
623 typedef typename Traits::SimplexRef SimplexRef;
624 typedef typename Traits::PointRef PointRef;
627 SimplexRef return_ref = storage.NullSimplex();
630 for(Iterator s_iter = S_begin; s_iter != S_end; ++s_iter) {
634 std::list<SimplexRef> new_simplices;
637 for (Iterator s_iter = S_begin; s_iter != S_end; ++s_iter) {
638 SimplexRef s_ref = *s_iter;
639 for(SimplexRef neighbor_ref : storage[s_ref].N) {
645 std::array<PointRef, Traits::NDim + 1> V;
646 PointRef v_in_removed;
647 PointRef v_in_neighbor;
649 storage[s_ref].V.begin(), storage[s_ref].V.end(),
650 storage[neighbor_ref].V.begin(), storage[neighbor_ref].V.end(),
651 &v_in_removed, &v_in_neighbor, V.begin());
653 V.back() = point_ref;
656 SimplexRef new_ref = storage.Promote();
657 new_simplices.push_back(new_ref);
659 std::copy(V.begin(), V.end(), storage[new_ref].V.begin());
660 storage[new_ref].ComputeCenter(storage);
663 std::fill(storage[new_ref].N.begin(), storage[new_ref].N.end(),
664 storage.NullSimplex());
667 storage[new_ref].SetNeighborAcross(point_ref, neighbor_ref);
668 storage[neighbor_ref].SetNeighborAcross(v_in_neighbor, new_ref);
687 for (SimplexRef wedge_ref : new_simplices) {
689 for (PointRef v_ref : storage[wedge_ref].V) {
691 if (storage[wedge_ref].NeighborAcross(v_ref) != storage.NullSimplex()) {
695 FindFillNeighbor<Traits>(storage, wedge_ref, v_ref, point_ref);
700 for (Iterator s_iter = S_begin; s_iter != S_end; ++s_iter) {
701 SimplexRef s_ref = *s_iter;
703 storage.Retire(s_ref);
708 std::list<Facet> link_facets;
709 for (SimplexRef s_ref : new_simplices) {
710 if (storage[s_ref].V[0] != storage.NullPoint()) {
711 SimplexRef n_ref = storage[s_ref].NeighborAcross(point_ref);
712 if (storage[n_ref].V[0] != storage.NullPoint()) {
713 link_facets.emplace_back();
714 link_facets.back().Construct(storage, s_ref, n_ref);
719 return_ref = new_simplices.front();
720 return Maintain(storage, point_ref, return_ref, link_facets);
723 template <
typename Traits>
725 typename Traits::Storage& storage,
const typename Traits::SimplexRef s_0,
726 const typename Traits::PointRef x_ref,
727 const typename Traits::Scalar epsilon) {
728 typedef typename Traits::SimplexRef SimplexRef;
729 std::list<SimplexRef> interference_set;
730 FuzzyWalk<Traits>(storage, s_0, storage[x_ref], epsilon,
731 std::back_inserter(interference_set));
732 return InsertReplace<Traits>(storage, x_ref, interference_set.begin(),
733 interference_set.end());
738 #endif // EDELSBRUNNER96_TRIANGULATION_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...
void FindWedgeNeighbor(typename Traits::Storage &storage, typename Traits::SimplexRef wedge_ref, int i)
Given a simplex which fills an empty wedge created by demotion of a simplex along the horizon ridge...
Traits::SimplexRef Triangulate(typename Traits::Storage &storage, std::initializer_list< typename Traits::PointRef > refs)
Initialize a triangulation with NDim+1 points and return the simplex.
Traits::SimplexRef InsertOutside(typename Traits::Storage &storage, typename Traits::SimplexRef simplex_ref, typename Traits::PointRef point_ref)
Inserts a point outside of the hull of the current point set. Note that simplex_ref must point to a h...
std::list< std::pair< typename Traits::SimplexRef, typename Traits::SimplexRef > > BuildHorizonRidge(typename Traits::Storage &storage, Container &visible_hull)
Build the horizon ridge, which is the set of all edges which border the x-visible hull...
bool IsFlippable(Storage &storage)
Return true if the facet is flippable.
void SymmetricDifference(InputIt1 first1, InputIt1 last1, InputIt2 first2, InputIt2 last2, OutputIt1 out1, OutputIt2 out2)
Collect in out1 elements from the first set not found in the second, and collect in out2 elements fro...
std::array< SimplexRef, 2 > s
the two simplices
A facet is a (d-1)-dimensional simplex.
The induced subcomplex of a facet between two simplices is the set of all simplices in the triangulat...
Traits::SimplexRef InsertReplace(typename Traits::Storage &storage, typename Traits::PointRef point_ref, Iterator S_begin, Iterator S_end)
Inserts a point into the triangulation, replacing the given simplex set which intersect the new point...
Traits::SimplexRef InsertInside(typename Traits::Storage &storage, typename Traits::SimplexRef simplex_ref, typename Traits::PointRef point_ref)
Inserts a point into a simplex, performs 1-to-n+1 flip, and performs the delaunay maintenance on the ...
void DemoteHullSimplices(typename Traits::Storage &storage, Container &visible_hull, typename Traits::PointRef point_ref)
For each infinite simplex references in hull_simplices, replace the null vertex with the vertex point...
std::list< typename Traits::SimplexRef > FillHorizonWedges(typename Traits::Storage &storage, Container &horizon_ridge, typename Traits::PointRef point_ref)
For each simplex pair (s1,s2) in , fill the empty wedge that was created when s1 was demoted to a non...
Traits::SimplexRef FuzzyWalkInsert(typename Traits::Storage &storage, const typename Traits::SimplexRef s_0, const typename Traits::PointRef x_ref, const typename Traits::Scalar epsilon)
Perform a fuzzy walk to get the set of simplices intersecting the query point, then insert the point ...
std::array< SimplexRef, Traits::NDim+2 > S
if S[i] is not null then it is the simplex in the triangulation composed of all the vertices in V exc...
simpex is a member of the visible hull
bool IsLocallyRegular(Storage &storage)
Return true if the facet is locally regular.
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 ...
bool StillExists(Storage &storage)
Returns true if the two simplex references still have the same version as the time when Construct was...
simplex has been removed during insertion of a point
Char8_t * copy(const Char8_t *s)
void Build(Storage &storage)
Fill the induced simplex by breadth-first search of the neighborhood about s[0] and s[1]...
std::array< PointRef, Traits::NDim+2 > V
the (sorted) vertices of the subcomplex
void FindFillNeighbor(typename Traits::Storage &storage, typename Traits::SimplexRef s_ref, typename Traits::PointRef v_ref, typename Traits::PointRef peak_ref)
Find the neighbor of a fill simplex that is across from v_ref.
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::SimplexRef Maintain(typename Traits::Storage &storage, typename Traits::PointRef point_ref, typename Traits::SimplexRef return_ref, std::list< Facet< Traits >> &link_facets)
While the link of the specified point is not locally Delaunay, continue flipping locally non-Delaunay...
void Flip(Storage &storage)
Flip the subcomplex.