Commit 5ff5a824 authored by Paul Asmuth's avatar Paul Asmuth
Browse files

add the intersect_poly_line{,seg} helper methods

parent 6233f09d
Loading
Loading
Loading
Loading
+41 −0
Original line number Diff line number Diff line
@@ -168,6 +168,47 @@ bool intersect_lineseg_lineseg(
  return true;
}

void intersect_poly_line(
    const Polygon2& p0,
    const vec2& p1,
    const vec2& v1,
    std::vector<vec2>* x) {
  // intersect with each edge of the polygon
  for (size_t i = 0; i < p0.vertices.size(); ++i) {
    Point p;
    auto p_found = intersect_line_lineseg(
        p1,
        v1,
        p0.vertices[i],
        p0.vertices[(i + 1) % p0.vertices.size()],
        &p);

    if (p_found) {
      x->push_back(p);
    }
  }
}

void intersect_poly_lineseg(
    const Polygon2& p0,
    const vec2& s1,
    const vec2& e1,
    std::vector<vec2>* x) {
  // intersect with each edge of the polygon
  for (size_t i = 0; i < p0.vertices.size(); ++i) {
    Point p;
    auto p_found = intersect_lineseg_lineseg(
        p0.vertices[i],
        p0.vertices[(i + 1) % p0.vertices.size()],
        s1,
        e1,
        &p);

    if (p_found) {
      x->push_back(p);
    }
  }
}

} // namespace fviz
+21 −0
Original line number Diff line number Diff line
@@ -18,6 +18,7 @@
#include "graphics/color.h"
#include "graphics/layer.h"
#include "graphics/geometry.h"
#include "graphics/polygon.h"
#include "return_code.h"
#include "sexpr.h"

@@ -59,5 +60,25 @@ bool intersect_lineseg_lineseg(
    vec2 e1,
    vec2* p = nullptr);

/**
 * Given a polygon and an (infinite) line defined by a point on the line p1 and
 * the lines direction v1, compute their points of intersection if any.
 */
void intersect_poly_line(
    const Polygon2& p0,
    const vec2& p1,
    const vec2& v1,
    std::vector<vec2>* x);

/**
 * Given a polygon and a line segement defined by its start and end points of the
 * two line segments s1, e1, compute their points of intersection if any.
 */
void intersect_poly_lineseg(
    const Polygon2& p0,
    const vec2& s1,
    const vec2& e1,
    std::vector<vec2>* x);

} // 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 <assert.h>
#include <stdlib.h>
#include <stdint.h>
#include <iostream>
#include "geometry.h"

namespace fviz {

/**
 * A polygon in 2D space defined by its vertices. A polygon is always closed;
 * for N vertices in the polygon, the polygon has N edges where one edge goes
 * from the last vertex in the list to the first vertex in the list.
 *
 * Note that polygons can be given in clockwise or counter-clockwise winding
 * order and that they may or may not self-intersect. Methods that work on
 * polygons will usually accept only a subset of these cases.
 */
struct Polygon2 {
  std::vector<vec2> vertices;
};

std::ostream& operator <<(std::ostream& os, const Polygon2& p);

} // namespace fviz
+13 −67
Original line number Diff line number Diff line
@@ -26,6 +26,14 @@ Path shape_hatch(
  auto direction = vec2_from_deg(angle_deg);
  auto ortho = vec2_from_deg(angle_deg + 90);

  Polygon2 clip_poly;
  clip_poly.vertices = {
    {clip.x,          clip.y + clip.h},
    {clip.x + clip.w, clip.y + clip.h},
    {clip.x + clip.w, clip.y},
    {clip.x,          clip.y},
  };

  Path p;
  for (size_t i = 0; i < 100; ++i) {
    // symmetry around the origin
@@ -37,76 +45,14 @@ Path shape_hatch(
      // find the intersections with the four borders of the clipping rectangle
      std::vector<Point> intersections;

      // top border
      {
        Point p;
        auto p_found = intersect_line_lineseg(
            o,
            direction,
            {clip.x         , clip.y},
            {clip.x + clip.w, clip.y},
            &p);

        if (p_found) {
          intersections.push_back(p);
        }
      }

      // bottom border
      {
        Point p;
        auto p_found = intersect_line_lineseg(
            o,
            direction,
            {clip.x         , clip.y + clip.h},
            {clip.x + clip.w, clip.y + clip.h},
            &p);

        if (p_found) {
          intersections.push_back(p);
        }
      }

      // right border
      {
        Point p;
        auto p_found = intersect_line_lineseg(
            o,
            direction,
            {clip.x + clip.w, clip.y},
            {clip.x + clip.w, clip.y + clip.h},
            &p);

        if (p_found) {
          intersections.push_back(p);
        }
      }

      // left border
      {
        Point p;
        auto p_found = intersect_line_lineseg(
      intersect_poly_line(
          clip_poly,
          o,
          direction,
            {clip.x, clip.y},
            {clip.x, clip.y + clip.h},
            &p);

        if (p_found) {
          intersections.push_back(p);
        }
      }
          &intersections);

      // stroke line between edge points
      if (intersections.size() >= 2) {
        auto line_max = vec2_mul(
            vec2_normalize(vec2_sub(intersections[0], intersections[1])),
            vec2_magnitude({clip.w, clip.h}));

        // double the line length to make sure there are no gaps
        intersections[0] = vec2_add(intersections[0], line_max);
        intersections[1] = vec2_sub(intersections[1], line_max);

        p.moveTo(intersections[0].x, clip.h - intersections[0].y);
        p.lineTo(intersections[1].x, clip.h - intersections[1].y);
      }