Path: blob/main/src/netedit/elements/data/GNEEdgeData.cpp
193674 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 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->getViewParent()->getEdgeDataFrame()->getIntervalSelector()->getDataInterval();66const std::string filteredAttribute = myNet->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}106default:107return 0;108}109}110111112bool113GNEEdgeData::isGenericDataVisible() const {114// get current data edit mode115DataEditMode dataMode = myNet->getViewNet()->getEditModes().dataEditMode;116// check if we have to filter generic data117if ((dataMode == DataEditMode::DATA_INSPECT) || (dataMode == DataEditMode::DATA_DELETE) || (dataMode == DataEditMode::DATA_SELECT)) {118return isVisibleInspectDeleteSelect();119} else if (myDataIntervalParent->getNet()->getViewParent()->getEdgeDataFrame()->shown()) {120// get selected data interval and filtered attribute121const GNEDataInterval* dataInterval = myNet->getViewParent()->getEdgeDataFrame()->getIntervalSelector()->getDataInterval();122const std::string filteredAttribute = myNet->getViewParent()->getEdgeDataFrame()->getAttributeSelector()->getFilteredAttribute();123// check interval124if ((dataInterval != nullptr) && (dataInterval != myDataIntervalParent)) {125return false;126}127// check attribute128if ((filteredAttribute.size() > 0) && (getParametersMap().count(filteredAttribute) == 0)) {129return false;130}131// all checks ok, then return true132return true;133} else {134// GNEEdgeDataFrame hidden, then return false135return false;136}137}138139140void141GNEEdgeData::updateGeometry() {142// calculate path143myNet->getDataPathManager()->calculateConsecutivePathEdges(this, SVC_IGNORING, getParentEdges());144}145146147Position148GNEEdgeData::getPositionInView() const {149return getParentEdges().front()->getPositionInView();150}151152153void154GNEEdgeData::writeGenericData(OutputDevice& device) const {155// open device (don't use SUMO_TAG_MEANDATA_EDGE)156device.openTag(SUMO_TAG_EDGE);157// write edge ID158device.writeAttr(SUMO_ATTR_ID, getParentEdges().front()->getID());159// iterate over attributes160for (const auto& attribute : getParametersMap()) {161// write attribute (don't use writeParams)162device.writeAttr(attribute.first, attribute.second);163}164// close device165device.closeTag();166}167168169bool170GNEEdgeData::isGenericDataValid() const {171return true;172}173174175std::string176GNEEdgeData::getGenericDataProblem() const {177return "";178}179180181void182GNEEdgeData::fixGenericDataProblem() {183throw InvalidArgument(getTagStr() + " cannot fix any problem");184}185186187void188GNEEdgeData::drawGL(const GUIVisualizationSettings& /*s*/) const {189// Nothing to draw190}191192193void194GNEEdgeData::computePathElement() {195// nothing to compute196}197198199void200GNEEdgeData::drawLanePartialGL(const GUIVisualizationSettings& s, const GNESegment* segment, const double offsetFront) const {201// get color202const auto color = setColor(s);203if (segment->getLane() && (color.alpha() != 0) && myNet->getViewNet()->getEditModes().isCurrentSupermodeData()) {204// get detail level205const auto d = s.getDetailLevel(1);206// draw geometry only if we'rent in drawForObjectUnderCursor mode207if (!s.drawForViewObjectsHandler) {208// draw over all edge's lanes209for (const auto& laneEdge : segment->getLane()->getParentEdge()->getChildLanes()) {210// Add a draw matrix211GLHelper::pushMatrix();212// Start with the drawing of the area translating matrix to origin213drawInLayer(GLO_EDGEDATA, offsetFront);214GLHelper::setColor(RGBColor::BLACK);215// draw geometry216GUIGeometry::drawGeometry(laneEdge->getDrawingConstants()->getDetail(), laneEdge->getLaneGeometry(), laneEdge->getDrawingConstants()->getDrawingWidth());217// translate to top218glTranslated(0, 0, 0.01);219GLHelper::setColor(color);220// draw internal box lines221GUIGeometry::drawGeometry(laneEdge->getDrawingConstants()->getDetail(), laneEdge->getLaneGeometry(), (laneEdge->getDrawingConstants()->getDrawingWidth() - 0.1));222// Pop last matrix223GLHelper::popMatrix();224// draw lock icon225GNEViewNetHelper::LockIcon::drawLockIcon(d, this, getType(), getPositionInView(), 1);226// draw filtered attribute227if (getParentEdges().front()->getChildLanes().front() == laneEdge) {228drawFilteredAttribute(s, laneEdge->getLaneShape(),229myNet->getViewParent()->getEdgeDataFrame()->getAttributeSelector()->getFilteredAttribute(),230myNet->getViewParent()->getEdgeDataFrame()->getIntervalSelector()->getDataInterval());231}232}233// draw dotted contour234segment->getContour()->drawDottedContours(s, d, this, s.dottedContourSettings.segmentWidth, true);235}236// calculate contour and draw dotted geometry237segment->getContour()->calculateContourEdge(s, d, segment->getLane()->getParentEdge(), this, getType(), true, true);238}239}240241242void243GNEEdgeData::drawJunctionPartialGL(const GUIVisualizationSettings& /*s*/, const GNESegment* /*segment*/, const double /*offsetFront*/) const {244// EdgeDatas don't use drawJunctionPartialGL over junction245}246247248GNELane*249GNEEdgeData::getFirstPathLane() const {250/* temporal */251return nullptr;252}253254255GNELane*256GNEEdgeData::getLastPathLane() const {257/* temporal */258return nullptr;259}260261262Boundary263GNEEdgeData::getCenteringBoundary() const {264return getParentEdges().front()->getCenteringBoundary();265}266267268std::string269GNEEdgeData::getAttribute(SumoXMLAttr key) const {270switch (key) {271case SUMO_ATTR_ID:272return getPartialID() + getParentEdges().front()->getID();273case GNE_ATTR_DATASET:274return myDataIntervalParent->getDataSetParent()->getID();275case SUMO_ATTR_BEGIN:276return myDataIntervalParent->getAttribute(SUMO_ATTR_BEGIN);277case SUMO_ATTR_END:278return myDataIntervalParent->getAttribute(SUMO_ATTR_END);279default:280return getCommonAttribute(key);281}282}283284285double286GNEEdgeData::getAttributeDouble(SumoXMLAttr key) const {287return getCommonAttributeDouble(key);288}289290291void292GNEEdgeData::setAttribute(SumoXMLAttr key, const std::string& value, GNEUndoList* undoList) {293if (value == getAttribute(key)) {294return; //avoid needless changes, later logic relies on the fact that attributes have changed295}296setCommonAttribute(key, value, undoList);297}298299300bool301GNEEdgeData::isValid(SumoXMLAttr key, const std::string& value) {302return isCommonAttributeValid(key, value);303}304305306bool GNEEdgeData::isAttributeEnabled(SumoXMLAttr key) const {307switch (key) {308case SUMO_ATTR_ID:309return false;310default:311return true;312}313}314315316std::string317GNEEdgeData::getPopUpID() const {318return getTagStr();319}320321322std::string323GNEEdgeData::getHierarchyName() const {324return getTagStr() + ": " + getParentEdges().front()->getID();325}326327328void329GNEEdgeData::setAttribute(SumoXMLAttr key, const std::string& value) {330setCommonAttribute(key, value);331if (!isTemplate()) {332myDataIntervalParent->getDataSetParent()->updateAttributeColors();333}334// mark interval toolbar for update335if (!isTemplate()) {336myNet->getViewNet()->getIntervalBar().markForUpdate();337}338}339340/****************************************************************************/341342343