Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
eclipse
GitHub Repository: eclipse/sumo
Path: blob/main/src/netedit/elements/additional/GNELaneAreaDetector.cpp
193724 views
1
/****************************************************************************/
2
// Eclipse SUMO, Simulation of Urban MObility; see https://eclipse.dev/sumo
3
// Copyright (C) 2001-2026 German Aerospace Center (DLR) and others.
4
// This program and the accompanying materials are made available under the
5
// terms of the Eclipse Public License 2.0 which is available at
6
// https://www.eclipse.org/legal/epl-2.0/
7
// This Source Code may also be made available under the following Secondary
8
// Licenses when the conditions for such availability set forth in the Eclipse
9
// Public License 2.0 are satisfied: GNU General Public License, version 2
10
// or later which is available at
11
// https://www.gnu.org/licenses/old-licenses/gpl-2.0-standalone.html
12
// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later
13
/****************************************************************************/
14
/// @file GNELaneAreaDetector.cpp
15
/// @author Pablo Alvarez Lopez
16
/// @date Nov 2015
17
///
18
//
19
/****************************************************************************/
20
#include <config.h>
21
22
#include <netedit/GNENet.h>
23
#include <netedit/GNESegment.h>
24
#include <netedit/GNETagProperties.h>
25
#include <netedit/changes/GNEChange_Attribute.h>
26
#include <utils/gui/div/GLHelper.h>
27
28
#include "GNELaneAreaDetector.h"
29
30
// ===========================================================================
31
// member method definitions
32
// ===========================================================================
33
34
GNELaneAreaDetector::GNELaneAreaDetector(SumoXMLTag tag, GNENet* net) :
35
GNEDetector(net, tag),
36
myMoveElementLaneDouble(new GNEMoveElementLaneDouble(this, SUMO_ATTR_POSITION, myStartPosOverLane,
37
SUMO_ATTR_ENDPOS, myEndPosPosOverLane, myFriendlyPosition)) {
38
}
39
40
41
GNELaneAreaDetector::GNELaneAreaDetector(const std::string& id, GNENet* net, FileBucket* fileBucket, GNELane* lane, const double pos, const double length, const SUMOTime freq,
42
const std::string& trafficLight, const std::string& outputFilename, const std::vector<std::string>& vehicleTypes, const std::vector<std::string>& nextEdges,
43
const std::string& detectPersons, const std::string& name, const SUMOTime timeThreshold, const double speedThreshold, const double jamThreshold, const bool friendlyPos,
44
const bool show, const Parameterised::Map& parameters) :
45
GNEDetector(id, net, fileBucket, SUMO_TAG_LANE_AREA_DETECTOR, freq, outputFilename, vehicleTypes, nextEdges, detectPersons, name, parameters),
46
myStartPosOverLane(pos),
47
myEndPosPosOverLane(pos + length),
48
myFriendlyPosition(friendlyPos),
49
myTimeThreshold(timeThreshold),
50
mySpeedThreshold(speedThreshold),
51
myJamThreshold(jamThreshold),
52
myTrafficLight(trafficLight),
53
myShow(show),
54
myMoveElementLaneDouble(new GNEMoveElementLaneDouble(this, SUMO_ATTR_POSITION, myStartPosOverLane, SUMO_ATTR_ENDPOS, myEndPosPosOverLane, myFriendlyPosition)) {
55
// set parents
56
setParent<GNELane*>(lane);
57
}
58
59
60
GNELaneAreaDetector::GNELaneAreaDetector(const std::string& id, GNENet* net, FileBucket* fileBucket, std::vector<GNELane*> lanes, const double pos, const double endPos, const SUMOTime freq,
61
const std::string& trafficLight, const std::string& outputFilename, const std::vector<std::string>& vehicleTypes, const std::vector<std::string>& nextEdges,
62
const std::string& detectPersons, const std::string& name, const SUMOTime timeThreshold, const double speedThreshold, const double jamThreshold, const bool friendlyPos, const bool show,
63
const Parameterised::Map& parameters) :
64
GNEDetector(id, net, fileBucket, GNE_TAG_MULTI_LANE_AREA_DETECTOR, freq, outputFilename, vehicleTypes, nextEdges,
65
detectPersons, name, parameters),
66
myStartPosOverLane(pos),
67
myEndPosPosOverLane(endPos),
68
myFriendlyPosition(friendlyPos),
69
myTimeThreshold(timeThreshold),
70
mySpeedThreshold(speedThreshold),
71
myJamThreshold(jamThreshold),
72
myTrafficLight(trafficLight),
73
myShow(show),
74
myMoveElementLaneDouble(new GNEMoveElementLaneDouble(this, SUMO_ATTR_POSITION, myStartPosOverLane, SUMO_ATTR_ENDPOS, myEndPosPosOverLane, myFriendlyPosition)) {
75
// set parents
76
setParents<GNELane*>(lanes);
77
}
78
79
80
GNELaneAreaDetector::~GNELaneAreaDetector() {
81
delete myMoveElementLaneDouble;
82
}
83
84
85
GNEMoveElement*
86
GNELaneAreaDetector::getMoveElement() const {
87
return myMoveElementLaneDouble;
88
}
89
90
91
Parameterised*
92
GNELaneAreaDetector::getParameters() {
93
return this;
94
}
95
96
97
void
98
GNELaneAreaDetector::writeAdditional(OutputDevice& device) const {
99
device.openTag(SUMO_TAG_LANE_AREA_DETECTOR);
100
// write common additional attributes
101
writeAdditionalAttributes(device);
102
// write move atributes
103
myMoveElementLaneDouble->writeMoveAttributes(device, (myTagProperty->getTag() == SUMO_TAG_LANE_AREA_DETECTOR));
104
// write common detector parameters
105
writeDetectorValues(device);
106
// write specific attributes
107
if (myTrafficLight.size() > 0) {
108
device.writeAttr(SUMO_ATTR_TLID, myTrafficLight);
109
}
110
if (myTimeThreshold != myTagProperty->getDefaultTimeValue(SUMO_ATTR_HALTING_TIME_THRESHOLD)) {
111
device.writeAttr(SUMO_ATTR_HALTING_TIME_THRESHOLD, time2string(myTimeThreshold));
112
}
113
if (mySpeedThreshold != myTagProperty->getDefaultDoubleValue(SUMO_ATTR_HALTING_SPEED_THRESHOLD)) {
114
device.writeAttr(SUMO_ATTR_HALTING_SPEED_THRESHOLD, mySpeedThreshold);
115
}
116
if (myJamThreshold != myTagProperty->getDefaultDoubleValue(SUMO_ATTR_JAM_DIST_THRESHOLD)) {
117
device.writeAttr(SUMO_ATTR_JAM_DIST_THRESHOLD, myJamThreshold);
118
}
119
if (myShow != myTagProperty->getDefaultBoolValue(SUMO_ATTR_SHOW_DETECTOR)) {
120
device.writeAttr(SUMO_ATTR_SHOW_DETECTOR, myShow);
121
}
122
// write parameters (Always after children to avoid problems with additionals.xsd)
123
writeParams(device);
124
device.closeTag();
125
}
126
127
128
bool
129
GNELaneAreaDetector::isAdditionalValid() const {
130
// only movement problems
131
return myMoveElementLaneDouble->isMoveElementValid();
132
}
133
134
135
std::string
136
GNELaneAreaDetector::getAdditionalProblem() const {
137
// only movement problems
138
return myMoveElementLaneDouble->getMovingProblem();
139
}
140
141
142
void
143
GNELaneAreaDetector::fixAdditionalProblem() {
144
// only movement problems
145
return myMoveElementLaneDouble->fixMovingProblem();
146
}
147
148
149
void
150
GNELaneAreaDetector::updateGeometry() {
151
// check E2 detector
152
if (myTagProperty->getTag() == GNE_TAG_MULTI_LANE_AREA_DETECTOR) {
153
// compute path
154
computePathElement();
155
} else {
156
// Cut shape using as delimitators fixed start position and fixed end position
157
myAdditionalGeometry.updateGeometry(getParentLanes().front()->getLaneShape(),
158
myMoveElementLaneDouble->getStartFixedPositionOverLane(true),
159
myMoveElementLaneDouble->getEndFixedPositionOverLane(true),
160
myMoveElementLaneDouble->myMovingLateralOffset);
161
}
162
}
163
164
165
void
166
GNELaneAreaDetector::drawGL(const GUIVisualizationSettings& s) const {
167
// check drawing conditions
168
if ((myTagProperty->getTag() == SUMO_TAG_LANE_AREA_DETECTOR) &&
169
myNet->getViewNet()->getDataViewOptions().showAdditionals() &&
170
!myNet->getViewNet()->selectingDetectorsTLSMode()) {
171
// Obtain exaggeration of the draw
172
const double E2Exaggeration = getExaggeration(s);
173
// get detail level
174
const auto d = s.getDetailLevel(E2Exaggeration);
175
// check if draw geometry points
176
const bool movingGeometryPoints = drawMovingGeometryPoints();
177
// draw geometry only if we'rent in drawForObjectUnderCursor mode
178
if (s.checkDrawAdditional(d, isAttributeCarrierSelected())) {
179
// draw E2
180
drawE2(s, d, E2Exaggeration, movingGeometryPoints);
181
// draw lock icon
182
GNEViewNetHelper::LockIcon::drawLockIcon(d, this, getType(), myAdditionalGeometry.getShape().getCentroid(), E2Exaggeration);
183
// Draw additional ID
184
drawAdditionalID(s);
185
// draw additional name
186
drawAdditionalName(s);
187
// check if draw geometry points
188
if (movingGeometryPoints) {
189
myAdditionalContour.drawDottedContourGeometryPoints(s, d, this, myAdditionalGeometry.getShape(), s.neteditSizeSettings.additionalGeometryPointRadius,
190
1, s.dottedContourSettings.segmentWidthSmall);
191
} else {
192
myAdditionalContour.drawDottedContours(s, d, this, s.dottedContourSettings.segmentWidth, true);
193
}
194
}
195
// check if we're calculating the contour or the moving geometry points
196
if (movingGeometryPoints) {
197
if (myStartPosOverLane != INVALID_DOUBLE) {
198
myAdditionalContour.calculateContourFirstGeometryPoint(s, d, this, myAdditionalGeometry.getShape(),
199
getType(), s.neteditSizeSettings.additionalGeometryPointRadius, 1);
200
}
201
if (movingGeometryPoints && (myEndPosPosOverLane != INVALID_DOUBLE)) {
202
myAdditionalContour.calculateContourLastGeometryPoint(s, d, this, myAdditionalGeometry.getShape(),
203
getType(), s.neteditSizeSettings.additionalGeometryPointRadius, 1);
204
}
205
} else {
206
// don't exaggerate contour
207
myAdditionalContour.calculateContourExtrudedShape(s, d, this, myAdditionalGeometry.getShape(), getType(), s.detectorSettings.E2Width,
208
E2Exaggeration, true, true, 0, nullptr, getParentLanes().front()->getParentEdge());
209
}
210
}
211
}
212
213
214
void
215
GNELaneAreaDetector::computePathElement() {
216
// calculate path
217
myNet->getNetworkPathManager()->calculateConsecutivePathLanes(this, getParentLanes());
218
}
219
220
221
void
222
GNELaneAreaDetector::drawLanePartialGL(const GUIVisualizationSettings& s, const GNESegment* segment, const double offsetFront) const {
223
// check if E2 can be drawn
224
if (segment->getLane() && (myTagProperty->getTag() == GNE_TAG_MULTI_LANE_AREA_DETECTOR) &&
225
myNet->getViewNet()->getDataViewOptions().showAdditionals() && !myNet->getViewNet()->selectingDetectorsTLSMode()) {
226
const bool movingGeometryPoints = drawMovingGeometryPoints();
227
// Obtain exaggeration of the draw
228
const double E2Exaggeration = getExaggeration(s);
229
// get detail level
230
const auto d = s.getDetailLevel(E2Exaggeration);
231
// calculate startPos
232
const double geometryDepartPos = getAttributeDouble(SUMO_ATTR_POSITION);
233
// get endPos
234
const double geometryEndPos = getAttributeDouble(SUMO_ATTR_ENDPOS);
235
// declare path geometry
236
GUIGeometry E2Geometry;
237
// update pathGeometry depending of first and last segment
238
if (segment->isFirstSegment() && segment->isLastSegment()) {
239
E2Geometry.updateGeometry(segment->getLane()->getLaneGeometry().getShape(),
240
geometryDepartPos,
241
Position::INVALID,
242
geometryEndPos,
243
Position::INVALID);
244
} else if (segment->isFirstSegment()) {
245
E2Geometry.updateGeometry(segment->getLane()->getLaneGeometry().getShape(),
246
geometryDepartPos,
247
Position::INVALID,
248
-1,
249
Position::INVALID);
250
} else if (segment->isLastSegment()) {
251
E2Geometry.updateGeometry(segment->getLane()->getLaneGeometry().getShape(),
252
-1,
253
Position::INVALID,
254
geometryEndPos,
255
Position::INVALID);
256
} else {
257
E2Geometry = segment->getLane()->getLaneGeometry();
258
}
259
// draw geometry only if we'rent in drawForObjectUnderCursor mode
260
if (s.checkDrawAdditional(d, isAttributeCarrierSelected())) {
261
// draw E2 partial
262
drawE2PartialLane(s, d, segment, offsetFront, E2Geometry, E2Exaggeration, movingGeometryPoints);
263
// draw additional ID
264
drawName(getCenteringBoundary().getCenter(), s.scale, s.addName);
265
// draw dotted contour
266
if (movingGeometryPoints) {
267
// get mouse position
268
const Position mousePosition = myNet->getViewNet()->getPositionInformation();
269
// get snap radius
270
const double snap_radius = myNet->getViewNet()->getVisualisationSettings().neteditSizeSettings.additionalGeometryPointRadius;
271
if (segment->getFromContour() && E2Geometry.getShape().front().distanceSquaredTo2D(mousePosition) <= (snap_radius * snap_radius)) {
272
segment->getFromContour()->drawDottedContours(s, d, this, s.dottedContourSettings.segmentWidthSmall, true);
273
} else if (segment->getToContour() && E2Geometry.getShape().back().distanceSquaredTo2D(mousePosition) <= (snap_radius * snap_radius)) {
274
segment->getToContour()->drawDottedContours(s, d, this, s.dottedContourSettings.segmentWidthSmall, true);
275
}
276
} else {
277
segment->getContour()->drawDottedContours(s, d, this, s.dottedContourSettings.segmentWidth, true);
278
}
279
}
280
// calculate contour and draw dotted geometry
281
segment->getContour()->calculateContourExtrudedShape(s, d, this, E2Geometry.getShape(), getType(), s.detectorSettings.E2Width,
282
E2Exaggeration, segment->isFirstSegment(), segment->isLastSegment(), 0, segment, segment->getLane()->getParentEdge());
283
// check if create from-to contours
284
if (segment->getFromContour()) {
285
segment->getFromContour()->calculateContourCircleShape(s, d, this, E2Geometry.getShape().front(),
286
s.neteditSizeSettings.additionalGeometryPointRadius, getType(), E2Exaggeration, segment->getLane()->getParentEdge());
287
} else if (segment->getToContour()) {
288
segment->getToContour()->calculateContourCircleShape(s, d, this, E2Geometry.getShape().back(),
289
s.neteditSizeSettings.additionalGeometryPointRadius, getType(), E2Exaggeration, segment->getLane()->getParentEdge());
290
}
291
// check if add this path element to redraw buffer
292
if (!gViewObjectsHandler.isPathElementMarkForRedraw(this) && segment->getContour()->checkDrawPathContour(s, d, this)) {
293
gViewObjectsHandler.addToRedrawPathElements(this);
294
}
295
}
296
}
297
298
299
void
300
GNELaneAreaDetector::drawJunctionPartialGL(const GUIVisualizationSettings& s, const GNESegment* segment, const double offsetFront) const {
301
// check if E2 can be drawn
302
if ((myTagProperty->getTag() == GNE_TAG_MULTI_LANE_AREA_DETECTOR) && segment->getPreviousLane() && segment->getNextLane() &&
303
myNet->getViewNet()->getDataViewOptions().showAdditionals() && !myNet->getViewNet()->selectingDetectorsTLSMode()) {
304
// Obtain exaggeration of the draw
305
const double E2Exaggeration = getExaggeration(s);
306
// get detail level
307
const auto d = s.getDetailLevel(E2Exaggeration);
308
// get flag for show only contour
309
const bool onlyContour = myNet->getViewNet()->getEditModes().isCurrentSupermodeNetwork() ? myNet->getViewNet()->getNetworkViewOptions().showConnections() : false;
310
// check if connection to next lane exist
311
const bool connectionExist = segment->getPreviousLane()->getLane2laneConnections().exist(segment->getNextLane());
312
// get geometry
313
const GUIGeometry& E2Geometry = connectionExist ? segment->getPreviousLane()->getLane2laneConnections().getLane2laneGeometry(segment->getNextLane()) :
314
GUIGeometry({segment->getPreviousLane()->getLaneShape().back(), segment->getNextLane()->getLaneShape().front()});
315
// draw geometry only if we'rent in drawForObjectUnderCursor mode
316
if (s.checkDrawAdditional(d, isAttributeCarrierSelected())) {
317
// draw E2 partial
318
drawE2PartialJunction(s, d, onlyContour, offsetFront, E2Geometry, E2Exaggeration);
319
// draw dotted contour
320
if (!drawMovingGeometryPoints()) {
321
segment->getContour()->drawDottedContours(s, d, this, s.dottedContourSettings.segmentWidth, true);
322
}
323
}
324
// calculate contour
325
segment->getContour()->calculateContourExtrudedShape(s, d, this, E2Geometry.getShape(), getType(), s.detectorSettings.E2Width, E2Exaggeration,
326
false, false, 0, segment, segment->getJunction());
327
// check if add this path element to redraw buffer
328
if (!gViewObjectsHandler.isPathElementMarkForRedraw(this) && segment->getContour()->checkDrawPathContour(s, d, this)) {
329
gViewObjectsHandler.addToRedrawPathElements(this);
330
}
331
}
332
}
333
334
335
std::string
336
GNELaneAreaDetector::getAttribute(SumoXMLAttr key) const {
337
switch (key) {
338
case SUMO_ATTR_POSITION:
339
return toString(myStartPosOverLane);
340
case SUMO_ATTR_ENDPOS:
341
return toString(myEndPosPosOverLane);
342
case SUMO_ATTR_TLID:
343
return myTrafficLight;
344
case SUMO_ATTR_LENGTH:
345
return toString(myEndPosPosOverLane - myStartPosOverLane);
346
case SUMO_ATTR_HALTING_TIME_THRESHOLD:
347
return time2string(myTimeThreshold);
348
case SUMO_ATTR_HALTING_SPEED_THRESHOLD:
349
return toString(mySpeedThreshold);
350
case SUMO_ATTR_JAM_DIST_THRESHOLD:
351
return toString(myJamThreshold);
352
case SUMO_ATTR_SHOW_DETECTOR:
353
return toString(myShow);
354
default:
355
return getDetectorAttribute(key);
356
}
357
}
358
359
360
double
361
GNELaneAreaDetector::getAttributeDouble(SumoXMLAttr key) const {
362
switch (key) {
363
case SUMO_ATTR_POSITION:
364
return myStartPosOverLane;
365
case SUMO_ATTR_ENDPOS:
366
return myEndPosPosOverLane;
367
case SUMO_ATTR_LENGTH:
368
return (myEndPosPosOverLane - myStartPosOverLane);
369
default:
370
return getDetectorAttributeDouble(key);
371
}
372
}
373
374
375
Position
376
GNELaneAreaDetector::getAttributePosition(SumoXMLAttr key) const {
377
return getDetectorAttributePosition(key);
378
}
379
380
381
PositionVector
382
GNELaneAreaDetector::getAttributePositionVector(SumoXMLAttr key) const {
383
return getCommonAttributePositionVector(key);
384
}
385
386
387
void
388
GNELaneAreaDetector::setAttribute(SumoXMLAttr key, const std::string& value, GNEUndoList* undoList) {
389
switch (key) {
390
case SUMO_ATTR_POSITION:
391
case SUMO_ATTR_ENDPOS:
392
case SUMO_ATTR_TLID:
393
case SUMO_ATTR_LENGTH:
394
case SUMO_ATTR_HALTING_TIME_THRESHOLD:
395
case SUMO_ATTR_HALTING_SPEED_THRESHOLD:
396
case SUMO_ATTR_JAM_DIST_THRESHOLD:
397
case SUMO_ATTR_SHOW_DETECTOR:
398
GNEChange_Attribute::changeAttribute(this, key, value, undoList);
399
break;
400
default:
401
setDetectorAttribute(key, value, undoList);
402
break;
403
}
404
}
405
406
407
bool
408
GNELaneAreaDetector::isValid(SumoXMLAttr key, const std::string& value) {
409
switch (key) {
410
case SUMO_ATTR_POSITION:
411
case SUMO_ATTR_ENDPOS:
412
return canParse<double>(value);
413
case SUMO_ATTR_TLID:
414
// temporal
415
return SUMOXMLDefinitions::isValidNetID(value);
416
case SUMO_ATTR_LENGTH:
417
return (canParse<double>(value) && (parse<double>(value) >= 0));
418
case SUMO_ATTR_HALTING_TIME_THRESHOLD:
419
return canParse<SUMOTime>(value) && (parse<SUMOTime>(value) >= 0);
420
case SUMO_ATTR_HALTING_SPEED_THRESHOLD:
421
return (canParse<double>(value) && (parse<double>(value) >= 0));
422
case SUMO_ATTR_JAM_DIST_THRESHOLD:
423
return (canParse<double>(value) && (parse<double>(value) >= 0));
424
case SUMO_ATTR_SHOW_DETECTOR:
425
return canParse<bool>(value);
426
default:
427
return isDetectorValid(key, value);
428
}
429
}
430
431
// ===========================================================================
432
// private
433
// ===========================================================================
434
435
void
436
GNELaneAreaDetector::drawE2(const GUIVisualizationSettings& s, const GUIVisualizationSettings::Detail d,
437
const double exaggeration, const bool movingGeometryPoints) const {
438
// declare color
439
RGBColor E2Color, textColor;
440
// set color
441
if (drawUsingSelectColor()) {
442
E2Color = s.colorSettings.selectedAdditionalColor;
443
textColor = E2Color.changedBrightness(-32);
444
} else if (areLaneConsecutives(getParentLanes())) {
445
E2Color = s.detectorSettings.E2Color;
446
textColor = RGBColor::BLACK;
447
}
448
// draw parent and child lines
449
drawParentChildLines(s, s.additionalSettings.connectionColor);
450
// push layer matrix
451
GLHelper::pushMatrix();
452
// translate to front
453
drawInLayer(GLO_E2DETECTOR);
454
// set color
455
GLHelper::setColor(E2Color);
456
// draw geometry
457
GUIGeometry::drawGeometry(d, myAdditionalGeometry, s.detectorSettings.E2Width * exaggeration);
458
// draw arrow
459
if (myAdditionalGeometry.getShape().size() > 1) {
460
glTranslated(0, 0, 0.1);
461
GLHelper::drawTriangleAtEnd(myAdditionalGeometry.getShape()[-2], myAdditionalGeometry.getShape()[-1], (double) 0.5, (double) 1, 0.5);
462
}
463
// draw E2 Logo
464
drawE2DetectorLogo(s, d, exaggeration, "E2", textColor);
465
// check if draw geometry points
466
if (movingGeometryPoints) {
467
drawLeftGeometryPoint(s, d, myAdditionalGeometry.getShape().front(), myAdditionalGeometry.getShapeRotations().front(), E2Color);
468
drawRightGeometryPoint(s, d, myAdditionalGeometry.getShape().back(), myAdditionalGeometry.getShapeRotations().back(), E2Color);
469
}
470
// pop layer matrix
471
GLHelper::popMatrix();
472
}
473
474
475
void
476
GNELaneAreaDetector::drawE2PartialLane(const GUIVisualizationSettings& s, const GUIVisualizationSettings::Detail d,
477
const GNESegment* segment, const double offsetFront,
478
const GUIGeometry& geometry, const double exaggeration, const bool movingGeometryPoints) const {
479
// obtain color
480
const RGBColor E2Color = drawUsingSelectColor() ? s.colorSettings.selectedAdditionalColor : s.detectorSettings.E2Color;
481
// push layer matrix
482
GLHelper::pushMatrix();
483
// Start with the drawing of the area traslating matrix to origin
484
glTranslated(0, 0, getType() + offsetFront);
485
// Set color
486
GLHelper::setColor(E2Color);
487
// draw geometry
488
GUIGeometry::drawGeometry(d, geometry, s.detectorSettings.E2Width * exaggeration);
489
// check if draw moving geometry points
490
if (movingGeometryPoints) {
491
if (segment->isFirstSegment()) {
492
// calculate and draw left geometry point
493
myAdditionalContour.calculateContourFirstGeometryPoint(s, d, this, geometry.getShape(),
494
getType(), s.neteditSizeSettings.additionalGeometryPointRadius, 1, true);
495
drawLeftGeometryPoint(s, d, geometry.getShape().front(), geometry.getShapeRotations().front(), E2Color, true);
496
}
497
if (segment->isLastSegment()) {
498
// calculate and draw right geometry point
499
myAdditionalContour.calculateContourLastGeometryPoint(s, d, this, geometry.getShape(),
500
getType(), s.neteditSizeSettings.additionalGeometryPointRadius, 1, true);
501
drawRightGeometryPoint(s, d, geometry.getShape().back(), geometry.getShapeRotations().back(), E2Color, true);
502
// draw arrow
503
if (geometry.getShape().size() > 1) {
504
glTranslated(0, 0, 0.1);
505
GLHelper::drawTriangleAtEnd(geometry.getShape()[-2], geometry.getShape()[-1], (double) 0.5, (double) 1, 0.5);
506
}
507
}
508
}
509
// Pop layer matrix
510
GLHelper::popMatrix();
511
// check if this is the label segment
512
if (segment->isLabelSegment()) {
513
// calculate middle point
514
const double middlePoint = (geometry.getShape().length2D() * 0.5);
515
// calculate position
516
const Position pos = geometry.getShape().positionAtOffset2D(middlePoint);
517
// calculate rotation
518
const double rot = s.getTextAngle((geometry.getShape().rotationDegreeAtOffset(middlePoint) * -1) + 90);
519
// Start pushing matrix
520
GLHelper::pushMatrix();
521
// Traslate to position
522
glTranslated(pos.x(), pos.y(), getType() + offsetFront + 0.1);
523
// rotate
524
glRotated(rot, 0, 0, 1);
525
// move
526
glTranslated(-1, 0, 0);
527
// scale text
528
glScaled(exaggeration, exaggeration, 1);
529
// draw E1 logo
530
GLHelper::drawText("E2 Multilane", Position(), .1, 1.5, RGBColor::BLACK);
531
// pop matrix
532
GLHelper::popMatrix();
533
}
534
535
}
536
537
538
void
539
GNELaneAreaDetector::drawE2PartialJunction(const GUIVisualizationSettings& s, const GUIVisualizationSettings::Detail d,
540
const bool onlyContour, const double offsetFront, const GUIGeometry& geometry,
541
const double exaggeration) const {
542
const bool invalid = geometry.getShape().length() == 2;
543
const double width = s.detectorSettings.E2Width * exaggeration * (invalid ? 0.5 : 1);
544
// Add a draw matrix
545
GLHelper::pushMatrix();
546
// Start with the drawing of the area traslating matrix to origin
547
glTranslated(0, 0, getType() + offsetFront);
548
// Set color of the base
549
if (drawUsingSelectColor()) {
550
GLHelper::setColor(s.colorSettings.selectedAdditionalColor);
551
} else if (invalid) {
552
GLHelper::setColor(RGBColor::RED);
553
} else {
554
GLHelper::setColor(s.detectorSettings.E2Color);
555
}
556
// check if draw only contour
557
if (onlyContour) {
558
GUIGeometry::drawContourGeometry(geometry, width);
559
} else {
560
GUIGeometry::drawGeometry(d, geometry, width);
561
}
562
// Pop last matrix
563
GLHelper::popMatrix();
564
}
565
566
567
void
568
GNELaneAreaDetector::setAttribute(SumoXMLAttr key, const std::string& value) {
569
switch (key) {
570
case SUMO_ATTR_LANE:
571
case SUMO_ATTR_LANES:
572
replaceAdditionalParentLanes(value);
573
break;
574
case SUMO_ATTR_POSITION:
575
myStartPosOverLane = parse<double>(value);
576
// update geometry (except for template)
577
if (getParentLanes().size() > 0) {
578
updateGeometry();
579
}
580
break;
581
case SUMO_ATTR_ENDPOS:
582
myEndPosPosOverLane = parse<double>(value);
583
// update geometry (except for template)
584
if (getParentLanes().size() > 0) {
585
updateGeometry();
586
}
587
break;
588
case SUMO_ATTR_TLID:
589
myTrafficLight = value;
590
break;
591
case SUMO_ATTR_LENGTH:
592
myEndPosPosOverLane = (myStartPosOverLane + parse<double>(value));
593
// update geometry (except for template)
594
if (getParentLanes().size() > 0) {
595
updateGeometry();
596
}
597
break;
598
case SUMO_ATTR_HALTING_TIME_THRESHOLD:
599
myTimeThreshold = TIME2STEPS(parse<double>(value));
600
break;
601
case SUMO_ATTR_HALTING_SPEED_THRESHOLD:
602
mySpeedThreshold = parse<double>(value);
603
break;
604
case SUMO_ATTR_JAM_DIST_THRESHOLD:
605
myJamThreshold = parse<double>(value);
606
break;
607
case SUMO_ATTR_SHOW_DETECTOR:
608
myShow = parse<bool>(value);
609
break;
610
default:
611
setDetectorAttribute(key, value);
612
break;
613
}
614
}
615
616
/****************************************************************************/
617
618