41#include <boost/array.hpp>
109 if (b ==
c)
return false;
110 return cross(b-a,
c-a) > 0;
131 for (std::size_t i = 2; i <
_boundary.size(); ++i) {
153 if (
size() <= 2)
return 0;
156 for (std::size_t i = 0; i <
size()-1; ++i) {
160 return fabs(a * 0.5);
165 if (
empty())
return {};
178 auto advance = [
this] (
size_t i,
Point const &n) {
181 auto j = (i + 1) %
size();
191 auto min_area = std::numeric_limits<Coord>::max();
197 for (
size_t i = 0; i <
size(); i++) {
201 auto const v = p2 - p1;
202 auto const n = v.cw();
219 auto const area =
w * h / v.lengthSq();
222 if (
area < min_area) {
235 ret[
Y] = std::numeric_limits<Coord>::infinity();
238 if (ret[
Y] >= i.
y()) {
251 ret[
Y] = -std::numeric_limits<Coord>::infinity();
254 if (ret[
Y] <= j.
y()) {
264template <
typename Iter,
typename Lex>
267 typename Lex::Secondary above;
268 Iter f = std::lower_bound(first, last, p, lex);
269 if (f == last)
return false;
271 if (p == *f)
return true;
275 Point a = *(f-1), b = *f;
277 if (above(p[
Y], a[
Y]) || above(b[
Y], p[
Y]))
return false;
281 if (above(p[
Y], y))
return false;
310 for (
unsigned i = 0; i < 4; ++i) {
355 return cross((p1 - p0), (p2 - p0));
361 angle_cmp(
Point o) : o(o) {}
367 if (a == b)
return false;
370 if (da == -db)
return false;
375 if((da[1] == 0) && (db[1] == 0))
376 return da[0] <
db[0];
387 double aa =
atan2(da);
388 double ab =
atan2(db);
393 return L2sq(da) < L2sq(db);
397 bool operator() (
Point const& a,
Point const& b)
402 if (a == b)
return false;
405 if (da == -db)
return false;
406 double dxy = da[
X] *
db[
Y];
407 double dyx = da[
Y] *
db[
X];
408 if (dxy > dyx)
return true;
409 else if (dxy < dyx)
return false;
410 return L2sq(da) < L2sq(db);
426ConvexHull::merge(
Point p) {
427 std::vector<Point> out;
429 int len = boundary.size();
432 if(boundary.empty() || boundary[0] != p)
433 boundary.push_back(p);
439 bool pre = is_left(p, -1);
440 for(
int i = 0; i <
len; i++) {
441 bool cur = is_left(p, i);
455 out.push_back(boundary[i]);
470ConvexHull::is_clockwise()
const {
473 Point first = boundary[0];
474 Point second = boundary[1];
475 for(std::vector<Point>::const_iterator it(boundary.begin()+2), e(boundary.end());
491ConvexHull::top_point_first()
const {
492 if(
size() <= 1)
return true;
493 std::vector<Point>::const_iterator pivot = boundary.begin();
494 for(std::vector<Point>::const_iterator it(boundary.begin()+1),
497 if((*it)[1] < (*pivot)[1])
499 else if(((*it)[1] == (*pivot)[1]) &&
500 ((*it)[0] < (*pivot)[0]))
503 return pivot == boundary.begin();
508ConvexHull::meets_invariants()
const {
509 return is_clockwise() && top_point_first();
516ConvexHull::is_degenerate()
const {
517 return boundary.size() < 3;
528 for(
int i = 0; i < 4; i++) {
532 else if(sn != side)
return false;
544 vector<pair<int, int> > ret;
549 double ap_angle =
atan2(a[ai+1] - a[ai]);
550 double bp_angle =
atan2(b[bi+1] - b[bi]);
551 Point L[2] = {a[ai], b[bi]};
552 while(ai <
int(a.
size()) || bi <
int(b.
size())) {
553 if(ap_angle == bp_angle) {
557 Point xs[4] = {a[ai-1], a[ai+1], b[bi-1], b[bi+1]};
558 if(
same_side(L, xs)) ret.push_back(make_pair(ai, bi));
561 if(
same_side(L, xs)) ret.push_back(make_pair(ai, bi));
564 if(
same_side(L, xs)) ret.push_back(make_pair(ai, bi));
567 if(
same_side(L, xs)) ret.push_back(make_pair(ai, bi));
575 std::cout <<
"parallel\n";
576 }
else if(ap_angle < bp_angle) {
580 Point xs[4] = {a[ai-1], a[ai+1], b[bi-1], b[bi+1]};
581 if(
same_side(L, xs)) ret.push_back(make_pair(ai, bi));
586 Point xs[4] = {a[ai-1], a[ai+1], b[bi-1], b[bi+1]};
587 if(
same_side(L, xs)) ret.push_back(make_pair(ai, bi));
595 while(it < a.boundary.
size() &&
596 a.boundary[it][
Y] > a.boundary[it-1][
Y])
613 while(al+1 < a.boundary.
size() &&
614 (a.boundary[al+1][
Y] > b.boundary[bl][
Y])) {
617 while(bl+1 < b.boundary.
size() &&
618 (b.boundary[bl+1][
Y] > a.boundary[al][
Y])) {
647 return idx?p.second:p.first;
656 std::cout <<
"---\n";
657 std::vector<pair<int, int> > bpair =
bridges(a, b);
664 unsigned state = (a[0][
Y] < b[0][
Y])?0:1;
665 ret.boundary.reserve(a.
size() + b.
size());
669 for(
unsigned k = 0; k < bpair.size(); k++) {
671 std::cout << bpair[k].first <<
" , " << bpair[k].second <<
"; "
672 << idx <<
", " <<
limit <<
", s: "
675 while(idx <=
limit) {
676 ret.boundary.push_back(chs[state][idx++]);
681 while(idx < chs[state].
size()) {
682 ret.boundary.push_back(chs[state][idx++]);
691 if(b.boundary[0] <= a.boundary[0])
694 result.boundary = a.boundary;
696 b.boundary.
begin(), b.boundary.
end());
711 if(b.boundary[0] <= a.boundary[0])
714 result.boundary = a.boundary;
716 b.boundary.
begin(), b.boundary.
end());
735 const unsigned n = boundary.size();
739 centroid = (boundary[0] + boundary[1])/2;
744 for (
unsigned i = n-1, j = 0; j <
n; i = j, j++) {
745 const double ai =
cross(boundary[j], boundary[i]);
747 centroid_tmp += (boundary[j] + boundary[i])*ai;
750 centroid = centroid_tmp / (3 * atmp);
758Point const * ConvexHull::furthest(
Point direction)
const {
759 Point const * p = &boundary[0];
760 double d =
dot(*p, direction);
761 for(
unsigned i = 1; i < boundary.size(); i++) {
762 double dd =
dot(boundary[i], direction);
777 Point tb = boundary.back();
778 double d = std::numeric_limits<double>::max();
779 for(
unsigned i = 0; i < boundary.size(); i++) {
780 Point tc = boundary[i];
782 Point ta = *furthest(n);
783 double td =
dot(n, ta-tb)/
dot(n,n);
Defines the different types of exceptions that 2geom can throw.
pair< double, double > Point
Convex hull based on the Andrew's monotone chain algorithm.
OptRect bounds() const
Compute the bounding rectangle of the convex hull.
std::vector< Point > _boundary
Sequence of points forming the convex hull polygon.
bool empty() const
Check for emptiness.
Point bottomPoint() const
Get the bottommost (maximum Y) point of the hull.
iterator end() const
Get the end iterator to the points that form the hull.
boost::iterator_range< UpperIterator > upperHull() const
Get an iterator range to the upper part of the hull.
ConvexHull()=default
Create an empty convex hull.
void swap(ConvexHull &other)
boost::iterator_range< LowerIterator > lowerHull() const
Get an iterator range to the lower part of the hull.
size_t size() const
Get the number of points in the hull.
ConvexHullLowerIterator LowerIterator
Coord bottom() const
Get the bottommost (maximum Y) coordinate of the hull.
Coord left() const
Get the leftmost (minimum X) coordinate of the hull.
bool contains(Point const &p) const
Check whether the given point is inside the hull.
std::vector< Point >::const_iterator UpperIterator
std::pair< Rotate, OptRect > minAreaRotation() const
Return a rotation that puts the convex hull into a position such that bounds() has minimal area,...
iterator begin() const
Get the begin iterator to the points that form the hull.
double area() const
Calculate the area of the convex hull.
Point const & front() const
Get the first, leftmost point in the hull.
Coord right() const
Get the rightmost (maximum X) coordinate of the hull.
Point topPoint() const
Get the topmost (minimum Y) point of the hull.
Coord top() const
Get the topmost (minimum Y) coordinate of the hull.
std::size_t _lower
Index one past the rightmost point, where the lower part of the boundary starts.
static CRect from_xywh(Coord x, Coord y, Coord w, Coord h)
Create rectangle from origin and dimensions.
CPoint corner(unsigned i) const
Return the n-th corner of the rectangle.
Axis-aligned rectangle that can be empty.
Two-dimensional point that doubles as a vector.
Coord length() const
Compute the distance from origin.
constexpr Coord y() const noexcept
Axis aligned, non-empty rectangle.
Rotation around the origin.
Convex hull data structures.
constexpr Coord lerp(Coord t, Coord a, Coord b)
Numerically stable linear interpolation.
double Coord
Floating point type used to store coordinates.
Various utility functions.
std::vector< pair< int, int > > bridges(ConvexHull a, ConvexHull b)
find bridging pairs between two convex hulls.
double SignedTriangleArea(Point p0, Point p1, Point p2)
int sgn(const T &x)
Sign function - indicates the sign of a numeric type.
static bool is_clockwise_turn(Point const &a, Point const &b, Point const &c)
bool same_side(Point L[2], Point xs[4])
double atan2(Point const &p)
OptCrossing intersection(Ray const &r1, Line const &l2)
int centroid(std::vector< Geom::Point > const &p, Geom::Point ¢roid, double &area)
polyCentroid: Calculates the centroid (xCentroid, yCentroid) and area of a polygon,...
ConvexHull graham_merge(ConvexHull a, ConvexHull b)
T idx_to_pair(pair< T, T > p, int idx)
ConvexHull merge(ConvexHull a, ConvexHull b)
ConvexHull sweepline_intersection(ConvexHull const &a, ConvexHull const &b)
ConvexHull andrew_merge(ConvexHull a, ConvexHull b)
double angle_between(Line const &l1, Line const &l2)
bool below_x_monotonic_polyline(Point const &p, Iter first, Iter last, Lex lex)
unsigned find_bottom_right(ConvexHull const &a)
Piecewise< SBasis > cross(Piecewise< D2< SBasis > > const &a, Piecewise< D2< SBasis > > const &b)
T dot(D2< T > const &a, D2< T > const &b)
D2< T > rot90(D2< T > const &a)
DB db
This is the actual database object.