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 % 166 1
Test Date: 2024-12-21 15:45:41 Functions: 3.6 % 28 1

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

Generated by: LCOV version 2.0-1