Path: blob/main/src/netedit/elements/additional/GNEDetector.cpp
193699 views
/****************************************************************************/1// Eclipse SUMO, Simulation of Urban MObility; see https://eclipse.dev/sumo2// Copyright (C) 2001-2026 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 GNEDetector.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/GNESegment.h>24#include <netedit/changes/GNEChange_Attribute.h>25#include <utils/gui/div/GLHelper.h>2627#include "GNEDetector.h"2829// ===========================================================================30// member method definitions31// ===========================================================================3233GNEDetector::GNEDetector(GNENet* net, SumoXMLTag tag) :34GNEAdditional(net, tag) {35}363738GNEDetector::GNEDetector(const std::string& id, GNENet* net, FileBucket* fileBucket, SumoXMLTag tag,39const SUMOTime period, const std::string& outputFilename, const std::vector<std::string>& vehicleTypes,40const std::vector<std::string>& nextEdges, const std::string& detectPersons, const std::string& name,41const Parameterised::Map& parameters) :42GNEAdditional(id, net, tag, fileBucket, name),43Parameterised(parameters),44myPeriod(period),45myOutputFilename(outputFilename),46myVehicleTypes(vehicleTypes),47myNextEdges(nextEdges),48myDetectPersons(detectPersons) {49// update output filename50if (outputFilename.empty()) {51myOutputFilename = id + ".xml";52}53}545556GNEDetector::GNEDetector(GNEAdditional* additionalParent, SumoXMLTag tag, const SUMOTime period,57const std::string& outputFilename, const std::string& name,58const Parameterised::Map& parameters) :59GNEAdditional(additionalParent, tag, name),60Parameterised(parameters),61myPeriod(period),62myOutputFilename(outputFilename) {63// set parents64setParent<GNEAdditional*>(additionalParent);65}666768GNEDetector::~GNEDetector() {}697071Parameterised*72GNEDetector::getParameters() {73return this;74}757677const Parameterised*78GNEDetector::getParameters() const {79return this;80}818283bool84GNEDetector::checkDrawMoveContour() const {85// get edit modes86const auto& editModes = myNet->getViewNet()->getEditModes();87// check if we're in move mode88if (!myNet->getViewNet()->isCurrentlyMovingElements() && editModes.isCurrentSupermodeNetwork() &&89!myNet->getViewNet()->getEditNetworkElementShapes().getEditedNetworkElement() &&90(editModes.networkEditMode == NetworkEditMode::NETWORK_MOVE) && myNet->getViewNet()->checkOverLockedElement(this, mySelected)) {91// only move the first element92if (myNet->getViewNet()->getViewObjectsSelector().getGUIGlObjectFront() == this) {93// special case for multiple lane area detectors94if (myTagProperty->getTag() == GNE_TAG_MULTI_LANE_AREA_DETECTOR) {95auto segment = gViewObjectsHandler.getSelectedSegment(this);96if (segment && segment->getJunction()) {97return false;98} else if (segment && segment->getLane()) {99// ensure that is the first or the last lane100if (segment->getLaneIndex() == 0) {101return true;102} else if (segment->getLaneIndex() == ((int)getParentLanes().size() - 1)) {103return true;104}105} else {106// this is the start or end point107return true;108}109} else {110return true;111}112}113}114return false;115}116117118Position119GNEDetector::getPositionInView() const {120return myAdditionalGeometry.getShape().getPolygonCenter();121}122123124void125GNEDetector::updateCenteringBoundary(const bool /*updateGrid*/) {126// nothing to update127}128129130void131GNEDetector::splitEdgeGeometry(const double splitPosition, const GNENetworkElement* originalElement,132const GNENetworkElement* newElement, GNEUndoList* undoList) {133// only split geometry of E2 multilane detectors134if (myTagProperty->getTag() == GNE_TAG_MULTI_LANE_AREA_DETECTOR) {135// obtain new list of E2 lanes136std::string newE2Lanes = getNewListOfParents(originalElement, newElement);137// update E2 Lanes138if (newE2Lanes.size() > 0) {139setAttribute(SUMO_ATTR_LANES, newE2Lanes, undoList);140}141} else if (splitPosition < getAttributeDouble(SUMO_ATTR_POSITION)) {142// change lane143setAttribute(SUMO_ATTR_LANE, newElement->getID(), undoList);144// now adjust start position145setAttribute(SUMO_ATTR_POSITION, toString(getAttributeDouble(SUMO_ATTR_POSITION) - splitPosition), undoList);146}147}148149150std::string151GNEDetector::getParentName() const {152return getParentLanes().front()->getID();153}154155156PositionVector GNEDetector::getAttributePositionVector(SumoXMLAttr key) const {157return getCommonAttributePositionVector(key);158}159160161std::string162GNEDetector::getPopUpID() const {163return getTagStr() + ": " + getID();164}165166167std::string168GNEDetector::getHierarchyName() const {169return getTagStr();170}171172173std::string174GNEDetector::getDetectorAttribute(SumoXMLAttr key) const {175switch (key) {176case SUMO_ATTR_ID:177return getMicrosimID();178case SUMO_ATTR_PERIOD:179if (myPeriod == SUMOTime_MAX_PERIOD) {180return "";181} else {182return time2string(myPeriod);183}184case SUMO_ATTR_NAME:185return myAdditionalName;186case SUMO_ATTR_FILE:187return myOutputFilename;188case SUMO_ATTR_VTYPES:189return toString(myVehicleTypes);190case SUMO_ATTR_NEXT_EDGES:191return toString(myNextEdges);192case SUMO_ATTR_DETECT_PERSONS:193return toString(myDetectPersons);194case GNE_ATTR_SHIFTLANEINDEX:195return "";196default:197return getMoveElement()->getMovingAttribute(key);198}199}200201202double203GNEDetector::getDetectorAttributeDouble(SumoXMLAttr key) const {204return getMoveElement()->getMovingAttributeDouble(key);205}206207208Position209GNEDetector::getDetectorAttributePosition(SumoXMLAttr key) const {210return getMoveElement()->getMovingAttributePosition(key);211}212213214void215GNEDetector::setDetectorAttribute(SumoXMLAttr key, const std::string& value, GNEUndoList* undoList) {216switch (key) {217case SUMO_ATTR_ID:218case SUMO_ATTR_PERIOD:219case SUMO_ATTR_NAME:220case SUMO_ATTR_FILE:221case SUMO_ATTR_VTYPES:222case SUMO_ATTR_NEXT_EDGES:223case SUMO_ATTR_DETECT_PERSONS:224case GNE_ATTR_SHIFTLANEINDEX:225GNEChange_Attribute::changeAttribute(this, key, value, undoList);226break;227default:228getMoveElement()->setMovingAttribute(key, value, undoList);229break;230}231}232233234235bool236GNEDetector::isDetectorValid(SumoXMLAttr key, const std::string& value) {237switch (key) {238case SUMO_ATTR_ID:239return isValidDetectorID(value);240case SUMO_ATTR_PERIOD:241if (value.empty()) {242return true;243} else {244return (canParse<double>(value) && (parse<double>(value) >= 0));245}246case SUMO_ATTR_NAME:247return SUMOXMLDefinitions::isValidAttribute(value);248case SUMO_ATTR_FILE:249return SUMOXMLDefinitions::isValidFilename(value);250case SUMO_ATTR_VTYPES:251if (value.empty()) {252return true;253} else {254return SUMOXMLDefinitions::isValidListOfTypeID(value);255}256case SUMO_ATTR_NEXT_EDGES:257if (value.empty()) {258return true;259} else {260return SUMOXMLDefinitions::isValidListOfNetIDs(value);261}262case SUMO_ATTR_DETECT_PERSONS:263if (value.empty()) {264return true;265} else {266return SUMOXMLDefinitions::PersonModeValues.hasString(value);267}268default:269return getMoveElement()->isMovingAttributeValid(key, value);270}271}272273274void275GNEDetector::writeDetectorValues(OutputDevice& device) const {276if ((myPeriod > 0) && (myPeriod != SUMOTime_MAX_PERIOD)) {277device.writeAttr(SUMO_ATTR_PERIOD, time2string(myPeriod));278}279if (myOutputFilename.size() > 0) {280device.writeAttr(SUMO_ATTR_FILE, myOutputFilename);281}282if (myVehicleTypes.size() > 0) {283device.writeAttr(SUMO_ATTR_VTYPES, myVehicleTypes);284}285if (myNextEdges.size() > 0) {286device.writeAttr(SUMO_ATTR_NEXT_EDGES, myNextEdges);287}288if ((myDetectPersons.size() > 0) && (myDetectPersons != SUMOXMLDefinitions::PersonModeValues.getString(PersonMode::NONE))) {289device.writeAttr(SUMO_ATTR_DETECT_PERSONS, myDetectPersons);290}291}292293294void295GNEDetector::setDetectorAttribute(SumoXMLAttr key, const std::string& value) {296switch (key) {297case SUMO_ATTR_ID:298// update microsimID299setAdditionalID(value);300break;301case SUMO_ATTR_PERIOD:302if (value.empty()) {303myPeriod = SUMOTime_MAX_PERIOD;304} else {305myPeriod = string2time(value);306}307break;308case SUMO_ATTR_FILE:309myOutputFilename = value;310break;311case SUMO_ATTR_NAME:312myAdditionalName = value;313break;314case SUMO_ATTR_VTYPES:315myVehicleTypes = parse<std::vector<std::string> >(value);316break;317case SUMO_ATTR_NEXT_EDGES:318myNextEdges = parse<std::vector<std::string> >(value);319break;320case SUMO_ATTR_DETECT_PERSONS:321myDetectPersons = value;322break;323case GNE_ATTR_SHIFTLANEINDEX:324shiftLaneIndex();325break;326default:327getMoveElement()->setMovingAttribute(key, value);328break;329}330}331332333void334GNEDetector::drawE1Shape(const GUIVisualizationSettings::Detail d, const double exaggeration,335const RGBColor& mainColor, const RGBColor& secondColor) const {336// push matrix337GLHelper::pushMatrix();338// set line width339glLineWidth(1.0);340// translate to center geometry341glTranslated(myAdditionalGeometry.getShape().front().x(), myAdditionalGeometry.getShape().front().y(), 0);342// rotate over lane343GUIGeometry::rotateOverLane(myAdditionalGeometry.getShapeRotations().front() + 90);344// scale345glScaled(exaggeration, exaggeration, 1);346// set main color347GLHelper::setColor(mainColor);348// begin draw square349glBegin(GL_QUADS);350// draw square351glVertex2d(-1.0, 2);352glVertex2d(-1.0, -2);353glVertex2d(1.0, -2);354glVertex2d(1.0, 2);355// end draw square356glEnd();357// move top358glTranslated(0, 0, .01);359// begin draw line360glBegin(GL_LINES);361// draw lines362glVertex2d(0, 2 - .1);363glVertex2d(0, -2 + .1);364// end draw line365glEnd();366// draw center only in draw in level 2367if (d <= GUIVisualizationSettings::Detail::AdditionalDetails) {368// set main color369GLHelper::setColor(secondColor);370// set polygon mode371glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);372// begin draw square373glBegin(GL_QUADS);374// draw square375glVertex2f(-1.0, 2);376glVertex2f(-1.0, -2);377glVertex2f(1.0, -2);378glVertex2f(1.0, 2);379// end draw square380glEnd();381// rotate 90 degrees382glRotated(90, 0, 0, -1);383//set polygon mode384glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);385// begin draw line386glBegin(GL_LINES);387// draw line388glVertex2d(0, 1.7);389glVertex2d(0, -1.7);390// end draw line391glEnd();392//arrow393glTranslated(2, 0, 0);394GLHelper::setColor(mainColor);395GLHelper::drawTriangleAtEnd(Position(0, 0), Position(0.5, 0), (double) 0.5, (double) 1);396}397// pop matrix398GLHelper::popMatrix();399}400401402void403GNEDetector::drawE1DetectorLogo(const GUIVisualizationSettings& s, const GUIVisualizationSettings::Detail d,404const double exaggeration, const std::string& logo, const RGBColor& textColor) const {405// only draw in level 2406if (d <= GUIVisualizationSettings::Detail::Text) {407// calculate position408const Position pos = myAdditionalGeometry.getShape().front();409// calculate rotation410const double rot = s.getTextAngle(myAdditionalGeometry.getShapeRotations().front() + 90);411// Start pushing matrix412GLHelper::pushMatrix();413// Traslate to position414glTranslated(pos.x(), pos.y(), 0.1);415// scale text416glScaled(exaggeration, exaggeration, 1);417// draw E1 logo418GLHelper::drawText(logo + " ", Position(), .1, 1.5, textColor, rot);419// pop matrix420GLHelper::popMatrix();421}422}423424425void426GNEDetector::drawE2DetectorLogo(const GUIVisualizationSettings& s, const GUIVisualizationSettings::Detail d,427const double exaggeration, const std::string& logo, const RGBColor& textColor) const {428// only draw in level 2429if (d <= GUIVisualizationSettings::Detail::Text) {430// calculate middle point431const double middlePoint = (myAdditionalGeometry.getShape().length2D() * 0.5);432// calculate position433const Position pos = myAdditionalGeometry.getShape().positionAtOffset2D(middlePoint);434// calculate rotation435const double rot = s.getTextAngle(myAdditionalGeometry.getShape().rotationDegreeAtOffset(middlePoint) + 90);436// Start pushing matrix437GLHelper::pushMatrix();438// Traslate to position439glTranslated(pos.x(), pos.y(), 0.1);440// scale text441glScaled(exaggeration, exaggeration, 1);442// draw E1 logo443GLHelper::drawText(logo, Position(), .1, 1.5, textColor, rot);444// pop matrix445GLHelper::popMatrix();446}447}448449/****************************************************************************/450451452