Path: blob/main/src/netedit/elements/data/GNEEdgeData.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 GNEEdgeData.cpp14/// @author Pablo Alvarez Lopez15/// @date Jan 202016///17// class for edge data18/****************************************************************************/1920#include <netedit/GNENet.h>21#include <netedit/GNETagProperties.h>22#include <netedit/GNESegment.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/data/GNEEdgeDataFrame.h>28#include <utils/gui/div/GLHelper.h>29#include <utils/gui/globjects/GLIncludes.h>3031#include "GNEEdgeData.h"32#include "GNEDataInterval.h"3334// ===========================================================================35// member method definitions36// ===========================================================================3738GNEEdgeData::GNEEdgeData(GNENet* net) :39GNEGenericData(GNE_TAG_EDGEREL_SINGLE, net) {40}414243GNEEdgeData::GNEEdgeData(GNEDataInterval* dataIntervalParent, GNEEdge* edge, const Parameterised::Map& parameters) :44GNEGenericData(GNE_TAG_EDGEREL_SINGLE, dataIntervalParent, parameters) {45// set parents46setParent<GNEEdge*>(edge);47}484950GNEEdgeData::~GNEEdgeData() {}515253RGBColor54GNEEdgeData::setColor(const GUIVisualizationSettings& s) const {55// set default color56RGBColor col = RGBColor::RED;57if (isAttributeCarrierSelected()) {58col = s.colorSettings.selectedEdgeDataColor;59} else if (s.dataColorer.getScheme().getName() == GUIVisualizationSettings::SCHEME_NAME_DATA_ATTRIBUTE_NUMERICAL) {60// user defined rainbow61const double val = getColorValue(s, s.dataColorer.getActive());62col = s.dataColorer.getScheme().getColor(val);63} else if (myNet->getViewNet()->getEditModes().dataEditMode == DataEditMode::DATA_EDGEDATA) {64// get selected data interval and filtered attribute65const GNEDataInterval* dataInterval = myNet->getViewNet()->getViewParent()->getEdgeDataFrame()->getIntervalSelector()->getDataInterval();66const std::string filteredAttribute = myNet->getViewNet()->getViewParent()->getEdgeDataFrame()->getAttributeSelector()->getFilteredAttribute();67// continue if there is a selected data interval and filtered attribute68if (dataInterval && (filteredAttribute.size() > 0)) {69if (dataInterval->getSpecificAttributeColors().at(myTagProperty->getTag()).exist(filteredAttribute)) {70// obtain minimum and maximum value71const double minValue = dataInterval->getSpecificAttributeColors().at(myTagProperty->getTag()).getMinValue(filteredAttribute);72const double maxValue = dataInterval->getSpecificAttributeColors().at(myTagProperty->getTag()).getMaxValue(filteredAttribute);73// get value74const double value = parse<double>(getParameter(filteredAttribute, "0"));75// return color76col = GNEViewNetHelper::getRainbowScaledColor(minValue, maxValue, value);77}78}79}80return col;81}828384double85GNEEdgeData::getColorValue(const GUIVisualizationSettings& s, int activeScheme) const {86switch (activeScheme) {87case 0:88return 0;89case 1:90return isAttributeCarrierSelected();91case 2:92return 0; // setfunctional color const GNEAdditional* TAZA = getParentAdditionals().front();93case 3:94return 0; // setfunctional color const GNEAdditional* TAZA = getParentAdditionals().back();95case 4:96// by numerical attribute value97try {98if (hasParameter(s.relDataAttr)) {99return StringUtils::toDouble(getParameter(s.relDataAttr, "-1"));100} else {101return GUIVisualizationSettings::MISSING_DATA;102}103} catch (NumberFormatException&) {104return GUIVisualizationSettings::MISSING_DATA;105}106}107return 0;108}109110111bool112GNEEdgeData::isGenericDataVisible() const {113// get current data edit mode114DataEditMode dataMode = myNet->getViewNet()->getEditModes().dataEditMode;115// check if we have to filter generic data116if ((dataMode == DataEditMode::DATA_INSPECT) || (dataMode == DataEditMode::DATA_DELETE) || (dataMode == DataEditMode::DATA_SELECT)) {117return isVisibleInspectDeleteSelect();118} else if (myDataIntervalParent->getNet()->getViewNet()->getViewParent()->getEdgeDataFrame()->shown()) {119// get selected data interval and filtered attribute120const GNEDataInterval* dataInterval = myNet->getViewNet()->getViewParent()->getEdgeDataFrame()->getIntervalSelector()->getDataInterval();121const std::string filteredAttribute = myNet->getViewNet()->getViewParent()->getEdgeDataFrame()->getAttributeSelector()->getFilteredAttribute();122// check interval123if ((dataInterval != nullptr) && (dataInterval != myDataIntervalParent)) {124return false;125}126// check attribute127if ((filteredAttribute.size() > 0) && (getParametersMap().count(filteredAttribute) == 0)) {128return false;129}130// all checks ok, then return true131return true;132} else {133// GNEEdgeDataFrame hidden, then return false134return false;135}136}137138139void140GNEEdgeData::updateGeometry() {141// calculate path142myNet->getDataPathManager()->calculateConsecutivePathEdges(this, SVC_IGNORING, getParentEdges());143}144145146Position147GNEEdgeData::getPositionInView() const {148return getParentEdges().front()->getPositionInView();149}150151152void153GNEEdgeData::writeGenericData(OutputDevice& device) const {154// open device (don't use SUMO_TAG_MEANDATA_EDGE)155device.openTag(SUMO_TAG_EDGE);156// write edge ID157device.writeAttr(SUMO_ATTR_ID, getParentEdges().front()->getID());158// iterate over attributes159for (const auto& attribute : getParametersMap()) {160// write attribute (don't use writeParams)161device.writeAttr(attribute.first, attribute.second);162}163// close device164device.closeTag();165}166167168bool169GNEEdgeData::isGenericDataValid() const {170return true;171}172173174std::string175GNEEdgeData::getGenericDataProblem() const {176return "";177}178179180void181GNEEdgeData::fixGenericDataProblem() {182throw InvalidArgument(getTagStr() + " cannot fix any problem");183}184185186void187GNEEdgeData::drawGL(const GUIVisualizationSettings& /*s*/) const {188// Nothing to draw189}190191192void193GNEEdgeData::computePathElement() {194// nothing to compute195}196197198void199GNEEdgeData::drawLanePartialGL(const GUIVisualizationSettings& s, const GNESegment* segment, const double offsetFront) const {200// get color201const auto color = setColor(s);202if (segment->getLane() && (color.alpha() != 0) && myNet->getViewNet()->getEditModes().isCurrentSupermodeData()) {203// get detail level204const auto d = s.getDetailLevel(1);205// draw geometry only if we'rent in drawForObjectUnderCursor mode206if (!s.drawForViewObjectsHandler) {207// draw over all edge's lanes208for (const auto& laneEdge : segment->getLane()->getParentEdge()->getChildLanes()) {209// Add a draw matrix210GLHelper::pushMatrix();211// Start with the drawing of the area translating matrix to origin212drawInLayer(GLO_EDGEDATA, offsetFront);213GLHelper::setColor(RGBColor::BLACK);214// draw geometry215GUIGeometry::drawGeometry(laneEdge->getDrawingConstants()->getDetail(), laneEdge->getLaneGeometry(), laneEdge->getDrawingConstants()->getDrawingWidth());216// translate to top217glTranslated(0, 0, 0.01);218GLHelper::setColor(color);219// draw internal box lines220GUIGeometry::drawGeometry(laneEdge->getDrawingConstants()->getDetail(), laneEdge->getLaneGeometry(), (laneEdge->getDrawingConstants()->getDrawingWidth() - 0.1));221// Pop last matrix222GLHelper::popMatrix();223// draw lock icon224GNEViewNetHelper::LockIcon::drawLockIcon(d, this, getType(), getPositionInView(), 1);225// draw filtered attribute226if (getParentEdges().front()->getChildLanes().front() == laneEdge) {227drawFilteredAttribute(s, laneEdge->getLaneShape(),228myNet->getViewNet()->getViewParent()->getEdgeDataFrame()->getAttributeSelector()->getFilteredAttribute(),229myNet->getViewNet()->getViewParent()->getEdgeDataFrame()->getIntervalSelector()->getDataInterval());230}231}232// draw dotted contour233segment->getContour()->drawDottedContours(s, d, this, s.dottedContourSettings.segmentWidth, true);234}235// calculate contour and draw dotted geometry236segment->getContour()->calculateContourEdge(s, d, segment->getLane()->getParentEdge(), this, getType(), true, true);237}238}239240241void242GNEEdgeData::drawJunctionPartialGL(const GUIVisualizationSettings& /*s*/, const GNESegment* /*segment*/, const double /*offsetFront*/) const {243// EdgeDatas don't use drawJunctionPartialGL over junction244}245246247GNELane*248GNEEdgeData::getFirstPathLane() const {249/* temporal */250return nullptr;251}252253254GNELane*255GNEEdgeData::getLastPathLane() const {256/* temporal */257return nullptr;258}259260261Boundary262GNEEdgeData::getCenteringBoundary() const {263return getParentEdges().front()->getCenteringBoundary();264}265266267std::string268GNEEdgeData::getAttribute(SumoXMLAttr key) const {269switch (key) {270case SUMO_ATTR_ID:271return getPartialID() + getParentEdges().front()->getID();272case GNE_ATTR_DATASET:273return myDataIntervalParent->getDataSetParent()->getID();274case SUMO_ATTR_BEGIN:275return myDataIntervalParent->getAttribute(SUMO_ATTR_BEGIN);276case SUMO_ATTR_END:277return myDataIntervalParent->getAttribute(SUMO_ATTR_END);278default:279return getCommonAttribute(this, key);280}281}282283284double285GNEEdgeData::getAttributeDouble(SumoXMLAttr key) const {286throw InvalidArgument(getTagStr() + " doesn't have a double attribute of type '" + toString(key) + "'");287}288289290void291GNEEdgeData::setAttribute(SumoXMLAttr key, const std::string& value, GNEUndoList* undoList) {292if (value == getAttribute(key)) {293return; //avoid needless changes, later logic relies on the fact that attributes have changed294}295setCommonAttribute(key, value, undoList);296}297298299bool300GNEEdgeData::isValid(SumoXMLAttr key, const std::string& value) {301return isCommonValid(key, value);302}303304305bool GNEEdgeData::isAttributeEnabled(SumoXMLAttr key) const {306switch (key) {307case SUMO_ATTR_ID:308return false;309default:310return true;311}312}313314315std::string316GNEEdgeData::getPopUpID() const {317return getTagStr();318}319320321std::string322GNEEdgeData::getHierarchyName() const {323return getTagStr() + ": " + getParentEdges().front()->getID();324}325326327void328GNEEdgeData::setAttribute(SumoXMLAttr key, const std::string& value) {329setCommonAttribute(this, key, value);330if (!isTemplate()) {331myDataIntervalParent->getDataSetParent()->updateAttributeColors();332}333// mark interval toolbar for update334myNet->getViewNet()->getIntervalBar().markForUpdate();335}336337/****************************************************************************/338339340