Path: blob/main/src/netedit/elements/data/GNETAZRelData.cpp
169685 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 GNETAZRelData.cpp14/// @author Pablo Alvarez Lopez15/// @date Jan 202016///17// class for TAZ relation data18/****************************************************************************/1920#include <netedit/GNENet.h>21#include <netedit/GNETagProperties.h>22#include <netedit/GNEUndoList.h>23#include <netedit/GNEViewNet.h>24#include <netedit/GNEViewParent.h>25#include <netedit/changes/GNEChange_Attribute.h>26#include <netedit/elements/additional/GNETAZ.h>27#include <netedit/frames/data/GNETAZRelDataFrame.h>28#include <utils/gui/div/GLHelper.h>29#include <utils/gui/div/GUIGlobalViewObjectsHandler.h>30#include <utils/gui/globjects/GLIncludes.h>3132#include "GNETAZRelData.h"33#include "GNEDataInterval.h"3435// ===========================================================================36// member method definitions37// ===========================================================================3839GNETAZRelData::GNETAZRelData(GNENet* net) :40GNEGenericData(SUMO_TAG_TAZREL, net),41myLastWidth(0) {42}434445GNETAZRelData::GNETAZRelData(GNEDataInterval* dataIntervalParent, GNEAdditional* fromTAZ, GNEAdditional* toTAZ,46const Parameterised::Map& parameters) :47GNEGenericData(SUMO_TAG_TAZREL, dataIntervalParent, parameters),48myLastWidth(0) {49// set parents50setParents<GNEAdditional*>({fromTAZ, toTAZ});51}525354GNETAZRelData::GNETAZRelData(GNEDataInterval* dataIntervalParent, GNEAdditional* TAZ,55const Parameterised::Map& parameters) :56GNEGenericData(SUMO_TAG_TAZREL, dataIntervalParent, parameters),57myLastWidth(0) {58// set parents59setParent<GNEAdditional*>(TAZ);60}616263GNETAZRelData::~GNETAZRelData() {}646566RGBColor67GNETAZRelData::setColor(const GUIVisualizationSettings& s) const {68RGBColor color;69if (isAttributeCarrierSelected()) {70color = s.colorSettings.selectedEdgeDataColor;71} else {72if (!setFunctionalColor(s.dataColorer.getActive(), color)) {73double val = getColorValue(s, s.dataColorer.getActive());74color = s.dataColorer.getScheme().getColor(val);75}76}77return color;78}798081double82GNETAZRelData::getColorValue(const GUIVisualizationSettings& s, int activeScheme) const {83switch (activeScheme) {84case 0:85return 0;86case 1:87return isAttributeCarrierSelected();88case 2:89return 0; // setfunctional color const GNEAdditional* TAZA = getParentAdditionals().front();90case 3:91return 0; // setfunctional color const GNEAdditional* TAZA = getParentAdditionals().back();92case 4:93// by numerical attribute value94try {95if (hasParameter(s.relDataAttr)) {96return StringUtils::toDouble(getParameter(s.relDataAttr, "-1"));97} else {98return GUIVisualizationSettings::MISSING_DATA;99}100} catch (NumberFormatException&) {101return GUIVisualizationSettings::MISSING_DATA;102}103104}105return 0;106107}108109110bool111GNETAZRelData::isGenericDataVisible() const {112// obtain pointer to TAZ data frame (only for code legibly)113const GNETAZRelDataFrame* TAZRelDataFrame = myNet->getViewNet()->getViewParent()->getTAZRelDataFrame();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()*/ true;119} else if (TAZRelDataFrame->shown()) {120// check interval121if ((TAZRelDataFrame->getIntervalSelector()->getDataInterval() != nullptr) &&122(TAZRelDataFrame->getIntervalSelector()->getDataInterval() != myDataIntervalParent)) {123return false;124}125// check attribute126if ((TAZRelDataFrame->getAttributeSelector()->getFilteredAttribute().size() > 0) &&127(getParametersMap().count(TAZRelDataFrame->getAttributeSelector()->getFilteredAttribute()) == 0)) {128return false;129}130// all checks ok, then return true131return true;132} else {133// GNETAZRelDataFrame hidden, then return false134return false;135}136}137138139void140GNETAZRelData::updateGeometry() {141// remove from grid142myNet->removeGLObjectFromGrid(this);143// get both TAZs144const GNEAdditional* TAZA = getParentAdditionals().front();145const GNEAdditional* TAZB = getParentAdditionals().back();146// check if this is the same TAZ147if (TAZA == TAZB) {148// declare ring149PositionVector ring;150// declare first point151std::pair<double, double> p1 = GLHelper::getCircleCoords().at(GLHelper::angleLookup(0));152// add 8 segments153for (int i = 0; i <= 8; ++i) {154const std::pair<double, double>& p2 = GLHelper::getCircleCoords().at(GLHelper::angleLookup(0 + i * 45));155// make al line between 0,0 and p2156PositionVector line = {Position(), Position(p2.first, p2.second)};157// extrapolate158line.extrapolate(3, false, true);159// add line back to ring160ring.push_back(line.back());161// update p1162p1 = p2;163}164// make a copy of ring165PositionVector ringCenter = ring;166// move ring to first geometry point167ring.add(TAZA->getAdditionalGeometry().getShape().front());168myTAZRelGeometry.updateGeometry(ring);169// move ringCenter to center170ringCenter.add(TAZA->getAttributePosition(SUMO_ATTR_CENTER));171myTAZRelGeometryCenter.updateGeometry(ringCenter);172} else {173// calculate line between to TAZ centers174PositionVector line = {TAZA->getAttributePosition(SUMO_ATTR_CENTER), TAZB->getAttributePosition(SUMO_ATTR_CENTER)};175// check line176if (line.length() < 1) {177line = {TAZA->getAttributePosition(SUMO_ATTR_CENTER) - 0.5, TAZB->getAttributePosition(SUMO_ATTR_CENTER) + 0.5};178}179// add offset to line180line.move2side(0.5 + myLastWidth);181// calculate middle point182const Position middlePoint = line.getLineCenter();183// get closest points to middlePoint184Position posA = TAZA->getAdditionalGeometry().getShape().positionAtOffset2D(TAZA->getAdditionalGeometry().getShape().nearest_offset_to_point2D(middlePoint));185Position posB = TAZB->getAdditionalGeometry().getShape().positionAtOffset2D(TAZB->getAdditionalGeometry().getShape().nearest_offset_to_point2D(middlePoint));186// check positions187if (posA == Position::INVALID) {188posA = TAZA->getAdditionalGeometry().getShape().front();189}190if (posB == Position::INVALID) {191posB = TAZB->getAdditionalGeometry().getShape().front();192}193// update geometry194if (posA.distanceTo(posB) < 1) {195myTAZRelGeometry.updateGeometry({posA - 0.5, posB + 0.5});196} else {197myTAZRelGeometry.updateGeometry({posA, posB});198}199// update center geometry200myTAZRelGeometryCenter.updateGeometry(line);201}202// add into grid again203myNet->addGLObjectIntoGrid(this);204}205206207Position208GNETAZRelData::getPositionInView() const {209return getParentAdditionals().front()->getAttributePosition(SUMO_ATTR_CENTER);210}211212213void214GNETAZRelData::writeGenericData(OutputDevice& device) const {215// open device216device.openTag(SUMO_TAG_TAZREL);217// write from218device.writeAttr(SUMO_ATTR_FROM, getParentAdditionals().front()->getID());219// write to220device.writeAttr(SUMO_ATTR_TO, getParentAdditionals().back()->getID());221// iterate over attributes222for (const auto& attribute : getParametersMap()) {223// write attribute (don't use writeParams)224device.writeAttr(attribute.first, attribute.second);225}226// close device227device.closeTag();228}229230231bool232GNETAZRelData::isGenericDataValid() const {233return true;234}235236237std::string238GNETAZRelData::getGenericDataProblem() const {239return "";240}241242243void244GNETAZRelData::fixGenericDataProblem() {245throw InvalidArgument(getTagStr() + " cannot fix any problem");246}247248249void250GNETAZRelData::drawGL(const GUIVisualizationSettings& s) const {251// draw boundaries252GLHelper::drawBoundary(s, getCenteringBoundary());253// draw TAZRels254if (drawTAZRel()) {255// get detail level256const auto d = s.getDetailLevel(1);257// draw geometry only if we'rent in drawForObjectUnderCursor mode258if (!s.drawForViewObjectsHandler) {259const auto& color = setColor(s);260// get flag for only draw contour261const bool onlyDrawContour = !isGenericDataVisible();262// push matrix263GLHelper::pushMatrix();264// translate to front265drawInLayer(GLO_TAZ + 1);266GLHelper::setColor(color);267// check if update lastWidth268const double width = onlyDrawContour ? 0.1 : 0.5 * s.tazRelWidthExaggeration;269if (width != myLastWidth) {270myLastWidth = width;271}272// draw geometry273if (onlyDrawContour) {274// draw depending of TAZRelDrawing275if (myNet->getViewNet()->getDataViewOptions().TAZRelDrawing()) {276GUIGeometry::drawGeometry(d, myTAZRelGeometryCenter, width);277} else {278GUIGeometry::drawGeometry(d, myTAZRelGeometry, width);279}280} else {281// draw depending of TAZRelDrawing282const GUIGeometry& geom = (myNet->getViewNet()->getDataViewOptions().TAZRelDrawing()283? myTAZRelGeometryCenter : myTAZRelGeometry);284GUIGeometry::drawGeometry(d, geom, width);285GLHelper::drawTriangleAtEnd(286*(geom.getShape().end() - 2),287*(geom.getShape().end() - 1),2881.5 + width, 1.5 + width, 0.5 + width);289}290// pop matrix291GLHelper::popMatrix();292// draw dotted contour293myTAZRelDataContour.drawDottedContours(s, d, this, s.dottedContourSettings.segmentWidth, true);294}295if (myNet->getViewNet()->getDataViewOptions().TAZRelDrawing()) {296// calculate contour and draw dotted geometry297myTAZRelDataContour.calculateContourExtrudedShape(s, d, this, myTAZRelGeometryCenter.getShape(), getType(),2980.5, 1, true, true, 0, nullptr, nullptr);299} else {300// calculate contour and draw dotted geometry301myTAZRelDataContour.calculateContourExtrudedShape(s, d, this, myTAZRelGeometry.getShape(), getType(),3020.5, 1, true, true, 0, nullptr, nullptr);303}304}305}306307308bool309GNETAZRelData::setFunctionalColor(int activeScheme, RGBColor& col) const {310switch (activeScheme) {311case 2: { // origin taz312const GNETAZ* from = dynamic_cast<const GNETAZ*>(getParentAdditionals().front());313col = from->getShapeColor();314return true;315}316case 3: { // destination taz317const GNETAZ* to = dynamic_cast<const GNETAZ*>(getParentAdditionals().back());318col = to->getShapeColor();319return true;320}321default:322return false;323}324}325326void327GNETAZRelData::computePathElement() {328// nothing to compute329}330331332void333GNETAZRelData::drawLanePartialGL(const GUIVisualizationSettings& /*s*/, const GNESegment* /*segment*/, const double /*offsetFront*/) const {334// nothing to draw335}336337338void339GNETAZRelData::drawJunctionPartialGL(const GUIVisualizationSettings& /*s*/, const GNESegment* /*segment*/, const double /*offsetFront*/) const {340// nothing to draw341}342343344GNELane*345GNETAZRelData::getFirstPathLane() const {346return nullptr;347}348349350GNELane*351GNETAZRelData::getLastPathLane() const {352return nullptr;353}354355356Boundary357GNETAZRelData::getCenteringBoundary() const {358Boundary b;359// add two shapes360b.add(myTAZRelGeometry.getShape().getBoxBoundary());361b.add(myTAZRelGeometryCenter.getShape().getBoxBoundary());362b.grow(20);363return b;364}365366367std::string368GNETAZRelData::getAttribute(SumoXMLAttr key) const {369switch (key) {370case SUMO_ATTR_ID:371if (getParentAdditionals().size() == 1) {372return getPartialID() + getParentAdditionals().front()->getID();373} else {374return getPartialID() + (getParentAdditionals().front()->getID() + "->" + getParentAdditionals().back()->getID());375}376case SUMO_ATTR_FROM:377return getParentAdditionals().front()->getID();378case SUMO_ATTR_TO:379return getParentAdditionals().back()->getID();380case GNE_ATTR_DATASET:381return myDataIntervalParent->getDataSetParent()->getID();382case SUMO_ATTR_BEGIN:383return myDataIntervalParent->getAttribute(SUMO_ATTR_BEGIN);384case SUMO_ATTR_END:385return myDataIntervalParent->getAttribute(SUMO_ATTR_END);386default:387return getCommonAttribute(this, key);388}389}390391392double393GNETAZRelData::getAttributeDouble(SumoXMLAttr key) const {394throw InvalidArgument(getTagStr() + " doesn't have a double attribute of type '" + toString(key) + "'");395}396397398void399GNETAZRelData::setAttribute(SumoXMLAttr key, const std::string& value, GNEUndoList* undoList) {400if (value == getAttribute(key)) {401return; //avoid needless changes, later logic relies on the fact that attributes have changed402}403switch (key) {404case SUMO_ATTR_FROM:405case SUMO_ATTR_TO:406GNEChange_Attribute::changeAttribute(this, key, value, undoList);407break;408default:409setCommonAttribute(key, value, undoList);410break;411}412}413414415bool416GNETAZRelData::isValid(SumoXMLAttr key, const std::string& value) {417switch (key) {418case SUMO_ATTR_FROM:419case SUMO_ATTR_TO:420return SUMOXMLDefinitions::isValidNetID(value) &&421(myNet->getAttributeCarriers()->retrieveAdditional(SUMO_TAG_TAZ, value, false) != nullptr);422default:423return isCommonValid(key, value);424}425}426427428bool GNETAZRelData::isAttributeEnabled(SumoXMLAttr key) const {429switch (key) {430case SUMO_ATTR_ID:431return false;432default:433return true;434}435}436437438std::string439GNETAZRelData::getPopUpID() const {440return getTagStr();441}442443444std::string445GNETAZRelData::getHierarchyName() const {446if (getParentAdditionals().size() == 1) {447return getTagStr() + ": " + getParentAdditionals().front()->getID();448} else {449return getTagStr() + ": " + getParentAdditionals().front()->getID() + "->" + getParentAdditionals().back()->getID();450}451}452453454bool455GNETAZRelData::drawTAZRel() const {456const auto& inspectedElements = myNet->getViewNet()->getInspectedElements();457// first check supermode458if (!myNet->getViewNet()->getEditModes().isCurrentSupermodeData()) {459return false;460}461// check TAZRelFrame462if (myNet->getViewNet()->getViewParent()->getTAZRelDataFrame()->shown()) {463// check dataSet464const GNEDataSet* dataSet = myNet->getViewNet()->getViewParent()->getTAZRelDataFrame()->getDataSetSelector()->getDataSet();465if (dataSet && (myDataIntervalParent->getDataSetParent() != dataSet)) {466return false;467}468// check interval469const GNEDataInterval* dataInterval = myNet->getViewNet()->getViewParent()->getTAZRelDataFrame()->getIntervalSelector()->getDataInterval();470if (dataInterval && (myDataIntervalParent != dataInterval)) {471return false;472}473}474// check if both draw TAZRel checkBox are disabled475if (!myNet->getViewNet()->getDataViewOptions().TAZRelOnlyFrom() && !myNet->getViewNet()->getDataViewOptions().TAZRelOnlyTo()) {476return false;477}478// check if we're inspecting a TAZ479if ((myNet->getViewNet()->getEditModes().dataEditMode == DataEditMode::DATA_INSPECT) &&480inspectedElements.isInspectingSingleElement() && (inspectedElements.getFirstAC()->getTagProperty()->getTag() == SUMO_TAG_TAZ)) {481// ignore TAZRels with one TAZParent482if (getParentAdditionals().size() == 2) {483if ((getParentAdditionals().front() == inspectedElements.getFirstAC()) &&484myNet->getViewNet()->getDataViewOptions().TAZRelOnlyFrom()) {485return true;486} else if ((getParentAdditionals().back() == inspectedElements.getFirstAC()) &&487myNet->getViewNet()->getDataViewOptions().TAZRelOnlyTo()) {488return true;489} else {490return false;491}492}493}494return true;495}496497498void499GNETAZRelData::setAttribute(SumoXMLAttr key, const std::string& value) {500switch (key) {501case SUMO_ATTR_FROM: {502// replace first TAZ Parent503replaceParentTAZElement(0, value);504// update geometry505updateGeometry();506break;507}508case SUMO_ATTR_TO: {509// replace second TAZ Parent510replaceParentTAZElement(1, value);511// update geometry512updateGeometry();513break;514}515default:516setCommonAttribute(this, key, value);517if (!isTemplate()) {518myDataIntervalParent->getDataSetParent()->updateAttributeColors();519}520break;521}522// mark interval toolbar for update523myNet->getViewNet()->getIntervalBar().markForUpdate();524}525526/****************************************************************************/527528529