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

test if two lines are parallel

parent 0af465b9
Loading
Loading
Loading
Loading
+9 −0
Original line number Diff line number Diff line
@@ -50,6 +50,15 @@ vec2 vec2_mul(const vec2& v, double s) {
  return {v.x * s, v.y * s};
}

double vec2_dot(const vec2& a, const vec2& b) {
  return a.x * b.x + a.y * b.y;
}

vec2 vec2_from_deg(double deg) {
  double a = (deg - 180.0) / 180.0 * M_PI;
  return {cos(a), sin(a)};
}

std::ostream& operator <<(std::ostream& os, const Point& p) {
  os << "Point(";
  os << p.x;
+2 −0
Original line number Diff line number Diff line
@@ -42,6 +42,8 @@ vec2 vec2_normalize(const vec2& v);
vec2 vec2_add(const vec2& a, const vec2& b);
vec2 vec2_sub(const vec2& a, const vec2& b);
vec2 vec2_mul(const vec2& v, double s);
double vec2_dot(const vec2& a, const vec2& b);
vec2 vec2_from_deg(double deg);

std::ostream& operator <<(std::ostream& os, const Point& c);
std::ostream& operator <<(std::ostream& os, const Rectangle& c);
+46 −0
Original line number Diff line number Diff line
/**
 * This file is part of the "fviz" project
 *   Copyright (c) 2018 Paul Asmuth
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
#include "intersect.h"

namespace fviz {

/**
 * Check if two lines intersect and if they do, return the intersection
 * point
 */
bool intersect_line_line(
    vec2 o0,
    vec2 v0,
    vec2 o1,
    vec2 v1,
    vec2* x /* = nullptr */) {
  // ensure the direction vectors are normalized
  v0 = vec2_normalize(v0);
  v1 = vec2_normalize(v1);

  // consider lines as parallel if the angle between them is smaller than some
  // threshold
  const double a_epsilon = 0.001;
  double a = acos(vec2_dot(v0, v1));
  double a_norm = fmod(M_PI - a, M_PI);

  if (a_norm < a_epsilon) {
    return false;
  }

  return true;
}

} // namespace fviz
+39 −0
Original line number Diff line number Diff line
/**
 * This file is part of the "fviz" project
 *   Copyright (c) 2018 Paul Asmuth
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
#pragma once
#include <unordered_map>
#include <optional>

#include "graphics/color.h"
#include "graphics/layer.h"
#include "graphics/geometry.h"
#include "return_code.h"
#include "sexpr.h"

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.
 */
bool intersect_line_line(
    vec2 o0,
    vec2 v0,
    vec2 o1,
    vec2 v1,
    vec2* x = nullptr);

} // namespace fviz
+152 −0
Original line number Diff line number Diff line
/**
 * This file is part of the "fviz" project
 *   Copyright (c) 2018 Paul Asmuth
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
#include "graphics/intersect.h"
#include "unittest.h"

using namespace fviz;

void test_intersect_parallel() {
  // some slope but offset in y -> parallel
  EXPECT_EQ(
      intersect_line_line(
          {0, 0},
          vec2_from_deg(45),
          {0, 1},
          vec2_from_deg(45),
          nullptr),
      false);

  // some slope but offset in x -> parallel
  EXPECT_EQ(
      intersect_line_line(
          {0, 1},
          vec2_from_deg(45),
          {0, 0},
          vec2_from_deg(45),
          nullptr),
      false);

  // coincident -> parallel
  EXPECT_EQ(
      intersect_line_line(
          {0, 0},
          vec2_from_deg(45),
          {0, 0},
          vec2_from_deg(45),
          nullptr),
      false);

  // 180 degree shifted angles -> parallel
  EXPECT_EQ(
      intersect_line_line(
          {0, 0},
          vec2_from_deg(45),
          {0, 0},
          vec2_from_deg(45 + 180),
          nullptr),
     false);

  // -180 degree shifted angles -> parallel
  EXPECT_EQ(
      intersect_line_line(
          {0, 0},
          vec2_from_deg(45),
          {0, 0},
          vec2_from_deg(45 - 180),
          nullptr),
      false);

  // 360 degree shifted angles -> parallel
  EXPECT_EQ(
      intersect_line_line(
          {0, 0},
          vec2_from_deg(45),
          {0, 0},
          vec2_from_deg(45 + 360),
          nullptr),
      false);

  // -360 degree shifted angles -> parallel
  EXPECT_EQ(
      intersect_line_line(
          {0, 0},
          vec2_from_deg(45),
          {0, 0},
          vec2_from_deg(45 + -360),
          nullptr),
      false);

  // angles very close to each other -> "parallel"
  EXPECT_EQ(
      intersect_line_line(
          {0, 0},
          vec2_from_deg(45),
          {0, 0},
          vec2_from_deg(45.0000001),
          nullptr),
      false);

  EXPECT_EQ(
      intersect_line_line(
          {0, 0},
          vec2_from_deg(45),
          {0, 0},
          vec2_from_deg(44.9999999),
          nullptr),
      false);

  // angles less close to each other -> not parallel
  EXPECT_EQ(
      intersect_line_line(
          {0, 0},
          vec2_from_deg(45),
          {0, 0},
          vec2_from_deg(45.01),
          nullptr),
      true);

  EXPECT_EQ(
      intersect_line_line(
          {0, 0},
          vec2_from_deg(45),
          {0, 0},
          vec2_from_deg(44.99),
          nullptr),
      true);

  // angles different and x offset -> not parallel
  EXPECT_EQ(
      intersect_line_line(
          {0, 0},
          vec2_from_deg(45),
          {1, 0},
          vec2_from_deg(45.1),
          nullptr),
      true);

  // angles different and x offset -> not parallel
  EXPECT_EQ(
      intersect_line_line(
          {0, 0},
          vec2_from_deg(45),
          {0, 1},
          vec2_from_deg(45.1),
          nullptr),
      true);
}

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