Sam Jaffe 6 years ago
parent
commit
ae5ae8d24e
3 changed files with 21 additions and 23 deletions
  1. 6 8
      math/include/game/math/compare.hpp
  2. 11 11
      math/src/common.cpp
  3. 4 4
      math/test/common_test.cxx

+ 6 - 8
math/include/game/math/compare.hpp

@@ -4,21 +4,19 @@
 #include <cmath>
 
 namespace math {
-  struct lessinf {
-    template <typename T>
-    bool operator()(T const & lhs, T const & rhs) {
-      return !isinf(lhs) && (isinf(rhs) || lhs < rhs);
-    }
-  };
-
   template <typename T>
   T safe_div(T num, T denom) {
     return (num == denom && denom == 0) ? 0 : num / denom;
   }
+  
+  template <typename T>
+  bool between_exclusive(T val, T min, T max) {
+    return val >= min && val < max;
+  }
 
   template <typename T>
   bool between(T val, T min, T max) {
-    return val >= min && (min == max || val < max);
+    return val >= min && val <= max;
   }
 
   template <typename T>

+ 11 - 11
math/src/common.cpp

@@ -37,18 +37,18 @@ namespace math {
     colinear = 0, clockwise = 1, anticlockwise = 2
   };
   
-  orientation orient(dim2::point const & p, dim2::point const & q,
-                     dim2::point const & r) {
-    float val = (q[1] - p[1]) * (r[0] - q[0]) - (q[0] - p[0]) * (r[1] - q[1]);
+  orientation orient(dim2::line const & ln, dim2::point const & pt) {
+    auto val = (ln.second[1] - ln.first[1]) * (pt[0] - ln.second[0]) -
+        (ln.second[0] - ln.first[0]) * (pt[1] - ln.second[1]);
     
     if (val == 0) return colinear;
     return (val > 0) ? clockwise : anticlockwise;
   }
   
   bool contains(dim2::line const & ln, dim2::point const & pt) {
-    auto xs = std::minmax(ln.first[0], ln.second[0], lessinf());
-    auto ys = std::minmax(ln.first[1], ln.second[1], lessinf());
-    return orient(ln.first, ln.second, pt) == colinear &&
+    auto xs = std::minmax(ln.first[0], ln.second[0]);
+    auto ys = std::minmax(ln.first[1], ln.second[1]);
+    return orient(ln, pt) == colinear &&
         between(pt[0], xs.first, xs.second) &&
         between(pt[1], ys.first, ys.second);
   }
@@ -68,7 +68,7 @@ namespace math {
     int hits = 0;
     for (auto l : segments) {
       if (!intersects(l, ray_x(pt, l))) continue;
-      if (orient(l.first, l.second, pt) == colinear) return contains(l, pt);
+      if (orient(l, pt) == colinear) return contains(l, pt);
       ++hits;
     }
     return (hits & 1) == 1;
@@ -81,10 +81,10 @@ namespace math {
   bool intersects(dim2::line const & lhs, dim2::line const & rhs) {
     // https://www.geeksforgeeks.org/check-if-two-given-line-segments-intersect/
     // Find the four orientations needed for general and special cases
-    orientation o1 = orient(lhs.first, lhs.second, rhs.first);
-    orientation o2 = orient(lhs.first, lhs.second, rhs.second);
-    orientation o3 = orient(rhs.first, rhs.second, lhs.first);
-    orientation o4 = orient(rhs.first, rhs.second, lhs.second);
+    orientation o1 = orient(lhs, rhs.first);
+    orientation o2 = orient(lhs, rhs.second);
+    orientation o3 = orient(rhs, lhs.first);
+    orientation o4 = orient(rhs, lhs.second);
     
     // General Case: Lines cross through each other
     if (o1 != o2 && o3 != o4)

+ 4 - 4
math/test/common_test.cxx

@@ -49,10 +49,10 @@ TEST_P(LineTest, ColinearOutsideDoesNotContain) {
 }
 
 std::vector<point> const line_ends{
-  {{1, 1}}, {{0, 1}}, {{1, 0}}
+  {{1, 1}}, {{0, 1}}, {{1, 0}}, {{-1, -1}}, {{0, -1}}, {{-1, 0}}
 };
 
-INSTANTIATE_TEST_CASE_P(ContainsPoint, LineTest,
+INSTANTIATE_TEST_CASE_P(Contains, LineTest,
     Combine(ValuesIn(line_ends), ValuesIn(generate(0, 100, 10))));
 
 struct UnitCircleTest : TestWithParam<point> {};
@@ -71,7 +71,7 @@ point unit_circle_angle(math::degree degs) {
   return point(make_vector(math::sin(degs), math::cos(degs)));
 }
 
-INSTANTIATE_TEST_CASE_P(LiesOnEdge, UnitCircleTest,
+INSTANTIATE_TEST_CASE_P(Contains, UnitCircleTest,
     ValuesIn(generate(0.0, 360.0, 5.0, unit_circle_angle)));
 
 struct UnitSquareTest : TestWithParam<std::tuple<float, float>> {};
@@ -90,6 +90,6 @@ TEST_F(UnitSquareTest, PointOutsideSquare) {
   EXPECT_FALSE(math::contains(unit, {{ 1.1f, 0.0f}}));
 }
 
-INSTANTIATE_TEST_CASE_P(ContainsPoint, UnitSquareTest,
+INSTANTIATE_TEST_CASE_P(Contains, UnitSquareTest,
     Combine(ValuesIn(generate(0.f, 1.f, 0.25f)),
             ValuesIn(generate(0.f, 1.f, 0.25f))));