Path: blob/main/src/netedit/elements/additional/GNELaneAreaDetector.cpp
193724 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 GNELaneAreaDetector.cpp14/// @author Pablo Alvarez Lopez15/// @date Nov 201516///17//18/****************************************************************************/19#include <config.h>2021#include <netedit/GNENet.h>22#include <netedit/GNESegment.h>23#include <netedit/GNETagProperties.h>24#include <netedit/changes/GNEChange_Attribute.h>25#include <utils/gui/div/GLHelper.h>2627#include "GNELaneAreaDetector.h"2829// ===========================================================================30// member method definitions31// ===========================================================================3233GNELaneAreaDetector::GNELaneAreaDetector(SumoXMLTag tag, GNENet* net) :34GNEDetector(net, tag),35myMoveElementLaneDouble(new GNEMoveElementLaneDouble(this, SUMO_ATTR_POSITION, myStartPosOverLane,36SUMO_ATTR_ENDPOS, myEndPosPosOverLane, myFriendlyPosition)) {37}383940GNELaneAreaDetector::GNELaneAreaDetector(const std::string& id, GNENet* net, FileBucket* fileBucket, GNELane* lane, const double pos, const double length, const SUMOTime freq,41const std::string& trafficLight, const std::string& outputFilename, const std::vector<std::string>& vehicleTypes, const std::vector<std::string>& nextEdges,42const std::string& detectPersons, const std::string& name, const SUMOTime timeThreshold, const double speedThreshold, const double jamThreshold, const bool friendlyPos,43const bool show, const Parameterised::Map& parameters) :44GNEDetector(id, net, fileBucket, SUMO_TAG_LANE_AREA_DETECTOR, freq, outputFilename, vehicleTypes, nextEdges, detectPersons, name, parameters),45myStartPosOverLane(pos),46myEndPosPosOverLane(pos + length),47myFriendlyPosition(friendlyPos),48myTimeThreshold(timeThreshold),49mySpeedThreshold(speedThreshold),50myJamThreshold(jamThreshold),51myTrafficLight(trafficLight),52myShow(show),53myMoveElementLaneDouble(new GNEMoveElementLaneDouble(this, SUMO_ATTR_POSITION, myStartPosOverLane, SUMO_ATTR_ENDPOS, myEndPosPosOverLane, myFriendlyPosition)) {54// set parents55setParent<GNELane*>(lane);56}575859GNELaneAreaDetector::GNELaneAreaDetector(const std::string& id, GNENet* net, FileBucket* fileBucket, std::vector<GNELane*> lanes, const double pos, const double endPos, const SUMOTime freq,60const std::string& trafficLight, const std::string& outputFilename, const std::vector<std::string>& vehicleTypes, const std::vector<std::string>& nextEdges,61const std::string& detectPersons, const std::string& name, const SUMOTime timeThreshold, const double speedThreshold, const double jamThreshold, const bool friendlyPos, const bool show,62const Parameterised::Map& parameters) :63GNEDetector(id, net, fileBucket, GNE_TAG_MULTI_LANE_AREA_DETECTOR, freq, outputFilename, vehicleTypes, nextEdges,64detectPersons, name, parameters),65myStartPosOverLane(pos),66myEndPosPosOverLane(endPos),67myFriendlyPosition(friendlyPos),68myTimeThreshold(timeThreshold),69mySpeedThreshold(speedThreshold),70myJamThreshold(jamThreshold),71myTrafficLight(trafficLight),72myShow(show),73myMoveElementLaneDouble(new GNEMoveElementLaneDouble(this, SUMO_ATTR_POSITION, myStartPosOverLane, SUMO_ATTR_ENDPOS, myEndPosPosOverLane, myFriendlyPosition)) {74// set parents75setParents<GNELane*>(lanes);76}777879GNELaneAreaDetector::~GNELaneAreaDetector() {80delete myMoveElementLaneDouble;81}828384GNEMoveElement*85GNELaneAreaDetector::getMoveElement() const {86return myMoveElementLaneDouble;87}888990Parameterised*91GNELaneAreaDetector::getParameters() {92return this;93}949596void97GNELaneAreaDetector::writeAdditional(OutputDevice& device) const {98device.openTag(SUMO_TAG_LANE_AREA_DETECTOR);99// write common additional attributes100writeAdditionalAttributes(device);101// write move atributes102myMoveElementLaneDouble->writeMoveAttributes(device, (myTagProperty->getTag() == SUMO_TAG_LANE_AREA_DETECTOR));103// write common detector parameters104writeDetectorValues(device);105// write specific attributes106if (myTrafficLight.size() > 0) {107device.writeAttr(SUMO_ATTR_TLID, myTrafficLight);108}109if (myTimeThreshold != myTagProperty->getDefaultTimeValue(SUMO_ATTR_HALTING_TIME_THRESHOLD)) {110device.writeAttr(SUMO_ATTR_HALTING_TIME_THRESHOLD, time2string(myTimeThreshold));111}112if (mySpeedThreshold != myTagProperty->getDefaultDoubleValue(SUMO_ATTR_HALTING_SPEED_THRESHOLD)) {113device.writeAttr(SUMO_ATTR_HALTING_SPEED_THRESHOLD, mySpeedThreshold);114}115if (myJamThreshold != myTagProperty->getDefaultDoubleValue(SUMO_ATTR_JAM_DIST_THRESHOLD)) {116device.writeAttr(SUMO_ATTR_JAM_DIST_THRESHOLD, myJamThreshold);117}118if (myShow != myTagProperty->getDefaultBoolValue(SUMO_ATTR_SHOW_DETECTOR)) {119device.writeAttr(SUMO_ATTR_SHOW_DETECTOR, myShow);120}121// write parameters (Always after children to avoid problems with additionals.xsd)122writeParams(device);123device.closeTag();124}125126127bool128GNELaneAreaDetector::isAdditionalValid() const {129// only movement problems130return myMoveElementLaneDouble->isMoveElementValid();131}132133134std::string135GNELaneAreaDetector::getAdditionalProblem() const {136// only movement problems137return myMoveElementLaneDouble->getMovingProblem();138}139140141void142GNELaneAreaDetector::fixAdditionalProblem() {143// only movement problems144return myMoveElementLaneDouble->fixMovingProblem();145}146147148void149GNELaneAreaDetector::updateGeometry() {150// check E2 detector151if (myTagProperty->getTag() == GNE_TAG_MULTI_LANE_AREA_DETECTOR) {152// compute path153computePathElement();154} else {155// Cut shape using as delimitators fixed start position and fixed end position156myAdditionalGeometry.updateGeometry(getParentLanes().front()->getLaneShape(),157myMoveElementLaneDouble->getStartFixedPositionOverLane(true),158myMoveElementLaneDouble->getEndFixedPositionOverLane(true),159myMoveElementLaneDouble->myMovingLateralOffset);160}161}162163164void165GNELaneAreaDetector::drawGL(const GUIVisualizationSettings& s) const {166// check drawing conditions167if ((myTagProperty->getTag() == SUMO_TAG_LANE_AREA_DETECTOR) &&168myNet->getViewNet()->getDataViewOptions().showAdditionals() &&169!myNet->getViewNet()->selectingDetectorsTLSMode()) {170// Obtain exaggeration of the draw171const double E2Exaggeration = getExaggeration(s);172// get detail level173const auto d = s.getDetailLevel(E2Exaggeration);174// check if draw geometry points175const bool movingGeometryPoints = drawMovingGeometryPoints();176// draw geometry only if we'rent in drawForObjectUnderCursor mode177if (s.checkDrawAdditional(d, isAttributeCarrierSelected())) {178// draw E2179drawE2(s, d, E2Exaggeration, movingGeometryPoints);180// draw lock icon181GNEViewNetHelper::LockIcon::drawLockIcon(d, this, getType(), myAdditionalGeometry.getShape().getCentroid(), E2Exaggeration);182// Draw additional ID183drawAdditionalID(s);184// draw additional name185drawAdditionalName(s);186// check if draw geometry points187if (movingGeometryPoints) {188myAdditionalContour.drawDottedContourGeometryPoints(s, d, this, myAdditionalGeometry.getShape(), s.neteditSizeSettings.additionalGeometryPointRadius,1891, s.dottedContourSettings.segmentWidthSmall);190} else {191myAdditionalContour.drawDottedContours(s, d, this, s.dottedContourSettings.segmentWidth, true);192}193}194// check if we're calculating the contour or the moving geometry points195if (movingGeometryPoints) {196if (myStartPosOverLane != INVALID_DOUBLE) {197myAdditionalContour.calculateContourFirstGeometryPoint(s, d, this, myAdditionalGeometry.getShape(),198getType(), s.neteditSizeSettings.additionalGeometryPointRadius, 1);199}200if (movingGeometryPoints && (myEndPosPosOverLane != INVALID_DOUBLE)) {201myAdditionalContour.calculateContourLastGeometryPoint(s, d, this, myAdditionalGeometry.getShape(),202getType(), s.neteditSizeSettings.additionalGeometryPointRadius, 1);203}204} else {205// don't exaggerate contour206myAdditionalContour.calculateContourExtrudedShape(s, d, this, myAdditionalGeometry.getShape(), getType(), s.detectorSettings.E2Width,207E2Exaggeration, true, true, 0, nullptr, getParentLanes().front()->getParentEdge());208}209}210}211212213void214GNELaneAreaDetector::computePathElement() {215// calculate path216myNet->getNetworkPathManager()->calculateConsecutivePathLanes(this, getParentLanes());217}218219220void221GNELaneAreaDetector::drawLanePartialGL(const GUIVisualizationSettings& s, const GNESegment* segment, const double offsetFront) const {222// check if E2 can be drawn223if (segment->getLane() && (myTagProperty->getTag() == GNE_TAG_MULTI_LANE_AREA_DETECTOR) &&224myNet->getViewNet()->getDataViewOptions().showAdditionals() && !myNet->getViewNet()->selectingDetectorsTLSMode()) {225const bool movingGeometryPoints = drawMovingGeometryPoints();226// Obtain exaggeration of the draw227const double E2Exaggeration = getExaggeration(s);228// get detail level229const auto d = s.getDetailLevel(E2Exaggeration);230// calculate startPos231const double geometryDepartPos = getAttributeDouble(SUMO_ATTR_POSITION);232// get endPos233const double geometryEndPos = getAttributeDouble(SUMO_ATTR_ENDPOS);234// declare path geometry235GUIGeometry E2Geometry;236// update pathGeometry depending of first and last segment237if (segment->isFirstSegment() && segment->isLastSegment()) {238E2Geometry.updateGeometry(segment->getLane()->getLaneGeometry().getShape(),239geometryDepartPos,240Position::INVALID,241geometryEndPos,242Position::INVALID);243} else if (segment->isFirstSegment()) {244E2Geometry.updateGeometry(segment->getLane()->getLaneGeometry().getShape(),245geometryDepartPos,246Position::INVALID,247-1,248Position::INVALID);249} else if (segment->isLastSegment()) {250E2Geometry.updateGeometry(segment->getLane()->getLaneGeometry().getShape(),251-1,252Position::INVALID,253geometryEndPos,254Position::INVALID);255} else {256E2Geometry = segment->getLane()->getLaneGeometry();257}258// draw geometry only if we'rent in drawForObjectUnderCursor mode259if (s.checkDrawAdditional(d, isAttributeCarrierSelected())) {260// draw E2 partial261drawE2PartialLane(s, d, segment, offsetFront, E2Geometry, E2Exaggeration, movingGeometryPoints);262// draw additional ID263drawName(getCenteringBoundary().getCenter(), s.scale, s.addName);264// draw dotted contour265if (movingGeometryPoints) {266// get mouse position267const Position mousePosition = myNet->getViewNet()->getPositionInformation();268// get snap radius269const double snap_radius = myNet->getViewNet()->getVisualisationSettings().neteditSizeSettings.additionalGeometryPointRadius;270if (segment->getFromContour() && E2Geometry.getShape().front().distanceSquaredTo2D(mousePosition) <= (snap_radius * snap_radius)) {271segment->getFromContour()->drawDottedContours(s, d, this, s.dottedContourSettings.segmentWidthSmall, true);272} else if (segment->getToContour() && E2Geometry.getShape().back().distanceSquaredTo2D(mousePosition) <= (snap_radius * snap_radius)) {273segment->getToContour()->drawDottedContours(s, d, this, s.dottedContourSettings.segmentWidthSmall, true);274}275} else {276segment->getContour()->drawDottedContours(s, d, this, s.dottedContourSettings.segmentWidth, true);277}278}279// calculate contour and draw dotted geometry280segment->getContour()->calculateContourExtrudedShape(s, d, this, E2Geometry.getShape(), getType(), s.detectorSettings.E2Width,281E2Exaggeration, segment->isFirstSegment(), segment->isLastSegment(), 0, segment, segment->getLane()->getParentEdge());282// check if create from-to contours283if (segment->getFromContour()) {284segment->getFromContour()->calculateContourCircleShape(s, d, this, E2Geometry.getShape().front(),285s.neteditSizeSettings.additionalGeometryPointRadius, getType(), E2Exaggeration, segment->getLane()->getParentEdge());286} else if (segment->getToContour()) {287segment->getToContour()->calculateContourCircleShape(s, d, this, E2Geometry.getShape().back(),288s.neteditSizeSettings.additionalGeometryPointRadius, getType(), E2Exaggeration, segment->getLane()->getParentEdge());289}290// check if add this path element to redraw buffer291if (!gViewObjectsHandler.isPathElementMarkForRedraw(this) && segment->getContour()->checkDrawPathContour(s, d, this)) {292gViewObjectsHandler.addToRedrawPathElements(this);293}294}295}296297298void299GNELaneAreaDetector::drawJunctionPartialGL(const GUIVisualizationSettings& s, const GNESegment* segment, const double offsetFront) const {300// check if E2 can be drawn301if ((myTagProperty->getTag() == GNE_TAG_MULTI_LANE_AREA_DETECTOR) && segment->getPreviousLane() && segment->getNextLane() &&302myNet->getViewNet()->getDataViewOptions().showAdditionals() && !myNet->getViewNet()->selectingDetectorsTLSMode()) {303// Obtain exaggeration of the draw304const double E2Exaggeration = getExaggeration(s);305// get detail level306const auto d = s.getDetailLevel(E2Exaggeration);307// get flag for show only contour308const bool onlyContour = myNet->getViewNet()->getEditModes().isCurrentSupermodeNetwork() ? myNet->getViewNet()->getNetworkViewOptions().showConnections() : false;309// check if connection to next lane exist310const bool connectionExist = segment->getPreviousLane()->getLane2laneConnections().exist(segment->getNextLane());311// get geometry312const GUIGeometry& E2Geometry = connectionExist ? segment->getPreviousLane()->getLane2laneConnections().getLane2laneGeometry(segment->getNextLane()) :313GUIGeometry({segment->getPreviousLane()->getLaneShape().back(), segment->getNextLane()->getLaneShape().front()});314// draw geometry only if we'rent in drawForObjectUnderCursor mode315if (s.checkDrawAdditional(d, isAttributeCarrierSelected())) {316// draw E2 partial317drawE2PartialJunction(s, d, onlyContour, offsetFront, E2Geometry, E2Exaggeration);318// draw dotted contour319if (!drawMovingGeometryPoints()) {320segment->getContour()->drawDottedContours(s, d, this, s.dottedContourSettings.segmentWidth, true);321}322}323// calculate contour324segment->getContour()->calculateContourExtrudedShape(s, d, this, E2Geometry.getShape(), getType(), s.detectorSettings.E2Width, E2Exaggeration,325false, false, 0, segment, segment->getJunction());326// check if add this path element to redraw buffer327if (!gViewObjectsHandler.isPathElementMarkForRedraw(this) && segment->getContour()->checkDrawPathContour(s, d, this)) {328gViewObjectsHandler.addToRedrawPathElements(this);329}330}331}332333334std::string335GNELaneAreaDetector::getAttribute(SumoXMLAttr key) const {336switch (key) {337case SUMO_ATTR_POSITION:338return toString(myStartPosOverLane);339case SUMO_ATTR_ENDPOS:340return toString(myEndPosPosOverLane);341case SUMO_ATTR_TLID:342return myTrafficLight;343case SUMO_ATTR_LENGTH:344return toString(myEndPosPosOverLane - myStartPosOverLane);345case SUMO_ATTR_HALTING_TIME_THRESHOLD:346return time2string(myTimeThreshold);347case SUMO_ATTR_HALTING_SPEED_THRESHOLD:348return toString(mySpeedThreshold);349case SUMO_ATTR_JAM_DIST_THRESHOLD:350return toString(myJamThreshold);351case SUMO_ATTR_SHOW_DETECTOR:352return toString(myShow);353default:354return getDetectorAttribute(key);355}356}357358359double360GNELaneAreaDetector::getAttributeDouble(SumoXMLAttr key) const {361switch (key) {362case SUMO_ATTR_POSITION:363return myStartPosOverLane;364case SUMO_ATTR_ENDPOS:365return myEndPosPosOverLane;366case SUMO_ATTR_LENGTH:367return (myEndPosPosOverLane - myStartPosOverLane);368default:369return getDetectorAttributeDouble(key);370}371}372373374Position375GNELaneAreaDetector::getAttributePosition(SumoXMLAttr key) const {376return getDetectorAttributePosition(key);377}378379380PositionVector381GNELaneAreaDetector::getAttributePositionVector(SumoXMLAttr key) const {382return getCommonAttributePositionVector(key);383}384385386void387GNELaneAreaDetector::setAttribute(SumoXMLAttr key, const std::string& value, GNEUndoList* undoList) {388switch (key) {389case SUMO_ATTR_POSITION:390case SUMO_ATTR_ENDPOS:391case SUMO_ATTR_TLID:392case SUMO_ATTR_LENGTH:393case SUMO_ATTR_HALTING_TIME_THRESHOLD:394case SUMO_ATTR_HALTING_SPEED_THRESHOLD:395case SUMO_ATTR_JAM_DIST_THRESHOLD:396case SUMO_ATTR_SHOW_DETECTOR:397GNEChange_Attribute::changeAttribute(this, key, value, undoList);398break;399default:400setDetectorAttribute(key, value, undoList);401break;402}403}404405406bool407GNELaneAreaDetector::isValid(SumoXMLAttr key, const std::string& value) {408switch (key) {409case SUMO_ATTR_POSITION:410case SUMO_ATTR_ENDPOS:411return canParse<double>(value);412case SUMO_ATTR_TLID:413// temporal414return SUMOXMLDefinitions::isValidNetID(value);415case SUMO_ATTR_LENGTH:416return (canParse<double>(value) && (parse<double>(value) >= 0));417case SUMO_ATTR_HALTING_TIME_THRESHOLD:418return canParse<SUMOTime>(value) && (parse<SUMOTime>(value) >= 0);419case SUMO_ATTR_HALTING_SPEED_THRESHOLD:420return (canParse<double>(value) && (parse<double>(value) >= 0));421case SUMO_ATTR_JAM_DIST_THRESHOLD:422return (canParse<double>(value) && (parse<double>(value) >= 0));423case SUMO_ATTR_SHOW_DETECTOR:424return canParse<bool>(value);425default:426return isDetectorValid(key, value);427}428}429430// ===========================================================================431// private432// ===========================================================================433434void435GNELaneAreaDetector::drawE2(const GUIVisualizationSettings& s, const GUIVisualizationSettings::Detail d,436const double exaggeration, const bool movingGeometryPoints) const {437// declare color438RGBColor E2Color, textColor;439// set color440if (drawUsingSelectColor()) {441E2Color = s.colorSettings.selectedAdditionalColor;442textColor = E2Color.changedBrightness(-32);443} else if (areLaneConsecutives(getParentLanes())) {444E2Color = s.detectorSettings.E2Color;445textColor = RGBColor::BLACK;446}447// draw parent and child lines448drawParentChildLines(s, s.additionalSettings.connectionColor);449// push layer matrix450GLHelper::pushMatrix();451// translate to front452drawInLayer(GLO_E2DETECTOR);453// set color454GLHelper::setColor(E2Color);455// draw geometry456GUIGeometry::drawGeometry(d, myAdditionalGeometry, s.detectorSettings.E2Width * exaggeration);457// draw arrow458if (myAdditionalGeometry.getShape().size() > 1) {459glTranslated(0, 0, 0.1);460GLHelper::drawTriangleAtEnd(myAdditionalGeometry.getShape()[-2], myAdditionalGeometry.getShape()[-1], (double) 0.5, (double) 1, 0.5);461}462// draw E2 Logo463drawE2DetectorLogo(s, d, exaggeration, "E2", textColor);464// check if draw geometry points465if (movingGeometryPoints) {466drawLeftGeometryPoint(s, d, myAdditionalGeometry.getShape().front(), myAdditionalGeometry.getShapeRotations().front(), E2Color);467drawRightGeometryPoint(s, d, myAdditionalGeometry.getShape().back(), myAdditionalGeometry.getShapeRotations().back(), E2Color);468}469// pop layer matrix470GLHelper::popMatrix();471}472473474void475GNELaneAreaDetector::drawE2PartialLane(const GUIVisualizationSettings& s, const GUIVisualizationSettings::Detail d,476const GNESegment* segment, const double offsetFront,477const GUIGeometry& geometry, const double exaggeration, const bool movingGeometryPoints) const {478// obtain color479const RGBColor E2Color = drawUsingSelectColor() ? s.colorSettings.selectedAdditionalColor : s.detectorSettings.E2Color;480// push layer matrix481GLHelper::pushMatrix();482// Start with the drawing of the area traslating matrix to origin483glTranslated(0, 0, getType() + offsetFront);484// Set color485GLHelper::setColor(E2Color);486// draw geometry487GUIGeometry::drawGeometry(d, geometry, s.detectorSettings.E2Width * exaggeration);488// check if draw moving geometry points489if (movingGeometryPoints) {490if (segment->isFirstSegment()) {491// calculate and draw left geometry point492myAdditionalContour.calculateContourFirstGeometryPoint(s, d, this, geometry.getShape(),493getType(), s.neteditSizeSettings.additionalGeometryPointRadius, 1, true);494drawLeftGeometryPoint(s, d, geometry.getShape().front(), geometry.getShapeRotations().front(), E2Color, true);495}496if (segment->isLastSegment()) {497// calculate and draw right geometry point498myAdditionalContour.calculateContourLastGeometryPoint(s, d, this, geometry.getShape(),499getType(), s.neteditSizeSettings.additionalGeometryPointRadius, 1, true);500drawRightGeometryPoint(s, d, geometry.getShape().back(), geometry.getShapeRotations().back(), E2Color, true);501// draw arrow502if (geometry.getShape().size() > 1) {503glTranslated(0, 0, 0.1);504GLHelper::drawTriangleAtEnd(geometry.getShape()[-2], geometry.getShape()[-1], (double) 0.5, (double) 1, 0.5);505}506}507}508// Pop layer matrix509GLHelper::popMatrix();510// check if this is the label segment511if (segment->isLabelSegment()) {512// calculate middle point513const double middlePoint = (geometry.getShape().length2D() * 0.5);514// calculate position515const Position pos = geometry.getShape().positionAtOffset2D(middlePoint);516// calculate rotation517const double rot = s.getTextAngle((geometry.getShape().rotationDegreeAtOffset(middlePoint) * -1) + 90);518// Start pushing matrix519GLHelper::pushMatrix();520// Traslate to position521glTranslated(pos.x(), pos.y(), getType() + offsetFront + 0.1);522// rotate523glRotated(rot, 0, 0, 1);524// move525glTranslated(-1, 0, 0);526// scale text527glScaled(exaggeration, exaggeration, 1);528// draw E1 logo529GLHelper::drawText("E2 Multilane", Position(), .1, 1.5, RGBColor::BLACK);530// pop matrix531GLHelper::popMatrix();532}533534}535536537void538GNELaneAreaDetector::drawE2PartialJunction(const GUIVisualizationSettings& s, const GUIVisualizationSettings::Detail d,539const bool onlyContour, const double offsetFront, const GUIGeometry& geometry,540const double exaggeration) const {541const bool invalid = geometry.getShape().length() == 2;542const double width = s.detectorSettings.E2Width * exaggeration * (invalid ? 0.5 : 1);543// Add a draw matrix544GLHelper::pushMatrix();545// Start with the drawing of the area traslating matrix to origin546glTranslated(0, 0, getType() + offsetFront);547// Set color of the base548if (drawUsingSelectColor()) {549GLHelper::setColor(s.colorSettings.selectedAdditionalColor);550} else if (invalid) {551GLHelper::setColor(RGBColor::RED);552} else {553GLHelper::setColor(s.detectorSettings.E2Color);554}555// check if draw only contour556if (onlyContour) {557GUIGeometry::drawContourGeometry(geometry, width);558} else {559GUIGeometry::drawGeometry(d, geometry, width);560}561// Pop last matrix562GLHelper::popMatrix();563}564565566void567GNELaneAreaDetector::setAttribute(SumoXMLAttr key, const std::string& value) {568switch (key) {569case SUMO_ATTR_LANE:570case SUMO_ATTR_LANES:571replaceAdditionalParentLanes(value);572break;573case SUMO_ATTR_POSITION:574myStartPosOverLane = parse<double>(value);575// update geometry (except for template)576if (getParentLanes().size() > 0) {577updateGeometry();578}579break;580case SUMO_ATTR_ENDPOS:581myEndPosPosOverLane = parse<double>(value);582// update geometry (except for template)583if (getParentLanes().size() > 0) {584updateGeometry();585}586break;587case SUMO_ATTR_TLID:588myTrafficLight = value;589break;590case SUMO_ATTR_LENGTH:591myEndPosPosOverLane = (myStartPosOverLane + parse<double>(value));592// update geometry (except for template)593if (getParentLanes().size() > 0) {594updateGeometry();595}596break;597case SUMO_ATTR_HALTING_TIME_THRESHOLD:598myTimeThreshold = TIME2STEPS(parse<double>(value));599break;600case SUMO_ATTR_HALTING_SPEED_THRESHOLD:601mySpeedThreshold = parse<double>(value);602break;603case SUMO_ATTR_JAM_DIST_THRESHOLD:604myJamThreshold = parse<double>(value);605break;606case SUMO_ATTR_SHOW_DETECTOR:607myShow = parse<bool>(value);608break;609default:610setDetectorAttribute(key, value);611break;612}613}614615/****************************************************************************/616617618