Path: blob/main/src/netedit/elements/data/GNEEdgeRelData.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 GNEEdgeRelData.cpp14/// @author Pablo Alvarez Lopez15/// @date Jan 202016///17// class for edge relation 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/GNEEdgeRelDataFrame.h>28#include <utils/gui/div/GLHelper.h>29#include <utils/gui/globjects/GLIncludes.h>3031#include "GNEEdgeRelData.h"32#include "GNEDataInterval.h"3334// ===========================================================================35// member method definitions36// ===========================================================================3738GNEEdgeRelData::GNEEdgeRelData(GNENet* net) :39GNEGenericData(SUMO_TAG_EDGEREL, net) {40}414243GNEEdgeRelData::GNEEdgeRelData(GNEDataInterval* dataIntervalParent, GNEEdge* fromEdge, GNEEdge* toEdge,44const Parameterised::Map& parameters) :45GNEGenericData(SUMO_TAG_EDGEREL, dataIntervalParent, parameters) {46// set parents47setParents<GNEEdge*>({fromEdge, toEdge});48}495051GNEEdgeRelData::~GNEEdgeRelData() {}525354RGBColor55GNEEdgeRelData::setColor(const GUIVisualizationSettings& s) const {56// set default color57RGBColor col = RGBColor::GREEN;58if (isAttributeCarrierSelected()) {59col = s.colorSettings.selectedEdgeDataColor;60} else if (s.dataColorer.getScheme().getName() == GUIVisualizationSettings::SCHEME_NAME_DATA_ATTRIBUTE_NUMERICAL) {61// user defined rainbow62double val = getColorValue(s, s.dataColorer.getActive());63col = s.dataColorer.getScheme().getColor(val);64} else if (myNet->getViewNet()->getEditModes().dataEditMode == DataEditMode::DATA_EDGERELDATA) {65// get selected data interval and filtered attribute66const GNEDataInterval* dataInterval = myNet->getViewNet()->getViewParent()->getEdgeRelDataFrame()->getIntervalSelector()->getDataInterval();67const std::string filteredAttribute = myNet->getViewNet()->getViewParent()->getEdgeRelDataFrame()->getAttributeSelector()->getFilteredAttribute();68// continue if there is a selected data interval and filtered attribute69if (dataInterval && (filteredAttribute.size() > 0)) {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"));75col = GNEViewNetHelper::getRainbowScaledColor(minValue, maxValue, value);76}77}78return col;79}808182double83GNEEdgeRelData::getColorValue(const GUIVisualizationSettings& s, int activeScheme) const {84switch (activeScheme) {85case 0:86return 0;87case 1:88return isAttributeCarrierSelected();89case 2:90return 0; // setfunctional color const GNEAdditional* TAZA = getParentAdditionals().front();91case 3:92return 0; // setfunctional color const GNEAdditional* TAZA = getParentAdditionals().back();93case 4:94// by numerical attribute value95try {96if (hasParameter(s.relDataAttr)) {97return StringUtils::toDouble(getParameter(s.relDataAttr, "-1"));98} else {99return GUIVisualizationSettings::MISSING_DATA;100}101} catch (NumberFormatException&) {102return GUIVisualizationSettings::MISSING_DATA;103}104}105return 0;106}107108109bool110GNEEdgeRelData::isGenericDataVisible() const {111// obtain pointer to edge data frame (only for code legibly)112const GNEEdgeRelDataFrame* edgeRelDataFrame = myNet->getViewNet()->getViewParent()->getEdgeRelDataFrame();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 (edgeRelDataFrame->shown()) {119// check interval120if ((edgeRelDataFrame->getIntervalSelector()->getDataInterval() != nullptr) &&121(edgeRelDataFrame->getIntervalSelector()->getDataInterval() != myDataIntervalParent)) {122return false;123}124// check attribute125if ((edgeRelDataFrame->getAttributeSelector()->getFilteredAttribute().size() > 0) &&126(getParametersMap().count(edgeRelDataFrame->getAttributeSelector()->getFilteredAttribute()) == 0)) {127return false;128}129// all checks ok, then return true130return true;131} else {132// GNEEdgeRelDataFrame hidden, then return false133return false;134}135}136137138void139GNEEdgeRelData::updateGeometry() {140// just compute path141computePathElement();142}143144145void146GNEEdgeRelData::drawGL(const GUIVisualizationSettings& /*s*/) const {147// Nothing to draw148}149150151void152GNEEdgeRelData::computePathElement() {153// calculate path154myNet->getDataPathManager()->calculateConsecutivePathEdges(this, SVC_IGNORING, getParentEdges());155}156157158void159GNEEdgeRelData::drawLanePartialGL(const GUIVisualizationSettings& s, const GNESegment* segment, const double offsetFront) const {160// get color161const auto color = setColor(s);162if (segment->getLane() && (color.alpha() != 0) && myNet->getViewNet()->getEditModes().isCurrentSupermodeData()) {163// get detail level164const auto d = s.getDetailLevel(1);165// draw over all edge's lanes166for (const auto& laneEdge : segment->getLane()->getParentEdge()->getChildLanes()) {167// get lane width168const double laneWidth = s.addSize.getExaggeration(s, laneEdge) * s.edgeRelWidthExaggeration *169(laneEdge->getParentEdge()->getNBEdge()->getLaneWidth(laneEdge->getIndex()) * 0.5);170// Add a draw matrix171GLHelper::pushMatrix();172// Start with the drawing of the area translating matrix to origin173drawInLayer(GLO_EDGERELDATA, offsetFront);174GLHelper::setColor(RGBColor::BLACK);175// draw box lines176177178GLHelper::drawBoxLines(laneEdge->getLaneShape(), laneEdge->getShapeRotations(),179laneEdge->getShapeLengths(), laneWidth);180// translate to top181glTranslated(0, 0, 0.01);182GLHelper::setColor(color);183// draw internal box lines184GLHelper::drawBoxLines(laneEdge->getLaneShape(), laneEdge->getShapeRotations(),185laneEdge->getShapeLengths(), (laneWidth - 0.1));186// Pop last matrix187GLHelper::popMatrix();188// draw lock icon189GNEViewNetHelper::LockIcon::drawLockIcon(d, this, getType(), getPositionInView(), 1);190// draw filtered attribute191if (getParentEdges().front()->getChildLanes().front() == laneEdge) {192drawFilteredAttribute(s, laneEdge->getLaneShape(),193myNet->getViewNet()->getViewParent()->getEdgeRelDataFrame()->getAttributeSelector()->getFilteredAttribute(),194myNet->getViewNet()->getViewParent()->getEdgeRelDataFrame()->getIntervalSelector()->getDataInterval());195}196// draw dotted contour197segment->getContour()->drawDottedContours(s, d, this, s.dottedContourSettings.segmentWidth, true);198}199// draw dotted contour200if (getParentEdges().front() == segment->getLane()->getParentEdge()) {201segment->getContour()->calculateContourEdge(s, d, getParentEdges().front(), this, getType(), true, false);202}203if (getParentEdges().back() == segment->getLane()->getParentEdge()) {204segment->getContour()->calculateContourEdge(s, d, getParentEdges().back(), this, getType(), false, true);205}206// check if add this path element to redraw buffer207if (!gViewObjectsHandler.isPathElementMarkForRedraw(this) && segment->getContour()->checkDrawPathContour(s, d, this)) {208gViewObjectsHandler.addToRedrawPathElements(this);209}210211}212}213214215void216GNEEdgeRelData::drawJunctionPartialGL(const GUIVisualizationSettings& s, const GNESegment* segment, const double /*offsetFront*/) const {217// get color218const auto color = setColor(s);219if ((color.alpha() != 0) && myNet->getViewNet()->getEditModes().isCurrentSupermodeData()) {220// get detail level221const auto d = s.getDetailLevel(1);222// get flag for only draw contour223224// finish225226// draw dotted contour227if (segment->getPreviousLane() && segment->getNextLane()) {228segment->getContour()->calculateContourEdges(s, d, segment->getPreviousLane()->getParentEdge(), segment->getNextLane()->getParentEdge());229}230// check if add this path element to redraw buffer231if (!gViewObjectsHandler.isPathElementMarkForRedraw(this) && segment->getContour()->checkDrawPathContour(s, d, this)) {232gViewObjectsHandler.addToRedrawPathElements(this);233}234}235}236237238GNELane*239GNEEdgeRelData::getFirstPathLane() const {240/* temporal */241return nullptr;242}243244245GNELane*246GNEEdgeRelData::getLastPathLane() const {247/* temporal */248return nullptr;249}250251252Position253GNEEdgeRelData::getPositionInView() const {254return getParentEdges().front()->getPositionInView();255}256257258void259GNEEdgeRelData::writeGenericData(OutputDevice& device) const {260// open device261device.openTag(SUMO_TAG_EDGEREL);262// write from263device.writeAttr(SUMO_ATTR_FROM, getParentEdges().front()->getID());264// write to265device.writeAttr(SUMO_ATTR_TO, getParentEdges().back()->getID());266// iterate over attributes267for (const auto& attribute : getParametersMap()) {268// write attribute (don't use writeParams)269device.writeAttr(attribute.first, attribute.second);270}271// close device272device.closeTag();273}274275276bool277GNEEdgeRelData::isGenericDataValid() const {278return true;279}280281282std::string283GNEEdgeRelData::getGenericDataProblem() const {284return "";285}286287288void289GNEEdgeRelData::fixGenericDataProblem() {290throw InvalidArgument(getTagStr() + " cannot fix any problem");291}292293294Boundary295GNEEdgeRelData::getCenteringBoundary() const {296return getParentEdges().front()->getCenteringBoundary();297}298299300std::string301GNEEdgeRelData::getAttribute(SumoXMLAttr key) const {302switch (key) {303case SUMO_ATTR_ID:304return getPartialID() + getParentEdges().front()->getID();305case SUMO_ATTR_FROM:306return getParentEdges().front()->getID();307case SUMO_ATTR_TO:308return getParentEdges().back()->getID();309case GNE_ATTR_DATASET:310return myDataIntervalParent->getDataSetParent()->getID();311case SUMO_ATTR_BEGIN:312return myDataIntervalParent->getAttribute(SUMO_ATTR_BEGIN);313case SUMO_ATTR_END:314return myDataIntervalParent->getAttribute(SUMO_ATTR_END);315default:316return getCommonAttribute(this, key);317}318}319320321double322GNEEdgeRelData::getAttributeDouble(SumoXMLAttr key) const {323throw InvalidArgument(getTagStr() + " doesn't have a double attribute of type '" + toString(key) + "'");324}325326327void328GNEEdgeRelData::setAttribute(SumoXMLAttr key, const std::string& value, GNEUndoList* undoList) {329if (value == getAttribute(key)) {330return; //avoid needless changes, later logic relies on the fact that attributes have changed331}332switch (key) {333case SUMO_ATTR_FROM:334case SUMO_ATTR_TO:335GNEChange_Attribute::changeAttribute(this, key, value, undoList);336break;337default:338setCommonAttribute(key, value, undoList);339break;340}341}342343344bool345GNEEdgeRelData::isValid(SumoXMLAttr key, const std::string& value) {346switch (key) {347case SUMO_ATTR_FROM:348return SUMOXMLDefinitions::isValidNetID(value) && (myNet->getAttributeCarriers()->retrieveEdge(value, false) != nullptr) &&349(value != getParentEdges().back()->getID());350case SUMO_ATTR_TO:351return SUMOXMLDefinitions::isValidNetID(value) && (myNet->getAttributeCarriers()->retrieveEdge(value, false) != nullptr) &&352(value != getParentEdges().front()->getID());353default:354return isCommonValid(key, value);355}356}357358359bool GNEEdgeRelData::isAttributeEnabled(SumoXMLAttr key) const {360switch (key) {361case SUMO_ATTR_ID:362return false;363default:364return true;365}366}367368369std::string370GNEEdgeRelData::getPopUpID() const {371return getTagStr();372}373374375std::string376GNEEdgeRelData::getHierarchyName() const {377return getTagStr() + ": " + getParentEdges().front()->getID() + "->" + getParentEdges().back()->getID();378}379380381void382GNEEdgeRelData::setAttribute(SumoXMLAttr key, const std::string& value) {383switch (key) {384case SUMO_ATTR_FROM: {385// change first edge386replaceFirstParentEdge(value);387break;388}389case SUMO_ATTR_TO: {390// change last edge391replaceLastParentEdge(value);392break;393}394default:395setCommonAttribute(this, key, value);396if (!isTemplate()) {397myDataIntervalParent->getDataSetParent()->updateAttributeColors();398}399break;400}401// mark interval toolbar for update402myNet->getViewNet()->getIntervalBar().markForUpdate();403}404405/****************************************************************************/406407408