Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
eclipse
GitHub Repository: eclipse/sumo
Path: blob/main/src/utils/geom/Boundary.cpp
169678 views
1
/****************************************************************************/
2
// Eclipse SUMO, Simulation of Urban MObility; see https://eclipse.dev/sumo
3
// Copyright (C) 2001-2025 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
Boundary::Boundary()
36
: myXmin(10000000000.0), myXmax(-10000000000.0),
37
myYmin(10000000000.0), myYmax(-10000000000.0),
38
myZmin(10000000000.0), myZmax(-10000000000.0),
39
myWasInitialised(false) {}
40
41
42
Boundary::Boundary(double x1, double y1, double x2, double y2)
43
: myXmin(10000000000.0), myXmax(-10000000000.0),
44
myYmin(10000000000.0), myYmax(-10000000000.0),
45
myZmin(10000000000.0), myZmax(-10000000000.0),
46
myWasInitialised(false) {
47
add(x1, y1);
48
add(x2, y2);
49
}
50
51
52
Boundary::Boundary(double x1, double y1, double z1, double x2, double y2, double z2)
53
: myXmin(10000000000.0), myXmax(-10000000000.0),
54
myYmin(10000000000.0), myYmax(-10000000000.0),
55
myZmin(10000000000.0), myZmax(-10000000000.0),
56
myWasInitialised(false) {
57
add(x1, y1, z1);
58
add(x2, y2, z2);
59
}
60
61
62
void
63
Boundary::reset() {
64
myXmin = 10000000000.0;
65
myXmax = -10000000000.0;
66
myYmin = 10000000000.0;
67
myYmax = -10000000000.0;
68
myZmin = 10000000000.0;
69
myZmax = -10000000000.0;
70
myWasInitialised = false;
71
}
72
73
74
void
75
Boundary::add(double x, double y, double z) {
76
if (!myWasInitialised) {
77
myYmin = y;
78
myYmax = y;
79
myXmin = x;
80
myXmax = x;
81
myZmin = z;
82
myZmax = z;
83
} else {
84
myXmin = myXmin < x ? myXmin : x;
85
myXmax = myXmax > x ? myXmax : x;
86
myYmin = myYmin < y ? myYmin : y;
87
myYmax = myYmax > y ? myYmax : y;
88
myZmin = myZmin < z ? myZmin : z;
89
myZmax = myZmax > z ? myZmax : z;
90
}
91
myWasInitialised = true;
92
}
93
94
95
void
96
Boundary::add(const Position& p) {
97
add(p.x(), p.y(), p.z());
98
}
99
100
101
void
102
Boundary::add(const Boundary& p) {
103
add(p.xmin(), p.ymin(), p.zmin());
104
add(p.xmax(), p.ymax(), p.zmax());
105
}
106
107
108
Position
109
Boundary::getCenter() const {
110
return Position((myXmin + myXmax) / (double) 2.0, (myYmin + myYmax) / (double) 2.0, (myZmin + myZmax) / (double) 2.0);
111
}
112
113
114
double
115
Boundary::xmin() const {
116
return myXmin;
117
}
118
119
120
double
121
Boundary::xmax() const {
122
return myXmax;
123
}
124
125
126
double
127
Boundary::ymin() const {
128
return myYmin;
129
}
130
131
132
double
133
Boundary::ymax() const {
134
return myYmax;
135
}
136
137
138
double
139
Boundary::zmin() const {
140
return myZmin;
141
}
142
143
144
double
145
Boundary::zmax() const {
146
return myZmax;
147
}
148
149
150
double
151
Boundary::getWidth() const {
152
return myXmax - myXmin;
153
}
154
155
156
double
157
Boundary::getHeight() const {
158
return myYmax - myYmin;
159
}
160
161
162
double
163
Boundary::getZRange() const {
164
return myZmax - myZmin;
165
}
166
167
168
bool
169
Boundary::around(const Position& p, double offset) const {
170
return
171
((p.x() <= myXmax + offset) && (p.x() >= myXmin - offset)) &&
172
((p.y() <= myYmax + offset) && (p.y() >= myYmin - offset)) &&
173
((p.z() <= myZmax + offset) && (p.z() >= myZmin - offset));
174
}
175
176
177
bool
178
Boundary::around2D(const Position& p, double offset) const {
179
return
180
((p.x() <= myXmax + offset) && (p.x() >= myXmin - offset)) &&
181
((p.y() <= myYmax + offset) && (p.y() >= myYmin - offset));
182
}
183
184
185
bool
186
Boundary::around2D(const double x, const double y) const {
187
return
188
((x <= myXmax) && (x >= myXmin)) &&
189
((y <= myYmax) && (y >= myYmin));
190
}
191
192
193
bool
194
Boundary::overlapsWith(const AbstractPoly& p, double offset) const {
195
if (
196
// check whether one of my points lies within the given poly
197
partialWithin(p, offset) ||
198
// check whether the polygon lies within me
199
p.partialWithin(*this, offset)) {
200
return true;
201
}
202
// check whether the bounderies cross
203
return
204
p.crosses(Position(myXmax + offset, myYmax + offset), Position(myXmin - offset, myYmax + offset))
205
||
206
p.crosses(Position(myXmin - offset, myYmax + offset), Position(myXmin - offset, myYmin - offset))
207
||
208
p.crosses(Position(myXmin - offset, myYmin - offset), Position(myXmax + offset, myYmin - offset))
209
||
210
p.crosses(Position(myXmax + offset, myYmin - offset), Position(myXmax + offset, myYmax + offset));
211
}
212
213
214
bool
215
Boundary::crosses(const Position& p1, const Position& p2) const {
216
const PositionVector line(p1, p2);
217
return
218
line.intersects(Position(myXmax, myYmax), Position(myXmin, myYmax))
219
||
220
line.intersects(Position(myXmin, myYmax), Position(myXmin, myYmin))
221
||
222
line.intersects(Position(myXmin, myYmin), Position(myXmax, myYmin))
223
||
224
line.intersects(Position(myXmax, myYmin), Position(myXmax, myYmax));
225
}
226
227
228
bool
229
Boundary::contains2D(const Boundary& b) const {
230
if ((myXmin <= b.xmin()) && (myYmin <= b.ymin()) &&
231
(myXmax >= b.xmax()) && (myYmax >= b.ymax())) {
232
return true;
233
} else {
234
return false;
235
}
236
}
237
238
239
bool
240
Boundary::overlaps2D(const Boundary& b) const {
241
if (around2D(b.myXmin, b.myYmin)) {
242
return true;
243
} else if (around2D(b.myXmin, b.myYmax)) {
244
return true;
245
} else if (around2D(b.myXmax, b.myYmin)) {
246
return true;
247
} else if (around2D(b.myXmax, b.myYmax)) {
248
return true;
249
} else {
250
return false;
251
}
252
}
253
254
255
bool
256
Boundary::isInitialised() const {
257
return myWasInitialised;
258
}
259
260
261
double
262
Boundary::distanceTo2D(const Position& p) const {
263
const double leftDist = myXmin - p.x();
264
const double rightDist = p.x() - myXmax;
265
const double bottomDist = myYmin - p.y();
266
const double topDist = p.y() - myYmax;
267
if (leftDist > 0.) {
268
if (bottomDist > 0.) {
269
return sqrt(leftDist * leftDist + bottomDist * bottomDist);
270
}
271
if (topDist > 0.) {
272
return sqrt(leftDist * leftDist + topDist * topDist);
273
}
274
return leftDist;
275
}
276
if (rightDist > 0.) {
277
if (bottomDist > 0.) {
278
return sqrt(rightDist * rightDist + bottomDist * bottomDist);
279
}
280
if (topDist > 0.) {
281
return sqrt(rightDist * rightDist + topDist * topDist);
282
}
283
return rightDist;
284
}
285
if (bottomDist > 0) {
286
return bottomDist;
287
}
288
if (topDist > 0) {
289
return topDist;
290
}
291
return 0.;
292
}
293
294
295
double
296
Boundary::distanceTo2D(const Boundary& b) const {
297
const double leftDist = myXmin - b.myXmax;
298
const double rightDist = b.myXmin - myXmax;
299
const double bottomDist = myYmin - b.myYmax;
300
const double topDist = b.myYmin - myYmax;
301
if (leftDist > 0.) {
302
if (bottomDist > 0.) {
303
return sqrt(leftDist * leftDist + bottomDist * bottomDist);
304
}
305
if (topDist > 0.) {
306
return sqrt(leftDist * leftDist + topDist * topDist);
307
}
308
return leftDist;
309
}
310
if (rightDist > 0.) {
311
if (bottomDist > 0.) {
312
return sqrt(rightDist * rightDist + bottomDist * bottomDist);
313
}
314
if (topDist > 0.) {
315
return sqrt(rightDist * rightDist + topDist * topDist);
316
}
317
return rightDist;
318
}
319
if (bottomDist > 0) {
320
return bottomDist;
321
}
322
if (topDist > 0) {
323
return topDist;
324
}
325
return 0.;
326
}
327
328
329
bool
330
Boundary::partialWithin(const AbstractPoly& poly, double offset) const {
331
return
332
poly.around(Position(myXmax, myYmax), offset) ||
333
poly.around(Position(myXmin, myYmax), offset) ||
334
poly.around(Position(myXmax, myYmin), offset) ||
335
poly.around(Position(myXmin, myYmin), offset);
336
}
337
338
339
Boundary&
340
Boundary::grow(double by) {
341
342
myXmax += by;
343
myYmax += by;
344
myXmin -= by;
345
myYmin -= by;
346
return *this;
347
}
348
349
350
Boundary&
351
Boundary::scale(double by) {
352
growWidth(by * (myXmax - myXmin));
353
growHeight(by * (myYmax - myYmin));
354
return *this;
355
}
356
357
358
void
359
Boundary::growWidth(double by) {
360
myXmin -= by;
361
myXmax += by;
362
}
363
364
365
void
366
Boundary::growHeight(double by) {
367
myYmin -= by;
368
myYmax += by;
369
}
370
371
void
372
Boundary::flipY() {
373
myYmin *= -1.0;
374
myYmax *= -1.0;
375
double tmp = myYmin;
376
myYmin = myYmax;
377
myYmax = tmp;
378
}
379
380
381
382
std::ostream&
383
operator<<(std::ostream& os, const Boundary& b) {
384
os << b.myXmin << "," << b.myYmin << "," << b.myXmax << "," << b.myYmax;
385
return os;
386
}
387
388
389
bool
390
Boundary::operator==(const Boundary& b) const {
391
return (
392
myXmin == b.myXmin &&
393
myXmax == b.myXmax &&
394
myYmin == b.myYmin &&
395
myYmax == b.myYmax &&
396
myZmin == b.myZmin &&
397
myZmax == b.myZmax &&
398
myWasInitialised == b.myWasInitialised);
399
}
400
401
402
bool
403
Boundary::operator!=(const Boundary& b) const {
404
return !(*this == b);
405
}
406
407
408
void
409
Boundary::set(double xmin, double ymin, double xmax, double ymax) {
410
/*
411
Takes care of the following extraneous cases w.r.t the input parameters:
412
- xmin > xmax
413
- ymin > ymax
414
*/
415
416
myXmin = MIN2(xmin, xmax);
417
myYmin = MIN2(ymin, ymax);
418
myXmax = MAX2(xmin, xmax);
419
myYmax = MAX2(ymin, ymax);
420
}
421
422
423
void
424
Boundary::setOffsets(double xmin, double ymin, double xmax, double ymax) {
425
myXmin = xmin;
426
myYmin = ymin;
427
myXmax = xmax;
428
myYmax = ymax;
429
}
430
431
432
void
433
Boundary::moveby(double x, double y, double z) {
434
myXmin += x;
435
myYmin += y;
436
myZmin += z;
437
myXmax += x;
438
myYmax += y;
439
myZmax += z;
440
}
441
442
443
PositionVector
444
Boundary::getShape(const bool closeShape) const {
445
PositionVector shape;
446
shape.push_back(Position(myXmin, myYmin));
447
shape.push_back(Position(myXmin, myYmax));
448
shape.push_back(Position(myXmax, myYmax));
449
shape.push_back(Position(myXmax, myYmin));
450
if (closeShape) {
451
shape.push_back(Position(myXmin, myYmin));
452
}
453
return shape;
454
}
455
456
/****************************************************************************/
457
458