Skip to content

Commit

Permalink
Deal with vertical lines
Browse files Browse the repository at this point in the history
  • Loading branch information
e-n-f committed Nov 9, 2023
1 parent 6bd0cdc commit 35231d3
Showing 1 changed file with 57 additions and 3 deletions.
60 changes: 57 additions & 3 deletions polygon.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
#include <vector>
#include <cmath>
#include "geometry.hpp"
#include "errors.hpp"

struct point {
double x;
Expand Down Expand Up @@ -69,6 +70,8 @@ void fix_opposites(std::vector<segment> &segs) {
segs.resize(out);
}

const std::pair<double, double> SAME_SLOPE = std::make_pair(INT_MAX, INT_MAX);

// https://stackoverflow.com/questions/563198/how-do-you-detect-where-two-line-segments-intersect
//
// beware of
Expand Down Expand Up @@ -100,7 +103,56 @@ std::pair<double, double> get_line_intersection(double p0_x, double p0_y, double
#endif
}

return std::make_pair(-1, -1);
return SAME_SLOPE;
}

bool vertical(std::vector<segment> &segs, size_t s, double y) {
if ((y > std::round(segs[s].first.y) && y < std::round(segs[s].second.y)) ||
(y > std::round(segs[s].second.y) && y < std::round(segs[s].first.y))) {
segs.push_back(std::make_pair(point(segs[s].first.x, y), segs[s].second));
segs[s] = std::make_pair(segs[s].first, point(segs[s].first.x, y));
return true;
}

return false;
}

bool intersect_collinear(std::vector<segment> &segs, size_t s1, size_t s2) {
bool changed = false;

if (std::round(segs[s1].first.x) == std::round(segs[s1].second.x)) {
// vertical

if (std::round(segs[s2].first.x) == std::round(segs[s2].second.x)) {
// in which case the other one should also be vertical

if (std::round(segs[s1].first.x) == std::round(segs[s2].first.x)) {
// collinear, not parallel

if (vertical(segs, s1, std::round(segs[s2].first.y))) {
changed = true;
}
if (vertical(segs, s1, std::round(segs[s2].second.y))) {
changed = true;
}
if (vertical(segs, s2, std::round(segs[s1].first.y))) {
changed = true;
}
if (vertical(segs, s2, std::round(segs[s1].second.y))) {
changed = true;
}
}
} else {
fprintf(stderr, "One segment is vertical and the other is not %f,%f to %f,%f; %f,%f to %f,%f.\n",
segs[s1].first.x, segs[s1].first.y, segs[s1].second.x, segs[s1].second.y,
segs[s2].first.x, segs[s2].first.y, segs[s2].second.x, segs[s2].second.y);
exit(EXIT_IMPOSSIBLE);
}
} else {
// XXX not vertical
}

return changed;
}

bool intersect(std::vector<segment> &segs, size_t s1, size_t s2) {
Expand Down Expand Up @@ -156,8 +208,10 @@ bool intersect(std::vector<segment> &segs, size_t s1, size_t s2) {
segs[s2] = std::make_pair(segs[s2].first, point(x, y));
changed = true;
}
} else if (intersections.first == -1 && intersections.second == -1) {
// XXX handle collinear
} else if (intersections == SAME_SLOPE) {
if (intersect_collinear(segs, s1, s2)) {
changed = true;
}
} else {
// could intersect, but does not
}
Expand Down

0 comments on commit 35231d3

Please sign in to comment.