generated from cubao/pybind11-rdp
-
Notifications
You must be signed in to change notification settings - Fork 5
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
adopt convex hull from concaveman (#28)
* not ready * fix * use stable predicates * fix * fix * fix * not ready * fix * fix * reset * init orient 2d * add macro * update * clean * fix * fix * not ready * fix compile * fix * fix * fix * fix * fix * fix --------- Co-authored-by: tang zhixiong <[email protected]>
- Loading branch information
1 parent
078c7da
commit 5cc777b
Showing
12 changed files
with
518 additions
and
13 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,142 @@ | ||
// https://github.com/mapbox/concaveman/pull/17/files | ||
|
||
// https://github.com/mourner/robust-predicates/blob/main/src/orient2d.js | ||
#pragma once | ||
|
||
#include "orient2d.hpp" | ||
#include <vector> | ||
#include <array> | ||
|
||
namespace cubao | ||
{ | ||
namespace convex_hull2 | ||
{ | ||
// https://github.com/mourner/robust-predicates/blob/main/src/orient2d.js | ||
|
||
inline double cross(const double *p1, const double *p2, const double *p3) | ||
{ | ||
return robust_predicates::orient2d(p1[0], p1[1], // | ||
p2[0], p2[1], // | ||
p3[0], p3[1]); | ||
} | ||
|
||
// https://github.com/mapbox/concaveman/blob/master/index.js | ||
// check if the edges (p1,q1) and (p2,q2) intersect | ||
inline bool intersects(const double *p1, const double *q1, // | ||
const double *p2, const double *q2) | ||
{ | ||
return !(p1[0] == q2[0] && p1[1] == q2[1]) && | ||
!(q1[0] == p2[0] && q1[1] == p2[1]) && | ||
(cross(p1, q1, p2) > 0) != (cross(p1, q1, q2) > 0) && | ||
(cross(p2, q2, p1) > 0) != (cross(p2, q2, q1) > 0); | ||
} | ||
|
||
inline std::vector<std::array<double, 3>> | ||
convexHull(std::vector<std::array<double, 3>> points) | ||
{ | ||
if (points.empty()) { | ||
return {}; | ||
} | ||
std::sort( | ||
points.begin(), points.end(), | ||
[](const std::array<double, 3> &a, const std::array<double, 3> &b) { | ||
return a[0] == b[0] ? a[1] < b[1] : a[0] < b[0]; | ||
}); | ||
points.erase(std::unique(points.begin(), points.end(), | ||
[](const auto &a, const auto &b) { | ||
return a[0] == b[0] && a[1] == b[1]; | ||
}), | ||
points.end()); | ||
|
||
std::vector<std::array<double, 3>> lower; | ||
for (size_t i = 0; i < points.size(); i++) { | ||
while (lower.size() >= 2 && | ||
cross(lower[lower.size() - 2].data(), | ||
lower[lower.size() - 1].data(), points[i].data()) <= 0) { | ||
lower.pop_back(); | ||
} | ||
lower.push_back(points[i]); | ||
} | ||
|
||
std::vector<std::array<double, 3>> upper; | ||
for (int i = points.size() - 1; i >= 0; i--) { | ||
while (upper.size() >= 2 && | ||
cross(upper[upper.size() - 2].data(), | ||
upper[upper.size() - 1].data(), points[i].data()) <= 0) { | ||
upper.pop_back(); | ||
} | ||
upper.push_back(points[i]); | ||
} | ||
|
||
upper.pop_back(); | ||
lower.pop_back(); | ||
lower.insert(lower.end(), upper.begin(), upper.end()); | ||
return lower; | ||
} | ||
|
||
// https://www.npmjs.com/package/point-in-polygon?activeTab=code | ||
inline bool pointInPolygon(const double *point, // | ||
const double *polygon, size_t length, // | ||
int start = -1, int end = -1) | ||
{ | ||
double x = point[0], y = point[1]; | ||
bool inside = false; | ||
if (start < 0) | ||
start = 0; | ||
if (end < 0) | ||
end = length; | ||
int len = end - start; | ||
for (int i = 0, j = len - 1; i < len; j = i++) { | ||
double xi = polygon[(i + start) * 2], yi = polygon[(i + start) * 2 + 1]; | ||
double xj = polygon[(j + start) * 2], yj = polygon[(j + start) * 2 + 1]; | ||
bool intersect = ((yi > y) != (yj > y)) && | ||
(x < (xj - xi) * (y - yi) / (yj - yi) + xi); | ||
if (intersect) | ||
inside = !inside; | ||
} | ||
return inside; | ||
} | ||
|
||
// speed up convex hull by filtering out points inside quadrilateral formed by 4 | ||
// extreme points | ||
inline std::vector<std::array<double, 3>> | ||
fastConvexHull(const std::vector<std::array<double, 3>> &points) | ||
{ | ||
if (points.empty()) { | ||
return {}; | ||
} | ||
|
||
auto left = points[0]; | ||
auto top = points[0]; | ||
auto right = points[0]; | ||
auto bottom = points[0]; | ||
|
||
// find the leftmost, rightmost, topmost and bottommost points | ||
for (const auto &p : points) { | ||
if (p[0] < left[0]) | ||
left = p; | ||
if (p[0] > right[0]) | ||
right = p; | ||
if (p[1] < top[1]) | ||
top = p; | ||
if (p[1] > bottom[1]) | ||
bottom = p; | ||
} | ||
|
||
// filter out points that are inside the resulting quadrilateral | ||
std::vector<std::array<double, 2>> cull = {{left[0], left[1]}, | ||
{top[0], top[1]}, | ||
{right[0], right[1]}, | ||
{bottom[0], bottom[1]}}; | ||
std::vector<std::array<double, 3>> filtered = {left, top, right, bottom}; | ||
for (const auto &p : points) { | ||
if (!pointInPolygon(&p[0], &cull[0][0], cull.size())) { | ||
filtered.push_back(p); | ||
} | ||
} | ||
// get convex hull around the filtered points | ||
return convexHull(filtered); | ||
} | ||
|
||
} // namespace convex_hull2 | ||
} // namespace cubao |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,135 @@ | ||
#pragma once | ||
|
||
#include <cmath> | ||
|
||
namespace cubao | ||
{ | ||
namespace robust_predicates | ||
{ | ||
// https://github.com/mourner/robust-predicates/blob/312178014c173cfa5ed0a8cb5496baaf82a63663/compile.js#L6 | ||
#define Fast_Two_Sum(a, b, x, y) \ | ||
do { \ | ||
x = a + b; \ | ||
y = b - (x - a); \ | ||
} while (0) | ||
|
||
#define Two_Sum(a, b, x, y) \ | ||
do { \ | ||
double bvirt; \ | ||
x = a + b; \ | ||
bvirt = x - a; \ | ||
y = a - (x - bvirt) + (b - bvirt); \ | ||
} while (0) | ||
|
||
#define Two_Diff_Tail(a, b, x, y) \ | ||
do { \ | ||
double bvirt = a - x; \ | ||
y = a - (x + bvirt) + (bvirt - b); \ | ||
} while (0) | ||
|
||
#define Two_Diff(a, b, x, y) \ | ||
do { \ | ||
x = a - b; \ | ||
Two_Diff_Tail(a, b, x, y); \ | ||
} while (0) | ||
|
||
#define Split(a, ahi, alo) \ | ||
do { \ | ||
double c = splitter * a; \ | ||
ahi = c - (c - a); \ | ||
alo = a - ahi; \ | ||
} while (0) | ||
|
||
#define Two_Product(a, b, x, y) \ | ||
do { \ | ||
double ahi, alo, bhi, blo; \ | ||
x = a * b; \ | ||
Split(a, ahi, alo); \ | ||
Split(b, bhi, blo); \ | ||
y = alo * blo - (x - ahi * bhi - alo * bhi - ahi * blo); \ | ||
} while (0) | ||
|
||
#define Two_Product_Presplit(a, b, bhi, blo, x, y) \ | ||
do { \ | ||
double ahi, alo; \ | ||
x = a * b; \ | ||
Split(a, ahi, alo); \ | ||
y = alo * blo - (x - ahi * bhi - alo * bhi - ahi * blo); \ | ||
} while (0) | ||
|
||
#define Square(a, x, y) \ | ||
do { \ | ||
double ahi, alo; \ | ||
x = a * a; \ | ||
Split(a, ahi, alo); \ | ||
y = alo * alo - (x - ahi * ahi - (ahi + ahi) * alo); \ | ||
} while (0) | ||
|
||
#define Two_One_Sum(a1, a0, b, x2, x1, x0) \ | ||
do { \ | ||
double _i; \ | ||
Two_Sum(a0, b, _i, x0); \ | ||
Two_Sum(a1, _i, x2, x1); \ | ||
} while (0) | ||
|
||
#define Two_One_Diff(a1, a0, b, x2, x1, x0) \ | ||
do { \ | ||
double _i; \ | ||
Two_Diff(a0, b, _i, x0); \ | ||
Two_Sum(a1, _i, x2, x1); \ | ||
} while (0) | ||
|
||
#define Two_Two_Sum(a1, a0, b1, b0, x3, x2, x1, x0) \ | ||
do { \ | ||
double _j, _0; \ | ||
Two_One_Sum(a1, a0, b0, _j, _0, x0); \ | ||
Two_One_Sum(_j, _0, b1, x3, x2, x1); \ | ||
} while (0) | ||
|
||
#define Two_Two_Diff(a1, a0, b1, b0, x3, x2, x1, x0) \ | ||
do { \ | ||
double _j, _0; \ | ||
Two_One_Diff(a1, a0, b0, _j, _0, x0); \ | ||
Two_One_Diff(_j, _0, b1, x3, x2, x1); \ | ||
} while (0) | ||
|
||
#define Two_One_Product(a1, a0, b, D) \ | ||
do { \ | ||
double bhi, blo, _i, _j, _0, _k, u3; \ | ||
Split(b, bhi, blo); \ | ||
Two_Product_Presplit(a0, b, bhi, blo, _i, D[0]); \ | ||
Two_Product_Presplit(a1, b, bhi, blo, _j, _0); \ | ||
Two_Sum(_i, _0, _k, D[1]); \ | ||
Fast_Two_Sum(_j, _k, u3, D[2]); \ | ||
D[3] = u3; \ | ||
} while (0) | ||
|
||
#define Cross_Product(a, b, c, d, D) \ | ||
do { \ | ||
double s1, s0, t1, t0, u3; \ | ||
Two_Product(a, d, s1, s0); \ | ||
Two_Product(c, b, t1, t0); \ | ||
Two_Two_Diff(s1, s0, t1, t0, u3, D[2], D[1], D[0]); \ | ||
D[3] = u3; \ | ||
} while (0) | ||
|
||
#define Two_Product_Sum(a, b, c, d, D) \ | ||
do { \ | ||
double s1, s0, t1, t0, u3; \ | ||
Two_Product(a, b, s1, s0); \ | ||
Two_Product(c, d, t1, t0); \ | ||
Two_Two_Sum(s1, s0, t1, t0, u3, D[2], D[1], D[0]); \ | ||
D[3] = u3; \ | ||
} while (0) | ||
|
||
#define Square_Sum(a, b, D) \ | ||
do { \ | ||
double s1, s0, t1, t0, u3; \ | ||
Square(a, s1, s0); \ | ||
Square(b, t1, t0); \ | ||
Two_Two_Sum(s1, s0, t1, t0, u3, D[2], D[1], D[0]); \ | ||
D[3] = u3; \ | ||
} while (0) | ||
|
||
} // namespace robust_predicates | ||
} // namespace cubao |
Oops, something went wrong.