Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
eclipse
GitHub Repository: eclipse/sumo
Path: blob/main/src/netedit/elements/additional/GNEOverheadWire.cpp
193904 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 GNEOverheadWire.cpp
15
/// @author Pablo Alvarez Lopez
16
/// @date Nov 2015
17
///
18
//
19
/****************************************************************************/
20
#include <config.h>
21
22
#include <netedit/changes/GNEChange_Attribute.h>
23
#include <netedit/elements/moving/GNEMoveElementLaneDouble.h>
24
#include <netedit/GNENet.h>
25
#include <netedit/GNESegment.h>
26
#include <utils/gui/div/GLHelper.h>
27
28
#include "GNEOverheadWire.h"
29
30
// ===========================================================================
31
// member method definitions
32
// ===========================================================================
33
34
GNEOverheadWire::GNEOverheadWire(GNENet* net) :
35
GNEAdditional(net, SUMO_TAG_OVERHEAD_WIRE_SECTION),
36
myMoveElementLaneDouble(new GNEMoveElementLaneDouble(this, SUMO_ATTR_STARTPOS, myStartPosOverLane,
37
SUMO_ATTR_ENDPOS, myEndPosPosOverLane, myFriendlyPosition)) {
38
}
39
40
41
GNEOverheadWire::GNEOverheadWire(const std::string& id, GNENet* net, FileBucket* fileBucket, std::vector<GNELane*> lanes, GNEAdditional* substation,
42
const double startPos, const double endPos, const bool friendlyPos, const std::vector<std::string>& forbiddenInnerLanes,
43
const Parameterised::Map& parameters) :
44
GNEAdditional(id, net, SUMO_TAG_OVERHEAD_WIRE_SECTION, fileBucket, ""),
45
Parameterised(parameters),
46
myStartPosOverLane(startPos),
47
myEndPosPosOverLane(endPos),
48
myFriendlyPosition(friendlyPos),
49
myForbiddenInnerLanes(forbiddenInnerLanes),
50
myMoveElementLaneDouble(new GNEMoveElementLaneDouble(this, SUMO_ATTR_STARTPOS, myStartPosOverLane,
51
SUMO_ATTR_ENDPOS, myEndPosPosOverLane, myFriendlyPosition)) {
52
// set parents
53
setParents<GNELane*>(lanes);
54
setParent<GNEAdditional*>(substation);
55
// update centering boundary without updating grid
56
updateCenteringBoundary(false);
57
}
58
59
60
GNEOverheadWire::~GNEOverheadWire() {
61
delete myMoveElementLaneDouble;
62
}
63
64
65
GNEMoveElement*
66
GNEOverheadWire::getMoveElement() const {
67
return myMoveElementLaneDouble;
68
}
69
70
71
Parameterised*
72
GNEOverheadWire::getParameters() {
73
return this;
74
}
75
76
77
const Parameterised*
78
GNEOverheadWire::getParameters() const {
79
return this;
80
}
81
82
83
void
84
GNEOverheadWire::writeAdditional(OutputDevice& device) const {
85
device.openTag(SUMO_TAG_OVERHEAD_WIRE_SECTION);
86
// write common additional attributes
87
writeAdditionalAttributes(device);
88
// write move atributes
89
myMoveElementLaneDouble->writeMoveAttributes(device, false);
90
// write specific attributes
91
device.writeAttr(SUMO_ATTR_SUBSTATIONID, getParentAdditionals().front()->getID());
92
if (!myForbiddenInnerLanes.empty()) {
93
device.writeAttr(SUMO_ATTR_OVERHEAD_WIRE_FORBIDDEN, myForbiddenInnerLanes);
94
}
95
// write parameters
96
writeParams(device);
97
device.closeTag();
98
}
99
100
101
bool
102
GNEOverheadWire::isAdditionalValid() const {
103
// only movement problems
104
return myMoveElementLaneDouble->isMoveElementValid();
105
}
106
107
108
std::string
109
GNEOverheadWire::getAdditionalProblem() const {
110
// only movement problems
111
return myMoveElementLaneDouble->getMovingProblem();
112
}
113
114
115
void
116
GNEOverheadWire::fixAdditionalProblem() {
117
// only movement problems
118
return myMoveElementLaneDouble->fixMovingProblem();
119
}
120
121
122
bool
123
GNEOverheadWire::checkDrawMoveContour() const {
124
return false;
125
}
126
127
128
void
129
GNEOverheadWire::updateGeometry() {
130
// compute path
131
computePathElement();
132
}
133
134
135
Position
136
GNEOverheadWire::getPositionInView() const {
137
return myAdditionalGeometry.getShape().getPolygonCenter();
138
}
139
140
141
void
142
GNEOverheadWire::updateCenteringBoundary(const bool /* updateGrid */) {
143
// nothing to update
144
}
145
146
147
void
148
GNEOverheadWire::splitEdgeGeometry(const double /* splitPosition */, const GNENetworkElement* originalElement, const GNENetworkElement* newElement, GNEUndoList* undoList) {
149
// obtain new list of lanes
150
std::string newLanes = getNewListOfParents(originalElement, newElement);
151
// update Lanes
152
if (newLanes.size() > 0) {
153
setAttribute(SUMO_ATTR_LANES, newLanes, undoList);
154
}
155
}
156
157
158
void
159
GNEOverheadWire::drawGL(const GUIVisualizationSettings& /*s*/) const {
160
// nothing to draw
161
}
162
163
164
void
165
GNEOverheadWire::computePathElement() {
166
// calculate path
167
myNet->getNetworkPathManager()->calculateConsecutivePathLanes(this, getParentLanes());
168
}
169
170
171
void
172
GNEOverheadWire::drawLanePartialGL(const GUIVisualizationSettings& s, const GNESegment* segment, const double offsetFront) const {
173
// calculate overheadWire width
174
const double overheadWireWidth = s.addSize.getExaggeration(s, segment->getLane());
175
// check if E2 can be drawn
176
if (segment->getLane() && myNet->getViewNet()->getDataViewOptions().showAdditionals()) {
177
// get detail level
178
const auto d = s.getDetailLevel(overheadWireWidth);
179
// calculate startPos
180
const double geometryDepartPos = getAttributeDouble(SUMO_ATTR_STARTPOS);
181
// get endPos
182
const double geometryEndPos = getAttributeDouble(SUMO_ATTR_ENDPOS);
183
// declare path geometry
184
GUIGeometry overheadWireGeometry;
185
// update pathGeometry depending of first and last segment
186
if (segment->isFirstSegment() && segment->isLastSegment()) {
187
overheadWireGeometry.updateGeometry(segment->getLane()->getLaneGeometry().getShape(),
188
geometryDepartPos,
189
Position::INVALID,
190
geometryEndPos,
191
Position::INVALID);
192
} else if (segment->isFirstSegment()) {
193
overheadWireGeometry.updateGeometry(segment->getLane()->getLaneGeometry().getShape(),
194
geometryDepartPos,
195
Position::INVALID,
196
-1,
197
Position::INVALID);
198
} else if (segment->isLastSegment()) {
199
overheadWireGeometry.updateGeometry(segment->getLane()->getLaneGeometry().getShape(),
200
-1,
201
Position::INVALID,
202
geometryEndPos,
203
Position::INVALID);
204
} else {
205
overheadWireGeometry = segment->getLane()->getLaneGeometry();
206
}
207
// get both geometries
208
auto overheadWireGeometryTop = overheadWireGeometry;
209
auto overheadWireGeometryBot = overheadWireGeometry;
210
// move to sides
211
overheadWireGeometryTop.moveGeometryToSide(overheadWireWidth * 0.5);
212
overheadWireGeometryBot.moveGeometryToSide(overheadWireWidth * -0.5);
213
// draw geometry only if we'rent in drawForObjectUnderCursor mode
214
if (s.checkDrawAdditional(d, isAttributeCarrierSelected())) {
215
// obtain color
216
const RGBColor overheadWireColorTop = drawUsingSelectColor() ? s.colorSettings.selectedAdditionalColor : s.additionalSettings.overheadWireColorTop;
217
const RGBColor overheadWireColorBot = drawUsingSelectColor() ? s.colorSettings.selectedAdditionalColor : s.additionalSettings.overheadWireColorBot;
218
// push layer matrix
219
GLHelper::pushMatrix();
220
// Start with the drawing of the area traslating matrix to origin
221
glTranslated(0, 0, getType() + offsetFront);
222
// Set top color
223
GLHelper::setColor(overheadWireColorTop);
224
// draw top geometry
225
GUIGeometry::drawGeometry(d, overheadWireGeometryTop, 0.2);
226
// Set bot color
227
GLHelper::setColor(overheadWireColorBot);
228
// draw bot geometry
229
GUIGeometry::drawGeometry(d, overheadWireGeometryBot, 0.2);
230
// draw geometry points
231
if (segment->isFirstSegment() && segment->isLastSegment()) {
232
drawLeftGeometryPoint(s, d, overheadWireGeometry.getShape().front(), overheadWireGeometry.getShapeRotations().front(), overheadWireColorTop, true);
233
drawRightGeometryPoint(s, d, overheadWireGeometry.getShape().back(), overheadWireGeometry.getShapeRotations().back(), overheadWireColorTop, true);
234
} else if (segment->isFirstSegment()) {
235
drawLeftGeometryPoint(s, d, overheadWireGeometry.getShape().front(), overheadWireGeometry.getShapeRotations().front(), overheadWireColorTop, true);
236
} else if (segment->isLastSegment()) {
237
drawRightGeometryPoint(s, d, overheadWireGeometry.getShape().back(), overheadWireGeometry.getShapeRotations().back(), overheadWireColorTop, true);
238
}
239
// Pop layer matrix
240
GLHelper::popMatrix();
241
// draw dotted contour
242
myAdditionalContour.drawDottedContours(s, d, this, s.dottedContourSettings.segmentWidth, true);
243
}
244
// declare trim geometry to draw
245
const auto shape = (segment->isFirstSegment() || segment->isLastSegment()) ? overheadWireGeometry.getShape() : segment->getLane()->getLaneShape();
246
// calculate contour and draw dotted geometry
247
myAdditionalContour.calculateContourExtrudedShape(s, d, this, shape, getType(), overheadWireWidth, 1, true, true, 0, segment, segment->getLane()->getParentEdge());
248
}
249
}
250
251
252
void
253
GNEOverheadWire::drawJunctionPartialGL(const GUIVisualizationSettings& s, const GNESegment* segment, const double offsetFront) const {
254
// calculate overheadWire width
255
const double overheadWireWidth = s.addSize.getExaggeration(s, segment->getPreviousLane());
256
// check if overhead wire can be drawn
257
if (myNet->getViewNet()->getDataViewOptions().showAdditionals() && segment->getPreviousLane() && segment->getNextLane()) {
258
// obtain color
259
const RGBColor overheadWireColorTop = drawUsingSelectColor() ? s.colorSettings.selectedAdditionalColor : s.additionalSettings.overheadWireColorTop;
260
const RGBColor overheadWireColorBot = drawUsingSelectColor() ? s.colorSettings.selectedAdditionalColor : s.additionalSettings.overheadWireColorBot;
261
// declare geometry
262
GUIGeometry overheadWireGeometry({segment->getPreviousLane()->getLaneShape().back(), segment->getNextLane()->getLaneShape().front()});
263
// get detail level
264
const auto d = s.getDetailLevel(1);
265
// check if exist connection
266
if (segment->getPreviousLane()->getLane2laneConnections().exist(segment->getNextLane())) {
267
overheadWireGeometry = segment->getPreviousLane()->getLane2laneConnections().getLane2laneGeometry(segment->getNextLane());
268
}
269
// get both geometries
270
auto overheadWireGeometryTop = overheadWireGeometry;
271
auto overheadWireGeometryBot = overheadWireGeometry;
272
// move to sides
273
overheadWireGeometryTop.moveGeometryToSide(overheadWireWidth * 0.5);
274
overheadWireGeometryBot.moveGeometryToSide(overheadWireWidth * -0.5);
275
// draw geometry only if we'rent in drawForObjectUnderCursor mode
276
if (s.checkDrawAdditional(d, isAttributeCarrierSelected())) {
277
// Add a draw matrix
278
GLHelper::pushMatrix();
279
// Start with the drawing of the area traslating matrix to origin
280
glTranslated(0, 0, getType() + offsetFront);
281
// Set top color
282
GLHelper::setColor(overheadWireColorTop);
283
// draw top geometry
284
GUIGeometry::drawGeometry(d, overheadWireGeometryTop, 0.2);
285
// Set bot color
286
GLHelper::setColor(overheadWireColorBot);
287
// draw bot geometry
288
GUIGeometry::drawGeometry(d, overheadWireGeometryBot, 0.2);
289
// Pop last matrix
290
GLHelper::popMatrix();
291
// draw dotted contour
292
myAdditionalContour.drawDottedContours(s, d, this, s.dottedContourSettings.segmentWidth, true);
293
}
294
// draw contours
295
if (segment->getPreviousLane()->getLane2laneConnections().exist(segment->getNextLane())) {
296
// get shape
297
const auto& shape = segment->getPreviousLane()->getLane2laneConnections().getLane2laneGeometry(segment->getNextLane()).getShape();
298
// calculate contour and draw dotted geometry
299
myAdditionalContour.calculateContourExtrudedShape(s, d, this, shape, getType(), overheadWireWidth, 1, true, true, 0, segment, segment->getJunction());
300
}
301
}
302
}
303
304
305
std::string
306
GNEOverheadWire::getAttribute(SumoXMLAttr key) const {
307
switch (key) {
308
case SUMO_ATTR_ID:
309
return getMicrosimID();
310
case SUMO_ATTR_SUBSTATIONID:
311
return getParentAdditionals().front()->getID();
312
case SUMO_ATTR_LANES:
313
return parseIDs(getParentLanes());
314
case SUMO_ATTR_STARTPOS:
315
return toString(myStartPosOverLane);
316
case SUMO_ATTR_ENDPOS:
317
return toString(myEndPosPosOverLane);
318
case SUMO_ATTR_OVERHEAD_WIRE_FORBIDDEN:
319
return toString(myForbiddenInnerLanes);
320
case GNE_ATTR_SHIFTLANEINDEX:
321
return "";
322
default:
323
return myMoveElementLaneDouble->getMovingAttribute(key);
324
}
325
}
326
327
328
double
329
GNEOverheadWire::getAttributeDouble(SumoXMLAttr key) const {
330
switch (key) {
331
case SUMO_ATTR_STARTPOS:
332
if (myStartPosOverLane < 0) {
333
return 0;
334
} else if (myStartPosOverLane > getParentLanes().front()->getParentEdge()->getNBEdge()->getFinalLength()) {
335
return getParentLanes().front()->getParentEdge()->getNBEdge()->getFinalLength();
336
} else {
337
return myStartPosOverLane;
338
}
339
case SUMO_ATTR_ENDPOS:
340
if (myEndPosPosOverLane < 0) {
341
return 0;
342
} else if (myEndPosPosOverLane > getParentLanes().back()->getParentEdge()->getNBEdge()->getFinalLength()) {
343
return getParentLanes().back()->getParentEdge()->getNBEdge()->getFinalLength();
344
} else {
345
return myEndPosPosOverLane;
346
}
347
default:
348
return myMoveElementLaneDouble->getMovingAttributeDouble(key);
349
}
350
}
351
352
353
Position
354
GNEOverheadWire::getAttributePosition(SumoXMLAttr key) const {
355
return myMoveElementLaneDouble->getMovingAttributePosition(key);
356
}
357
358
359
PositionVector
360
GNEOverheadWire::getAttributePositionVector(SumoXMLAttr key) const {
361
return getCommonAttributePositionVector(key);
362
}
363
364
365
void
366
GNEOverheadWire::setAttribute(SumoXMLAttr key, const std::string& value, GNEUndoList* undoList) {
367
switch (key) {
368
case SUMO_ATTR_ID:
369
case SUMO_ATTR_SUBSTATIONID:
370
case SUMO_ATTR_LANES:
371
case SUMO_ATTR_STARTPOS:
372
case SUMO_ATTR_ENDPOS:
373
case SUMO_ATTR_OVERHEAD_WIRE_FORBIDDEN:
374
GNEChange_Attribute::changeAttribute(this, key, value, undoList);
375
break;
376
default:
377
myMoveElementLaneDouble->setMovingAttribute(key, value, undoList);
378
break;
379
}
380
}
381
382
383
bool
384
GNEOverheadWire::isValid(SumoXMLAttr key, const std::string& value) {
385
switch (key) {
386
case SUMO_ATTR_ID:
387
return isValidAdditionalID(value);
388
case SUMO_ATTR_SUBSTATIONID:
389
if (value.empty()) {
390
return false;
391
} else {
392
return (myNet->getAttributeCarriers()->retrieveAdditional(SUMO_TAG_TRACTION_SUBSTATION, value, false) != nullptr);
393
}
394
case SUMO_ATTR_OVERHEAD_WIRE_FORBIDDEN:
395
return true;
396
default:
397
return myMoveElementLaneDouble->isMovingAttributeValid(key, value);
398
}
399
}
400
401
402
std::string
403
GNEOverheadWire::getPopUpID() const {
404
return getTagStr() + ": " + getID();
405
}
406
407
408
std::string
409
GNEOverheadWire::getHierarchyName() const {
410
return getTagStr();
411
}
412
413
// ===========================================================================
414
// private
415
// ===========================================================================
416
417
void
418
GNEOverheadWire::setAttribute(SumoXMLAttr key, const std::string& value) {
419
switch (key) {
420
case SUMO_ATTR_ID:
421
// update microsimID
422
setAdditionalID(value);
423
break;
424
case SUMO_ATTR_SUBSTATIONID:
425
replaceAdditionalParent(SUMO_TAG_TRACTION_SUBSTATION, value, 0);
426
break;
427
case SUMO_ATTR_LANES:
428
replaceAdditionalParentLanes(value);
429
break;
430
case SUMO_ATTR_OVERHEAD_WIRE_FORBIDDEN:
431
myForbiddenInnerLanes = parse<std::vector<std::string> >(value);
432
break;
433
case GNE_ATTR_SHIFTLANEINDEX:
434
shiftLaneIndex();
435
break;
436
default:
437
myMoveElementLaneDouble->setMovingAttribute(key, value);
438
break;
439
}
440
// update geometry (except for template)
441
if (getParentLanes().size() > 0) {
442
updateGeometry();
443
}
444
}
445
446
/****************************************************************************/
447
448