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