Skip to content
Snippets Groups Projects
Commit cbeab170 authored by Bruno Freitas Tissei's avatar Bruno Freitas Tissei
Browse files

Add geometry functions and minor fixes

parent f1d7f03d
No related branches found
No related tags found
No related merge requests found
...@@ -23,21 +23,21 @@ struct ConvexHull { ...@@ -23,21 +23,21 @@ struct ConvexHull {
*/ */
int run(const vector<dd> &v) { int run(const vector<dd> &v) {
int k = 0; int k = 0;
vector<int> ans(v.sz * 2); vector<int> ans(v.size() * 2);
sort(v.begin(), v.end(), [](const dd &a, const dd &b) { sort(all(v), [](const dd &a, const dd &b) {
return (a.fi == b.fi) ? (a.se < b.se) : (a.fi < b.fi); return (a.fi == b.fi) ? (a.se < b.se) : (a.fi < b.fi);
}); });
// Uppermost part of convex hull // Uppermost part of convex hull
for (int i = 0; i < v.sz; ++i) { for (int i = 0; i < v.size(); ++i) {
while (k >= 2 && cross(v[ans[k - 2]], v[ans[k - 1]], v[i]) < 0) while (k >= 2 && cross(v[ans[k - 2]], v[ans[k - 1]], v[i]) < 0)
k--; k--;
ans[k++] = i; ans[k++] = i;
} }
// Lowermost part of convex hull // Lowermost part of convex hull
for (int i = v.sz - 2, t = k + 1; i >= 0; --i) { for (int i = v.size() - 2, t = k + 1; i >= 0; --i) {
while (k >= t && cross(v[ans[k - 2]], v[ans[k - 1]], v[i]) < 0) while (k >= t && cross(v[ans[k - 2]], v[ans[k - 1]], v[i]) < 0)
k--; k--;
ans[k++] = i; ans[k++] = i;
......
...@@ -2,21 +2,124 @@ ...@@ -2,21 +2,124 @@
* Geometry functions * Geometry functions
*/ */
struct Vector { template <typename T>
double x, y; struct Point {
T x, y;
Vector(double x, double y) : x(x), y(y) {} Point(T x, T y) : x(x), y(y) {}
double dot_product(Vector v) { return x * v.x + y * v.y; } Point operator+(Point p) { return Point(x + p.x, y + p.y); }
double cross_product(Vector v) { return x * v.y - v.x * y; } Point operator-(Point p) { return Point(x - p.x, y - p.y); }
T dot(Point p) { return (x * p.x) + (y * p.y); }
T cross(Point p) { return (x * p.y) - (y * p.y); }
/**
* Returns angle between this and p:
* atan2(y, x) is in the range [-180,180]. To get [0, 360],
* atan2(-y, -x) + 180 is used
*/
T angle(Point p) {
return ((atan2(-cross(p), -dot(p)) * 180.0) / M_PI) + 180.0;
}
/**
* Returns cosine value between this and p.
*/
T cosine(Point p) {
return (dot(p) / (sqrt(dot(*this)) * sqrt(p.dot(p))));
}
/**
* Returns sine value between this and p.
*/
T sine(Point p) {
return (cross(p) / (sqrt(dot(*this)) * sqrt(p.dot(p))));
}
/**
* Finds orientation of ordered triplet (a,b,c).
* 0 - Colinear;
* 1 - Clockwise;
* 2 - Counterclockwise.
*/
static int orientation(Point a, Point b, Point c) {
T val = (b - a).cross(c - b);
if (val == 0)
return 0;
return (val > 0) ? 1 : 2;
}
};
template <typename T>
struct Segment {
Point<T> a, b;
Segment(Point a, Point b) : a(a), b(b) {}
/**
* Checks if points p and q are on the same side of the segment.
*/
bool same_side(Point p, Point q) {
T cpp = (p - a).cross(b - a);
T cpq = (q - a).cross(b - a);
return ((cpp > 0 && cpq > 0) || (cpp < 0 && cpq < 0));
}
/**
* Checks if point p is on the segment.
*/
bool on_segment(Point p) {
return (p.x <= max(a.x, b.x) &&
p.x >= min(a.x, b.x) &&
p.y <= max(a.y, b.y) &&
p.y >= min(a.y, b.y));
}
/**
* Checks if segment intersects with s.
*/
bool intersect(Segment s) {
int o1 = Point::orientation( a, b, s.a);
int o2 = Point::orientation( a, b, s.b);
int o3 = Point::orientation(s.a, s.b, a);
int o4 = Point::orientation(s.a, s.b, b);
if (o1 != o2 && o3 != o4)
return true;
if (o1 == 0 && on_segment(s.a)) return true;
if (o2 == 0 && on_segment(s.b)) return true;
if (o3 == 0 && s.on_segment(a)) return true;
if (o4 == 0 && s.on_segment(b)) return true;
return false;
}
};
template <typename T>
struct Polygon {
vector<Point<T>> vertices;
Polygon() {}
Polygon(vector<Point> vertices) : vertices(vertices) {}
/**
* Adds a vertex to the polygon.
*/
void add_point(Point p) { vertices.pb(p); }
/** /**
* Returns angle between this and v. * Returns area of polygon (only works when vertices are sorted in clockwise
* or counterclockwise order).
*/ */
double angle(Vector v) { double area() {
double ans = 0;
for (int i = 0; i < vertices.size(); ++i)
ans += vertices[i].cross(vertices[(i + 1) % vertices.size()]);
// atan2(y, x) is in the range [-180,180]. To get [0, 360], return fabs(ans) / 2.0;
// atan2(-y, -x) + 180 is used
return ((atan2(-cross_product(v), -dot_product(v)) * 180.0) / M_PI) + 180.0;
} }
}; };
...@@ -50,7 +50,7 @@ struct LCA { ...@@ -50,7 +50,7 @@ struct LCA {
*/ */
void preprocess(int v) { void preprocess(int v) {
mset(par, -1); mset(par, -1);
//*** mset(cost, 0; //*** mset(cost, 0);
dfs(v); dfs(v);
} }
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment