From cbeab170cff48ee76bda8e602e190ba62fa17c50 Mon Sep 17 00:00:00 2001
From: Bruno Freitas Tissei <bft15@inf.ufpr.br>
Date: Tue, 16 Apr 2019 21:50:02 -0300
Subject: [PATCH] Add geometry functions and minor fixes

Signed-off-by: Bruno Freitas Tissei <bft15@inf.ufpr.br>
---
 algorithms/geometry/convex_hull.cpp        |   8 +-
 algorithms/geometry/geometry_functions.cpp | 123 +++++++++++++++++++--
 algorithms/graph/lca.cpp                   |   2 +-
 3 files changed, 118 insertions(+), 15 deletions(-)

diff --git a/algorithms/geometry/convex_hull.cpp b/algorithms/geometry/convex_hull.cpp
index b9fb75a..4f4f262 100644
--- a/algorithms/geometry/convex_hull.cpp
+++ b/algorithms/geometry/convex_hull.cpp
@@ -23,21 +23,21 @@ struct ConvexHull {
    */
   int run(const vector<dd> &v) {
     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);
     });
 
     // 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) 
         k--;
       ans[k++] = i;
     }
 
     // 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) 
         k--;
       ans[k++] = i;
diff --git a/algorithms/geometry/geometry_functions.cpp b/algorithms/geometry/geometry_functions.cpp
index 97b6abe..0984d21 100644
--- a/algorithms/geometry/geometry_functions.cpp
+++ b/algorithms/geometry/geometry_functions.cpp
@@ -2,21 +2,124 @@
  * Geometry functions
  */
 
-struct Vector {
-  double x, y; 
+template <typename T>
+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; }
-  double cross_product(Vector v) { return x * v.y - v.x * y; }
+  Point operator+(Point p) { return Point(x + p.x, y + p.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], 
-    // atan2(-y, -x) + 180 is used
-    return ((atan2(-cross_product(v), -dot_product(v)) * 180.0) / M_PI) + 180.0;
+    return fabs(ans) / 2.0;
   }
 };
diff --git a/algorithms/graph/lca.cpp b/algorithms/graph/lca.cpp
index b3faae5..136a2c0 100644
--- a/algorithms/graph/lca.cpp
+++ b/algorithms/graph/lca.cpp
@@ -50,7 +50,7 @@ struct LCA {
    */
   void preprocess(int v) {
     mset(par, -1);
-    //*** mset(cost, 0;
+    //*** mset(cost, 0);
     dfs(v);
   }
 
-- 
GitLab