6#define _USE_MATH_DEFINES
15#define M_PI 3.14159265358979323846
32 return !(*
this == other);
37 std::vector<std::pair<Point, Point>> edge_list;
38 if (
vertices.size() < 2)
return edge_list;
40 for (
size_t i = 0; i <
vertices.size(); ++i) {
41 size_t next = (i + 1) %
vertices.size();
55 for (
size_t i = 0; i <
vertices.size(); ++i) {
56 size_t next = (i + 1) %
vertices.size();
66 for (
size_t i = 0; i <
vertices.size(); ++i) {
67 size_t next = (i + 1) %
vertices.size();
76 double cx = 0.0, cy = 0.0;
77 for (
const auto& vertex :
vertices) {
90 for (
const auto& vertex :
vertices) {
91 min_x = std::min(min_x, vertex.x);
92 max_x = std::max(max_x, vertex.x);
93 min_y = std::min(min_y, vertex.y);
94 max_y = std::max(max_y, vertex.y);
97 return Rectangle(min_x, min_y, max_x - min_x, max_y - min_y);
102 if (
vertices.size() < 3)
return false;
104 bool sign_positive =
false;
105 bool sign_negative =
false;
107 for (
size_t i = 0; i <
vertices.size(); ++i) {
108 size_t j = (i + 1) %
vertices.size();
109 size_t k = (i + 2) %
vertices.size();
113 double cross = v1.
x * v2.
y - v1.
y * v2.
x;
118 if (sign_positive && sign_negative)
return false;
129 if (
vertices.size() < 3)
return true;
131 auto edge_list =
edges();
132 for (
size_t i = 0; i < edge_list.size(); ++i) {
133 for (
size_t j = i + 2; j < edge_list.size(); ++j) {
134 if (i == 0 && j == edge_list.size() - 1)
continue;
137 edge_list[j].first, edge_list[j].second)) {
147 if (
vertices.size() < 3)
return false;
152 for (
size_t i = 0; i <
vertices.size(); ++i) {
165 auto edge_list =
edges();
166 for (
const auto& edge : edge_list) {
176 std::vector<size_t> sharp_angles;
177 if (
vertices.size() < 3)
return sharp_angles;
179 for (
size_t i = 0; i <
vertices.size(); ++i) {
181 if (angle < threshold_degrees) {
182 sharp_angles.push_back(i);
193 size_t next = (vertex_index + 1) %
vertices.size();
198 double dot = v1.
x * v2.
x + v1.
y * v2.
y;
199 double mag1 = std::sqrt(v1.
x * v1.
x + v1.
y * v1.
y);
200 double mag2 = std::sqrt(v2.
x * v2.
x + v2.
y * v2.
y);
204 double cos_angle = dot / (mag1 * mag2);
205 cos_angle = std::max(-1.0, std::min(1.0, cos_angle));
207 return std::acos(cos_angle) * 180.0 /
M_PI;
211 std::vector<double> angles;
212 for (
size_t i = 0; i <
vertices.size(); ++i) {
222 double min_distance = std::numeric_limits<double>::max();
225 for (
const auto& vertex :
vertices) {
227 min_distance = std::min(min_distance, dist);
231 for (
const auto& vertex : other.
vertices) {
233 min_distance = std::min(min_distance, dist);
244 double min_distance = std::numeric_limits<double>::max();
245 auto edge_list =
edges();
247 for (
const auto& edge : edge_list) {
249 min_distance = std::min(min_distance, dist);
256 double min_distance = std::numeric_limits<double>::max();
258 for (
const auto& vertex :
vertices) {
259 double dist = vertex.distance_to_line(line_start, line_end);
260 min_distance = std::min(min_distance, dist);
270 double min_distance =
vertices[0].distance_to(point);
272 for (
const auto& vertex :
vertices) {
273 double dist = vertex.distance_to(point);
274 if (dist < min_distance) {
285 auto this_edges =
edges();
286 auto other_edges = other.
edges();
288 double min_distance = std::numeric_limits<double>::max();
290 for (
const auto& edge1 : this_edges) {
291 for (
const auto& edge2 : other_edges) {
293 edge1.first, edge1.second, edge2.first, edge2.second);
294 min_distance = std::min(min_distance, dist);
302 const Polygon& other,
double threshold_distance)
const {
304 std::vector<std::tuple<Point, Point, double>> narrow_regions;
305 auto this_edges =
edges();
306 auto other_edges = other.
edges();
308 for (
const auto& edge1 : this_edges) {
309 for (
const auto& edge2 : other_edges) {
311 edge1.first, edge1.second, edge2.first, edge2.second);
313 if (dist < threshold_distance) {
314 Point closest1 = edge1.first;
315 Point closest2 = edge2.first;
316 narrow_regions.emplace_back(closest1, closest2, dist);
321 return narrow_regions;
326 auto this_edges =
edges();
327 auto other_edges = other.
edges();
329 for (
const auto& edge1 : this_edges) {
330 for (
const auto& edge2 : other_edges) {
332 edge2.first, edge2.second)) {
342 std::vector<Point> intersections;
343 auto this_edges =
edges();
344 auto other_edges = other.
edges();
346 for (
const auto& edge1 : this_edges) {
347 for (
const auto& edge2 : other_edges) {
350 edge1.first, edge1.second, edge2.first, edge2.second,
intersects);
353 intersections.push_back(intersection);
358 return intersections;
362 auto edge_list =
edges();
364 for (
size_t i = 0; i < edge_list.size(); ++i) {
365 for (
size_t j = i + 2; j < edge_list.size(); ++j) {
366 if (i == 0 && j == edge_list.size() - 1)
continue;
369 edge_list[j].first, edge_list[j].second)) {
396 std::stringstream ss;
398 for (
size_t i = 0; i <
vertices.size(); ++i) {
399 if (i > 0) ss <<
", ";
412 const Point& seg1_start,
const Point& seg1_end,
413 const Point& seg2_start,
const Point& seg2_end) {
416 Point mid1((seg1_start.
x + seg1_end.
x) / 2, (seg1_start.
y + seg1_end.
y) / 2);
417 Point mid2((seg2_start.
x + seg2_end.
x) / 2, (seg2_start.
y + seg2_end.
y) / 2);
422 const Point& seg1_start,
const Point& seg1_end,
423 const Point& seg2_start,
const Point& seg2_end,
428 double x1 = seg1_start.
x, y1 = seg1_start.
y;
429 double x2 = seg1_end.
x, y2 = seg1_end.
y;
430 double x3 = seg2_start.
x, y3 = seg2_start.
y;
431 double x4 = seg2_end.
x, y4 = seg2_end.
y;
433 double denom = (x1 - x2) * (y3 - y4) - (y1 - y2) * (x3 - x4);
438 double t = ((x1 - x3) * (y3 - y4) - (y1 - y3) * (x3 - x4)) / denom;
439 double u = -((x1 - x2) * (y1 - y3) - (y1 - y2) * (x1 - x3)) / denom;
441 if (t >= 0 && t <= 1 && u >= 0 && u <= 1) {
443 return Point(x1 + t * (x2 - x1), y1 + t * (y2 - y1));
450 const Point& seg1_start,
const Point& seg1_end,
451 const Point& seg2_start,
const Point& seg2_end) {
460 std::size_t hash = 0;
461 for (
const auto& vertex : polygon.
vertices) {
462 hash ^= std::hash<double>()(vertex.x) + std::hash<double>()(vertex.y) + 0x9e3779b9 + (hash << 6) + (hash >> 2);
469 const Point& seg2_start,
const Point& seg2_end) {
474 double dot = v1.
x * v2.
x + v1.
y * v2.
y;
475 double mag1 = std::sqrt(v1.
x * v1.
x + v1.
y * v1.
y);
476 double mag2 = std::sqrt(v2.
x * v2.
x + v2.
y * v2.
y);
480 double cos_angle = dot / (mag1 * mag2);
481 cos_angle = std::max(-1.0, std::min(1.0, cos_angle));
483 return std::acos(cos_angle) * 180.0 /
M_PI;
2D point with high-precision coordinates and utility methods
double distance_to_line(const Point &line_start, const Point &line_end) const
Calculate distance from this point to a line segment.
static constexpr double TOLERANCE
Default precision tolerance for floating point comparisons.
double distance_to(const Point &other) const
Calculate Euclidean distance to another point.
Polygon class supporting both convex and concave polygons.
bool operator==(const Polygon &other) const
Equality operator.
std::vector< Point > intersection_points(const Polygon &other) const
Find intersection points between polygon edges.
void remove_vertex(size_t index)
Remove vertex at specific index.
std::vector< std::pair< Point, Point > > edges() const
Get polygon edges as pairs of consecutive vertices.
static Point line_segment_intersection(const Point &seg1_start, const Point &seg1_end, const Point &seg2_start, const Point &seg2_end, bool &intersects)
Helper function to find intersection point of two line segments.
bool point_on_boundary(const Point &point, double tolerance=Point::TOLERANCE) const
Check if point is on polygon boundary.
double distance_to(const Polygon &other) const
Calculate minimum distance to another polygon.
Rectangle bounding_box() const
Calculate axis-aligned bounding box.
std::vector< double > all_vertex_angles() const
Get all vertex angles.
bool operator!=(const Polygon &other) const
Inequality operator.
std::vector< size_t > get_sharp_angles(double threshold_degrees=30.0) const
Find vertices with sharp angles.
double vertex_angle(size_t vertex_index) const
Calculate angle at a specific vertex.
static bool segments_intersect(const Point &seg1_start, const Point &seg1_end, const Point &seg2_start, const Point &seg2_end)
Helper function to check if two line segments intersect.
Point centroid() const
Calculate polygon centroid.
Point closest_point_to(const Point &point) const
Find closest point on polygon boundary to given point.
bool intersects(const Polygon &other) const
Check if this polygon intersects with another polygon.
std::string to_string() const
Get string representation.
bool is_simple() const
Check if polygon is simple (no self-intersections)
void insert_vertex(size_t index, const Point &vertex)
Insert vertex at specific index.
double perimeter() const
Calculate polygon perimeter.
std::vector< Point > vertices
Polygon vertices in order.
std::vector< std::tuple< Point, Point, double > > find_narrow_regions(const Polygon &other, double threshold_distance) const
Find narrow regions where edges are too close.
bool is_convex() const
Check if polygon is convex.
bool is_clockwise() const
Check if polygon is clockwise oriented.
double min_edge_distance_to(const Polygon &other) const
Calculate minimum distance between this polygon's edges and another polygon's edges.
bool has_self_intersections() const
Check if polygon edges intersect (for self-intersection detection)
double signed_area() const
Calculate signed area (preserves orientation)
Polygon()=default
Default constructor - creates empty polygon.
void add_vertex(const Point &vertex)
Add vertex to polygon.
double distance_to_line(const Point &line_start, const Point &line_end) const
Calculate minimum distance to a line segment.
bool contains_point(const Point &point) const
Check if point is inside polygon (ray casting algorithm)
double area() const
Calculate polygon area using shoelace formula.
static double segment_to_segment_distance(const Point &seg1_start, const Point &seg1_end, const Point &seg2_start, const Point &seg2_end)
Helper function to calculate distance between two line segments.
Axis-aligned rectangle for bounding boxes and simple EDA components.
std::ostream & operator<<(std::ostream &os, const Point &point)
double angle_between_vectors(const Point &v1, const Point &v2)
Calculate angle between two vectors in degrees.
bool segments_intersect(const Point &seg1_start, const Point &seg1_end, const Point &seg2_start, const Point &seg2_end)
Check if two line segments intersect.
Main namespace for ZLayout library.
Polygon class for complex geometric shapes and EDA components.
std::size_t operator()(const Polygon &polygon) const