Eclipse SUMO - Simulation of Urban MObility
Loading...
Searching...
No Matches
GUIGeometry.cpp
Go to the documentation of this file.
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/****************************************************************************/
18// File for geometry classes and functions
19/****************************************************************************/
25
26#include "GUIGeometry.h"
27
28#define CIRCLE_RESOLUTION (double)10 // inverse in degrees
29
30// ===========================================================================
31// static member definitions
32// ===========================================================================
34
35// ===========================================================================
36// method definitions
37// ===========================================================================
38
41
42
44 myShape(shape) {
45 // calculate shape rotation and lengths
47}
48
49
50GUIGeometry::GUIGeometry(const PositionVector& shape, const std::vector<double>& shapeRotations,
51 const std::vector<double>& shapeLengths) :
52 myShape(shape),
53 myShapeRotations(shapeRotations),
54 myShapeLengths(shapeLengths) {
55}
56
57
58void
60 // clear geometry
62 // update shape
63 myShape = shape;
64 // calculate shape rotation and lengths
66}
67
68
69void
70GUIGeometry::updateGeometry(const PositionVector& shape, const double posOverShape,
71 const double lateralOffset) {
72 // first clear geometry
74 // get shape length
75 const double shapeLength = shape.length();
76 // calculate position and rotation
77 if (posOverShape < 0) {
78 myShape.push_back(shape.positionAtOffset(0, lateralOffset));
79 myShapeRotations.push_back(shape.rotationDegreeAtOffset(0));
80 } else if (posOverShape > shapeLength) {
81 myShape.push_back(shape.positionAtOffset(shapeLength, lateralOffset));
82 myShapeRotations.push_back(shape.rotationDegreeAtOffset(shapeLength));
83 } else {
84 myShape.push_back(shape.positionAtOffset(posOverShape, lateralOffset));
85 myShapeRotations.push_back(shape.rotationDegreeAtOffset(posOverShape));
86 }
87}
88
89
90void
91GUIGeometry::updateGeometry(const PositionVector& shape, double starPosOverShape,
92 double endPosOverShape, const double lateralOffset) {
93 // first clear geometry
95 // set new shape
96 myShape = shape;
97 // set lateral offset
98 myShape.move2side(lateralOffset);
99 // get shape length
100 const double shapeLength = myShape.length2D();
101 // set initial beginTrim value
102 if (starPosOverShape < 0) {
103 endPosOverShape = 0;
104 }
105 // set initial endtrim value
106 if (starPosOverShape < 0) {
107 endPosOverShape = shapeLength;
108 }
109 // check maximum beginTrim
110 if (starPosOverShape > (shapeLength - POSITION_EPS)) {
111 endPosOverShape = (shapeLength - POSITION_EPS);
112 }
113 // check maximum endTrim
114 if ((endPosOverShape > shapeLength)) {
115 endPosOverShape = shapeLength;
116 }
117 // check sub-vector
118 if (endPosOverShape <= starPosOverShape) {
119 endPosOverShape = endPosOverShape + POSITION_EPS;
120 }
121 // trim shape
122 myShape = myShape.getSubpart2D(starPosOverShape, endPosOverShape);
123 // calculate shape rotation and lengths
125}
126
127
128void
129GUIGeometry::updateGeometry(const PositionVector& shape, double beginTrimPosition, const Position& extraFirstPosition,
130 double endTrimPosition, const Position& extraLastPosition) {
131 // first clear geometry
133 // set new shape
134 myShape = shape;
135 // check trim values
136 if ((beginTrimPosition != -1) || (endTrimPosition != -1)) {
137 // get shape length
138 const double shapeLength = myShape.length2D();
139 // set initial beginTrim value
140 if (beginTrimPosition < 0) {
141 beginTrimPosition = 0;
142 }
143 // set initial endtrim value
144 if (endTrimPosition < 0) {
145 endTrimPosition = shapeLength;
146 }
147 // check maximum beginTrim
148 if (beginTrimPosition > (shapeLength - POSITION_EPS)) {
149 beginTrimPosition = (shapeLength - POSITION_EPS);
150 }
151 // check maximum endTrim
152 if ((endTrimPosition > shapeLength)) {
153 endTrimPosition = shapeLength;
154 }
155 // check sub-vector
156 if (endTrimPosition <= beginTrimPosition) {
157 endTrimPosition = endTrimPosition + POSITION_EPS;
158 }
159 // trim shape
160 myShape = myShape.getSubpart2D(beginTrimPosition, endTrimPosition);
161 // add extra positions
162 if (extraFirstPosition != Position::INVALID) {
163 myShape.push_front_noDoublePos(extraFirstPosition);
164 }
165 if (extraLastPosition != Position::INVALID) {
166 myShape.push_back_noDoublePos(extraLastPosition);
167 }
168 }
169 // calculate shape rotation and lengths
171}
172
173
174void
175GUIGeometry::updateSinglePosGeometry(const Position& position, const double rotation) {
176 // first clear geometry
178 // set position and rotation
179 myShape.push_back(position);
180 myShapeRotations.push_back(rotation);
181}
182
183
185 // clear geometry containers
186 myShape.clear();
187 myShapeRotations.clear();
188 myShapeLengths.clear();
189}
190
191
192void
194 // move shape
195 myShape.move2side(amount);
196}
197
198
199void
200GUIGeometry::scaleGeometry(const double scale) {
201 // scale shape and lengths
202 myShape.scaleRelative(scale);
203 // scale lengths
204 for (auto& shapeLength : myShapeLengths) {
205 shapeLength *= scale;
206 }
207}
208
209
210const PositionVector&
212 return myShape;
213}
214
215
216const std::vector<double>&
220
221
222const std::vector<double>&
226
227
228double
230 // return rotation (angle) of the vector constructed by points first and second
231 return ((double)atan2((second.x() - first.x()), (first.y() - second.y())) * (double) 180.0 / (double)M_PI);
232}
233
234
235double
236GUIGeometry::calculateLength(const Position& first, const Position& second) {
237 // return 2D distance between two points
238 return first.distanceTo2D(second);
239}
240
241
242void
243GUIGeometry::adjustStartPosGeometricPath(double& startPos, const PositionVector& startLaneShape,
244 double& endPos, const PositionVector& endLaneShape) {
245 // adjust both, if start and end lane are the same
246 if ((startLaneShape.size() > 0) &&
247 (endLaneShape.size() > 0) &&
248 (startLaneShape == endLaneShape) &&
249 (startPos != -1) &&
250 (endPos != -1)) {
251 if (startPos >= endPos) {
252 endPos = (startPos + POSITION_EPS);
253 }
254 }
255 // adjust startPos
256 if ((startPos != -1) && (startLaneShape.size() > 0)) {
257 if (startPos < POSITION_EPS) {
258 startPos = POSITION_EPS;
259 }
260 if (startPos > (startLaneShape.length() - POSITION_EPS)) {
261 startPos = (startLaneShape.length() - POSITION_EPS);
262 }
263 }
264 // adjust endPos
265 if ((endPos != -1) && (endLaneShape.size() > 0)) {
266 if (endPos < POSITION_EPS) {
267 endPos = POSITION_EPS;
268 }
269 if (endPos > (endLaneShape.length() - POSITION_EPS)) {
270 endPos = (endLaneShape.length() - POSITION_EPS);
271 }
272 }
273}
274
275
276void
278 const double width, double offset) {
279 // continue depending of detail level
281 GLHelper::drawBoxLines(geometry.getShape(), geometry.getShapeRotations(), geometry.getShapeLengths(), width, 0, offset);
283 // set line width
284 glLineWidth(static_cast<float>(width));
285 // draw a simple line
286 GLHelper::drawLine(geometry.getShape());
287 // restore line width
288 glLineWidth(1);
289 } else {
290 // draw a simple line
291 GLHelper::drawLine(geometry.getShape());
292 }
293}
294
295
296void
298 const std::vector<RGBColor>& colors, const double width, double offset) {
299 // continue depending of detail level
301 GLHelper::drawBoxLines(geometry.getShape(), geometry.getShapeRotations(), geometry.getShapeLengths(), colors, width, 0, offset);
302 } else {
303 // set first color
304 GLHelper::setColor(*colors.begin());
305 // set width
307 // set line width
308 glLineWidth(static_cast<float>(width));
309 // draw a simple line
310 GLHelper::drawLine(geometry.getShape());
311 // restore line width
312 glLineWidth(1);
313 } else {
314 // draw a simple line
315 GLHelper::drawLine(geometry.getShape());
316 }
317 }
318}
319
320
321void
322GUIGeometry::drawContourGeometry(const GUIGeometry& geometry, const double width, const bool drawExtremes) {
323 // get shapes
324 PositionVector shapeA = geometry.getShape();
325 PositionVector shapeB = geometry.getShape();
326 // move both shapes
327 shapeA.move2side((width - 0.1));
328 shapeB.move2side((width - 0.1) * -1);
329 // check if we have to drawn extremes
330 if (drawExtremes) {
331 // reverse shape B
332 shapeB = shapeB.reverse();
333 // append shape B to shape A
334 shapeA.append(shapeB, 0);
335 // close shape A
336 shapeA.closePolygon();
337 // draw box lines using shapeA
338 GLHelper::drawBoxLines(shapeA, 0.1);
339 } else {
340 // draw box lines using shapeA
341 GLHelper::drawBoxLines(shapeA, 0.1);
342 // draw box lines using shapeA
343 GLHelper::drawBoxLines(shapeB, 0.1);
344 }
345}
346
347
348void
350 const RGBColor& color, const double radius, const double exaggeration,
351 const bool editingElevation) {
352 // check detail level
354 // get exaggeratedRadio
355 const double exaggeratedRadio = (radius * exaggeration);
356 // iterate over geometryPoints
357 for (const auto& geometryPos : shape) {
358 // push geometry point matrix
360 // move to vertex
361 glTranslated(geometryPos.x(), geometryPos.y(), 0.2);
362 // set color
363 GLHelper::setColor(color);
364 // draw circle detailled
365 GLHelper::drawFilledCircleDetailled(d, exaggeratedRadio);
366 // pop geometry point matrix
368 // draw elevation or special symbols (Start, End and Block)
370 if (editingElevation) {
371 // Push Z matrix
373 // draw Z (elevation)
374 GLHelper::drawText(toString(geometryPos.z()), geometryPos, 0.3, 0.7, color.invertedColor());
375 // pop Z matrix
377 } else if (geometryPos == shape.front()) {
378 // push "S" matrix
380 // draw a "s" over first point
381 GLHelper::drawText("S", geometryPos, 0.3, 2 * exaggeratedRadio, color.invertedColor());
382 // pop "S" matrix
384 } else if (geometryPos == shape.back()) {
385 // push "E" matrix
387 // draw a "e" over last point if polygon isn't closed
388 GLHelper::drawText("E", geometryPos, 0.3, 2 * exaggeratedRadio, color.invertedColor());
389 // pop "E" matrix
391 }
392 }
393 }
394 }
395}
396
397
398void
400 const RGBColor& color, const bool drawEntire, const double lineWidth) {
402 // calculate rotation
403 const double rot = RAD2DEG(parent.angleTo2D(child)) + 90;
404 // calculate distance between origin and destination
405 const double distanceSquared = parent.distanceSquaredTo2D(child);
406 // Add a draw matrix for details
408 // move back
409 glTranslated(0, 0, -1);
410 // draw box line
411 if (drawEntire) {
412 // draw first box line
414 GLHelper::drawBoxLine(parent, rot, sqrt(distanceSquared), lineWidth);
415 // move front
416 glTranslated(0, 0, 0.1);
417 // draw second box line
418 GLHelper::setColor(color);
419 GLHelper::drawBoxLine(parent, rot, sqrt(distanceSquared), .04);
420 } else if (distanceSquared > 25) {
421 // draw first box line with length 4.9
423 GLHelper::drawBoxLine(parent, rot, 4.9, lineWidth);
424 glTranslated(0, 0, 0.1);
425 // draw second box line with length 4.9
426 GLHelper::setColor(color);
427 GLHelper::drawBoxLine(parent, rot, 4.9, .04);
428 // draw arrow depending of distanceSquared (10*10)
429 if (distanceSquared > 100) {
430 // calculate positionVector between both points
431 const PositionVector vector = {parent, child};
432 // draw first arrow at end
435 vector.positionAtOffset2D(5),
439 // move front
440 glTranslated(0, 0, 0.1);
441 // draw second arrow at end
442 GLHelper::setColor(color);
444 vector.positionAtOffset2D(5),
448 }
449 }
450 // pop draw matrix
452 }
453}
454
455
456void
458 const RGBColor& color, const bool drawEntire, const double lineWidth) {
460 // calculate distance between origin and destination
461 const double distanceSquared = child.distanceSquaredTo2D(parent);
462 // calculate subline width
463 const double sublineWidth = (lineWidth * 0.8);
464 // calculate rotation
465 const double rot = RAD2DEG(child.angleTo2D(parent)) + 90;
466 // Add a draw matrix for details
468 // move back
469 glTranslated(0, 0, -1);
470 // set color
471 GLHelper::setColor(color);
472 // draw box line
473 if (drawEntire || (distanceSquared < 25)) {
474 // set color
475 GLHelper::setColor(color);
476 // draw first box line
478 GLHelper::drawBoxLine(child, rot, sqrt(distanceSquared), lineWidth);
479 // move front
480 glTranslated(0, 0, 0.1);
481 // draw second box line
482 GLHelper::setColor(color);
483 GLHelper::drawBoxLine(child, rot, sqrt(distanceSquared), sublineWidth);
484 } else {
485 // draw first box line with length 4.9
487 GLHelper::drawBoxLine(child, rot, 4.9, lineWidth);
488 glTranslated(0, 0, 0.1);
489 // draw second box line with length
490 GLHelper::setColor(color);
491 GLHelper::drawBoxLine(child, rot, 4.9, sublineWidth);
492 // draw arrow depending of distanceSquared (10*10)
493 if (distanceSquared > 100) {
494 // calculate positionVector between both points
495 const PositionVector vector = {child, parent};
496 // draw first arrow at end
499 vector.positionAtOffset2D(5),
503 // move front
504 glTranslated(0, 0, 0.1);
505 // draw second arrow at end
506 GLHelper::setColor(color);
508 vector.positionAtOffset2D(5),
512 }
513 }
514 // pop draw matrix
516 }
517}
518
519
521GUIGeometry::getVertexCircleAroundPosition(const Position& pos, const double width, const int steps) {
522 // first check if we have to fill myCircleCoords (only once)
523 if (myCircleCoords.size() == 0) {
524 for (int i = 0; i <= (int)(360 * CIRCLE_RESOLUTION); ++i) {
525 const double x = (double) sin(DEG2RAD(i / CIRCLE_RESOLUTION));
526 const double y = (double) cos(DEG2RAD(i / CIRCLE_RESOLUTION));
527 myCircleCoords.push_back(Position(x, y));
528 }
529 }
530 PositionVector vertexCircle;
531 const double inc = 360 / (double)steps;
532 // obtain all vertices
533 for (int i = 0; i <= steps; ++i) {
534 const Position& vertex = myCircleCoords[GUIGeometry::angleLookup(i * inc)];
535 vertexCircle.push_back(Position(vertex.x() * width, vertex.y() * width));
536 }
537 // move result using position
538 vertexCircle.add(pos);
539 return vertexCircle;
540}
541
542
543void
545 // rotate using rotation calculated in PositionVector
546 glRotated((rot * -1) + 90, 0, 0, 1);
547}
548
549
550int
551GUIGeometry::angleLookup(const double angleDeg) {
552 const int numCoords = (int)myCircleCoords.size() - 1;
553 int index = ((int)(floor(angleDeg * CIRCLE_RESOLUTION + 0.5))) % numCoords;
554 if (index < 0) {
555 index += numCoords;
556 }
557 assert(index >= 0);
558 return (int)index;
559}
560
561
562void
564 // clear rotations and lengths
565 myShapeRotations.clear();
566 myShapeLengths.clear();
567 // Get number of parts of the shape
568 int numberOfSegments = (int)myShape.size() - 1;
569 // If number of segments is more than 0
570 if (numberOfSegments >= 0) {
571 // Reserve memory (To improve efficiency)
572 myShapeRotations.reserve(numberOfSegments);
573 myShapeLengths.reserve(numberOfSegments);
574 // Calculate lengths and rotations for every shape
575 for (int i = 0; i < numberOfSegments; i++) {
576 myShapeRotations.push_back(calculateRotation(myShape[i], myShape[i + 1]));
577 myShapeLengths.push_back(calculateLength(myShape[i], myShape[i + 1]));
578 }
579 }
580}
581
582/****************************************************************************/
#define CIRCLE_RESOLUTION
Definition GLHelper.cpp:49
#define DEG2RAD(x)
Definition GeomHelper.h:35
#define RAD2DEG(x)
Definition GeomHelper.h:36
std::string toString(const T &t, std::streamsize accuracy=gPrecision)
Definition ToString.h:46
static void drawLine(const Position &beg, double rot, double visLength)
Draws a thin line.
Definition GLHelper.cpp:438
static void setColor(const RGBColor &c)
Sets the gl-color to this value.
Definition GLHelper.cpp:654
static void drawTriangleAtEnd(const Position &p1, const Position &p2, double tLength, double tWidth, const double extraOffset=0)
Draws a triangle at the end of the given line.
Definition GLHelper.cpp:629
static void popMatrix()
pop matrix
Definition GLHelper.cpp:130
static void drawBoxLines(const PositionVector &geom, const std::vector< double > &rots, const std::vector< double > &lengths, double width, int cornerDetail=0, double offset=0)
Draws thick lines.
Definition GLHelper.cpp:347
static void drawBoxLine(const Position &beg, double rot, double visLength, double width, double offset=0)
Draws a thick line.
Definition GLHelper.cpp:295
static void drawFilledCircleDetailled(const GUIVisualizationSettings::Detail d, const double radius)
Draws a filled circle around (0,0) depending of level of detail.
Definition GLHelper.cpp:539
static void pushMatrix()
push matrix
Definition GLHelper.cpp:117
static void drawText(const std::string &text, const Position &pos, const double layer, const double size, const RGBColor &col=RGBColor::BLACK, const double angle=0, const int align=0, double width=-1)
Definition GLHelper.cpp:756
static void rotateOverLane(const double rot)
rotate over lane (used by Lock icons, detector logos, etc.)
void moveGeometryToSide(const double amount)
move current shape to side
const std::vector< double > & getShapeRotations() const
The rotations of the single shape parts.
static void drawGeometryPoints(const GUIVisualizationSettings::Detail d, const PositionVector &shape, const RGBColor &color, const double radius, const double exaggeration, const bool editingElevation)
draw geometry points
static PositionVector myCircleCoords
Storage for precomputed sin/cos-values describing a circle.
void scaleGeometry(const double scale)
scale geometry
static PositionVector getVertexCircleAroundPosition(const Position &pos, const double width, const int steps=8)
get a circle around the given position
void calculateShapeRotationsAndLengths()
calculate shape rotations and lengths
std::vector< double > myShapeLengths
The lengths of the shape (note: Always size = myShape.size()-1)
static void adjustStartPosGeometricPath(double &startPos, const PositionVector &startLaneShape, double &endPos, const PositionVector &endLaneShape)
adjust start and end positions in geometric path
void clearGeometry()
clear geometry
static int angleLookup(const double angleDeg)
normalize angle for lookup in myCircleCoords
static void drawContourGeometry(const GUIGeometry &geometry, const double width, const bool drawExtremes=false)
draw contour geometry
static void drawGeometry(const GUIVisualizationSettings::Detail d, const GUIGeometry &geometry, const double width, double offset=0)
draw geometry
PositionVector myShape
element shape
void updateSinglePosGeometry(const Position &position, const double rotation)
update position and rotation
static double calculateRotation(const Position &first, const Position &second)
return angle between two points (used in geometric calculations)
static void drawChildLine(const GUIVisualizationSettings &s, const Position &child, const Position &parent, const RGBColor &color, const bool drawEntire, const double lineWidth)
draw line between child and parent (used in netedit)
const PositionVector & getShape() const
The shape of the additional element.
void updateGeometry(const PositionVector &shape)
update entire geometry
const std::vector< double > & getShapeLengths() const
The lengths of the single shape parts.
std::vector< double > myShapeRotations
The rotations of the shape (note: Always size = myShape.size()-1)
GUIGeometry()
default constructor
static void drawParentLine(const GUIVisualizationSettings &s, const Position &parent, const Position &child, const RGBColor &color, const bool drawEntire, const double lineWidth)
draw line between parent and children (used in netedit)
static double calculateLength(const Position &first, const Position &second)
return length between two points (used in geometric calculations)
Stores the information about how to visualize structures.
bool drawForRectangleSelection
whether drawing is performed for the purpose of selecting objects using a rectangle
GUIVisualizationAdditionalSettings additionalSettings
Additional settings.
A point in 2D or 3D with translation and scaling methods.
Definition Position.h:37
double distanceSquaredTo2D(const Position &p2) const
returns the square of the distance to another position (Only using x and y positions)
Definition Position.h:281
static const Position INVALID
used to indicate that a position is valid
Definition Position.h:322
double distanceTo2D(const Position &p2) const
returns the euclidean distance in the x-y-plane
Definition Position.h:276
double x() const
Returns the x-position.
Definition Position.h:55
double angleTo2D(const Position &other) const
returns the angle in the plane of the vector pointing from here to the other position (in radians bet...
Definition Position.h:286
double y() const
Returns the y-position.
Definition Position.h:60
A list of positions.
double length2D() const
Returns the length.
void append(const PositionVector &v, double sameThreshold=2.0)
double length() const
Returns the length.
void push_front_noDoublePos(const Position &p)
insert in front a non double position
double rotationDegreeAtOffset(double pos) const
Returns the rotation at the given length.
Position positionAtOffset(double pos, double lateralOffset=0) const
Returns the position at the given length.
void add(double xoff, double yoff, double zoff)
void closePolygon()
ensures that the last position equals the first
void move2side(double amount, double maxExtension=100)
move position vector to side using certain amount
PositionVector getSubpart2D(double beginOffset, double endOffset) const
get subpart of a position vector in two dimensions (Z is ignored)
void scaleRelative(double factor)
enlarges/shrinks the polygon by a factor based at the centroid
void push_back_noDoublePos(const Position &p)
insert in back a non double position
PositionVector reverse() const
reverse position vector
Position positionAtOffset2D(double pos, double lateralOffset=0) const
Returns the position at the given length.
RGBColor invertedColor() const
obtain inverted of current RGBColor
Definition RGBColor.cpp:183
RGBColor changedBrightness(int change, int toChange=3) const
Returns a new color with altered brightness.
Definition RGBColor.cpp:200
#define M_PI
Definition odrSpiral.cpp:45
static const double arrowLength
arrow length
static const double arrowWidth
arrow width
static const double arrowOffset
arrow offset