Line data Source code
1 : /****************************************************************************/
2 : // Eclipse SUMO, Simulation of Urban MObility; see https://eclipse.dev/sumo
3 : // Copyright (C) 2001-2024 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 GUIOverheadWire.cpp
15 : /// @author Jakub Sevcik (RICE)
16 : /// @author Jan Prikryl (RICE)
17 : /// @author Mirko Barthauer
18 : /// @date 2019-12-15
19 : ///
20 : // The gui-version of a MSOverheadWire
21 : /****************************************************************************/
22 : #include <config.h>
23 :
24 : #include <string>
25 : #include <utils/common/MsgHandler.h>
26 : #include <utils/geom/PositionVector.h>
27 : #include <utils/geom/Boundary.h>
28 : #include <utils/geom/GeomHelper.h>
29 : #include <utils/gui/div/GLHelper.h>
30 : #include <utils/common/ToString.h>
31 : #include <utils/traction_wire/Node.h>
32 : #include <microsim/MSNet.h>
33 : #include <microsim/MSLane.h>
34 : #include <microsim/MSEdge.h>
35 : #include <utils/gui/globjects/GUIGLObjectPopupMenu.h>
36 : #include <utils/gui/windows/GUIAppEnum.h>
37 : #include <gui/GUIGlobals.h>
38 : #include <utils/gui/div/GUIParameterTableWindow.h>
39 : #include <gui/GUIApplicationWindow.h>
40 : #include <microsim/logging/FunctionBinding.h>
41 : #include <utils/gui/div/GUIGlobalSelection.h>
42 : #include <foreign/fontstash/fontstash.h>
43 : #include <utils/gui/globjects/GLIncludes.h>
44 : #include <utils/vehicle/SUMOVehicle.h>
45 : #include <microsim/MSVehicleType.h>
46 : #include "GUINet.h"
47 : #include "GUIEdge.h"
48 : #include "GUIPerson.h"
49 : #include "GUIOverheadWire.h"
50 :
51 :
52 : // ===========================================================================
53 : // method definitions
54 : // ===========================================================================
55 12 : GUIOverheadWire::GUIOverheadWire(const std::string& id, MSLane& lane, double frompos, double topos, bool voltageSource) :
56 : MSOverheadWire(id, lane, frompos, topos, voltageSource),
57 12 : GUIGlObject_AbstractAdd(GLO_OVERHEAD_WIRE_SEGMENT, id, GUIIconSubSys::getIcon(GUIIcon::OVERHEADWIRE)) {
58 : myFGShape = lane.getShape();
59 24 : myFGShape = myFGShape.getSubpart(
60 : lane.interpolateLanePosToGeometryPos(frompos),
61 : lane.interpolateLanePosToGeometryPos(topos));
62 12 : myFGShapeRotations.reserve(myFGShape.size() - 1);
63 12 : myFGShapeLengths.reserve(myFGShape.size() - 1);
64 12 : int e = (int)myFGShape.size() - 1;
65 24 : for (int i = 0; i < e; ++i) {
66 12 : const Position& f = myFGShape[i];
67 12 : const Position& s = myFGShape[i + 1];
68 12 : myFGShapeLengths.push_back(f.distanceTo(s));
69 12 : myFGShapeRotations.push_back((double)atan2((s.x() - f.x()), (f.y() - s.y())) * (double) 180.0 / (double)M_PI);
70 : }
71 : PositionVector tmp = myFGShape;
72 12 : tmp.move2side(1.5);
73 :
74 : // position of the centre of the lane + move2side
75 : //myFGSignPos = tmp.getLineCenter();
76 :
77 : // position of beginning of the lane + move2side (2 equivallent commands ?)
78 : //myFGSignPos = tmp.positionAtOffset(double(0.0));
79 12 : myFGSignPos = tmp[0];
80 :
81 12 : myFGSignRot = 0;
82 12 : if (tmp.length() != 0) {
83 12 : myFGSignRot = myFGShape.rotationDegreeAtOffset(double((myFGShape.length() / 2.)));
84 12 : const double rotSign = MSGlobals::gLefthand ? -1 : 1;
85 12 : myFGSignRot -= 90 * rotSign;
86 : }
87 12 : }
88 :
89 :
90 24 : GUIOverheadWire::~GUIOverheadWire() {
91 24 : }
92 :
93 1 : GUIOverheadWireClamp::GUIOverheadWireClamp(const std::string& id, MSLane& lane_start, MSLane& lane_end) :
94 1 : GUIGlObject_AbstractAdd(GLO_OVERHEAD_WIRE_SEGMENT, id, GUIIconSubSys::getIcon(GUIIcon::OVERHEADWIRE_CLAMP)) {
95 : myFGShape.clear();
96 1 : myFGShape.push_back(lane_start.getShape().front());
97 1 : myFGShape.push_back(lane_end.getShape().back());
98 1 : }
99 :
100 0 : GUIOverheadWireClamp::~GUIOverheadWireClamp() {
101 0 : }
102 :
103 : GUIParameterTableWindow*
104 0 : GUIOverheadWire::getParameterWindow(GUIMainWindow& app, GUISUMOAbstractView&) {
105 : // Create table items
106 0 : GUIParameterTableWindow* ret = new GUIParameterTableWindow(app, *this);
107 :
108 : // add items
109 0 : ret->mkItem(TL("begin position [m]"), false, myBegPos);
110 0 : ret->mkItem(TL("end position [m]"), false, myEndPos);
111 : //ret->mkItem(TL("voltage [V]"), false, myVoltage);
112 :
113 : // close building
114 0 : ret->closeBuilding();
115 0 : return ret;
116 : }
117 :
118 :
119 : GUIGLObjectPopupMenu*
120 0 : GUIOverheadWire::getPopUpMenu(GUIMainWindow& app, GUISUMOAbstractView& parent) {
121 0 : GUIGLObjectPopupMenu* ret = new GUIGLObjectPopupMenu(app, parent, *this);
122 0 : buildPopupHeader(ret, app);
123 0 : buildCenterPopupEntry(ret);
124 0 : buildNameCopyPopupEntry(ret);
125 0 : buildSelectionPopupEntry(ret);
126 0 : buildShowParamsPopupEntry(ret);
127 0 : buildPositionCopyEntry(ret, app);
128 0 : return ret;
129 : }
130 :
131 :
132 : double
133 28 : GUIOverheadWire::getExaggeration(const GUIVisualizationSettings& s) const {
134 28 : return s.addSize.getExaggeration(s, this);
135 : }
136 :
137 :
138 : Boundary
139 40 : GUIOverheadWire::getCenteringBoundary() const {
140 40 : Boundary b = myFGShape.getBoxBoundary();
141 40 : b.grow(20);
142 40 : return b;
143 0 : }
144 :
145 :
146 : void
147 28 : GUIOverheadWire::drawGL(const GUIVisualizationSettings& s) const {
148 : // Draw overhead wire segment
149 28 : GLHelper::pushName(getGlID());
150 28 : GLHelper::pushMatrix();
151 28 : RGBColor lightgray(211, 211, 211, 255);
152 28 : RGBColor green(76, 170, 50, 255);
153 28 : RGBColor yellow(255, 235, 0, 255);
154 28 : RGBColor yellowCharge(255, 180, 0, 255);
155 28 : RGBColor redCharge(255, 51, 51, 255);
156 28 : RGBColor redChargeOverheadWire(180, 0, 0, 255);
157 :
158 56 : GUIColorScheme scheme = GUIColorScheme("by overhead wire current", RGBColor::BLACK, "road", true);
159 : double range = 200;
160 28 : scheme.clear();
161 28 : scheme.addColor(RGBColor::RED, (0));
162 28 : scheme.addColor(RGBColor::ORANGE, (range * 1 / 6.0));
163 28 : scheme.addColor(RGBColor::YELLOW, (range * 2 / 6.0));
164 28 : scheme.addColor(RGBColor::GREEN, (range * 3 / 6.0));
165 28 : scheme.addColor(RGBColor::CYAN, (range * 4 / 6.0));
166 28 : scheme.addColor(RGBColor::BLUE, (range * 5 / 6.0));
167 56 : scheme.addColor(RGBColor::MAGENTA, (200));
168 :
169 : // draw the area depending if the vehicle is charging
170 28 : glTranslated(0, 0, getType());
171 :
172 : // get relative line thickness
173 28 : const double exaggeration = getExaggeration(s);
174 :
175 : //right catenary
176 28 : double toPos = getEndLanePosition();
177 : double fromPos = 0;
178 : PositionVector myFGShape_aux = myFGShape;
179 28 : const MSLane& lane_aux = getLane();
180 : std::vector<double> myFGShapeRotations_aux;
181 : std::vector<double> myFGShapeLengths_aux;
182 : int e_aux = 0;
183 : Node* node = NULL;
184 : double voltage = 0;
185 :
186 28 : if (myCircuitStartNodePos != NULL) {
187 16 : voltage = myCircuitStartNodePos->getVoltage();
188 16 : GLHelper::setColor(scheme.getColor(MAX2(0.0, voltage - 400)));
189 : }
190 :
191 28 : Circuit* circuit = getCircuit();
192 : // loop over charging vehicles under the overhead wire segment to color the wire segment parts according to the voltage level
193 : // lock access to myChargingVehicles
194 28 : lock();
195 31 : for (auto it = myChargingVehicles.begin(); it != myChargingVehicles.end(); ++it) {
196 : // position of the vehicle on the lane
197 3 : fromPos = (*it)->getPositionOnLane() - ((*it)->getVehicleType().getLength() / 2);
198 3 : if (fromPos < 0) {
199 : fromPos = 0;
200 : };
201 :
202 : myFGShape_aux = myFGShape;
203 6 : myFGShape_aux = myFGShape_aux.getSubpart(
204 : lane_aux.interpolateLanePosToGeometryPos(fromPos),
205 : lane_aux.interpolateLanePosToGeometryPos(toPos));
206 :
207 : myFGShapeRotations_aux.clear();
208 : myFGShapeLengths_aux.clear();
209 :
210 3 : myFGShapeRotations_aux.reserve(myFGShape.size() - 1);
211 3 : myFGShapeLengths_aux.reserve(myFGShape.size() - 1);
212 :
213 3 : e_aux = (int)myFGShape_aux.size() - 1;
214 6 : for (int i = 0; i < e_aux; ++i) {
215 3 : const Position& f_aux = myFGShape_aux[i];
216 3 : const Position& s_aux = myFGShape_aux[i + 1];
217 3 : myFGShapeLengths_aux.push_back(f_aux.distanceTo(s_aux));
218 3 : myFGShapeRotations_aux.push_back((double)atan2((s_aux.x() - f_aux.x()), (f_aux.y() - s_aux.y())) * (double) 180.0 / (double)M_PI);
219 : }
220 :
221 : voltage = 0;
222 3 : if (circuit != nullptr) {
223 : // RICE_CHECK: it caused crash of SUMO GUI often in debug mode and
224 : // vector "_STL_VERIFY(_Mycont->_Myfirst <= _Ptr && _Ptr < _Mycont->_Mylast,
225 : // "can't dereference out of range vector iterator"); "
226 0 : circuit->lock();
227 0 : node = circuit->getNode("pos_" + (*it)->getID());
228 0 : if (node != nullptr) {
229 0 : voltage = node->getVoltage();
230 : }
231 0 : circuit->unlock();
232 : }
233 3 : GLHelper::setColor(scheme.getColor(MAX2(0.0, voltage - 400)));
234 3 : GLHelper::drawBoxLines(myFGShape_aux, myFGShapeRotations_aux, myFGShapeLengths_aux, exaggeration / 8, 0, 0.5);
235 :
236 : toPos = fromPos;
237 : }
238 28 : unlock();
239 :
240 : // coloring the last remaining part of wire's segment
241 : myFGShape_aux = myFGShape;
242 :
243 56 : myFGShape_aux = myFGShape_aux.getSubpart(
244 : lane_aux.interpolateLanePosToGeometryPos(getBeginLanePosition()),
245 : lane_aux.interpolateLanePosToGeometryPos(toPos));
246 :
247 : myFGShapeRotations_aux.clear();
248 : myFGShapeLengths_aux.clear();
249 :
250 28 : myFGShapeRotations_aux.reserve(myFGShape.size() - 1);
251 28 : myFGShapeLengths_aux.reserve(myFGShape.size() - 1);
252 :
253 28 : e_aux = (int)myFGShape_aux.size() - 1;
254 56 : for (int i = 0; i < e_aux; ++i) {
255 28 : const Position& f_aux = myFGShape_aux[i];
256 28 : const Position& s_aux = myFGShape_aux[i + 1];
257 28 : myFGShapeLengths_aux.push_back(f_aux.distanceTo(s_aux));
258 28 : myFGShapeRotations_aux.push_back((double)atan2((s_aux.x() - f_aux.x()), (f_aux.y() - s_aux.y())) * (double) 180.0 / (double)M_PI);
259 : }
260 28 : GLHelper::drawBoxLines(myFGShape_aux, myFGShapeRotations_aux, myFGShapeLengths_aux, exaggeration / 8, 0, 0.5);
261 :
262 :
263 : //left catenary
264 : //coloring of left-side overhead wire segment in case of
265 : // * a vehicle is under the segment
266 : // * a vehicle is at least under the traction substation of the segment
267 : // * no vehicle is connected to the traction substation of the segment
268 28 : if (getElecHybridCount() > 0) {
269 2 : GLHelper::setColor(redChargeOverheadWire);
270 26 : } else if (myTractionSubstation != NULL && myTractionSubstation->getElecHybridCount() > 0) {
271 0 : GLHelper::setColor(yellowCharge);
272 : } else {
273 26 : GLHelper::setColor(green);
274 : }
275 28 : GLHelper::drawBoxLines(myFGShape, myFGShapeRotations, myFGShapeLengths, exaggeration / 8, 0, -0.5);
276 :
277 :
278 : // draw details unless zoomed out to far
279 28 : if (s.scale * exaggeration >= 10 && myVoltageSource) {
280 :
281 : // push charging power matrix
282 0 : GLHelper::pushMatrix();
283 : // draw charging power
284 0 : const double lineAngle = s.getTextAngle(myFGSignRot);
285 0 : glTranslated(myFGSignPos.x(), myFGSignPos.y(), 0);
286 0 : glRotated(-lineAngle, 0, 0, 1);
287 0 : GLHelper::drawText((toString(getTractionSubstation()->getSubstationVoltage()) + " V").c_str(), Position(1.2, 0), .1, 1.f, RGBColor(114, 210, 252), 0, FONS_ALIGN_LEFT);
288 : // pop charging power matrix
289 0 : GLHelper::popMatrix();
290 :
291 : // draw the sign
292 0 : glTranslated(myFGSignPos.x(), myFGSignPos.y(), 0);
293 : int noPoints = 9;
294 0 : if (s.scale * exaggeration > 25) {
295 0 : noPoints = MIN2((int)(9.0 + (s.scale * exaggeration) / 10.0), 36);
296 : }
297 :
298 0 : glScaled(exaggeration, exaggeration, 1);
299 0 : GLHelper::drawFilledCircle((double) 1.1, noPoints);
300 0 : glTranslated(0, 0, .1);
301 :
302 0 : GLHelper::setColor(yellow);
303 0 : GLHelper::drawFilledCircle((double) 0.9, noPoints);
304 :
305 0 : if (s.scale * exaggeration >= 4.5) {
306 0 : GLHelper::drawText("C", Position(), .1, 1.6, lightgray, myFGSignRot);
307 : }
308 :
309 0 : glTranslated(5, 0, 0);
310 :
311 : }
312 :
313 :
314 28 : GLHelper::popMatrix();
315 28 : GLHelper::popName();
316 28 : drawName(getCenteringBoundary().getCenter(), s.scale, s.addName);
317 28 : }
318 :
319 :
320 : GUIParameterTableWindow*
321 0 : GUIOverheadWireClamp::getParameterWindow(GUIMainWindow& app, GUISUMOAbstractView&) {
322 : // Create table items
323 0 : GUIParameterTableWindow* ret = new GUIParameterTableWindow(app, *this);
324 :
325 : // add items
326 : //ret->mkItem(TL("begin position [m]"), false, NAN);
327 : //ret->mkItem(TL("end position [m]"), false, NAN);
328 : //ret->mkItem(TL("voltage [V]"), false, NAN);
329 :
330 : // close building
331 0 : ret->closeBuilding();
332 0 : return ret;
333 : }
334 :
335 :
336 : GUIGLObjectPopupMenu*
337 0 : GUIOverheadWireClamp::getPopUpMenu(GUIMainWindow& app, GUISUMOAbstractView& parent) {
338 0 : GUIGLObjectPopupMenu* ret = new GUIGLObjectPopupMenu(app, parent, *this);
339 0 : buildPopupHeader(ret, app);
340 0 : buildCenterPopupEntry(ret);
341 0 : buildNameCopyPopupEntry(ret);
342 0 : buildSelectionPopupEntry(ret);
343 0 : buildShowParamsPopupEntry(ret);
344 0 : buildPositionCopyEntry(ret, app);
345 0 : return ret;
346 : }
347 :
348 :
349 : double
350 2 : GUIOverheadWireClamp::getExaggeration(const GUIVisualizationSettings& s) const {
351 2 : return s.addSize.getExaggeration(s, this);
352 : }
353 :
354 :
355 : Boundary
356 3 : GUIOverheadWireClamp::getCenteringBoundary() const {
357 3 : Boundary b = myFGShape.getBoxBoundary();
358 3 : b.grow(20);
359 3 : return b;
360 0 : }
361 :
362 :
363 : void
364 2 : GUIOverheadWireClamp::drawGL(const GUIVisualizationSettings& s) const {
365 : // Draw overhead wire segment
366 2 : GLHelper::pushName(getGlID());
367 2 : GLHelper::pushMatrix();
368 2 : RGBColor lightgray(211, 211, 211, 255);
369 2 : RGBColor green(76, 170, 50, 255);
370 2 : RGBColor yellow(255, 235, 0, 255);
371 2 : RGBColor yellowCharge(255, 180, 0, 255);
372 2 : RGBColor redCharge(255, 51, 51, 255);
373 2 : RGBColor redChargeOverheadWire(180, 0, 0, 255);
374 :
375 : // draw the area depending if the vehicle is charging
376 2 : glTranslated(0, 0, getType());
377 :
378 :
379 2 : GLHelper::setColor(redChargeOverheadWire);
380 :
381 :
382 2 : const double exaggeration = getExaggeration(s);
383 : //exaggeration - wide of line
384 :
385 :
386 :
387 : PositionVector myFGShape_aux = myFGShape;
388 : std::vector<double> myFGShapeRotations_aux;
389 : std::vector<double> myFGShapeLengths_aux;
390 :
391 : myFGShapeRotations_aux.clear();
392 : myFGShapeLengths_aux.clear();
393 :
394 2 : myFGShapeRotations_aux.reserve(myFGShape.size() - 1);
395 2 : myFGShapeLengths_aux.reserve(myFGShape.size() - 1);
396 :
397 2 : int e_aux = (int)myFGShape_aux.size() - 1;
398 4 : for (int i = 0; i < e_aux; ++i) {
399 2 : const Position& f_aux = myFGShape_aux[i];
400 2 : const Position& s_aux = myFGShape_aux[i + 1];
401 2 : myFGShapeLengths_aux.push_back(f_aux.distanceTo(s_aux));
402 2 : myFGShapeRotations_aux.push_back((double)atan2((s_aux.x() - f_aux.x()), (f_aux.y() - s_aux.y())) * (double) 180.0 / (double)M_PI);
403 : }
404 :
405 : //GLHelper::setColor(green);
406 2 : GLHelper::drawBoxLines(myFGShape_aux, myFGShapeRotations_aux, myFGShapeLengths_aux, exaggeration / 8, 0, 0.5);
407 :
408 : //GLHelper::drawBoxLines(myFGShape, myFGShapeRotations, myFGShapeLengths, exaggeration / 8, 0, -0.5);
409 :
410 :
411 :
412 2 : GLHelper::popMatrix();
413 2 : GLHelper::popName();
414 2 : drawName(getCenteringBoundary().getCenter(), s.scale, s.addName);
415 2 : }
416 :
417 :
418 : /****************************************************************************/
|