Line data Source code
1 : /****************************************************************************/
2 : // Eclipse SUMO, Simulation of Urban MObility; see https://eclipse.dev/sumo
3 : // Copyright (C) 2001-2024 German Aerospace Center (DLR) and others.
4 : // This program and the accompanying materials are made available under the
5 : // terms of the Eclipse Public License 2.0 which is available at
6 : // https://www.eclipse.org/legal/epl-2.0/
7 : // This Source Code may also be made available under the following Secondary
8 : // Licenses when the conditions for such availability set forth in the Eclipse
9 : // Public License 2.0 are satisfied: GNU General Public License, version 2
10 : // or later which is available at
11 : // https://www.gnu.org/licenses/old-licenses/gpl-2.0-standalone.html
12 : // SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later
13 : /****************************************************************************/
14 : /// @file Boundary.cpp
15 : /// @author Daniel Krajzewicz
16 : /// @author Jakob Erdmann
17 : /// @author Michael Behrisch
18 : /// @date Sept 2002
19 : ///
20 : // A class that stores the 2D geometrical boundary
21 : /****************************************************************************/
22 : #include <config.h>
23 : #include <utility>
24 :
25 : #include <utils/common/StdDefs.h>
26 : #include "GeomHelper.h"
27 : #include "Boundary.h"
28 : #include "PositionVector.h"
29 : #include "Position.h"
30 :
31 :
32 : // ===========================================================================
33 : // method definitions
34 : // ===========================================================================
35 4772817 : Boundary::Boundary()
36 4772817 : : myXmin(10000000000.0), myXmax(-10000000000.0),
37 4772817 : myYmin(10000000000.0), myYmax(-10000000000.0),
38 4772817 : myZmin(10000000000.0), myZmax(-10000000000.0),
39 4772817 : myWasInitialised(false) {}
40 :
41 :
42 132704 : Boundary::Boundary(double x1, double y1, double x2, double y2)
43 132704 : : myXmin(10000000000.0), myXmax(-10000000000.0),
44 132704 : myYmin(10000000000.0), myYmax(-10000000000.0),
45 132704 : myZmin(10000000000.0), myZmax(-10000000000.0),
46 132704 : myWasInitialised(false) {
47 132704 : add(x1, y1);
48 132704 : add(x2, y2);
49 132704 : }
50 :
51 :
52 0 : Boundary::Boundary(double x1, double y1, double z1, double x2, double y2, double z2)
53 0 : : myXmin(10000000000.0), myXmax(-10000000000.0),
54 0 : myYmin(10000000000.0), myYmax(-10000000000.0),
55 0 : myZmin(10000000000.0), myZmax(-10000000000.0),
56 0 : myWasInitialised(false) {
57 0 : add(x1, y1, z1);
58 0 : add(x2, y2, z2);
59 0 : }
60 :
61 :
62 11281488 : Boundary::~Boundary() {}
63 :
64 :
65 : void
66 2032 : Boundary::reset() {
67 2032 : myXmin = 10000000000.0;
68 2032 : myXmax = -10000000000.0;
69 2032 : myYmin = 10000000000.0;
70 2032 : myYmax = -10000000000.0;
71 2032 : myZmin = 10000000000.0;
72 2032 : myZmax = -10000000000.0;
73 2032 : myWasInitialised = false;
74 2032 : }
75 :
76 :
77 : void
78 12840146 : Boundary::add(double x, double y, double z) {
79 12840146 : if (!myWasInitialised) {
80 4145280 : myYmin = y;
81 4145280 : myYmax = y;
82 4145280 : myXmin = x;
83 4145280 : myXmax = x;
84 4145280 : myZmin = z;
85 4145280 : myZmax = z;
86 : } else {
87 8694866 : myXmin = myXmin < x ? myXmin : x;
88 8694866 : myXmax = myXmax > x ? myXmax : x;
89 8694866 : myYmin = myYmin < y ? myYmin : y;
90 8694866 : myYmax = myYmax > y ? myYmax : y;
91 8694866 : myZmin = myZmin < z ? myZmin : z;
92 8711232 : myZmax = myZmax > z ? myZmax : z;
93 : }
94 12840146 : myWasInitialised = true;
95 12840146 : }
96 :
97 :
98 : void
99 10905246 : Boundary::add(const Position& p) {
100 10905246 : add(p.x(), p.y(), p.z());
101 10905246 : }
102 :
103 :
104 : void
105 833399 : Boundary::add(const Boundary& p) {
106 833399 : add(p.xmin(), p.ymin(), p.zmin());
107 833399 : add(p.xmax(), p.ymax(), p.zmax());
108 833399 : }
109 :
110 :
111 : Position
112 319838 : Boundary::getCenter() const {
113 319838 : return Position((myXmin + myXmax) / (double) 2.0, (myYmin + myYmax) / (double) 2.0, (myZmin + myZmax) / (double) 2.0);
114 : }
115 :
116 :
117 : double
118 2918920 : Boundary::xmin() const {
119 2918920 : return myXmin;
120 : }
121 :
122 :
123 : double
124 2378826 : Boundary::xmax() const {
125 2378826 : return myXmax;
126 : }
127 :
128 :
129 : double
130 3080071 : Boundary::ymin() const {
131 3080071 : return myYmin;
132 : }
133 :
134 :
135 : double
136 2540711 : Boundary::ymax() const {
137 2540711 : return myYmax;
138 : }
139 :
140 :
141 : double
142 833404 : Boundary::zmin() const {
143 833404 : return myZmin;
144 : }
145 :
146 :
147 : double
148 833404 : Boundary::zmax() const {
149 833404 : return myZmax;
150 : }
151 :
152 :
153 : double
154 10809844 : Boundary::getWidth() const {
155 10809844 : return myXmax - myXmin;
156 : }
157 :
158 :
159 : double
160 7775403 : Boundary::getHeight() const {
161 7775403 : return myYmax - myYmin;
162 : }
163 :
164 :
165 : double
166 1694 : Boundary::getZRange() const {
167 1694 : return myZmax - myZmin;
168 : }
169 :
170 :
171 : bool
172 792460 : Boundary::around(const Position& p, double offset) const {
173 : return
174 401685 : ((p.x() <= myXmax + offset) && (p.x() >= myXmin - offset)) &&
175 803808 : ((p.y() <= myYmax + offset) && (p.y() >= myYmin - offset)) &&
176 2776 : ((p.z() <= myZmax + offset) && (p.z() >= myZmin - offset));
177 : }
178 :
179 :
180 : bool
181 0 : Boundary::around2D(const Position& p, double offset) const {
182 : return
183 0 : ((p.x() <= myXmax + offset) && (p.x() >= myXmin - offset)) &&
184 0 : ((p.y() <= myYmax + offset) && (p.y() >= myYmin - offset));
185 : }
186 :
187 :
188 : bool
189 0 : Boundary::around2D(const double x, const double y) const {
190 : return
191 0 : ((x <= myXmax) && (x >= myXmin)) &&
192 0 : ((y <= myYmax) && (y >= myYmin));
193 : }
194 :
195 :
196 : bool
197 100824 : Boundary::overlapsWith(const AbstractPoly& p, double offset) const {
198 : if (
199 : // check whether one of my points lies within the given poly
200 199533 : partialWithin(p, offset) ||
201 : // check whether the polygon lies within me
202 98709 : p.partialWithin(*this, offset)) {
203 2228 : return true;
204 : }
205 : // check whether the bounderies cross
206 : return
207 197192 : p.crosses(Position(myXmax + offset, myYmax + offset), Position(myXmin - offset, myYmax + offset))
208 98596 : ||
209 295788 : p.crosses(Position(myXmin - offset, myYmax + offset), Position(myXmin - offset, myYmin - offset))
210 98595 : ||
211 295786 : p.crosses(Position(myXmin - offset, myYmin - offset), Position(myXmax + offset, myYmin - offset))
212 98596 : ||
213 295786 : p.crosses(Position(myXmax + offset, myYmin - offset), Position(myXmax + offset, myYmax + offset));
214 : }
215 :
216 :
217 : bool
218 393202 : Boundary::crosses(const Position& p1, const Position& p2) const {
219 393202 : const PositionVector line(p1, p2);
220 : return
221 393202 : line.intersects(Position(myXmax, myYmax), Position(myXmin, myYmax))
222 393200 : ||
223 1179602 : line.intersects(Position(myXmin, myYmax), Position(myXmin, myYmin))
224 393199 : ||
225 1179600 : line.intersects(Position(myXmin, myYmin), Position(myXmax, myYmin))
226 393202 : ||
227 1572800 : line.intersects(Position(myXmax, myYmin), Position(myXmax, myYmax));
228 393202 : }
229 :
230 :
231 : bool
232 0 : Boundary::contains2D(const Boundary& b) const {
233 0 : if ((myXmin <= b.xmin()) && (myYmin <= b.ymin()) &&
234 0 : (myXmax >= b.xmax()) && (myYmax >= b.ymax())) {
235 : return true;
236 : } else {
237 0 : return false;
238 : }
239 : }
240 :
241 :
242 : bool
243 0 : Boundary::overlaps2D(const Boundary& b) const {
244 0 : if (around2D(b.myXmin, b.myYmin)) {
245 : return true;
246 0 : } else if (around2D(b.myXmin, b.myYmax)) {
247 : return true;
248 0 : } else if (around2D(b.myXmax, b.myYmin)) {
249 : return true;
250 0 : } else if (around2D(b.myXmax, b.myYmax)) {
251 : return true;
252 : } else {
253 : return false;
254 : }
255 : }
256 :
257 :
258 : bool
259 0 : Boundary::isInitialised() const {
260 0 : return myWasInitialised;
261 : }
262 :
263 :
264 : double
265 6474 : Boundary::distanceTo2D(const Position& p) const {
266 6474 : const double leftDist = myXmin - p.x();
267 6474 : const double rightDist = p.x() - myXmax;
268 6474 : const double bottomDist = myYmin - p.y();
269 6474 : const double topDist = p.y() - myYmax;
270 6474 : if (leftDist > 0.) {
271 4712 : if (bottomDist > 0.) {
272 3499 : return sqrt(leftDist * leftDist + bottomDist * bottomDist);
273 : }
274 1213 : if (topDist > 0.) {
275 453 : return sqrt(leftDist * leftDist + topDist * topDist);
276 : }
277 : return leftDist;
278 : }
279 1762 : if (rightDist > 0.) {
280 257 : if (bottomDist > 0.) {
281 187 : return sqrt(rightDist * rightDist + bottomDist * bottomDist);
282 : }
283 70 : if (topDist > 0.) {
284 26 : return sqrt(rightDist * rightDist + topDist * topDist);
285 : }
286 : return rightDist;
287 : }
288 1505 : if (bottomDist > 0) {
289 : return bottomDist;
290 : }
291 790 : if (topDist > 0) {
292 37 : return topDist;
293 : }
294 : return 0.;
295 : }
296 :
297 :
298 : double
299 29260 : Boundary::distanceTo2D(const Boundary& b) const {
300 29260 : const double leftDist = myXmin - b.myXmax;
301 29260 : const double rightDist = b.myXmin - myXmax;
302 29260 : const double bottomDist = myYmin - b.myYmax;
303 29260 : const double topDist = b.myYmin - myYmax;
304 29260 : if (leftDist > 0.) {
305 1290 : if (bottomDist > 0.) {
306 207 : return sqrt(leftDist * leftDist + bottomDist * bottomDist);
307 : }
308 1083 : if (topDist > 0.) {
309 451 : return sqrt(leftDist * leftDist + topDist * topDist);
310 : }
311 : return leftDist;
312 : }
313 27970 : if (rightDist > 0.) {
314 13048 : if (bottomDist > 0.) {
315 234 : return sqrt(rightDist * rightDist + bottomDist * bottomDist);
316 : }
317 12814 : if (topDist > 0.) {
318 7871 : return sqrt(rightDist * rightDist + topDist * topDist);
319 : }
320 : return rightDist;
321 : }
322 14922 : if (bottomDist > 0) {
323 : return bottomDist;
324 : }
325 13765 : if (topDist > 0) {
326 3531 : return topDist;
327 : }
328 : return 0.;
329 : }
330 :
331 :
332 : bool
333 199239 : Boundary::partialWithin(const AbstractPoly& poly, double offset) const {
334 : return
335 396858 : poly.around(Position(myXmax, myYmax), offset) ||
336 594180 : poly.around(Position(myXmin, myYmax), offset) ||
337 595800 : poly.around(Position(myXmax, myYmin), offset) ||
338 595583 : poly.around(Position(myXmin, myYmin), offset);
339 : }
340 :
341 :
342 : Boundary&
343 1068127 : Boundary::grow(double by) {
344 :
345 1068127 : myXmax += by;
346 1068127 : myYmax += by;
347 1068127 : myXmin -= by;
348 1068127 : myYmin -= by;
349 1068127 : return *this;
350 : }
351 :
352 :
353 : Boundary&
354 0 : Boundary::scale(double by) {
355 0 : growWidth(by * (myXmax - myXmin));
356 0 : growHeight(by * (myYmax - myYmin));
357 0 : return *this;
358 : }
359 :
360 :
361 : void
362 1864865 : Boundary::growWidth(double by) {
363 1864865 : myXmin -= by;
364 1864865 : myXmax += by;
365 1864865 : }
366 :
367 :
368 : void
369 1145983 : Boundary::growHeight(double by) {
370 1145983 : myYmin -= by;
371 1145983 : myYmax += by;
372 1145983 : }
373 :
374 : void
375 24 : Boundary::flipY() {
376 24 : myYmin *= -1.0;
377 24 : myYmax *= -1.0;
378 : double tmp = myYmin;
379 24 : myYmin = myYmax;
380 24 : myYmax = tmp;
381 24 : }
382 :
383 :
384 :
385 : std::ostream&
386 7008 : operator<<(std::ostream& os, const Boundary& b) {
387 28032 : os << b.myXmin << "," << b.myYmin << "," << b.myXmax << "," << b.myYmax;
388 7008 : return os;
389 : }
390 :
391 :
392 : bool
393 370 : Boundary::operator==(const Boundary& b) const {
394 : return (
395 370 : myXmin == b.myXmin &&
396 0 : myXmax == b.myXmax &&
397 0 : myYmin == b.myYmin &&
398 0 : myYmax == b.myYmax &&
399 0 : myZmin == b.myZmin &&
400 370 : myZmax == b.myZmax &&
401 0 : myWasInitialised == b.myWasInitialised);
402 : }
403 :
404 :
405 : bool
406 0 : Boundary::operator!=(const Boundary& b) const {
407 0 : return !(*this == b);
408 : }
409 :
410 :
411 : void
412 411 : Boundary::set(double xmin, double ymin, double xmax, double ymax) {
413 : /*
414 : Takes care of the following extraneous cases w.r.t the input parameters:
415 : - xmin > xmax
416 : - ymin > ymax
417 : */
418 :
419 411 : myXmin = MIN2(xmin, xmax);
420 411 : myYmin = MIN2(ymin, ymax);
421 411 : myXmax = MAX2(xmin, xmax);
422 411 : myYmax = MAX2(ymin, ymax);
423 411 : }
424 :
425 :
426 : void
427 2 : Boundary::setOffsets(double xmin, double ymin, double xmax, double ymax) {
428 2 : myXmin = xmin;
429 2 : myYmin = ymin;
430 2 : myXmax = xmax;
431 2 : myYmax = ymax;
432 2 : }
433 :
434 :
435 : void
436 1247 : Boundary::moveby(double x, double y, double z) {
437 1247 : myXmin += x;
438 1247 : myYmin += y;
439 1247 : myZmin += z;
440 1247 : myXmax += x;
441 1247 : myYmax += y;
442 1247 : myZmax += z;
443 1247 : }
444 :
445 :
446 : PositionVector
447 2068 : Boundary::getShape(const bool closeShape) const {
448 2068 : PositionVector shape;
449 2068 : shape.push_back(Position(myXmin, myYmin));
450 2068 : shape.push_back(Position(myXmin, myYmax));
451 2068 : shape.push_back(Position(myXmax, myYmax));
452 2068 : shape.push_back(Position(myXmax, myYmin));
453 2068 : if (closeShape) {
454 2068 : shape.push_back(Position(myXmin, myYmin));
455 : }
456 2068 : return shape;
457 0 : }
458 :
459 : /****************************************************************************/
|