LCOV - code coverage report
Current view: top level - src/utils/gui/div - GUIViewObjectsHandler.cpp (source / functions) Coverage Total Hit
Test: lcov.info Lines: 0.6 % 163 1
Test Date: 2025-12-06 15:35:27 Functions: 3.2 % 31 1

            Line data    Source code
       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    GUIViewObjectsHandler.cpp
      15              : /// @author  Pablo Alvarez Lopez
      16              : /// @date    Jun 22
      17              : ///
      18              : // class used for handle objects over view
      19              : /****************************************************************************/
      20              : #include <config.h>
      21              : #include <algorithm>
      22              : 
      23              : #include <utils/shapes/Shape.h>
      24              : 
      25              : #include "GUIViewObjectsHandler.h"
      26              : 
      27              : 
      28              : // ===========================================================================
      29              : // method definitions
      30              : // ===========================================================================
      31              : 
      32         8612 : GUIViewObjectsHandler::GUIViewObjectsHandler() {}
      33              : 
      34              : 
      35              : void
      36            0 : GUIViewObjectsHandler::reset() {
      37              :     // reset recompute boundaries
      38            0 :     recomputeBoundaries = GLO_NETWORK;
      39              :     // clear objects containers
      40              :     mySortedSelectedObjects.clear();
      41              :     mySelectedObjects.clear();
      42            0 :     myNumberOfSelectedObjects = 0;
      43              :     myRedrawPathElements.clear();
      44              :     // reset marked elements
      45              :     myMergingJunctions.clear();
      46            0 :     markedEdge = nullptr;
      47            0 :     markedLane = nullptr;
      48            0 :     markedTAZ = nullptr;
      49            0 :     markedRoute = nullptr;
      50            0 :     markedFirstGeometryPoint = nullptr;
      51            0 :     markedSecondGeometryPoint = nullptr;
      52            0 : }
      53              : 
      54              : 
      55              : const Position&
      56            0 : GUIViewObjectsHandler::getSelectionPosition() const {
      57            0 :     return mySelectionPosition;
      58              : }
      59              : 
      60              : 
      61              : const Triangle&
      62            0 : GUIViewObjectsHandler::getSelectionTriangle() const {
      63            0 :     return mySelectionTriangle;
      64              : }
      65              : 
      66              : 
      67              : void
      68            0 : GUIViewObjectsHandler::setSelectionPosition(const Position& pos) {
      69              :     // set position selection
      70            0 :     mySelectionPosition = pos;
      71              :     // invalidate selection triangle
      72              :     mySelectionTriangle = Triangle::INVALID;
      73            0 : }
      74              : 
      75              : 
      76              : void
      77            0 : GUIViewObjectsHandler::setSelectionTriangle(const Triangle& triangle) {
      78              :     // invalidate position selection
      79            0 :     mySelectionPosition = Position::INVALID;
      80              :     // set selection triangle
      81              :     mySelectionTriangle = triangle;
      82            0 : }
      83              : 
      84              : 
      85              : bool
      86            0 : GUIViewObjectsHandler::selectingUsingRectangle() const {
      87            0 :     return mySelectionTriangle != Triangle::INVALID;
      88              : }
      89              : 
      90              : 
      91              : bool
      92            0 : GUIViewObjectsHandler::checkBoundaryParentObject(const GUIGlObject* GLObject, const double layer,
      93              :         const GUIGlObject* parent) {
      94              :     // first check if we're selecting for boundary
      95            0 :     if (mySelectionTriangle == Triangle::INVALID) {
      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            0 :     if (finder != mySelectedObjects.end() && finder->second && !isObjectSelected(GLObject)) {
     102              :         // insert element with full boundary
     103            0 :         return selectObject(GLObject, layer, false, nullptr);
     104              :     } else {
     105            0 :         return false;
     106              :     }
     107              : }
     108              : 
     109              : 
     110              : bool
     111            0 : GUIViewObjectsHandler::checkCircleObject(const GUIVisualizationSettings::Detail d, const GUIGlObject* GLObject,
     112              :         const Position& center, const double radius, const double layer) {
     113              :     // first check that object doesn't exist
     114            0 :     if (isObjectSelected(GLObject)) {
     115              :         return false;
     116              :     } else {
     117              :         // declare squared radius
     118            0 :         const double squaredRadius = (radius * radius);
     119              :         // continue depending if we're selecting a position or a boundary
     120            0 :         if (selectingUsingRectangle()) {
     121              :             // continue depending of detail level
     122            0 :             if (d <= GUIVisualizationSettings::Detail::PreciseSelection) {
     123              :                 // check if triangle intersect with circle
     124            0 :                 if (mySelectionTriangle.intersectWithCircle(center, radius)) {
     125            0 :                     return selectObject(GLObject, layer, false, nullptr);
     126              :                 } else {
     127              :                     return false;
     128              :                 }
     129              :             } else {
     130              :                 // simply check if center is within triangle
     131            0 :                 if (mySelectionTriangle.isPositionWithin(center)) {
     132            0 :                     return selectObject(GLObject, layer, false, nullptr);
     133              :                 } else {
     134              :                     return false;
     135              :                 }
     136              :             }
     137              :         } else if (mySelectionPosition != Position::INVALID) {
     138              :             // check distance between selection position and center
     139            0 :             if (mySelectionPosition.distanceSquaredTo2D(center) <= squaredRadius) {
     140            0 :                 return selectObject(GLObject, layer, false, nullptr);
     141              :             } else {
     142              :                 return false;
     143              :             }
     144              :         } else {
     145              :             return false;
     146              :         }
     147              :     }
     148              : }
     149              : 
     150              : 
     151              : bool
     152            0 : GUIViewObjectsHandler::checkGeometryPoint(const GUIVisualizationSettings::Detail d, const GUIGlObject* GLObject,
     153              :         const PositionVector& shape, const int index, const double layer, const double radius) {
     154              :     // obtain geometry point pos
     155            0 :     const auto geometryPointPos = shape[index];
     156              :     // declare squared radius
     157            0 :     const double squaredRadius = (radius * radius);
     158              :     // continue depending if we're selecting a position or a boundary
     159            0 :     if (selectingUsingRectangle()) {
     160              :         // continue depending of detail level
     161            0 :         if (d <= GUIVisualizationSettings::Detail::PreciseSelection) {
     162              :             // calculate boundary for geometry point
     163            0 :             Boundary geometryPointBoundary;
     164            0 :             geometryPointBoundary.add(geometryPointPos);
     165              :             // check if center is within mySelectionBoundary
     166            0 :             if (mySelectionTriangle.intersectWithCircle(geometryPointPos, radius)) {
     167            0 :                 return selectGeometryPoint(GLObject, index, layer);
     168              :             } else {
     169              :                 return false;
     170              :             }
     171              :         } else {
     172              :             // simply check if center is within triangle
     173            0 :             if (mySelectionTriangle.isPositionWithin(geometryPointPos)) {
     174            0 :                 return selectObject(GLObject, layer, false, nullptr);
     175              :             } else {
     176              :                 return false;
     177              :             }
     178              :         }
     179              :     } else if (mySelectionPosition != Position::INVALID) {
     180              :         // check distance between selection position and center
     181            0 :         if (mySelectionPosition.distanceSquaredTo2D(geometryPointPos) <= squaredRadius) {
     182            0 :             return selectGeometryPoint(GLObject, index, layer);
     183              :         } else {
     184              :             return false;
     185              :         }
     186              :     } else {
     187              :         return false;
     188              :     }
     189              : }
     190              : 
     191              : 
     192              : bool
     193            0 : GUIViewObjectsHandler::checkPositionOverShape(const GUIVisualizationSettings::Detail d, const GUIGlObject* GLObject,
     194              :         const PositionVector& shape, const double layer, const double distance) {
     195              :     // only process if we're selecting a precise position
     196            0 :     if ((mySelectionPosition != Position::INVALID) && (d <= GUIVisualizationSettings::Detail::PreciseSelection)) {
     197              :         // obtain nearest position over shape
     198            0 :         const auto nearestOffset = shape.nearest_offset_to_point2D(mySelectionPosition);
     199            0 :         const auto nearestPos = shape.positionAtOffset2D(nearestOffset);
     200              :         // check distance nearest position and pos
     201            0 :         if (mySelectionPosition.distanceSquaredTo2D(nearestPos) <= (distance * distance)) {
     202            0 :             return selectPositionOverShape(GLObject, nearestPos, layer, nearestOffset);
     203              :         } else {
     204              :             return false;
     205              :         }
     206              :     } else {
     207              :         return false;
     208              :     }
     209              : }
     210              : 
     211              : 
     212              : bool
     213            0 : GUIViewObjectsHandler::checkShapeObject(const GUIGlObject* GLObject, const PositionVector& shape, const Boundary& shapeBoundary,
     214              :                                         const double layer, const GNESegment* segment) {
     215              :     // first check that object doesn't exist
     216            0 :     if (isObjectSelected(GLObject)) {
     217              :         return false;
     218            0 :     } else if (selectingUsingRectangle()) {
     219              :         // avoid invalid boundaries
     220            0 :         if (!shapeBoundary.isInitialised()) {
     221              :             return false;
     222              :         }
     223              :         // check if triangle contains the given shape
     224            0 :         if (mySelectionTriangle.intersectWithShape(shape, shapeBoundary)) {
     225            0 :             return selectObject(GLObject, layer, false, segment);
     226              :         }
     227              :         // no intersection, then return false
     228              :         return false;
     229              :     } else if (mySelectionPosition != Position::INVALID) {
     230              :         // check if selection position is around shape
     231            0 :         if (shape.around(mySelectionPosition)) {
     232            0 :             return selectObject(GLObject, layer, false, segment);
     233              :         } else {
     234              :             return false;
     235              :         }
     236              :     } else {
     237              :         return false;
     238              :     }
     239              : }
     240              : 
     241              : 
     242              : bool
     243            0 : GUIViewObjectsHandler::selectObject(const GUIGlObject* GLObject, const double layer, const bool checkDuplicated,
     244              :                                     const GNESegment* segment) {
     245              :     // first check that object doesn't exist
     246            0 :     if (checkDuplicated && isObjectSelected(GLObject)) {
     247              :         return false;
     248              :     } else {
     249            0 :         auto& layerContainer = mySortedSelectedObjects[layer * -1];
     250            0 :         layerContainer.append(ObjectContainer(GLObject));
     251            0 :         mySelectedObjects[GLObject] = segment;
     252            0 :         myNumberOfSelectedObjects++;
     253            0 :         return true;
     254              :     }
     255              : }
     256              : 
     257              : 
     258              : bool
     259            0 : GUIViewObjectsHandler::selectGeometryPoint(const GUIGlObject* GLObject, const int newIndex,
     260              :         const double layer) {
     261              :     // avoid to insert duplicated elements
     262            0 :     for (auto& elementLayer : mySortedSelectedObjects) {
     263            0 :         for (auto& element : elementLayer.second) {
     264            0 :             if (element.object == GLObject) {
     265              :                 // avoid double points
     266            0 :                 for (auto& index : element.geometryPoints) {
     267            0 :                     if (index == newIndex) {
     268              :                         return false;
     269              :                     }
     270              :                 }
     271              :                 // add new index
     272            0 :                 element.geometryPoints.push_back(newIndex);
     273            0 :                 return true;
     274              :             }
     275              :         }
     276              :     }
     277              :     // no element found then add it
     278            0 :     auto& layerContainer = mySortedSelectedObjects[layer * -1];
     279            0 :     layerContainer.append(ObjectContainer(GLObject));
     280            0 :     layerContainer.back().geometryPoints.push_back(newIndex);
     281            0 :     mySelectedObjects[GLObject] = nullptr;
     282            0 :     myNumberOfSelectedObjects++;
     283            0 :     return true;
     284              : }
     285              : 
     286              : 
     287              : bool
     288            0 : GUIViewObjectsHandler::selectPositionOverShape(const GUIGlObject* GLObject, const Position& pos, const double layer,
     289              :         const double offset) {
     290              :     // avoid to insert duplicated elements
     291            0 :     for (auto& elementLayer : mySortedSelectedObjects) {
     292            0 :         for (auto& element : elementLayer.second) {
     293            0 :             if (element.object == GLObject) {
     294              :                 if (element.posOverShape != Position::INVALID) {
     295              :                     return false;
     296              :                 } else {
     297              :                     // set position and offset over shape
     298            0 :                     element.posOverShape = pos;
     299            0 :                     element.offset = offset;
     300            0 :                     return true;
     301              :                 }
     302              :             }
     303              :         }
     304              :     }
     305              :     // no element found then add it
     306            0 :     auto& layerContainer = mySortedSelectedObjects[layer * -1];
     307            0 :     layerContainer.append(ObjectContainer(GLObject));
     308            0 :     layerContainer.back().posOverShape = pos;
     309            0 :     mySelectedObjects[GLObject] = nullptr;
     310            0 :     myNumberOfSelectedObjects++;
     311            0 :     return true;
     312              : }
     313              : 
     314              : 
     315              : bool
     316            0 : GUIViewObjectsHandler::isObjectSelected(const GUIGlObject* GLObject) const {
     317            0 :     return mySelectedObjects.find(GLObject) != mySelectedObjects.end();
     318              : }
     319              : 
     320              : 
     321              : bool
     322            0 : GUIViewObjectsHandler::checkRectangleSelection(const GUIVisualizationSettings& s, const GUIGlObject* GLObject,
     323              :         const double layer, const GUIGlObject* parent) {
     324            0 :     if (!s.drawForRectangleSelection) {
     325              :         return false;
     326              :     } else {
     327            0 :         return checkBoundaryParentObject(GLObject, layer, parent);
     328              :     }
     329              : }
     330              : 
     331              : 
     332              : const GUIViewObjectsHandler::GLObjectsSortedContainer&
     333            0 : GUIViewObjectsHandler::getSelectedObjects() const {
     334            0 :     return mySortedSelectedObjects;
     335              : }
     336              : 
     337              : 
     338              : const GNESegment*
     339            0 : GUIViewObjectsHandler::getSelectedSegment(const GUIGlObject* GLObject) const {
     340              :     auto finder = mySelectedObjects.find(GLObject);
     341            0 :     if (finder != mySelectedObjects.end()) {
     342            0 :         return finder->second;
     343              :     } else {
     344              :         return nullptr;
     345              :     }
     346              : }
     347              : 
     348              : 
     349              : const std::vector<int>&
     350            0 : GUIViewObjectsHandler::getSelectedGeometryPoints(const GUIGlObject* GLObject) const {
     351              :     // avoid to insert duplicated elements
     352            0 :     for (auto& elementLayer : mySortedSelectedObjects) {
     353            0 :         for (auto& element : elementLayer.second) {
     354            0 :             if (element.object == GLObject) {
     355            0 :                 return element.geometryPoints;
     356              :             }
     357              :         }
     358              :     }
     359            0 :     return myEmptyGeometryPoints;
     360              : }
     361              : 
     362              : 
     363              : const Position&
     364            0 : GUIViewObjectsHandler::getSelectedPositionOverShape(const GUIGlObject* GLObject) const {
     365              :     // avoid to insert duplicated elements
     366            0 :     for (auto& elementLayer : mySortedSelectedObjects) {
     367            0 :         for (auto& element : elementLayer.second) {
     368            0 :             if (element.object == GLObject) {
     369            0 :                 return element.posOverShape;
     370              :             }
     371              :         }
     372              :     }
     373              :     return Position::INVALID;
     374              : }
     375              : 
     376              : 
     377              : int
     378            0 : GUIViewObjectsHandler::getNumberOfSelectedObjects() const {
     379            0 :     return myNumberOfSelectedObjects;
     380              : }
     381              : 
     382              : 
     383              : void
     384            0 : GUIViewObjectsHandler::reverseSelectedObjects() {
     385            0 :     for (auto& layerContainer : mySortedSelectedObjects) {
     386              :         std::reverse(layerContainer.second.begin(), layerContainer.second.end());
     387              :     }
     388            0 : }
     389              : 
     390              : 
     391              : const std::set<const GNEPathElement*>&
     392            0 : GUIViewObjectsHandler::getRedrawPathElements() const {
     393            0 :     return myRedrawPathElements;
     394              : }
     395              : 
     396              : 
     397              : bool
     398            0 : GUIViewObjectsHandler::isPathElementMarkForRedraw(const GNEPathElement* pathElement) const {
     399            0 :     if (myRedrawPathElements.empty()) {
     400              :         return false;
     401              :     } else {
     402              :         return myRedrawPathElements.find(pathElement) != myRedrawPathElements.end();
     403              :     }
     404              : }
     405              : 
     406              : 
     407              : void
     408            0 : GUIViewObjectsHandler::addToRedrawPathElements(const GNEPathElement* pathElement) {
     409              :     myRedrawPathElements.insert(pathElement);
     410            0 : }
     411              : 
     412              : 
     413              : const std::vector<const GNEJunction*>&
     414            0 : GUIViewObjectsHandler::getMergingJunctions() const {
     415            0 :     return myMergingJunctions;
     416              : }
     417              : 
     418              : 
     419              : bool
     420            0 : GUIViewObjectsHandler::addMergingJunctions(const GNEJunction* junction) {
     421              :     // avoid insert duplicated junctions
     422            0 :     for (const auto mergingJunctions : myMergingJunctions) {
     423            0 :         if (mergingJunctions == junction) {
     424              :             return false;
     425              :         }
     426              :     }
     427            0 :     myMergingJunctions.push_back(junction);
     428            0 :     return true;
     429              : }
     430              : 
     431              : 
     432              : void
     433            0 : GUIViewObjectsHandler::updateFrontObject(const GUIGlObject* GLObject) {
     434              :     ObjectContainer frontElement(nullptr);
     435              :     // extract element
     436            0 :     for (auto& elementLayer : mySortedSelectedObjects) {
     437              :         auto it = elementLayer.second.begin();
     438            0 :         while (it != elementLayer.second.end()) {
     439            0 :             if (it->object == GLObject) {
     440              :                 // copy element to front element
     441            0 :                 frontElement.object = it->object;
     442            0 :                 frontElement.geometryPoints = it->geometryPoints;
     443              :                 // remove element from myElementsUnderCursor
     444            0 :                 it = elementLayer.second.erase(it);
     445              :             } else {
     446              :                 it++;
     447              :             }
     448              :         }
     449              :     }
     450              :     // add element again wit a new layer
     451            0 :     if (frontElement.object) {
     452            0 :         mySortedSelectedObjects[(double)GLO_FRONTELEMENT].append(frontElement);
     453              :     }
     454            0 : }
     455              : 
     456              : 
     457              : void
     458            0 : GUIViewObjectsHandler::isolateEdgeGeometryPoints() {
     459              :     // declare object container for edge
     460              :     ObjectContainer edgeWithGeometryPoints(nullptr);
     461              :     // check if there are edges with geometry points in mySortedSelectedObjects
     462            0 :     for (auto& elementLayer : mySortedSelectedObjects) {
     463            0 :         for (auto element : elementLayer.second) {
     464            0 :             if ((element.object->getType() == GLO_EDGE) && (element.geometryPoints.size() > 0)) {
     465              :                 edgeWithGeometryPoints = element;
     466              :             }
     467              :         }
     468              :     }
     469              :     // continue if something was found
     470            0 :     if (edgeWithGeometryPoints.object != nullptr) {
     471              :         // clear all selected objects
     472              :         mySortedSelectedObjects.clear();
     473              :         // add edge with geometry points as front element
     474            0 :         mySortedSelectedObjects[(double)GLO_FRONTELEMENT].append(edgeWithGeometryPoints);
     475              :     }
     476            0 : }
     477              : 
     478              : 
     479              : void
     480            0 : GUIViewObjectsHandler::ObjectContainerLayer::append(const ObjectContainer& objectContainer) {
     481            0 :     if (capacity() == size()) {
     482            0 :         if (size() < 10) {
     483            0 :             reserve(size() + 10);
     484              :         } else {
     485            0 :             reserve(size() + 1000);
     486              :         }
     487              :     }
     488            0 :     push_back(objectContainer);
     489            0 : }
     490              : 
     491              : /****************************************************************************/
        

Generated by: LCOV version 2.0-1