Commit 5854a130 authored by Paul Asmuth's avatar Paul Asmuth
Browse files

check if two line segments intersect

parent db944e47
Loading
Loading
Loading
Loading
+79 −0
Original line number Diff line number Diff line
@@ -88,5 +88,84 @@ bool intersect_line_line(
  return true;
}

bool intersect_line_lineseg(
    vec2 p0,
    vec2 v0,
    vec2 s1,
    vec2 e1,
    vec2* p /* = nullptr */) {
  // find the intersection between the infinite lines given by {p0, v1} and the
  // infinite line that passes through {s0, e0}
  vec2 pt;
  auto pt_exists = intersect_line_line(
      p0,
      v0,
      s1,
      vec2_normalize(vec2_sub(e1, s1)),
      &pt);

  if (!pt_exists) {
    return false;
  }

  // check if the intersection point is outside of the line segment
  if (pt.x < std::min(s1.x, e1.x) ||
      pt.x > std::max(s1.x, e1.x) ||
      pt.y < std::min(s1.y, e1.y) ||
      pt.y > std::max(s1.y, e1.y)) {
    return false;
  }

  // we found a point of intersection that is located on the line segment,
  // return it
  if (p) {
    *p = pt;
  }

  return true;
}

bool intersect_lineseg_lineseg(
    vec2 s0,
    vec2 e0,
    vec2 s1,
    vec2 e1,
    vec2* p /* = nullptr */) {
  // find the intersection between the infinite lines that pass through {s0, e0}
  // and {s1, e1} respectively
  vec2 pt;
  auto pt_exists = intersect_line_line(
      s0,
      vec2_sub(e0, s0),
      s1,
      vec2_normalize(vec2_sub(e1, s1)),
      &pt);

  if (!pt_exists) {
    return false;
  }

  // check if the intersection point is outside of one of the lines segments
  if (pt.x < std::min(s0.x, e0.x) ||
      pt.x > std::max(s0.x, e0.x) ||
      pt.y < std::min(s0.y, e0.y) ||
      pt.y > std::max(s0.y, e0.y) ||
      pt.x < std::min(s1.x, e1.x) ||
      pt.x > std::max(s1.x, e1.x) ||
      pt.y < std::min(s1.y, e1.y) ||
      pt.y > std::max(s1.y, e1.y)) {
    return false;
  }

  // we found a point of intersection that is located on both line segments,
  // return it
  if (p) {
    *p = pt;
  }

  return true;
}


} // namespace fviz
+24 −0
Original line number Diff line number Diff line
@@ -35,5 +35,29 @@ bool intersect_line_line(
    vec2 v1,
    vec2* p = nullptr);

/**
 * Given an infinite line defined by a point on the line and a direction vector
 * and a line segment defined by its start and end point, compute their point of
 * intersection if any. Returns false if the two lines are parallel.
 */
bool intersect_line_lineseg(
    vec2 p0,
    vec2 v0,
    vec2 s1,
    vec2 e1,
    vec2* p = nullptr);

/**
 * Given two line sgements defined by the two start and end points of the two
 * line segments s0, s1 and e1, e2, compute their point of intersection if any.
 * Returns false if the two line segements are parallel or coincident.
 */
bool intersect_lineseg_lineseg(
    vec2 s0,
    vec2 e0,
    vec2 s1,
    vec2 e1,
    vec2* p = nullptr);

} // namespace fviz
+42 −0
Original line number Diff line number Diff line
@@ -162,8 +162,50 @@ void test_intersect_point() {
  EXPECT_EQ(p.y, 4);
}


void test_intersect_linesegs() {
  {
    Point p;
    EXPECT_EQ(
        intersect_lineseg_lineseg(
            {1, 1},
            {3, 1},
            {1, 4},
            {3, 4},
            &p),
        false);
  }

  {
    Point p;
    EXPECT_EQ(
        intersect_lineseg_lineseg(
            {1, 1},
            {4, 4},
            {1, 4},
            {4, 1},
            &p),
        true);
    EXPECT_EQ(p.x, 2.5);
    EXPECT_EQ(p.y, 2.5);
  }

  {
    Point p;
    EXPECT_EQ(
        intersect_lineseg_lineseg(
            {1, 1},
            {4, 2},
            {1, 4},
            {4, 3},
            &p),
        false);
  }
}

int main(int argc, char** argv) {
  test_intersect_parallel();
  test_intersect_point();
  test_intersect_linesegs();
}