Path: blob/main/src/netedit/elements/additional/GNEOverheadWire.cpp
193904 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 GNEOverheadWire.cpp14/// @author Pablo Alvarez Lopez15/// @date Nov 201516///17//18/****************************************************************************/19#include <config.h>2021#include <netedit/changes/GNEChange_Attribute.h>22#include <netedit/elements/moving/GNEMoveElementLaneDouble.h>23#include <netedit/GNENet.h>24#include <netedit/GNESegment.h>25#include <utils/gui/div/GLHelper.h>2627#include "GNEOverheadWire.h"2829// ===========================================================================30// member method definitions31// ===========================================================================3233GNEOverheadWire::GNEOverheadWire(GNENet* net) :34GNEAdditional(net, SUMO_TAG_OVERHEAD_WIRE_SECTION),35myMoveElementLaneDouble(new GNEMoveElementLaneDouble(this, SUMO_ATTR_STARTPOS, myStartPosOverLane,36SUMO_ATTR_ENDPOS, myEndPosPosOverLane, myFriendlyPosition)) {37}383940GNEOverheadWire::GNEOverheadWire(const std::string& id, GNENet* net, FileBucket* fileBucket, std::vector<GNELane*> lanes, GNEAdditional* substation,41const double startPos, const double endPos, const bool friendlyPos, const std::vector<std::string>& forbiddenInnerLanes,42const Parameterised::Map& parameters) :43GNEAdditional(id, net, SUMO_TAG_OVERHEAD_WIRE_SECTION, fileBucket, ""),44Parameterised(parameters),45myStartPosOverLane(startPos),46myEndPosPosOverLane(endPos),47myFriendlyPosition(friendlyPos),48myForbiddenInnerLanes(forbiddenInnerLanes),49myMoveElementLaneDouble(new GNEMoveElementLaneDouble(this, SUMO_ATTR_STARTPOS, myStartPosOverLane,50SUMO_ATTR_ENDPOS, myEndPosPosOverLane, myFriendlyPosition)) {51// set parents52setParents<GNELane*>(lanes);53setParent<GNEAdditional*>(substation);54// update centering boundary without updating grid55updateCenteringBoundary(false);56}575859GNEOverheadWire::~GNEOverheadWire() {60delete myMoveElementLaneDouble;61}626364GNEMoveElement*65GNEOverheadWire::getMoveElement() const {66return myMoveElementLaneDouble;67}686970Parameterised*71GNEOverheadWire::getParameters() {72return this;73}747576const Parameterised*77GNEOverheadWire::getParameters() const {78return this;79}808182void83GNEOverheadWire::writeAdditional(OutputDevice& device) const {84device.openTag(SUMO_TAG_OVERHEAD_WIRE_SECTION);85// write common additional attributes86writeAdditionalAttributes(device);87// write move atributes88myMoveElementLaneDouble->writeMoveAttributes(device, false);89// write specific attributes90device.writeAttr(SUMO_ATTR_SUBSTATIONID, getParentAdditionals().front()->getID());91if (!myForbiddenInnerLanes.empty()) {92device.writeAttr(SUMO_ATTR_OVERHEAD_WIRE_FORBIDDEN, myForbiddenInnerLanes);93}94// write parameters95writeParams(device);96device.closeTag();97}9899100bool101GNEOverheadWire::isAdditionalValid() const {102// only movement problems103return myMoveElementLaneDouble->isMoveElementValid();104}105106107std::string108GNEOverheadWire::getAdditionalProblem() const {109// only movement problems110return myMoveElementLaneDouble->getMovingProblem();111}112113114void115GNEOverheadWire::fixAdditionalProblem() {116// only movement problems117return myMoveElementLaneDouble->fixMovingProblem();118}119120121bool122GNEOverheadWire::checkDrawMoveContour() const {123return false;124}125126127void128GNEOverheadWire::updateGeometry() {129// compute path130computePathElement();131}132133134Position135GNEOverheadWire::getPositionInView() const {136return myAdditionalGeometry.getShape().getPolygonCenter();137}138139140void141GNEOverheadWire::updateCenteringBoundary(const bool /* updateGrid */) {142// nothing to update143}144145146void147GNEOverheadWire::splitEdgeGeometry(const double /* splitPosition */, const GNENetworkElement* originalElement, const GNENetworkElement* newElement, GNEUndoList* undoList) {148// obtain new list of lanes149std::string newLanes = getNewListOfParents(originalElement, newElement);150// update Lanes151if (newLanes.size() > 0) {152setAttribute(SUMO_ATTR_LANES, newLanes, undoList);153}154}155156157void158GNEOverheadWire::drawGL(const GUIVisualizationSettings& /*s*/) const {159// nothing to draw160}161162163void164GNEOverheadWire::computePathElement() {165// calculate path166myNet->getNetworkPathManager()->calculateConsecutivePathLanes(this, getParentLanes());167}168169170void171GNEOverheadWire::drawLanePartialGL(const GUIVisualizationSettings& s, const GNESegment* segment, const double offsetFront) const {172// calculate overheadWire width173const double overheadWireWidth = s.addSize.getExaggeration(s, segment->getLane());174// check if E2 can be drawn175if (segment->getLane() && myNet->getViewNet()->getDataViewOptions().showAdditionals()) {176// get detail level177const auto d = s.getDetailLevel(overheadWireWidth);178// calculate startPos179const double geometryDepartPos = getAttributeDouble(SUMO_ATTR_STARTPOS);180// get endPos181const double geometryEndPos = getAttributeDouble(SUMO_ATTR_ENDPOS);182// declare path geometry183GUIGeometry overheadWireGeometry;184// update pathGeometry depending of first and last segment185if (segment->isFirstSegment() && segment->isLastSegment()) {186overheadWireGeometry.updateGeometry(segment->getLane()->getLaneGeometry().getShape(),187geometryDepartPos,188Position::INVALID,189geometryEndPos,190Position::INVALID);191} else if (segment->isFirstSegment()) {192overheadWireGeometry.updateGeometry(segment->getLane()->getLaneGeometry().getShape(),193geometryDepartPos,194Position::INVALID,195-1,196Position::INVALID);197} else if (segment->isLastSegment()) {198overheadWireGeometry.updateGeometry(segment->getLane()->getLaneGeometry().getShape(),199-1,200Position::INVALID,201geometryEndPos,202Position::INVALID);203} else {204overheadWireGeometry = segment->getLane()->getLaneGeometry();205}206// get both geometries207auto overheadWireGeometryTop = overheadWireGeometry;208auto overheadWireGeometryBot = overheadWireGeometry;209// move to sides210overheadWireGeometryTop.moveGeometryToSide(overheadWireWidth * 0.5);211overheadWireGeometryBot.moveGeometryToSide(overheadWireWidth * -0.5);212// draw geometry only if we'rent in drawForObjectUnderCursor mode213if (s.checkDrawAdditional(d, isAttributeCarrierSelected())) {214// obtain color215const RGBColor overheadWireColorTop = drawUsingSelectColor() ? s.colorSettings.selectedAdditionalColor : s.additionalSettings.overheadWireColorTop;216const RGBColor overheadWireColorBot = drawUsingSelectColor() ? s.colorSettings.selectedAdditionalColor : s.additionalSettings.overheadWireColorBot;217// push layer matrix218GLHelper::pushMatrix();219// Start with the drawing of the area traslating matrix to origin220glTranslated(0, 0, getType() + offsetFront);221// Set top color222GLHelper::setColor(overheadWireColorTop);223// draw top geometry224GUIGeometry::drawGeometry(d, overheadWireGeometryTop, 0.2);225// Set bot color226GLHelper::setColor(overheadWireColorBot);227// draw bot geometry228GUIGeometry::drawGeometry(d, overheadWireGeometryBot, 0.2);229// draw geometry points230if (segment->isFirstSegment() && segment->isLastSegment()) {231drawLeftGeometryPoint(s, d, overheadWireGeometry.getShape().front(), overheadWireGeometry.getShapeRotations().front(), overheadWireColorTop, true);232drawRightGeometryPoint(s, d, overheadWireGeometry.getShape().back(), overheadWireGeometry.getShapeRotations().back(), overheadWireColorTop, true);233} else if (segment->isFirstSegment()) {234drawLeftGeometryPoint(s, d, overheadWireGeometry.getShape().front(), overheadWireGeometry.getShapeRotations().front(), overheadWireColorTop, true);235} else if (segment->isLastSegment()) {236drawRightGeometryPoint(s, d, overheadWireGeometry.getShape().back(), overheadWireGeometry.getShapeRotations().back(), overheadWireColorTop, true);237}238// Pop layer matrix239GLHelper::popMatrix();240// draw dotted contour241myAdditionalContour.drawDottedContours(s, d, this, s.dottedContourSettings.segmentWidth, true);242}243// declare trim geometry to draw244const auto shape = (segment->isFirstSegment() || segment->isLastSegment()) ? overheadWireGeometry.getShape() : segment->getLane()->getLaneShape();245// calculate contour and draw dotted geometry246myAdditionalContour.calculateContourExtrudedShape(s, d, this, shape, getType(), overheadWireWidth, 1, true, true, 0, segment, segment->getLane()->getParentEdge());247}248}249250251void252GNEOverheadWire::drawJunctionPartialGL(const GUIVisualizationSettings& s, const GNESegment* segment, const double offsetFront) const {253// calculate overheadWire width254const double overheadWireWidth = s.addSize.getExaggeration(s, segment->getPreviousLane());255// check if overhead wire can be drawn256if (myNet->getViewNet()->getDataViewOptions().showAdditionals() && segment->getPreviousLane() && segment->getNextLane()) {257// obtain color258const RGBColor overheadWireColorTop = drawUsingSelectColor() ? s.colorSettings.selectedAdditionalColor : s.additionalSettings.overheadWireColorTop;259const RGBColor overheadWireColorBot = drawUsingSelectColor() ? s.colorSettings.selectedAdditionalColor : s.additionalSettings.overheadWireColorBot;260// declare geometry261GUIGeometry overheadWireGeometry({segment->getPreviousLane()->getLaneShape().back(), segment->getNextLane()->getLaneShape().front()});262// get detail level263const auto d = s.getDetailLevel(1);264// check if exist connection265if (segment->getPreviousLane()->getLane2laneConnections().exist(segment->getNextLane())) {266overheadWireGeometry = segment->getPreviousLane()->getLane2laneConnections().getLane2laneGeometry(segment->getNextLane());267}268// get both geometries269auto overheadWireGeometryTop = overheadWireGeometry;270auto overheadWireGeometryBot = overheadWireGeometry;271// move to sides272overheadWireGeometryTop.moveGeometryToSide(overheadWireWidth * 0.5);273overheadWireGeometryBot.moveGeometryToSide(overheadWireWidth * -0.5);274// draw geometry only if we'rent in drawForObjectUnderCursor mode275if (s.checkDrawAdditional(d, isAttributeCarrierSelected())) {276// Add a draw matrix277GLHelper::pushMatrix();278// Start with the drawing of the area traslating matrix to origin279glTranslated(0, 0, getType() + offsetFront);280// Set top color281GLHelper::setColor(overheadWireColorTop);282// draw top geometry283GUIGeometry::drawGeometry(d, overheadWireGeometryTop, 0.2);284// Set bot color285GLHelper::setColor(overheadWireColorBot);286// draw bot geometry287GUIGeometry::drawGeometry(d, overheadWireGeometryBot, 0.2);288// Pop last matrix289GLHelper::popMatrix();290// draw dotted contour291myAdditionalContour.drawDottedContours(s, d, this, s.dottedContourSettings.segmentWidth, true);292}293// draw contours294if (segment->getPreviousLane()->getLane2laneConnections().exist(segment->getNextLane())) {295// get shape296const auto& shape = segment->getPreviousLane()->getLane2laneConnections().getLane2laneGeometry(segment->getNextLane()).getShape();297// calculate contour and draw dotted geometry298myAdditionalContour.calculateContourExtrudedShape(s, d, this, shape, getType(), overheadWireWidth, 1, true, true, 0, segment, segment->getJunction());299}300}301}302303304std::string305GNEOverheadWire::getAttribute(SumoXMLAttr key) const {306switch (key) {307case SUMO_ATTR_ID:308return getMicrosimID();309case SUMO_ATTR_SUBSTATIONID:310return getParentAdditionals().front()->getID();311case SUMO_ATTR_LANES:312return parseIDs(getParentLanes());313case SUMO_ATTR_STARTPOS:314return toString(myStartPosOverLane);315case SUMO_ATTR_ENDPOS:316return toString(myEndPosPosOverLane);317case SUMO_ATTR_OVERHEAD_WIRE_FORBIDDEN:318return toString(myForbiddenInnerLanes);319case GNE_ATTR_SHIFTLANEINDEX:320return "";321default:322return myMoveElementLaneDouble->getMovingAttribute(key);323}324}325326327double328GNEOverheadWire::getAttributeDouble(SumoXMLAttr key) const {329switch (key) {330case SUMO_ATTR_STARTPOS:331if (myStartPosOverLane < 0) {332return 0;333} else if (myStartPosOverLane > getParentLanes().front()->getParentEdge()->getNBEdge()->getFinalLength()) {334return getParentLanes().front()->getParentEdge()->getNBEdge()->getFinalLength();335} else {336return myStartPosOverLane;337}338case SUMO_ATTR_ENDPOS:339if (myEndPosPosOverLane < 0) {340return 0;341} else if (myEndPosPosOverLane > getParentLanes().back()->getParentEdge()->getNBEdge()->getFinalLength()) {342return getParentLanes().back()->getParentEdge()->getNBEdge()->getFinalLength();343} else {344return myEndPosPosOverLane;345}346default:347return myMoveElementLaneDouble->getMovingAttributeDouble(key);348}349}350351352Position353GNEOverheadWire::getAttributePosition(SumoXMLAttr key) const {354return myMoveElementLaneDouble->getMovingAttributePosition(key);355}356357358PositionVector359GNEOverheadWire::getAttributePositionVector(SumoXMLAttr key) const {360return getCommonAttributePositionVector(key);361}362363364void365GNEOverheadWire::setAttribute(SumoXMLAttr key, const std::string& value, GNEUndoList* undoList) {366switch (key) {367case SUMO_ATTR_ID:368case SUMO_ATTR_SUBSTATIONID:369case SUMO_ATTR_LANES:370case SUMO_ATTR_STARTPOS:371case SUMO_ATTR_ENDPOS:372case SUMO_ATTR_OVERHEAD_WIRE_FORBIDDEN:373GNEChange_Attribute::changeAttribute(this, key, value, undoList);374break;375default:376myMoveElementLaneDouble->setMovingAttribute(key, value, undoList);377break;378}379}380381382bool383GNEOverheadWire::isValid(SumoXMLAttr key, const std::string& value) {384switch (key) {385case SUMO_ATTR_ID:386return isValidAdditionalID(value);387case SUMO_ATTR_SUBSTATIONID:388if (value.empty()) {389return false;390} else {391return (myNet->getAttributeCarriers()->retrieveAdditional(SUMO_TAG_TRACTION_SUBSTATION, value, false) != nullptr);392}393case SUMO_ATTR_OVERHEAD_WIRE_FORBIDDEN:394return true;395default:396return myMoveElementLaneDouble->isMovingAttributeValid(key, value);397}398}399400401std::string402GNEOverheadWire::getPopUpID() const {403return getTagStr() + ": " + getID();404}405406407std::string408GNEOverheadWire::getHierarchyName() const {409return getTagStr();410}411412// ===========================================================================413// private414// ===========================================================================415416void417GNEOverheadWire::setAttribute(SumoXMLAttr key, const std::string& value) {418switch (key) {419case SUMO_ATTR_ID:420// update microsimID421setAdditionalID(value);422break;423case SUMO_ATTR_SUBSTATIONID:424replaceAdditionalParent(SUMO_TAG_TRACTION_SUBSTATION, value, 0);425break;426case SUMO_ATTR_LANES:427replaceAdditionalParentLanes(value);428break;429case SUMO_ATTR_OVERHEAD_WIRE_FORBIDDEN:430myForbiddenInnerLanes = parse<std::vector<std::string> >(value);431break;432case GNE_ATTR_SHIFTLANEINDEX:433shiftLaneIndex();434break;435default:436myMoveElementLaneDouble->setMovingAttribute(key, value);437break;438}439// update geometry (except for template)440if (getParentLanes().size() > 0) {441updateGeometry();442}443}444445/****************************************************************************/446447448