Eclipse SUMO - Simulation of Urban MObility
Loading...
Searching...
No Matches
GUIViewObjectsHandler.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-2026 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// class used for handle objects over view
19/****************************************************************************/
20#include <config.h>
21#include <algorithm>
22
23#include <utils/shapes/Shape.h>
24
26
27
28// ===========================================================================
29// method definitions
30// ===========================================================================
31
33
34
35void
37 // reset recompute boundaries
39 // clear objects containers
41 mySelectedObjects.clear();
44 // reset marked elements
45 myMergingJunctions.clear();
46 markedEdge = nullptr;
47 markedLane = nullptr;
48 markedTAZ = nullptr;
49 markedRoute = nullptr;
52}
53
54
55const Position&
59
60
61const Triangle&
65
66
67void
69 // set position selection
71 // invalidate selection triangle
73}
74
75
76void
78 // invalidate position selection
80 // set selection triangle
81 mySelectionTriangle = triangle;
82}
83
84
85bool
89
90
91bool
93 const double layer, const GUIGlObject* parent) {
94 // first check if we're selecting for boundary
96 return false;
97 }
98 // try to find parent in seleted object
99 auto finder = mySelectedObjects.find(parent);
100 // if parent was found and was inserted with full boundary, insert it
101 if (finder != mySelectedObjects.end() && finder->second && !isObjectSelected(GLObject)) {
102 // insert element with full boundary
103 return selectObject(s, GLObject, layer, false, nullptr);
104 } else {
105 return false;
106 }
107}
108
109
110bool
112 const GUIGlObject* GLObject, const Position& center, const double radius, const double layer) {
113 // first check that object doesn't exist
114 if (isObjectSelected(GLObject)) {
115 return false;
116 } else {
117 // declare squared radius
118 const double squaredRadius = (radius * radius);
119 // continue depending if we're selecting a position or a boundary
121 // continue depending of detail level
123 // check if triangle intersect with circle
124 if (mySelectionTriangle.intersectWithCircle(center, radius)) {
125 return selectObject(s, GLObject, layer, false, nullptr);
126 } else {
127 return false;
128 }
129 } else {
130 // simply check if center is within triangle
132 return selectObject(s, GLObject, layer, false, nullptr);
133 } else {
134 return false;
135 }
136 }
138 // check distance between selection position and center
139 if (mySelectionPosition.distanceSquaredTo2D(center) <= squaredRadius) {
140 return selectObject(s, GLObject, layer, false, nullptr);
141 } else {
142 return false;
143 }
144 } else {
145 return false;
146 }
147 }
148}
149
150
151bool
153 const GUIGlObject* GLObject, const PositionVector& shape, const int index, const double layer, const double radius) {
154 // obtain geometry point pos
155 const auto geometryPointPos = shape[index];
156 // declare squared radius
157 const double squaredRadius = (radius * radius);
158 // continue depending if we're selecting a position or a boundary
160 // continue depending of detail level
162 // calculate boundary for geometry point
163 Boundary geometryPointBoundary;
164 geometryPointBoundary.add(geometryPointPos);
165 // check if center is within mySelectionBoundary
166 if (mySelectionTriangle.intersectWithCircle(geometryPointPos, radius)) {
167 return selectGeometryPoint(GLObject, index, layer);
168 } else {
169 return false;
170 }
171 } else {
172 // simply check if center is within triangle
173 if (mySelectionTriangle.isPositionWithin(geometryPointPos)) {
174 return selectObject(s, GLObject, layer, false, nullptr);
175 } else {
176 return false;
177 }
178 }
180 // check distance between selection position and center
181 if (mySelectionPosition.distanceSquaredTo2D(geometryPointPos) <= squaredRadius) {
182 return selectGeometryPoint(GLObject, index, layer);
183 } else {
184 return false;
185 }
186 } else {
187 return false;
188 }
189}
190
191
192bool
194 const PositionVector& shape, const double layer, const double distance) {
195 // only process if we're selecting a precise position
197 // obtain nearest position over shape
198 const auto nearestOffset = shape.nearest_offset_to_point2D(mySelectionPosition);
199 const auto nearestPos = shape.positionAtOffset2D(nearestOffset);
200 // check distance nearest position and pos
201 if (mySelectionPosition.distanceSquaredTo2D(nearestPos) <= (distance * distance)) {
202 return selectPositionOverShape(GLObject, nearestPos, layer, nearestOffset);
203 } else {
204 return false;
205 }
206 } else {
207 return false;
208 }
209}
210
211
212bool
214 const Boundary& shapeBoundary, const double layer, const GNESegment* segment) {
215 // first check that object doesn't exist
216 if (isObjectSelected(GLObject)) {
217 return false;
218 } else if (selectingUsingRectangle()) {
219 // avoid invalid boundaries
220 if (!shapeBoundary.isInitialised()) {
221 return false;
222 }
223 // check if triangle contains the given shape
224 if (mySelectionTriangle.intersectWithShape(shape, shapeBoundary)) {
225 return selectObject(s, GLObject, layer, false, segment);
226 }
227 // no intersection, then return false
228 return false;
230 // check if selection position is around shape
231 if (shape.around(mySelectionPosition)) {
232 return selectObject(s, GLObject, layer, false, segment);
233 } else {
234 return false;
235 }
236 } else {
237 return false;
238 }
239}
240
241
242bool
244 const bool checkDuplicated, const GNESegment* segment) {
245 // check that object is visible and it doesn't was selected previously
246 if (!GLObject->isVisible(s)) {
247 return false;
248 } else if (checkDuplicated && isObjectSelected(GLObject)) {
249 return false;
250 } else {
251 auto& layerContainer = mySortedSelectedObjects[layer * -1];
252 layerContainer.append(ObjectContainer(GLObject));
253 mySelectedObjects[GLObject] = segment;
255 return true;
256 }
257}
258
259
260bool
261GUIViewObjectsHandler::selectGeometryPoint(const GUIGlObject* GLObject, const int newIndex,
262 const double layer) {
263 // avoid to insert duplicated elements
264 for (auto& elementLayer : mySortedSelectedObjects) {
265 for (auto& element : elementLayer.second) {
266 if (element.object == GLObject) {
267 // avoid double points
268 for (auto& index : element.geometryPoints) {
269 if (index == newIndex) {
270 return false;
271 }
272 }
273 // add new index
274 element.geometryPoints.push_back(newIndex);
275 return true;
276 }
277 }
278 }
279 // no element found then add it
280 auto& layerContainer = mySortedSelectedObjects[layer * -1];
281 layerContainer.append(ObjectContainer(GLObject));
282 layerContainer.back().geometryPoints.push_back(newIndex);
283 mySelectedObjects[GLObject] = nullptr;
285 return true;
286}
287
288
289bool
290GUIViewObjectsHandler::selectPositionOverShape(const GUIGlObject* GLObject, const Position& pos, const double layer,
291 const double offset) {
292 // avoid to insert duplicated elements
293 for (auto& elementLayer : mySortedSelectedObjects) {
294 for (auto& element : elementLayer.second) {
295 if (element.object == GLObject) {
296 if (element.posOverShape != Position::INVALID) {
297 return false;
298 } else {
299 // set position and offset over shape
300 element.posOverShape = pos;
301 element.offset = offset;
302 return true;
303 }
304 }
305 }
306 }
307 // no element found then add it
308 auto& layerContainer = mySortedSelectedObjects[layer * -1];
309 layerContainer.append(ObjectContainer(GLObject));
310 layerContainer.back().posOverShape = pos;
311 mySelectedObjects[GLObject] = nullptr;
313 return true;
314}
315
316
317bool
319 return mySelectedObjects.find(GLObject) != mySelectedObjects.end();
320}
321
322
323bool
325 const double layer, const GUIGlObject* parent) {
327 return false;
328 } else {
329 return checkBoundaryParentObject(s, GLObject, layer, parent);
330 }
331}
332
333
338
339
340const GNESegment*
342 auto finder = mySelectedObjects.find(GLObject);
343 if (finder != mySelectedObjects.end()) {
344 return finder->second;
345 } else {
346 return nullptr;
347 }
348}
349
350
351const std::vector<int>&
353 // avoid to insert duplicated elements
354 for (auto& elementLayer : mySortedSelectedObjects) {
355 for (auto& element : elementLayer.second) {
356 if (element.object == GLObject) {
357 return element.geometryPoints;
358 }
359 }
360 }
362}
363
364
365const Position&
367 // avoid to insert duplicated elements
368 for (auto& elementLayer : mySortedSelectedObjects) {
369 for (auto& element : elementLayer.second) {
370 if (element.object == GLObject) {
371 return element.posOverShape;
372 }
373 }
374 }
375 return Position::INVALID;
376}
377
378
379int
383
384
385void
387 for (auto& layerContainer : mySortedSelectedObjects) {
388 std::reverse(layerContainer.second.begin(), layerContainer.second.end());
389 }
390}
391
392
393const std::set<const GNEPathElement*>&
397
398
399bool
401 if (myRedrawPathElements.empty()) {
402 return false;
403 } else {
404 return myRedrawPathElements.find(pathElement) != myRedrawPathElements.end();
405 }
406}
407
408
409void
413
414
415const std::vector<const GNEJunction*>&
419
420
421bool
423 // avoid insert duplicated junctions
424 for (const auto mergingJunctions : myMergingJunctions) {
425 if (mergingJunctions == junction) {
426 return false;
427 }
428 }
429 myMergingJunctions.push_back(junction);
430 return true;
431}
432
433
434void
436 ObjectContainer frontElement(nullptr);
437 // extract element
438 for (auto& elementLayer : mySortedSelectedObjects) {
439 auto it = elementLayer.second.begin();
440 while (it != elementLayer.second.end()) {
441 if (it->object == GLObject) {
442 // copy element to front element
443 frontElement.object = it->object;
444 frontElement.geometryPoints = it->geometryPoints;
445 // remove element from myElementsUnderCursor
446 it = elementLayer.second.erase(it);
447 } else {
448 it++;
449 }
450 }
451 }
452 // add element again wit a new layer
453 if (frontElement.object) {
454 mySortedSelectedObjects[(double)GLO_FRONTELEMENT].append(frontElement);
455 }
456}
457
458
459void
461 // declare object container for edge
462 ObjectContainer edgeWithGeometryPoints(nullptr);
463 // check if there are edges with geometry points in mySortedSelectedObjects
464 for (auto& elementLayer : mySortedSelectedObjects) {
465 for (auto element : elementLayer.second) {
466 if ((element.object->getType() == GLO_EDGE) && (element.geometryPoints.size() > 0)) {
467 edgeWithGeometryPoints = element;
468 }
469 }
470 }
471 // continue if something was found
472 if (edgeWithGeometryPoints.object != nullptr) {
473 // clear all selected objects
475 // add edge with geometry points as front element
476 mySortedSelectedObjects[(double)GLO_FRONTELEMENT].append(edgeWithGeometryPoints);
477 }
478}
479
480
481void
483 if (capacity() == size()) {
484 if (size() < 10) {
485 reserve(size() + 10);
486 } else {
487 reserve(size() + 1000);
488 }
489 }
490 push_back(objectContainer);
491}
492
493/****************************************************************************/
@ GLO_FRONTELEMENT
front element (used in netedit)
@ GLO_EDGE
an edge
@ GLO_NETWORK
The network - empty.
A class that stores a 2D geometrical boundary.
Definition Boundary.h:39
void add(double x, double y, double z=0)
Makes the boundary include the given coordinate.
Definition Boundary.cpp:75
bool isInitialised() const
check if Boundary is Initialised
Definition Boundary.cpp:256
virtual bool isVisible(const GUIVisualizationSettings &) const
check if object is visible (Currently used only in netedit)
Triangle mySelectionTriangle
selection triangle
void setSelectionPosition(const Position &pos)
set selection position
void addToRedrawPathElements(const GNEPathElement *pathElement)
add path element to redrawing set
bool selectObject(const GUIVisualizationSettings &s, const GUIGlObject *GLObject, const double layer, const bool checkDuplicated, const GNESegment *segment)
std::unordered_map< const GUIGlObject *, const GNESegment * > mySelectedObjects
map with selected elements and if was selected with full boundary (used only to avoid double selectio...
const GNERoute * markedRoute
marked route (used in create vehicle mode)
bool selectGeometryPoint(const GUIGlObject *GLObject, const int newIndex, const double layer)
add geometryPoint into list of elements under cursor
int getNumberOfSelectedObjects() const
get number of selected objects
std::vector< const GNEJunction * > myMergingJunctions
merging junctions
const Position & getSelectionPosition() const
const Triangle & getSelectionTriangle() const
get selection triangle
void reverseSelectedObjects()
reverse selected objects
void isolateEdgeGeometryPoints()
isolate edge geometry points (used for moving)
void reset()
reset view objects handler
const GUIGlObject * markedTAZ
marked TAZ (used in create TAZRel mode)
const Position & getSelectedPositionOverShape(const GUIGlObject *GLObject) const
get position over shape
bool checkCircleObject(const GUIVisualizationSettings &s, const GUIVisualizationSettings::Detail d, const GUIGlObject *GLObject, const Position &center, const double radius, const double layer)
check if mouse is within elements geometry (for circles)
bool addMergingJunctions(const GNEJunction *junction)
add to merging junctions (used for marking junctions to merge)
std::map< double, ObjectContainerLayer > GLObjectsSortedContainer
typedef for pack elements sorted by layer
void setSelectionTriangle(const Triangle &triangle)
set selection triangle
GUIGlObjectType recomputeBoundaries
recompute boundaries
const GLObjectsSortedContainer & getSelectedObjects() const
get all elements under cursor sorted by layer
const GNEEdge * markedEdge
marked edge (used in create edge mode, for splitting)
int myNumberOfSelectedObjects
number of selected objects
const GNELane * markedLane
marked lane (used in create edge mode, for splitting)
bool checkBoundaryParentObject(const GUIVisualizationSettings &s, const GUIGlObject *GLObject, const double layer, const GUIGlObject *parent)
bool checkShapeObject(const GUIVisualizationSettings &s, const GUIGlObject *GLObject, const PositionVector &shape, const Boundary &shapeBoundary, const double layer, const GNESegment *segment)
check (closed) shape element
bool checkGeometryPoint(const GUIVisualizationSettings &s, const GUIVisualizationSettings::Detail d, const GUIGlObject *GLObject, const PositionVector &shape, const int index, const double layer, const double radius)
check if mouse is within geometry point
Position mySelectionPosition
position
bool isPathElementMarkForRedraw(const GNEPathElement *pathElement) const
check if the given path element has to be redraw again
const GUIGlObject * markedSecondGeometryPoint
marked first geometry point (used for moving/delete geometry points)
bool isObjectSelected(const GUIGlObject *GLObject) const
check if element was already selected
const std::vector< int > & getSelectedGeometryPoints(const GUIGlObject *GLObject) const
get geometry points for the given glObject
void updateFrontObject(const GUIGlObject *GLObject)
move the given object to the front (currently used only in netedit)
bool checkPositionOverShape(const GUIVisualizationSettings::Detail d, const GUIGlObject *GLObject, const PositionVector &shape, const double layer, const double distance)
check if mouse is within geometry point
std::set< const GNEPathElement * > myRedrawPathElements
set with path elements marked for redrawing
const GNESegment * getSelectedSegment(const GUIGlObject *GLObject) const
get segment associated with the given GLObject (if exist)
GLObjectsSortedContainer mySortedSelectedObjects
selected element sorted by layer
bool selectingUsingRectangle() const
return true if we're selecting using a triangle
std::vector< int > myEmptyGeometryPoints
empty geometry points
bool checkRectangleSelection(const GUIVisualizationSettings &s, const GUIGlObject *GLObject, const double layer, const GUIGlObject *parent)
check rectangle selection
const GUIGlObject * markedFirstGeometryPoint
marked first geometry point (used for moving/delete geometry points)
const std::set< const GNEPathElement * > & getRedrawPathElements() const
bool selectPositionOverShape(const GUIGlObject *GLObject, const Position &pos, const double layer, const double offset)
select position over shape (for example, the position over a lane shape)
const std::vector< const GNEJunction * > & getMergingJunctions() const
Stores the information about how to visualize structures.
bool drawForRectangleSelection
whether drawing is performed for the purpose of selecting objects using a rectangle
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:278
static const Position INVALID
used to indicate that a position is valid
Definition Position.h:323
A list of positions.
double nearest_offset_to_point2D(const Position &p, bool perpendicular=true) const
return the nearest offest to point 2D
Position positionAtOffset2D(double pos, double lateralOffset=0, bool extrapolateBeyond=false) const
Returns the position at the given length.
bool around(const Position &p, double offset=0) const
Returns the information whether the position vector describes a polygon lying around the given point.
A simple triangle defined in 3D.
Definition Triangle.h:35
bool isPositionWithin(const Position &pos) const
check if the given position is within this triangle
Definition Triangle.cpp:54
static const Triangle INVALID
invalid triangle
Definition Triangle.h:39
bool intersectWithShape(const PositionVector &shape) const
check if the given shape is within or intersect with this triangle
Definition Triangle.cpp:69
bool intersectWithCircle(const Position &center, const double radius) const
check if the given circle intersect with this triangle
Definition Triangle.cpp:117
std::vector< int > geometryPoints
vector with geometry points
void append(const ObjectContainer &objectContainer)