ZLayout EDA Library v1.0.0
Advanced Electronic Design Automation Layout Library with Bilingual Documentation
Loading...
Searching...
No Matches
rectangle.cpp
Go to the documentation of this file.
1
5
8#include <algorithm>
9#include <sstream>
10#include <stdexcept>
11#include <cmath>
12
13namespace zlayout {
14namespace geometry {
15
16Rectangle::Rectangle(double x, double y, double width, double height)
17 : x(x), y(y), width(width), height(height) {
18 if (width < 0 || height < 0) {
19 throw std::invalid_argument("Rectangle dimensions must be non-negative");
20 }
21}
22
24 : x(std::min(bottom_left.x, top_right.x)),
25 y(std::min(bottom_left.y, top_right.y)),
26 width(std::abs(top_right.x - bottom_left.x)),
27 height(std::abs(top_right.y - bottom_left.y)) {
28}
29
30bool Rectangle::operator==(const Rectangle& other) const {
31 return std::abs(x - other.x) < Point::TOLERANCE &&
32 std::abs(y - other.y) < Point::TOLERANCE &&
33 std::abs(width - other.width) < Point::TOLERANCE &&
34 std::abs(height - other.height) < Point::TOLERANCE;
35}
36
37bool Rectangle::operator!=(const Rectangle& other) const {
38 return !(*this == other);
39}
40
41bool Rectangle::operator<(const Rectangle& other) const {
42 // Compare by area first, then by x-coordinate for consistent ordering
43 double this_area = area();
44 double other_area = other.area();
45 if (std::abs(this_area - other_area) > Point::TOLERANCE) {
46 return this_area < other_area;
47 }
48
49 // If areas are equal, compare by x-coordinate
50 if (std::abs(x - other.x) > Point::TOLERANCE) {
51 return x < other.x;
52 }
53
54 // If x-coordinates are equal, compare by y-coordinate
55 if (std::abs(y - other.y) > Point::TOLERANCE) {
56 return y < other.y;
57 }
58
59 // If x and y are equal, compare by width
60 if (std::abs(width - other.width) > Point::TOLERANCE) {
61 return width < other.width;
62 }
63
64 // Finally compare by height
65 return height < other.height;
66}
67
69 return Point(x + width / 2.0, y + height / 2.0);
70}
71
72std::vector<Point> Rectangle::corners() const {
73 return {
74 Point(x, y), // bottom-left
75 Point(x + width, y), // bottom-right
76 Point(x + width, y + height), // top-right
77 Point(x, y + height) // top-left
78 };
79}
80
84
85bool Rectangle::is_valid() const {
86 return width >= 0 && height >= 0;
87}
88
89bool Rectangle::contains_point(const Point& point) const {
90 return point.x >= x && point.x <= x + width &&
91 point.y >= y && point.y <= y + height;
92}
93
94bool Rectangle::contains_rectangle(const Rectangle& other) const {
95 return other.x >= x && other.y >= y &&
96 other.x + other.width <= x + width &&
97 other.y + other.height <= y + height;
98}
99
100bool Rectangle::intersects(const Rectangle& other) const {
101 return !(other.x >= x + width || other.x + other.width <= x ||
102 other.y >= y + height || other.y + other.height <= y);
103}
104
106 if (!intersects(other)) {
107 return Rectangle(0, 0, 0, 0); // Empty rectangle
108 }
109
110 double left = std::max(x, other.x);
111 double right = std::min(x + width, other.x + other.width);
112 double bottom = std::max(y, other.y);
113 double top = std::min(y + height, other.y + other.height);
114
115 return Rectangle(left, bottom, right - left, top - bottom);
116}
117
119 if (is_empty()) return other;
120 if (other.is_empty()) return *this;
121
122 double left = std::min(x, other.x);
123 double right = std::max(x + width, other.x + other.width);
124 double bottom = std::min(y, other.y);
125 double top = std::max(y + height, other.y + other.height);
126
127 return Rectangle(left, bottom, right - left, top - bottom);
128}
129
130Rectangle Rectangle::expand(double margin) const {
131 return Rectangle(x - margin, y - margin,
132 width + 2 * margin, height + 2 * margin);
133}
134
135Rectangle Rectangle::expand(double left, double right, double bottom, double top) const {
136 return Rectangle(x - left, y - bottom,
137 width + left + right, height + bottom + top);
138}
139
141 return Rectangle(x + offset.x, y + offset.y, width, height);
142}
143
144Rectangle Rectangle::scale(double factor) const {
145 Point center_point = center();
146 double new_width = width * factor;
147 double new_height = height * factor;
148
149 return Rectangle(center_point.x - new_width / 2.0,
150 center_point.y - new_height / 2.0,
151 new_width, new_height);
152}
153
154Rectangle Rectangle::scale(double x_factor, double y_factor) const {
155 Point center_point = center();
156 double new_width = width * x_factor;
157 double new_height = height * y_factor;
158
159 return Rectangle(center_point.x - new_width / 2.0,
160 center_point.y - new_height / 2.0,
161 new_width, new_height);
162}
163
164double Rectangle::distance_to(const Rectangle& other) const {
165 if (intersects(other)) {
166 return 0.0;
167 }
168
169 // Calculate distance between closest edges
170 double dx = 0.0, dy = 0.0;
171
172 if (other.x + other.width < x) {
173 dx = x - (other.x + other.width);
174 } else if (other.x > x + width) {
175 dx = other.x - (x + width);
176 }
177
178 if (other.y + other.height < y) {
179 dy = y - (other.y + other.height);
180 } else if (other.y > y + height) {
181 dy = other.y - (y + height);
182 }
183
184 return std::sqrt(dx * dx + dy * dy);
185}
186
187double Rectangle::distance_to(const Point& point) const {
188 if (contains_point(point)) {
189 return 0.0;
190 }
191
192 double dx = std::max(0.0, std::max(x - point.x, point.x - (x + width)));
193 double dy = std::max(0.0, std::max(y - point.y, point.y - (y + height)));
194
195 return std::sqrt(dx * dx + dy * dy);
196}
197
199 auto corner_points = corners();
200 return Polygon(corner_points);
201}
202
203std::string Rectangle::to_string() const {
204 std::ostringstream oss;
205 oss << "Rectangle(x=" << x << ", y=" << y
206 << ", width=" << width << ", height=" << height << ")";
207 return oss.str();
208}
209
210std::ostream& operator<<(std::ostream& os, const Rectangle& rect) {
211 os << rect.to_string();
212 return os;
213}
214
215// Static utility functions
216
218 return Rectangle(center.x - width / 2.0, center.y - height / 2.0, width, height);
219}
220
221Rectangle Rectangle::bounding_box(const std::vector<Point>& points) {
222 if (points.empty()) {
223 return Rectangle(0, 0, 0, 0);
224 }
225
226 double min_x = points[0].x, max_x = points[0].x;
227 double min_y = points[0].y, max_y = points[0].y;
228
229 for (const auto& point : points) {
230 min_x = std::min(min_x, point.x);
231 max_x = std::max(max_x, point.x);
232 min_y = std::min(min_y, point.y);
233 max_y = std::max(max_y, point.y);
234 }
235
236 return Rectangle(min_x, min_y, max_x - min_x, max_y - min_y);
237}
238
239Rectangle Rectangle::bounding_box(const std::vector<Rectangle>& rectangles) {
240 if (rectangles.empty()) {
241 return Rectangle(0, 0, 0, 0);
242 }
243
244 Rectangle result = rectangles[0];
245 for (size_t i = 1; i < rectangles.size(); ++i) {
246 result = result.union_with(rectangles[i]);
247 }
248
249 return result;
250}
251
252// RectangleHash implementation
253
254std::size_t RectangleHash::operator()(const Rectangle& rect) const {
255 std::hash<double> hasher;
256 std::size_t h1 = hasher(rect.x);
257 std::size_t h2 = hasher(rect.y);
258 std::size_t h3 = hasher(rect.width);
259 std::size_t h4 = hasher(rect.height);
260
261 // Combine hashes
262 return h1 ^ (h2 << 1) ^ (h3 << 2) ^ (h4 << 3);
263}
264
265} // namespace geometry
266} // namespace zlayout
2D point with high-precision coordinates and utility methods
Definition point.hpp:23
double x
X coordinate.
Definition point.hpp:25
static constexpr double TOLERANCE
Default precision tolerance for floating point comparisons.
Definition point.hpp:29
double y
Y coordinate.
Definition point.hpp:26
Polygon class supporting both convex and concave polygons.
Definition polygon.hpp:25
Axis-aligned rectangle for bounding boxes and simple EDA components.
Definition rectangle.hpp:26
double top() const
Get top edge Y coordinate.
Definition rectangle.hpp:98
Point bottom_left() const
Get bottom-left corner point.
double left() const
Get left edge X coordinate.
Definition rectangle.hpp:83
bool is_valid() const
Check if rectangle is valid (positive dimensions)
Definition rectangle.cpp:85
double area() const
Calculate rectangle area.
double y
Y coordinate of bottom-left corner.
Definition rectangle.hpp:29
std::string to_string() const
Get string representation.
Polygon to_polygon() const
Convert rectangle to polygon representation.
std::vector< Point > corners() const
Get all four corner points.
Definition rectangle.cpp:72
Rectangle scale(double factor) const
Scale rectangle by given factor (around center)
Point center() const
Get center point of rectangle.
Definition rectangle.cpp:68
Point top_right() const
Get top-right corner point.
Rectangle intersection(const Rectangle &other) const
Calculate intersection rectangle with another rectangle.
bool operator!=(const Rectangle &other) const
Inequality operator.
Definition rectangle.cpp:37
bool operator<(const Rectangle &other) const
Less than operator for sorting.
Definition rectangle.cpp:41
Rectangle()
Default constructor - creates empty rectangle at origin.
Definition rectangle.hpp:36
double height
Height of rectangle.
Definition rectangle.hpp:31
double right() const
Get right edge X coordinate.
Definition rectangle.hpp:88
Rectangle translate(const Point &offset) const
Translate rectangle by given offset.
static Rectangle bounding_box(const std::vector< Point > &points)
Create bounding rectangle for a set of points.
bool is_empty() const
Check if rectangle is empty (zero area)
Definition rectangle.cpp:81
Rectangle union_with(const Rectangle &other) const
Calculate union rectangle that contains both rectangles.
static Rectangle from_center(const Point &center, double width, double height)
Create rectangle from center point and dimensions.
bool intersects(const Rectangle &other) const
Check if this rectangle intersects with another rectangle.
bool contains_rectangle(const Rectangle &other) const
Check if another rectangle is completely inside this rectangle.
Definition rectangle.cpp:94
bool contains_point(const Point &point) const
Check if point is inside rectangle (inclusive of boundary)
Definition rectangle.cpp:89
Rectangle expand(double margin) const
Expand rectangle by given margin in all directions.
double x
X coordinate of bottom-left corner.
Definition rectangle.hpp:28
double distance_to(const Rectangle &other) const
Calculate minimum distance to another rectangle.
bool operator==(const Rectangle &other) const
Equality operator.
Definition rectangle.cpp:30
double width
Width of rectangle.
Definition rectangle.hpp:30
std::ostream & operator<<(std::ostream &os, const Point &point)
Definition point.cpp:144
Main namespace for ZLayout library.
Definition component.hpp:20
Polygon class for complex geometric shapes and EDA components.
Axis-aligned rectangle class for bounding boxes and simple components.
std::size_t operator()(const Rectangle &rect) const