Path: blob/main/src/netedit/elements/additional/GNEEntryExitDetector.cpp
169684 views
/****************************************************************************/1// Eclipse SUMO, Simulation of Urban MObility; see https://eclipse.dev/sumo2// Copyright (C) 2001-2025 German Aerospace Center (DLR) and others.3// This program and the accompanying materials are made available under the4// terms of the Eclipse Public License 2.0 which is available at5// https://www.eclipse.org/legal/epl-2.0/6// This Source Code may also be made available under the following Secondary7// Licenses when the conditions for such availability set forth in the Eclipse8// Public License 2.0 are satisfied: GNU General Public License, version 29// or later which is available at10// https://www.gnu.org/licenses/old-licenses/gpl-2.0-standalone.html11// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later12/****************************************************************************/13/// @file GNEEntryExitDetector.cpp14/// @author Pablo Alvarez Lopez15/// @date Nov 201516///17//18/****************************************************************************/19#include <config.h>2021#include <netedit/GNENet.h>22#include <netedit/GNETagProperties.h>23#include <netedit/GNEUndoList.h>24#include <netedit/GNEViewNet.h>25#include <netedit/GNEViewParent.h>26#include <netedit/changes/GNEChange_Attribute.h>27#include <netedit/frames/network/GNETLSEditorFrame.h>28#include <utils/gui/div/GLHelper.h>29#include <utils/gui/globjects/GLIncludes.h>30#include <utils/gui/div/GUIGlobalViewObjectsHandler.h>3132#include "GNEEntryExitDetector.h"33#include "GNEAdditionalHandler.h"3435// ===========================================================================36// member method definitions37// ===========================================================================3839GNEEntryExitDetector::GNEEntryExitDetector(SumoXMLTag entryExitTag, GNENet* net) :40GNEDetector(net, entryExitTag) {41}424344GNEEntryExitDetector::GNEEntryExitDetector(SumoXMLTag entryExitTag, GNEAdditional* parent, GNELane* lane, const double pos,45const bool friendlyPos, const Parameterised::Map& parameters) :46GNEDetector(parent, entryExitTag, pos, 0, lane, "", "", friendlyPos, parameters) {47// update centering boundary without updating grid48updateCenteringBoundary(false);49}505152GNEEntryExitDetector::~GNEEntryExitDetector() {}535455void56GNEEntryExitDetector::writeAdditional(OutputDevice& device) const {57device.openTag(getTagProperty()->getTag());58device.writeAttr(SUMO_ATTR_LANE, getParentLanes().front()->getID());59device.writeAttr(SUMO_ATTR_POSITION, myPositionOverLane);60// write common detector parameters61writeDetectorValues(device);62// write parameters63writeParams(device);64device.closeTag();65}666768bool69GNEEntryExitDetector::isAdditionalValid() const {70// with friendly position enabled position are "always fixed"71if (myFriendlyPosition) {72return true;73} else {74return fabs(myPositionOverLane) <= getParentLanes().front()->getParentEdge()->getNBEdge()->getFinalLength();75}76}777879std::string80GNEEntryExitDetector::getAdditionalProblem() const {81// obtain final length82const double len = getParentLanes().front()->getParentEdge()->getNBEdge()->getFinalLength();83// check if detector has a problem84if (GNEAdditionalHandler::checkLanePosition(myPositionOverLane, 0, len, myFriendlyPosition)) {85return "";86} else {87// declare variable for error position88std::string errorPosition;89// check positions over lane90if (myPositionOverLane < 0) {91errorPosition = (toString(SUMO_ATTR_POSITION) + " < 0");92}93if (myPositionOverLane > len) {94errorPosition = (toString(SUMO_ATTR_POSITION) + TL(" > lanes's length"));95}96return errorPosition;97}98}99100101void102GNEEntryExitDetector::fixAdditionalProblem() {103// declare new position104double newPositionOverLane = myPositionOverLane;105// fix pos and length checkAndFixDetectorPosition106double length = 0;107GNEAdditionalHandler::fixLanePosition(newPositionOverLane, length, getParentLanes().front()->getParentEdge()->getNBEdge()->getFinalLength());108// set new position109setAttribute(SUMO_ATTR_POSITION, toString(newPositionOverLane), myNet->getViewNet()->getUndoList());110}111112113void114GNEEntryExitDetector::updateGeometry() {115// update geometry116myAdditionalGeometry.updateGeometry(getParentLanes().front()->getLaneShape(), getGeometryPositionOverLane(), myMoveElementLateralOffset);117// update centering boundary without updating grid118updateCenteringBoundary(false);119}120121122void123GNEEntryExitDetector::drawGL(const GUIVisualizationSettings& s) const {124// first check if additional has to be drawn125if (myNet->getViewNet()->getDataViewOptions().showAdditionals() &&126!myNet->getViewNet()->selectingDetectorsTLSMode()) {127// Set initial values128const double entryExitExaggeration = getExaggeration(s);129// get detail level130const auto d = s.getDetailLevel(entryExitExaggeration);131// draw geometry only if we'rent in drawForObjectUnderCursor mode132if (s.checkDrawAdditional(d, isAttributeCarrierSelected())) {133// draw parent and child lines134drawParentChildLines(s, s.additionalSettings.connectionColor);135// Push layer matrix136GLHelper::pushMatrix();137// translate to front138drawInLayer(GLO_DET_ENTRY);139// Set color140RGBColor color;141if (drawUsingSelectColor()) {142color = s.colorSettings.selectedAdditionalColor;143} else if (myTagProperty->getTag() == SUMO_TAG_DET_ENTRY) {144color = s.detectorSettings.E3EntryColor;145} else if (myTagProperty->getTag() == SUMO_TAG_DET_EXIT) {146color = s.detectorSettings.E3ExitColor;147}148// draw parts149drawBody(d, color, entryExitExaggeration);150drawEntryLogo(d, color, entryExitExaggeration);151drawE3Logo(d, color, entryExitExaggeration);152// pop layer matrix153GLHelper::popMatrix();154// draw additional name155drawAdditionalName(s);156// draw lock icon157GNEViewNetHelper::LockIcon::drawLockIcon(d, this, getType(), myAdditionalGeometry.getShape().getCentroid(),158entryExitExaggeration);159// draw dotted contour160myAdditionalContour.drawDottedContours(s, d, this, s.dottedContourSettings.segmentWidth, true);161}162// calculate contour163myAdditionalContour.calculateContourRectangleShape(s, d, this, myAdditionalGeometry.getShape().front(), 2.7, 1.6,164getType(), 2, 0, myAdditionalGeometry.getShapeRotations().front(), entryExitExaggeration,165getParentLanes().front()->getParentEdge());166}167}168169170std::string171GNEEntryExitDetector::getAttribute(SumoXMLAttr key) const {172switch (key) {173case GNE_ATTR_PARENT:174return getParentAdditionals().at(0)->getID();175default:176return getDetectorAttribute(key);177}178}179180181double182GNEEntryExitDetector::getAttributeDouble(SumoXMLAttr key) const {183switch (key) {184case SUMO_ATTR_POSITION:185return myPositionOverLane;186default:187throw InvalidArgument(getTagStr() + " doesn't have an attribute of type '" + toString(key) + "'");188}189}190191192void193GNEEntryExitDetector::setAttribute(SumoXMLAttr key, const std::string& value, GNEUndoList* undoList) {194switch (key) {195case GNE_ATTR_PARENT:196GNEChange_Attribute::changeAttribute(this, key, value, undoList);197break;198default:199setDetectorAttribute(key, value, undoList);200break;201}202}203204205bool206GNEEntryExitDetector::isValid(SumoXMLAttr key, const std::string& value) {207switch (key) {208case GNE_ATTR_PARENT:209return (myNet->getAttributeCarriers()->retrieveAdditional(SUMO_TAG_ENTRY_EXIT_DETECTOR, value, false) != nullptr);210default:211return isDetectorValid(key, value);212}213}214215216void217GNEEntryExitDetector::drawBody(const GUIVisualizationSettings::Detail d,218const RGBColor& color, const double exaggeration) const {219// check detail level220if (d <= GUIVisualizationSettings::Detail::Additionals) {221// Push polygon matrix222GLHelper::pushMatrix();223// set color224GLHelper::setColor(color);225// set polygon mode226glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);227// move to position228glTranslated(myAdditionalGeometry.getShape().front().x(), myAdditionalGeometry.getShape().front().y(), 0);229// rotate over lane230GUIGeometry::rotateOverLane(myAdditionalGeometry.getShapeRotations().front() + 90);231// scale232glScaled(exaggeration, exaggeration, 1);233// check detail level234if (d <= GUIVisualizationSettings::Detail::AdditionalDetails) {235// Draw polygon236glBegin(GL_LINES);237glVertex2d(1.7, 0);238glVertex2d(-1.7, 0);239glEnd();240glBegin(GL_QUADS);241glVertex2d(-1.7, .5);242glVertex2d(-1.7, -.5);243glVertex2d(1.7, -.5);244glVertex2d(1.7, .5);245glEnd();246// first Arrow247glTranslated(1.5, 0, 0);248GLHelper::drawBoxLine(Position(0, 4), 0, 2, .05);249GLHelper::drawTriangleAtEnd(Position(0, 4), Position(0, 1), (double) 1, (double) .25);250// second Arrow251glTranslated(-3, 0, 0);252GLHelper::drawBoxLine(Position(0, 4), 0, 2, .05);253GLHelper::drawTriangleAtEnd(Position(0, 4), Position(0, 1), (double) 1, (double) .25);254} else {255// Draw square in drawy for selecting mode256glBegin(GL_QUADS);257glVertex2d(-1.7, 4.3);258glVertex2d(-1.7, -.5);259glVertex2d(1.7, -.5);260glVertex2d(1.7, 4.3);261glEnd();262}263// Pop polygon matrix264GLHelper::popMatrix();265}266}267268269void270GNEEntryExitDetector::drawEntryLogo(const GUIVisualizationSettings::Detail d,271const RGBColor& color, const double exaggeration) const {272// check detail level273if (d <= GUIVisualizationSettings::Detail::AdditionalDetails) {274// Push matrix275GLHelper::pushMatrix();276// set color277GLHelper::setColor(color);278// Traslate to center of detector279glTranslated(myAdditionalGeometry.getShape().front().x(), myAdditionalGeometry.getShape().front().y(), getType() + 0.1);280// rotate over lane281GUIGeometry::rotateOverLane(myAdditionalGeometry.getShapeRotations().front());282//move to logo position283glTranslated(1.9, 0, 0);284// scale285glScaled(exaggeration, exaggeration, 1);286//move to logo position287glTranslated(1.7, 0, 0);288// rotate 90 degrees lane289glRotated(90, 0, 0, 1);290// draw Entry or Exit text if isn't being drawn for selecting291if (d <= GUIVisualizationSettings::Detail::Text) {292if (myTagProperty->getTag() == SUMO_TAG_DET_ENTRY) {293GLHelper::drawText("Entry", Position(), .1, 1, color, 180);294} else if (myTagProperty->getTag() == SUMO_TAG_DET_EXIT) {295GLHelper::drawText("Exit", Position(), .1, 1, color, 180);296}297} else {298GLHelper::drawBoxLine(Position(0, 1), 0, 2, 1);299}300// pop matrix301GLHelper::popMatrix();302}303}304305306void307GNEEntryExitDetector::drawE3Logo(const GUIVisualizationSettings::Detail d,308const RGBColor& color, const double exaggeration) const {309// check detail level310if (d <= GUIVisualizationSettings::Detail::Text) {311// Push matrix312GLHelper::pushMatrix();313// set color314GLHelper::setColor(color);315// Traslate to center of detector316glTranslated(myAdditionalGeometry.getShape().front().x(), myAdditionalGeometry.getShape().front().y(), getType() + 0.1);317// rotate over lane318GUIGeometry::rotateOverLane(myAdditionalGeometry.getShapeRotations().front());319//move to logo position320glTranslated(1.9, 0, 0);321// scale322glScaled(exaggeration, exaggeration, 1);323// draw E3 logo324GLHelper::drawText("E3", Position(0, 0), .1, 2.8, color);325// pop matrix326GLHelper::popMatrix();327}328}329330331void332GNEEntryExitDetector::setAttribute(SumoXMLAttr key, const std::string& value) {333switch (key) {334case GNE_ATTR_PARENT:335replaceAdditionalParent(SUMO_TAG_ENTRY_EXIT_DETECTOR, value, 0);336break;337default:338setDetectorAttribute(key, value);339break;340}341}342343344void345GNEEntryExitDetector::setMoveShape(const GNEMoveResult& moveResult) {346// change position347myPositionOverLane = moveResult.newFirstPos;348// set lateral offset349myMoveElementLateralOffset = moveResult.firstLaneOffset;350// update geometry351updateGeometry();352}353354355void356GNEEntryExitDetector::commitMoveShape(const GNEMoveResult& moveResult, GNEUndoList* undoList) {357// reset lateral offset358myMoveElementLateralOffset = 0;359// begin change attribute360undoList->begin(this, "position of " + getTagStr());361// set startPosition362setAttribute(SUMO_ATTR_POSITION, toString(moveResult.newFirstPos), undoList);363// check if lane has to be changed364if (moveResult.newFirstLane) {365// set new lane366setAttribute(SUMO_ATTR_LANE, moveResult.newFirstLane->getID(), undoList);367}368// end change attribute369undoList->end();370}371372/****************************************************************************/373374375