Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
eclipse
GitHub Repository: eclipse/sumo
Path: blob/main/src/netedit/elements/additional/GNEOverheadWire.cpp
169684 views
1
/****************************************************************************/
2
// Eclipse SUMO, Simulation of Urban MObility; see https://eclipse.dev/sumo
3
// Copyright (C) 2001-2025 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/GNENet.h>
23
#include <netedit/GNESegment.h>
24
#include <netedit/GNEUndoList.h>
25
#include <netedit/GNEViewNet.h>
26
#include <netedit/changes/GNEChange_Attribute.h>
27
#include <netedit/changes/GNEChange_Connection.h>
28
#include <netedit/elements/network/GNEConnection.h>
29
#include <utils/gui/div/GLHelper.h>
30
#include <utils/gui/globjects/GLIncludes.h>
31
#include <utils/gui/div/GUIGlobalViewObjectsHandler.h>
32
33
#include "GNEOverheadWire.h"
34
#include "GNEAdditionalHandler.h"
35
36
// ===========================================================================
37
// member method definitions
38
// ===========================================================================
39
40
GNEOverheadWire::GNEOverheadWire(GNENet* net) :
41
GNEAdditional("", net, "", SUMO_TAG_OVERHEAD_WIRE_SECTION, "") {
42
}
43
44
45
GNEOverheadWire::GNEOverheadWire(const std::string& id, GNENet* net, const std::string& filename, std::vector<GNELane*> lanes, GNEAdditional* substation,
46
const double startPos, const double endPos, const bool friendlyPos, const std::vector<std::string>& forbiddenInnerLanes,
47
const Parameterised::Map& parameters) :
48
GNEAdditional(id, net, filename, SUMO_TAG_OVERHEAD_WIRE_SECTION, ""),
49
Parameterised(parameters),
50
myStartPos(startPos),
51
myEndPos(endPos),
52
myFriendlyPosition(friendlyPos),
53
myForbiddenInnerLanes(forbiddenInnerLanes) {
54
// set parents
55
setParents<GNELane*>(lanes);
56
setParent<GNEAdditional*>(substation);
57
// update centering boundary without updating grid
58
updateCenteringBoundary(false);
59
}
60
61
62
GNEOverheadWire::~GNEOverheadWire() {
63
}
64
65
66
GNEMoveOperation*
67
GNEOverheadWire::getMoveOperation() {
68
// check modes and detector type
69
if (myNet->getViewNet()->getEditModes().isCurrentSupermodeNetwork() &&
70
(myNet->getViewNet()->getEditModes().networkEditMode == NetworkEditMode::NETWORK_MOVE)) {
71
return getMoveOperationMultiLane(myStartPos, myEndPos);
72
} else {
73
return nullptr;
74
}
75
}
76
77
78
void
79
GNEOverheadWire::writeAdditional(OutputDevice& device) const {
80
device.openTag(SUMO_TAG_OVERHEAD_WIRE_SECTION);
81
device.writeAttr(SUMO_ATTR_ID, getID());
82
device.writeAttr(SUMO_ATTR_SUBSTATIONID, getParentAdditionals().front()->getID());
83
device.writeAttr(SUMO_ATTR_LANES, getAttribute(SUMO_ATTR_LANES));
84
device.writeAttr(SUMO_ATTR_STARTPOS, myStartPos);
85
device.writeAttr(SUMO_ATTR_ENDPOS, myEndPos);
86
if (myFriendlyPosition) {
87
device.writeAttr(SUMO_ATTR_FRIENDLY_POS, myFriendlyPosition);
88
}
89
if (!myForbiddenInnerLanes.empty()) {
90
device.writeAttr(SUMO_ATTR_OVERHEAD_WIRE_FORBIDDEN, myForbiddenInnerLanes);
91
}
92
// write parameters
93
writeParams(device);
94
device.closeTag();
95
}
96
97
98
bool
99
GNEOverheadWire::isAdditionalValid() const {
100
// first check if there is connection between all consecutive lanes
101
if (areLaneConsecutives(getParentLanes())) {
102
// with friendly position enabled position are "always fixed"
103
if (myFriendlyPosition) {
104
return true;
105
} else {
106
return (myStartPos >= 0) &&
107
(myEndPos >= 0) &&
108
((myStartPos) <= getParentLanes().front()->getParentEdge()->getNBEdge()->getFinalLength()) &&
109
((myEndPos) <= getParentLanes().back()->getParentEdge()->getNBEdge()->getFinalLength());
110
}
111
} else {
112
return false;
113
}
114
}
115
116
117
std::string
118
GNEOverheadWire::getAdditionalProblem() const {
119
// declare variable for error position
120
std::string errorFirstLanePosition, separator, errorLastLanePosition;
121
// abort if lanes aren't consecutives
122
if (!areLaneConsecutives(getParentLanes())) {
123
return TL("lanes aren't consecutives");
124
}
125
// abort if lanes aren't connected
126
if (!areLaneConnected(getParentLanes())) {
127
return TL("lanes aren't connected");
128
}
129
// check positions over first lane
130
if (myStartPos < 0) {
131
errorFirstLanePosition = (toString(SUMO_ATTR_STARTPOS) + " < 0");
132
}
133
if (myStartPos > getParentLanes().front()->getParentEdge()->getNBEdge()->getFinalLength()) {
134
errorFirstLanePosition = (toString(SUMO_ATTR_STARTPOS) + TL(" > lanes's length"));
135
}
136
// check positions over last lane
137
if (myEndPos < 0) {
138
errorLastLanePosition = (toString(SUMO_ATTR_ENDPOS) + " < 0");
139
}
140
if (myEndPos > getParentLanes().back()->getParentEdge()->getNBEdge()->getFinalLength()) {
141
errorLastLanePosition = (toString(SUMO_ATTR_ENDPOS) + TL(" > lanes's length"));
142
}
143
// check separator
144
if ((errorFirstLanePosition.size() > 0) && (errorLastLanePosition.size() > 0)) {
145
separator = TL(" and ");
146
}
147
// return error message
148
return errorFirstLanePosition + separator + errorLastLanePosition;
149
}
150
151
152
void
153
GNEOverheadWire::fixAdditionalProblem() {
154
if (!areLaneConsecutives(getParentLanes())) {
155
// build connections between all consecutive lanes
156
bool foundConnection = true;
157
int i = 0;
158
// iterate over all lanes, and stop if myE2valid is false
159
while (i < ((int)getParentLanes().size() - 1)) {
160
// change foundConnection to false
161
foundConnection = false;
162
// if a connection between "from" lane and "to" lane of connection is found, change myE2valid to true again
163
for (const auto& connection : getParentLanes().at(i)->getParentEdge()->getGNEConnections()) {
164
if ((connection->getLaneFrom() == getParentLanes().at(i)) && (connection->getLaneTo() == getParentLanes().at(i + 1))) {
165
foundConnection = true;
166
}
167
}
168
// if connection wasn't found
169
if (!foundConnection) {
170
// create new connection manually
171
NBEdge::Connection newCon(getParentLanes().at(i)->getIndex(), getParentLanes().at(i + 1)->getParentEdge()->getNBEdge(), getParentLanes().at(i + 1)->getIndex());
172
// allow to undo creation of new lane
173
myNet->getViewNet()->getUndoList()->add(new GNEChange_Connection(getParentLanes().at(i)->getParentEdge(), newCon, false, true), true);
174
}
175
// update lane iterator
176
i++;
177
}
178
} else {
179
// declare new positions
180
double newPositionOverLane = myStartPos;
181
double newEndPositionOverLane = myEndPos;
182
// fix pos and length checkAndFixDetectorPosition
183
GNEAdditionalHandler::fixMultiLanePosition(
184
newPositionOverLane, getParentLanes().front()->getParentEdge()->getNBEdge()->getFinalLength(),
185
newEndPositionOverLane, getParentLanes().back()->getParentEdge()->getNBEdge()->getFinalLength());
186
// set new position and endPosition
187
setAttribute(SUMO_ATTR_STARTPOS, toString(newPositionOverLane), myNet->getViewNet()->getUndoList());
188
setAttribute(SUMO_ATTR_ENDPOS, toString(newEndPositionOverLane), myNet->getViewNet()->getUndoList());
189
}
190
}
191
192
193
bool
194
GNEOverheadWire::checkDrawMoveContour() const {
195
return false;
196
}
197
198
199
void
200
GNEOverheadWire::updateGeometry() {
201
// compute path
202
computePathElement();
203
}
204
205
206
Position
207
GNEOverheadWire::getPositionInView() const {
208
return myAdditionalGeometry.getShape().getPolygonCenter();
209
}
210
211
212
void
213
GNEOverheadWire::updateCenteringBoundary(const bool /* updateGrid */) {
214
// nothing to update
215
}
216
217
218
void
219
GNEOverheadWire::splitEdgeGeometry(const double /* splitPosition */, const GNENetworkElement* originalElement, const GNENetworkElement* newElement, GNEUndoList* undoList) {
220
// obtain new list of lanes
221
std::string newLanes = getNewListOfParents(originalElement, newElement);
222
// update Lanes
223
if (newLanes.size() > 0) {
224
setAttribute(SUMO_ATTR_LANES, newLanes, undoList);
225
}
226
}
227
228
229
void
230
GNEOverheadWire::drawGL(const GUIVisualizationSettings& /*s*/) const {
231
// nothing to draw
232
}
233
234
235
void
236
GNEOverheadWire::computePathElement() {
237
// calculate path
238
myNet->getNetworkPathManager()->calculateConsecutivePathLanes(this, getParentLanes());
239
}
240
241
242
void
243
GNEOverheadWire::drawLanePartialGL(const GUIVisualizationSettings& s, const GNESegment* segment, const double offsetFront) const {
244
// calculate overheadWire width
245
const double overheadWireWidth = s.addSize.getExaggeration(s, segment->getLane());
246
// check if E2 can be drawn
247
if (segment->getLane() && myNet->getViewNet()->getDataViewOptions().showAdditionals()) {
248
// get detail level
249
const auto d = s.getDetailLevel(overheadWireWidth);
250
// calculate startPos
251
const double geometryDepartPos = getAttributeDouble(SUMO_ATTR_STARTPOS);
252
// get endPos
253
const double geometryEndPos = getAttributeDouble(SUMO_ATTR_ENDPOS);
254
// declare path geometry
255
GUIGeometry overheadWireGeometry;
256
// update pathGeometry depending of first and last segment
257
if (segment->isFirstSegment() && segment->isLastSegment()) {
258
overheadWireGeometry.updateGeometry(segment->getLane()->getLaneGeometry().getShape(),
259
geometryDepartPos,
260
Position::INVALID,
261
geometryEndPos,
262
Position::INVALID);
263
} else if (segment->isFirstSegment()) {
264
overheadWireGeometry.updateGeometry(segment->getLane()->getLaneGeometry().getShape(),
265
geometryDepartPos,
266
Position::INVALID,
267
-1,
268
Position::INVALID);
269
} else if (segment->isLastSegment()) {
270
overheadWireGeometry.updateGeometry(segment->getLane()->getLaneGeometry().getShape(),
271
-1,
272
Position::INVALID,
273
geometryEndPos,
274
Position::INVALID);
275
} else {
276
overheadWireGeometry = segment->getLane()->getLaneGeometry();
277
}
278
// get both geometries
279
auto overheadWireGeometryTop = overheadWireGeometry;
280
auto overheadWireGeometryBot = overheadWireGeometry;
281
// move to sides
282
overheadWireGeometryTop.moveGeometryToSide(overheadWireWidth * 0.5);
283
overheadWireGeometryBot.moveGeometryToSide(overheadWireWidth * -0.5);
284
// draw geometry only if we'rent in drawForObjectUnderCursor mode
285
if (s.checkDrawAdditional(d, isAttributeCarrierSelected())) {
286
// obtain color
287
const RGBColor overheadWireColorTop = drawUsingSelectColor() ? s.colorSettings.selectedAdditionalColor : s.additionalSettings.overheadWireColorTop;
288
const RGBColor overheadWireColorBot = drawUsingSelectColor() ? s.colorSettings.selectedAdditionalColor : s.additionalSettings.overheadWireColorBot;
289
// push layer matrix
290
GLHelper::pushMatrix();
291
// Start with the drawing of the area traslating matrix to origin
292
glTranslated(0, 0, getType() + offsetFront);
293
// Set top color
294
GLHelper::setColor(overheadWireColorTop);
295
// draw top geometry
296
GUIGeometry::drawGeometry(d, overheadWireGeometryTop, 0.2);
297
// Set bot color
298
GLHelper::setColor(overheadWireColorBot);
299
// draw bot geometry
300
GUIGeometry::drawGeometry(d, overheadWireGeometryBot, 0.2);
301
// draw geometry points
302
if (segment->isFirstSegment() && segment->isLastSegment()) {
303
drawLeftGeometryPoint(s, d, overheadWireGeometry.getShape().front(), overheadWireGeometry.getShapeRotations().front(), overheadWireColorTop, true);
304
drawRightGeometryPoint(s, d, overheadWireGeometry.getShape().back(), overheadWireGeometry.getShapeRotations().back(), overheadWireColorTop, true);
305
} else if (segment->isFirstSegment()) {
306
drawLeftGeometryPoint(s, d, overheadWireGeometry.getShape().front(), overheadWireGeometry.getShapeRotations().front(), overheadWireColorTop, true);
307
} else if (segment->isLastSegment()) {
308
drawRightGeometryPoint(s, d, overheadWireGeometry.getShape().back(), overheadWireGeometry.getShapeRotations().back(), overheadWireColorTop, true);
309
}
310
// Pop layer matrix
311
GLHelper::popMatrix();
312
// draw dotted contour
313
myAdditionalContour.drawDottedContours(s, d, this, s.dottedContourSettings.segmentWidth, true);
314
}
315
// declare trim geometry to draw
316
const auto shape = (segment->isFirstSegment() || segment->isLastSegment()) ? overheadWireGeometry.getShape() : segment->getLane()->getLaneShape();
317
// calculate contour and draw dotted geometry
318
myAdditionalContour.calculateContourExtrudedShape(s, d, this, shape, getType(), overheadWireWidth, 1, true, true, 0, segment, segment->getLane()->getParentEdge());
319
}
320
}
321
322
323
void
324
GNEOverheadWire::drawJunctionPartialGL(const GUIVisualizationSettings& s, const GNESegment* segment, const double offsetFront) const {
325
// calculate overheadWire width
326
const double overheadWireWidth = s.addSize.getExaggeration(s, segment->getPreviousLane());
327
// check if overhead wire can be drawn
328
if (myNet->getViewNet()->getDataViewOptions().showAdditionals() && segment->getPreviousLane() && segment->getNextLane()) {
329
// obtain color
330
const RGBColor overheadWireColorTop = drawUsingSelectColor() ? s.colorSettings.selectedAdditionalColor : s.additionalSettings.overheadWireColorTop;
331
const RGBColor overheadWireColorBot = drawUsingSelectColor() ? s.colorSettings.selectedAdditionalColor : s.additionalSettings.overheadWireColorBot;
332
// declare geometry
333
GUIGeometry overheadWireGeometry({segment->getPreviousLane()->getLaneShape().back(), segment->getNextLane()->getLaneShape().front()});
334
// get detail level
335
const auto d = s.getDetailLevel(1);
336
// check if exist connection
337
if (segment->getPreviousLane()->getLane2laneConnections().exist(segment->getNextLane())) {
338
overheadWireGeometry = segment->getPreviousLane()->getLane2laneConnections().getLane2laneGeometry(segment->getNextLane());
339
}
340
// get both geometries
341
auto overheadWireGeometryTop = overheadWireGeometry;
342
auto overheadWireGeometryBot = overheadWireGeometry;
343
// move to sides
344
overheadWireGeometryTop.moveGeometryToSide(overheadWireWidth * 0.5);
345
overheadWireGeometryBot.moveGeometryToSide(overheadWireWidth * -0.5);
346
// draw geometry only if we'rent in drawForObjectUnderCursor mode
347
if (s.checkDrawAdditional(d, isAttributeCarrierSelected())) {
348
// Add a draw matrix
349
GLHelper::pushMatrix();
350
// Start with the drawing of the area traslating matrix to origin
351
glTranslated(0, 0, getType() + offsetFront);
352
// Set top color
353
GLHelper::setColor(overheadWireColorTop);
354
// draw top geometry
355
GUIGeometry::drawGeometry(d, overheadWireGeometryTop, 0.2);
356
// Set bot color
357
GLHelper::setColor(overheadWireColorBot);
358
// draw bot geometry
359
GUIGeometry::drawGeometry(d, overheadWireGeometryBot, 0.2);
360
// Pop last matrix
361
GLHelper::popMatrix();
362
// draw dotted contour
363
myAdditionalContour.drawDottedContours(s, d, this, s.dottedContourSettings.segmentWidth, true);
364
}
365
// draw contours
366
if (segment->getPreviousLane()->getLane2laneConnections().exist(segment->getNextLane())) {
367
// get shape
368
const auto& shape = segment->getPreviousLane()->getLane2laneConnections().getLane2laneGeometry(segment->getNextLane()).getShape();
369
// calculate contour and draw dotted geometry
370
myAdditionalContour.calculateContourExtrudedShape(s, d, this, shape, getType(), overheadWireWidth, 1, true, true, 0, segment, segment->getJunction());
371
}
372
}
373
}
374
375
376
std::string
377
GNEOverheadWire::getAttribute(SumoXMLAttr key) const {
378
switch (key) {
379
case SUMO_ATTR_ID:
380
return getMicrosimID();
381
case SUMO_ATTR_SUBSTATIONID:
382
return getParentAdditionals().front()->getID();
383
case SUMO_ATTR_LANES:
384
return parseIDs(getParentLanes());
385
case SUMO_ATTR_STARTPOS:
386
return toString(myStartPos);
387
case SUMO_ATTR_ENDPOS:
388
return toString(myEndPos);
389
case SUMO_ATTR_FRIENDLY_POS:
390
return toString(myFriendlyPosition);
391
case SUMO_ATTR_OVERHEAD_WIRE_FORBIDDEN:
392
return toString(myForbiddenInnerLanes);
393
case GNE_ATTR_SHIFTLANEINDEX:
394
return "";
395
default:
396
return getCommonAttribute(this, key);
397
}
398
}
399
400
401
double
402
GNEOverheadWire::getAttributeDouble(SumoXMLAttr key) const {
403
switch (key) {
404
case SUMO_ATTR_STARTPOS:
405
if (myStartPos < 0) {
406
return 0;
407
} else if (myStartPos > getParentLanes().front()->getParentEdge()->getNBEdge()->getFinalLength()) {
408
return getParentLanes().front()->getParentEdge()->getNBEdge()->getFinalLength();
409
} else {
410
return myStartPos;
411
}
412
case SUMO_ATTR_ENDPOS:
413
if (myEndPos < 0) {
414
return 0;
415
} else if (myEndPos > getParentLanes().back()->getParentEdge()->getNBEdge()->getFinalLength()) {
416
return getParentLanes().back()->getParentEdge()->getNBEdge()->getFinalLength();
417
} else {
418
return myEndPos;
419
}
420
default:
421
throw InvalidArgument(getTagStr() + " doesn't have an attribute of type '" + toString(key) + "'");
422
}
423
}
424
425
426
const Parameterised::Map&
427
GNEOverheadWire::getACParametersMap() const {
428
return getParametersMap();
429
}
430
431
432
void
433
GNEOverheadWire::setAttribute(SumoXMLAttr key, const std::string& value, GNEUndoList* undoList) {
434
switch (key) {
435
case SUMO_ATTR_ID:
436
case SUMO_ATTR_SUBSTATIONID:
437
case SUMO_ATTR_LANES:
438
case SUMO_ATTR_STARTPOS:
439
case SUMO_ATTR_ENDPOS:
440
case SUMO_ATTR_FRIENDLY_POS:
441
case SUMO_ATTR_OVERHEAD_WIRE_FORBIDDEN:
442
GNEChange_Attribute::changeAttribute(this, key, value, undoList);
443
break;
444
default:
445
setCommonAttribute(key, value, undoList);
446
break;
447
}
448
}
449
450
451
bool
452
GNEOverheadWire::isValid(SumoXMLAttr key, const std::string& value) {
453
switch (key) {
454
case SUMO_ATTR_ID:
455
return isValidAdditionalID(value);
456
case SUMO_ATTR_SUBSTATIONID:
457
if (value.empty()) {
458
return false;
459
} else {
460
return (myNet->getAttributeCarriers()->retrieveAdditional(SUMO_TAG_TRACTION_SUBSTATION, value, false) != nullptr);
461
}
462
case SUMO_ATTR_STARTPOS:
463
if (value.empty() || (value == LANE_START)) {
464
return true;
465
} else {
466
return canParse<double>(value);
467
}
468
case SUMO_ATTR_ENDPOS:
469
if (value.empty() || (value == LANE_END)) {
470
return true;
471
} else {
472
return canParse<double>(value);
473
}
474
case SUMO_ATTR_FRIENDLY_POS:
475
return canParse<bool>(value);
476
case SUMO_ATTR_OVERHEAD_WIRE_FORBIDDEN:
477
return true;
478
default:
479
return isCommonValid(key, value);
480
}
481
}
482
483
484
std::string
485
GNEOverheadWire::getPopUpID() const {
486
return getTagStr() + ": " + getID();
487
}
488
489
490
std::string
491
GNEOverheadWire::getHierarchyName() const {
492
return getTagStr();
493
}
494
495
// ===========================================================================
496
// private
497
// ===========================================================================
498
499
void
500
GNEOverheadWire::setAttribute(SumoXMLAttr key, const std::string& value) {
501
switch (key) {
502
case SUMO_ATTR_ID:
503
// update microsimID
504
setAdditionalID(value);
505
break;
506
case SUMO_ATTR_SUBSTATIONID:
507
replaceAdditionalParent(SUMO_TAG_TRACTION_SUBSTATION, value, 0);
508
break;
509
case SUMO_ATTR_LANES:
510
replaceAdditionalParentLanes(value);
511
break;
512
case SUMO_ATTR_STARTPOS:
513
if (value.empty() || (value == LANE_START)) {
514
myStartPos = INVALID_DOUBLE;
515
} else {
516
myStartPos = parse<double>(value);
517
}
518
// update geometry (except for template)
519
if (getParentLanes().size() > 0) {
520
updateGeometry();
521
}
522
break;
523
case SUMO_ATTR_ENDPOS:
524
if (value.empty() || (value == LANE_END)) {
525
myEndPos = INVALID_DOUBLE;
526
} else {
527
myEndPos = parse<double>(value);
528
}
529
// update geometry (except for template)
530
if (getParentLanes().size() > 0) {
531
updateGeometry();
532
}
533
break;
534
case SUMO_ATTR_FRIENDLY_POS:
535
myFriendlyPosition = parse<bool>(value);
536
break;
537
case SUMO_ATTR_OVERHEAD_WIRE_FORBIDDEN:
538
myForbiddenInnerLanes = parse<std::vector<std::string> >(value);
539
break;
540
case GNE_ATTR_SHIFTLANEINDEX:
541
shiftLaneIndex();
542
break;
543
default:
544
setCommonAttribute(this, key, value);
545
break;
546
}
547
}
548
549
void
550
GNEOverheadWire::setMoveShape(const GNEMoveResult& moveResult) {
551
if ((moveResult.operationType == GNEMoveOperation::OperationType::SINGLE_LANE_MOVE_FIRST) ||
552
(moveResult.operationType == GNEMoveOperation::OperationType::MULTIPLE_LANES_MOVE_FIRST)) {
553
// change only start position
554
myStartPos = moveResult.newFirstPos;
555
} else if ((moveResult.operationType == GNEMoveOperation::OperationType::SINGLE_LANE_MOVE_LAST) ||
556
(moveResult.operationType == GNEMoveOperation::OperationType::MULTIPLE_LANES_MOVE_LAST)) {
557
// change only end position
558
myEndPos = moveResult.newFirstPos;
559
} else {
560
// change both position
561
myStartPos = moveResult.newFirstPos;
562
myEndPos = moveResult.newLastPos;
563
}
564
// update geometry
565
updateGeometry();
566
}
567
568
569
void
570
GNEOverheadWire::commitMoveShape(const GNEMoveResult& moveResult, GNEUndoList* undoList) {
571
// begin change attribute
572
undoList->begin(this, "position of " + getTagStr());
573
// set attributes depending of operation type
574
if ((moveResult.operationType == GNEMoveOperation::OperationType::SINGLE_LANE_MOVE_FIRST) ||
575
(moveResult.operationType == GNEMoveOperation::OperationType::MULTIPLE_LANES_MOVE_FIRST)) {
576
// set only start position
577
setAttribute(SUMO_ATTR_STARTPOS, toString(moveResult.newFirstPos), undoList);
578
} else if ((moveResult.operationType == GNEMoveOperation::OperationType::SINGLE_LANE_MOVE_LAST) ||
579
(moveResult.operationType == GNEMoveOperation::OperationType::MULTIPLE_LANES_MOVE_LAST)) {
580
// set only end position
581
setAttribute(SUMO_ATTR_ENDPOS, toString(moveResult.newFirstPos), undoList);
582
} else {
583
// set both positions
584
setAttribute(SUMO_ATTR_STARTPOS, toString(moveResult.newFirstPos), undoList);
585
setAttribute(SUMO_ATTR_ENDPOS, toString(moveResult.newLastPos), undoList);
586
}
587
// end change attribute
588
undoList->end();
589
}
590
591
592
double
593
GNEOverheadWire::getStartGeometryPositionOverLane() const {
594
// get lane final and shape length
595
const double laneLength = getParentLanes().front()->getParentEdge()->getNBEdge()->getFinalLength();
596
// get startPosition
597
double fixedPos = myStartPos;
598
// adjust fixedPos
599
if (fixedPos < 0) {
600
fixedPos += laneLength;
601
}
602
fixedPos *= getParentLanes().front()->getLengthGeometryFactor();
603
// return depending of fixedPos
604
if (fixedPos < 0) {
605
return 0;
606
} else if (fixedPos > (getParentLanes().front()->getLaneShapeLength() - POSITION_EPS)) {
607
return (getParentLanes().front()->getLaneShapeLength() - POSITION_EPS);
608
} else {
609
return fixedPos;
610
}
611
}
612
613
614
double
615
GNEOverheadWire::getEndGeometryPositionOverLane() const {
616
// get lane final and shape length
617
const double laneLength = getParentLanes().back()->getParentEdge()->getNBEdge()->getFinalLength();
618
// get endPosition
619
double fixedPos = myEndPos;
620
// adjust fixedPos
621
if (fixedPos < 0) {
622
fixedPos += laneLength;
623
}
624
fixedPos *= getParentLanes().back()->getLengthGeometryFactor();
625
// return depending of fixedPos
626
if (fixedPos < POSITION_EPS) {
627
return POSITION_EPS;
628
} else if (fixedPos > getParentLanes().back()->getLaneShapeLength()) {
629
return getParentLanes().back()->getLaneShapeLength();
630
} else {
631
return fixedPos;
632
}
633
}
634
635
/****************************************************************************/
636
637