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 4117050 : Boundary::Boundary()
36 4117050 : : myXmin(10000000000.0), myXmax(-10000000000.0),
37 4117050 : myYmin(10000000000.0), myYmax(-10000000000.0),
38 4117050 : myZmin(10000000000.0), myZmax(-10000000000.0),
39 4117050 : myWasInitialised(false) {}
40 :
41 :
42 106794 : Boundary::Boundary(double x1, double y1, double x2, double y2)
43 106794 : : myXmin(10000000000.0), myXmax(-10000000000.0),
44 106794 : myYmin(10000000000.0), myYmax(-10000000000.0),
45 106794 : myZmin(10000000000.0), myZmax(-10000000000.0),
46 106794 : myWasInitialised(false) {
47 106794 : add(x1, y1);
48 106794 : add(x2, y2);
49 106794 : }
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 10098872 : Boundary::~Boundary() {}
63 :
64 :
65 : void
66 2384 : Boundary::reset() {
67 2384 : myXmin = 10000000000.0;
68 2384 : myXmax = -10000000000.0;
69 2384 : myYmin = 10000000000.0;
70 2384 : myYmax = -10000000000.0;
71 2384 : myZmin = 10000000000.0;
72 2384 : myZmax = -10000000000.0;
73 2384 : myWasInitialised = false;
74 2384 : }
75 :
76 :
77 : void
78 12234926 : Boundary::add(double x, double y, double z) {
79 12234926 : if (!myWasInitialised) {
80 3603396 : myYmin = y;
81 3603396 : myYmax = y;
82 3603396 : myXmin = x;
83 3603396 : myXmax = x;
84 3603396 : myZmin = z;
85 3603396 : myZmax = z;
86 : } else {
87 8631530 : myXmin = myXmin < x ? myXmin : x;
88 8631530 : myXmax = myXmax > x ? myXmax : x;
89 8631530 : myYmin = myYmin < y ? myYmin : y;
90 8631530 : myYmax = myYmax > y ? myYmax : y;
91 8631530 : myZmin = myZmin < z ? myZmin : z;
92 8686856 : myZmax = myZmax > z ? myZmax : z;
93 : }
94 12234926 : myWasInitialised = true;
95 12234926 : }
96 :
97 :
98 : void
99 10352911 : Boundary::add(const Position& p) {
100 10352911 : add(p.x(), p.y(), p.z());
101 10352911 : }
102 :
103 :
104 : void
105 832773 : Boundary::add(const Boundary& p) {
106 832773 : add(p.xmin(), p.ymin(), p.zmin());
107 832773 : add(p.xmax(), p.ymax(), p.zmax());
108 832773 : }
109 :
110 :
111 : Position
112 310728 : Boundary::getCenter() const {
113 310728 : return Position((myXmin + myXmax) / (double) 2.0, (myYmin + myYmax) / (double) 2.0, (myZmin + myZmax) / (double) 2.0);
114 : }
115 :
116 :
117 : double
118 2842546 : Boundary::xmin() const {
119 2842546 : return myXmin;
120 : }
121 :
122 :
123 : double
124 2357091 : Boundary::xmax() const {
125 2357091 : return myXmax;
126 : }
127 :
128 :
129 : double
130 3013400 : Boundary::ymin() const {
131 3013400 : return myYmin;
132 : }
133 :
134 :
135 : double
136 2528679 : Boundary::ymax() const {
137 2528679 : return myYmax;
138 : }
139 :
140 :
141 : double
142 832783 : Boundary::zmin() const {
143 832783 : return myZmin;
144 : }
145 :
146 :
147 : double
148 832783 : Boundary::zmax() const {
149 832783 : return myZmax;
150 : }
151 :
152 :
153 : double
154 9936582 : Boundary::getWidth() const {
155 9936582 : return myXmax - myXmin;
156 : }
157 :
158 :
159 : double
160 6998009 : Boundary::getHeight() const {
161 6998009 : return myYmax - myYmin;
162 : }
163 :
164 :
165 : double
166 1835 : Boundary::getZRange() const {
167 1835 : return myZmax - myZmin;
168 : }
169 :
170 :
171 : bool
172 792208 : Boundary::around(const Position& p, double offset) const {
173 : return
174 401419 : (p.x() <= myXmax + offset && p.x() >= myXmin - offset) &&
175 803571 : (p.y() <= myYmax + offset && p.y() >= myYmin - offset) &&
176 2784 : (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 100756 : Boundary::overlapsWith(const AbstractPoly& p, double offset) const {
190 : if (
191 : // check whether one of my points lies within the given poly
192 199394 : partialWithin(p, offset) ||
193 : // check whether the polygon lies within me
194 98638 : p.partialWithin(*this, offset)) {
195 2231 : return true;
196 : }
197 : // check whether the bounderies cross
198 : return
199 197050 : p.crosses(Position(myXmax + offset, myYmax + offset), Position(myXmin - offset, myYmax + offset))
200 98525 : ||
201 98525 : p.crosses(Position(myXmin - offset, myYmax + offset), Position(myXmin - offset, myYmin - offset))
202 98523 : ||
203 98523 : p.crosses(Position(myXmin - offset, myYmin - offset), Position(myXmax + offset, myYmin - offset))
204 197048 : ||
205 197048 : p.crosses(Position(myXmax + offset, myYmin - offset), Position(myXmax + offset, myYmax + offset));
206 : }
207 :
208 :
209 : bool
210 393216 : Boundary::crosses(const Position& p1, const Position& p2) const {
211 393216 : const PositionVector line(p1, p2);
212 : return
213 393216 : line.intersects(Position(myXmax, myYmax), Position(myXmin, myYmax))
214 393212 : ||
215 393212 : line.intersects(Position(myXmin, myYmax), Position(myXmin, myYmin))
216 393210 : ||
217 393210 : line.intersects(Position(myXmin, myYmin), Position(myXmax, myYmin))
218 786424 : ||
219 786424 : line.intersects(Position(myXmax, myYmin), Position(myXmax, myYmax));
220 393216 : }
221 :
222 :
223 : double
224 0 : Boundary::contains(const Boundary& b) const {
225 0 : if ((myXmin <= b.xmin()) && (myYmin <= b.ymin()) &&
226 0 : (myXmax >= b.xmax()) && (myYmax >= b.ymax())) {
227 : return true;
228 : } else {
229 0 : return false;
230 : }
231 : }
232 :
233 :
234 : bool
235 0 : Boundary::isInitialised() const {
236 0 : return myWasInitialised;
237 : }
238 :
239 :
240 : double
241 6470 : Boundary::distanceTo2D(const Position& p) const {
242 6470 : const double leftDist = myXmin - p.x();
243 6470 : const double rightDist = p.x() - myXmax;
244 6470 : const double bottomDist = myYmin - p.y();
245 6470 : const double topDist = p.y() - myYmax;
246 6470 : if (leftDist > 0.) {
247 4645 : if (bottomDist > 0.) {
248 3440 : return sqrt(leftDist * leftDist + bottomDist * bottomDist);
249 : }
250 1205 : if (topDist > 0.) {
251 470 : return sqrt(leftDist * leftDist + topDist * topDist);
252 : }
253 : return leftDist;
254 : }
255 1825 : if (rightDist > 0.) {
256 244 : if (bottomDist > 0.) {
257 180 : return sqrt(rightDist * rightDist + bottomDist * bottomDist);
258 : }
259 64 : if (topDist > 0.) {
260 24 : return sqrt(rightDist * rightDist + topDist * topDist);
261 : }
262 : return rightDist;
263 : }
264 1581 : if (bottomDist > 0) {
265 : return bottomDist;
266 : }
267 885 : if (topDist > 0) {
268 48 : return topDist;
269 : }
270 : return 0.;
271 : }
272 :
273 :
274 : double
275 27789 : Boundary::distanceTo2D(const Boundary& b) const {
276 27789 : const double leftDist = myXmin - b.myXmax;
277 27789 : const double rightDist = b.myXmin - myXmax;
278 27789 : const double bottomDist = myYmin - b.myYmax;
279 27789 : const double topDist = b.myYmin - myYmax;
280 27789 : if (leftDist > 0.) {
281 1282 : if (bottomDist > 0.) {
282 203 : return sqrt(leftDist * leftDist + bottomDist * bottomDist);
283 : }
284 1079 : if (topDist > 0.) {
285 448 : return sqrt(leftDist * leftDist + topDist * topDist);
286 : }
287 : return leftDist;
288 : }
289 26507 : if (rightDist > 0.) {
290 11921 : if (bottomDist > 0.) {
291 264 : return sqrt(rightDist * rightDist + bottomDist * bottomDist);
292 : }
293 11657 : if (topDist > 0.) {
294 6837 : return sqrt(rightDist * rightDist + topDist * topDist);
295 : }
296 : return rightDist;
297 : }
298 14586 : if (bottomDist > 0) {
299 : return bottomDist;
300 : }
301 13452 : if (topDist > 0) {
302 3363 : return topDist;
303 : }
304 : return 0.;
305 : }
306 :
307 :
308 : bool
309 199178 : Boundary::partialWithin(const AbstractPoly& poly, double offset) const {
310 : return
311 396732 : poly.around(Position(myXmax, myYmax), offset) ||
312 394811 : poly.around(Position(myXmin, myYmax), offset) ||
313 593475 : poly.around(Position(myXmax, myYmin), offset) ||
314 197040 : poly.around(Position(myXmin, myYmin), offset);
315 : }
316 :
317 :
318 : Boundary&
319 1063006 : Boundary::grow(double by) {
320 :
321 1063006 : myXmax += by;
322 1063006 : myYmax += by;
323 1063006 : myXmin -= by;
324 1063006 : myYmin -= by;
325 1063006 : return *this;
326 : }
327 :
328 :
329 : Boundary&
330 0 : Boundary::scale(double by) {
331 0 : growWidth(by * (myXmax - myXmin));
332 0 : growHeight(by * (myYmax - myYmin));
333 0 : return *this;
334 : }
335 :
336 :
337 : void
338 1794644 : Boundary::growWidth(double by) {
339 1794644 : myXmin -= by;
340 1794644 : myXmax += by;
341 1794644 : }
342 :
343 :
344 : void
345 965870 : Boundary::growHeight(double by) {
346 965870 : myYmin -= by;
347 965870 : myYmax += by;
348 965870 : }
349 :
350 : void
351 25 : Boundary::flipY() {
352 25 : myYmin *= -1.0;
353 25 : myYmax *= -1.0;
354 : double tmp = myYmin;
355 25 : myYmin = myYmax;
356 25 : myYmax = tmp;
357 25 : }
358 :
359 :
360 :
361 : std::ostream&
362 7572 : operator<<(std::ostream& os, const Boundary& b) {
363 30288 : os << b.myXmin << "," << b.myYmin << "," << b.myXmax << "," << b.myYmax;
364 7572 : return os;
365 : }
366 :
367 :
368 : bool
369 370 : Boundary::operator==(const Boundary& b) const {
370 : return (
371 370 : myXmin == b.myXmin &&
372 0 : myXmax == b.myXmax &&
373 0 : myYmin == b.myYmin &&
374 0 : myYmax == b.myYmax &&
375 0 : myZmin == b.myZmin &&
376 370 : myZmax == b.myZmax &&
377 0 : myWasInitialised == b.myWasInitialised);
378 : }
379 :
380 :
381 : bool
382 0 : Boundary::operator!=(const Boundary& b) const {
383 0 : return !(*this == b);
384 : }
385 :
386 :
387 : void
388 400 : Boundary::set(double xmin, double ymin, double xmax, double ymax) {
389 : /*
390 : Takes care of the following extraneous cases w.r.t the input parameters:
391 : - xmin > xmax
392 : - ymin > ymax
393 : */
394 :
395 400 : myXmin = MIN2(xmin, xmax);
396 400 : myYmin = MIN2(ymin, ymax);
397 400 : myXmax = MAX2(xmin, xmax);
398 400 : myYmax = MAX2(ymin, ymax);
399 400 : }
400 :
401 :
402 : void
403 2 : Boundary::setOffsets(double xmin, double ymin, double xmax, double ymax) {
404 2 : myXmin = xmin;
405 2 : myYmin = ymin;
406 2 : myXmax = xmax;
407 2 : myYmax = ymax;
408 2 : }
409 :
410 :
411 : void
412 1825 : Boundary::moveby(double x, double y, double z) {
413 1825 : myXmin += x;
414 1825 : myYmin += y;
415 1825 : myZmin += z;
416 1825 : myXmax += x;
417 1825 : myYmax += y;
418 1825 : myZmax += z;
419 1825 : }
420 :
421 :
422 : PositionVector
423 1416 : Boundary::getShape(const bool closeShape) const {
424 1416 : PositionVector shape;
425 1416 : shape.push_back(Position(myXmin, myYmin));
426 1416 : shape.push_back(Position(myXmin, myYmax));
427 1416 : shape.push_back(Position(myXmax, myYmax));
428 1416 : shape.push_back(Position(myXmax, myYmin));
429 1416 : if (closeShape) {
430 1416 : shape.push_back(Position(myXmin, myYmin));
431 : }
432 1416 : return shape;
433 0 : }
434 :
435 : /****************************************************************************/
|