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

Generated by: LCOV version 2.0-1