31 #include <boost/graph/dijkstra_shortest_paths.hpp>
32 #include <boost/graph/filtered_graph.hpp>
34 #include <boost/geometry/algorithms/num_points.hpp>
35 #include <boost/geometry/algorithms/append.hpp>
36 #include <boost/geometry/algorithms/area.hpp>
37 #if Boost_VERSION_MACRO >= 107500
38 # include <boost/geometry/strategies/strategies.hpp>
40 # include <boost/geometry/strategies/agnostic/point_in_point.hpp>
42 #include <boost/geometry/algorithms/correct.hpp>
43 #include <boost/geometry/algorithms/distance.hpp>
54 namespace bg = boost::geometry;
57 namespace alphashape {
68 det(
double r00,
double r01,
double r10,
double r11) {
69 return r00 * r11 - r01 * r10;
81 auto denom = 2 *
det(ax, ay, bx, by);
87 auto numx =
det(ay, ax * ax + ay * ay, by, bx * bx + by * by);
88 auto numy =
det(ax, ax * ax + ay * ay, bx, bx * bx + by * by);
90 return Bpoint {cx - numx / denom, cy + numy / denom};
93 template <
typename B_G,
typename V>
97 std::vector<V> predecessors(boost::num_vertices(subg));
98 std::vector<double> distances(num_vertices(subg));
99 pgassert(predecessors.size() == boost::num_vertices(subg));
100 pgassert(distances.size() == boost::num_vertices(subg));
103 CHECK_FOR_INTERRUPTS();
106 boost::dijkstra_shortest_paths(subg, source,
107 boost::predecessor_map(&predecessors[0])
109 .distance_map(&distances[0])
112 }
catch (boost::exception
const& ex) {
115 }
catch (std::exception &e) {
125 template <
typename B_G,
typename V>
127 get_polygon(
V source,
V target,
const std::vector<V> & predecessors,
const B_G &graph, std::set<E> &edges_used) {
132 if (target == predecessors[target]) {
133 pgassert(bg::num_points(polygon) == 0);
140 bg::append(polygon.outer(), graph[source].point);
145 while (target != source || target != predecessors[target]) {
146 bg::append(polygon.outer(), graph[target].point);
147 edges_used.insert(boost::edge(predecessors[target], target, graph).first);
148 target = predecessors[target];
150 bg::correct(polygon);
157 return lhs.second > rhs.second;
187 std::vector<Triangle> adjacent_to_side;
199 if (!a_r.second)
continue;
202 adjacent_to_side.push_back(face);
211 if (adjacent_to_side.size() == 2) {
228 std::vector<E> edges(t.begin(), t.end());
232 c = (c == a || c == b)?
graph.
target(edges[1]) : c;
233 pgassert(a != b && a != c && b!= c);
236 return bg::distance(center,
graph[a].point);
244 return radius(t) <= alpha;
249 std::map<Triangle, double> border_triangles;
250 std::map<Triangle, double> inner_triangles;
254 if (t.second.size() == 2) {
255 border_triangles[t.first] =
radius(t.first);
257 inner_triangles[t.first] =
radius(t.first);
261 pgassert(border_triangles.size() + inner_triangles.size() == i);
263 auto max_border_triangle = *std::min_element(border_triangles.begin(), border_triangles.end(), CompareRadius());
264 auto max_inner_triangle = *std::min_element(inner_triangles.begin(), inner_triangles.end(), CompareRadius());
266 double max_border_radius = max_border_triangle.second;
267 double max_inner_radius = max_inner_triangle.second;
270 auto count = border_triangles.size() + inner_triangles.size();
271 while (max_border_radius >= max_inner_radius) {
272 auto max_border_triangle = *std::min_element(border_triangles.begin(), border_triangles.end(), CompareRadius());
273 auto max_inner_triangle = *std::min_element(inner_triangles.begin(), inner_triangles.end(), CompareRadius());
277 border_triangles.erase(max_border_triangle.first);
285 if (inner_triangles.find(t) != inner_triangles.end()) {
286 inner_triangles.erase(t);
287 border_triangles[t] =
radius(t);
291 auto new_max_border_triangle = *std::min_element(
292 border_triangles.begin(), border_triangles.end(), CompareRadius());
293 auto new_max_inner_triangle = *std::min_element(
294 inner_triangles.begin(), inner_triangles.end(), CompareRadius());
296 if (new_max_border_triangle.second < new_max_inner_triangle.second) {
301 border_triangles.erase(t);
302 inner_triangles[t] =
radius(t);
304 border_triangles[max_border_triangle.first] = max_border_triangle.second;
307 max_border_radius = new_max_border_triangle.second;
308 max_inner_radius = new_max_inner_triangle.second;
309 pgassert(count > (border_triangles.size() + inner_triangles.size()));
310 count = border_triangles.size() + inner_triangles.size();;
314 log <<
"Using Alpha:" << max_border_radius * max_border_radius;
321 std::set<Triangle> &used,
322 std::set<E> &border_edges,
323 double alpha)
const {
332 auto original = used.size();
334 if (original == used.size())
return;
336 std::set<E> common_sides;
343 std::set_intersection(
344 face.begin(), face.end(),
345 adj_t.begin(), adj_t.end(),
346 std::inserter(border_edges, border_edges.end()));
348 std::set_intersection(
349 face.begin(), face.end(),
350 adj_t.begin(), adj_t.end(),
351 std::inserter(common_sides, common_sides.end()));
361 face.begin(), face.end(),
362 common_sides.begin(), common_sides.end(),
363 std::inserter(border_edges, border_edges.end()));
369 std::vector<Bpoly> shape;
373 std::set<Triangle> used;
374 using Subgraph = boost::filtered_graph<BG, EdgesFilter, boost::keep_all>;
386 if (border_edges.
edges.empty())
continue;
388 std::vector<Bpoly> polys;
391 while (!border_edges.
edges.empty()) {
392 auto first_edge = *border_edges.
edges.begin();
393 border_edges.
edges.erase(first_edge);
397 auto source = boost::source(first_edge, subg);
398 auto target = boost::target(first_edge, subg);
402 std::set<E> edges_used;
403 auto poly =
get_polygon(source, target, predecessors, subg, edges_used);
405 for (
const auto &e : edges_used) {
406 border_edges.
edges.erase(e);
409 pgassert(bg::num_points(poly) >= 3 || bg::num_points(poly) == 0);
411 if (bg::num_points(poly) == 0)
continue;
416 if (bg::num_points(poly) >= 3) {
422 area = bg::area(poly);
424 auto new_area = bg::area(poly);
425 if (new_area > area) {
431 polys.push_back(polygon);
438 polys.push_back(poly);
447 if (!polys.empty()) {
448 polygon.inners().resize(polys.size());
450 for (
const auto &inner_ring : polys) {
451 bg::assign(polygon.inners()[i++], inner_ring);
458 shape.push_back(polygon);