Commit db944e47 authored by Paul Asmuth's avatar Paul Asmuth
Browse files

find the point of intersection of two lines

parent f3a98206
Loading
Loading
Loading
Loading
+53 −7
Original line number Diff line number Diff line
@@ -15,16 +15,12 @@

namespace fviz {

/**
 * Check if two lines intersect and if they do, return the intersection
 * point
 */
bool intersect_line_line(
    vec2 o0,
    vec2 p0,
    vec2 v0,
    vec2 o1,
    vec2 p1,
    vec2 v1,
    vec2* x /* = nullptr */) {
    vec2* p /* = nullptr */) {
  // ensure the direction vectors are normalized
  v0 = vec2_normalize(v0);
  v1 = vec2_normalize(v1);
@@ -39,6 +35,56 @@ bool intersect_line_line(
    return false;
  }

  // if the lines are not parallel, but the user is not interested in the
  // intersection point, return
  if (!p) {
    return true;
  }

  // the next step is to compute the point of intersection. we start with the
  // implicit expressions that define the global y coordinates of all points on
  // the input lines in terms of the global x coordinate written in the standard
  // form:
  //
  //     aN * x + bN * y = cN
  //
  // we already have the direction vector (a and b) as an input argument, so
  // we can find a valid c that satisfies the equation simply by evaluating the
  // left part of the equation with the known point on the line that we also
  // have.
  auto a0 = -v0.y;
  auto a1 = -v1.y;
  auto b0 = v0.x;
  auto b1 = v1.x;
  auto c0 = a0 * p0.x + b0 * p0.y;
  auto c1 = a1 * p1.x + b1 * p1.y;

  // the x coordinate of the point of intersection can now be determined
  // by solving the following system of linear equations. the two equations are
  // the standard-form line equations derived above.
  //
  //    a0 * x + b0 * y = c0
  //    a1 * x + b1 * y = c1
  //
  // or written in matrix coefficient form:
  //
  //    | a0  b0 |     | x |     | c0 |
  //    |        |  +  |   |  =  |    |
  //    | a1  b1 |     | y |     | c1 |
  //
  // this system can be solved using cramer's rule (there must be a solution
  // since the lines are already determined not to be parallel). to do so, we
  // first calculate the three "denominator", "x numerator" and "y numerator"
  // determinants of the (substituted) coefficient matrix and then compute the
  // result by dividing the determinants as defined by cramer's rule:

  auto dd = (a0 * b1 - b0 * a1); // standard determinant
  auto dx = (b1 * c0 - b0 * c1); // replace x coefficients (a0/a1) with solution
  auto dy = (a0 * c1 - a1 * c0); // replace y coefficients (b0/b1) with solution

  p->x = dx / dd;
  p->y = dy / dd;

  return true;
}

+6 −6
Original line number Diff line number Diff line
@@ -24,16 +24,16 @@
namespace fviz {

/**
 * Given two (infinite) lines defined by a point on each of the the lines o0, o1
 * (their 'origins') and their normal direction vectors v0, v1, compute the point
 * of intersection. Returns false if the two lines are parallel.
 * Given two (infinite) lines defined by a point on each of the the lines p0, p1
 * and their normal direction vectors v0, v1, compute the point of intersection.
 * Returns false if the two lines are parallel.
 */
bool intersect_line_line(
    vec2 o0,
    vec2 p0,
    vec2 v0,
    vec2 o1,
    vec2 p1,
    vec2 v1,
    vec2* x = nullptr);
    vec2* p = nullptr);

} // namespace fviz
+17 −0
Original line number Diff line number Diff line
@@ -146,7 +146,24 @@ void test_intersect_parallel() {
      true);
}

void test_intersect_point() {
  Point p;

  EXPECT_EQ(
      intersect_line_line(
          {0, 0},
          {1, 2},
          {0, 2},
          {1, 1},
          &p),
      true);

  EXPECT_EQ(p.x, 2);
  EXPECT_EQ(p.y, 4);
}

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