#include <config.h>
#include <string>
#include <utils/common/MsgHandler.h>
#include <utils/geom/PositionVector.h>
#include <utils/geom/Boundary.h>
#include <utils/geom/GeomHelper.h>
#include <utils/gui/div/GLHelper.h>
#include <utils/common/ToString.h>
#include <utils/traction_wire/Node.h>
#include <microsim/MSNet.h>
#include <microsim/MSLane.h>
#include <microsim/MSEdge.h>
#include <utils/gui/globjects/GUIGLObjectPopupMenu.h>
#include <utils/gui/windows/GUIAppEnum.h>
#include <gui/GUIGlobals.h>
#include <utils/gui/div/GUIParameterTableWindow.h>
#include <gui/GUIApplicationWindow.h>
#include <microsim/logging/FunctionBinding.h>
#include <utils/gui/div/GUIGlobalSelection.h>
#include <foreign/fontstash/fontstash.h>
#include <utils/gui/globjects/GLIncludes.h>
#include <utils/vehicle/SUMOVehicle.h>
#include <microsim/MSVehicleType.h>
#include "GUINet.h"
#include "GUIEdge.h"
#include "GUIPerson.h"
#include "GUIOverheadWire.h"
GUIOverheadWire::GUIOverheadWire(const std::string& id, MSLane& lane, double frompos, double topos, bool voltageSource) :
MSOverheadWire(id, lane, frompos, topos, voltageSource),
GUIGlObject_AbstractAdd(GLO_OVERHEAD_WIRE_SEGMENT, id, GUIIconSubSys::getIcon(GUIIcon::OVERHEADWIRE)) {
myFGShape = lane.getShape();
myFGShape = myFGShape.getSubpart(
lane.interpolateLanePosToGeometryPos(frompos),
lane.interpolateLanePosToGeometryPos(topos));
myFGShapeRotations.reserve(myFGShape.size() - 1);
myFGShapeLengths.reserve(myFGShape.size() - 1);
int e = (int)myFGShape.size() - 1;
for (int i = 0; i < e; ++i) {
const Position& f = myFGShape[i];
const Position& s = myFGShape[i + 1];
myFGShapeLengths.push_back(f.distanceTo(s));
myFGShapeRotations.push_back((double)atan2((s.x() - f.x()), (f.y() - s.y())) * (double) 180.0 / (double)M_PI);
}
PositionVector tmp = myFGShape;
tmp.move2side(1.5);
myFGSignPos = tmp[0];
myFGSignRot = 0;
if (tmp.length() != 0) {
myFGSignRot = myFGShape.rotationDegreeAtOffset(double((myFGShape.length() / 2.)));
const double rotSign = MSGlobals::gLefthand ? -1 : 1;
myFGSignRot -= 90 * rotSign;
}
}
GUIOverheadWire::~GUIOverheadWire() {
}
GUIOverheadWireClamp::GUIOverheadWireClamp(const std::string& id, MSLane& lane_start, MSLane& lane_end) :
GUIGlObject_AbstractAdd(GLO_OVERHEAD_WIRE_SEGMENT, id, GUIIconSubSys::getIcon(GUIIcon::OVERHEADWIRE_CLAMP)) {
myFGShape.clear();
myFGShape.push_back(lane_start.getShape().front());
myFGShape.push_back(lane_end.getShape().back());
}
GUIOverheadWireClamp::~GUIOverheadWireClamp() {
}
GUIParameterTableWindow*
GUIOverheadWire::getParameterWindow(GUIMainWindow& app, GUISUMOAbstractView&) {
GUIParameterTableWindow* ret = new GUIParameterTableWindow(app, *this);
ret->mkItem(TL("begin position [m]"), false, myBegPos);
ret->mkItem(TL("end position [m]"), false, myEndPos);
ret->closeBuilding();
return ret;
}
GUIGLObjectPopupMenu*
GUIOverheadWire::getPopUpMenu(GUIMainWindow& app, GUISUMOAbstractView& parent) {
GUIGLObjectPopupMenu* ret = new GUIGLObjectPopupMenu(app, parent, this);
buildPopupHeader(ret, app);
buildCenterPopupEntry(ret);
buildNameCopyPopupEntry(ret);
buildSelectionPopupEntry(ret);
buildShowParamsPopupEntry(ret);
buildPositionCopyEntry(ret, app);
return ret;
}
double
GUIOverheadWire::getExaggeration(const GUIVisualizationSettings& s) const {
return s.addSize.getExaggeration(s, this);
}
Boundary
GUIOverheadWire::getCenteringBoundary() const {
Boundary b = myFGShape.getBoxBoundary();
b.grow(20);
return b;
}
void
GUIOverheadWire::drawGL(const GUIVisualizationSettings& s) const {
GLHelper::pushName(getGlID());
GLHelper::pushMatrix();
RGBColor lightgray(211, 211, 211, 255);
RGBColor green(76, 170, 50, 255);
RGBColor yellow(255, 235, 0, 255);
RGBColor yellowCharge(255, 180, 0, 255);
RGBColor redCharge(255, 51, 51, 255);
RGBColor redChargeOverheadWire(180, 0, 0, 255);
GUIColorScheme scheme = GUIColorScheme("by overhead wire current", RGBColor::BLACK, "road", true);
double range = 200;
scheme.clear();
scheme.addColor(RGBColor::RED, (0));
scheme.addColor(RGBColor::ORANGE, (range * 1 / 6.0));
scheme.addColor(RGBColor::YELLOW, (range * 2 / 6.0));
scheme.addColor(RGBColor::GREEN, (range * 3 / 6.0));
scheme.addColor(RGBColor::CYAN, (range * 4 / 6.0));
scheme.addColor(RGBColor::BLUE, (range * 5 / 6.0));
scheme.addColor(RGBColor::MAGENTA, (200));
glTranslated(0, 0, getType());
const double exaggeration = getExaggeration(s);
double toPos = getEndLanePosition();
double fromPos = 0;
PositionVector myFGShape_aux = myFGShape;
const MSLane& lane_aux = getLane();
std::vector<double> myFGShapeRotations_aux;
std::vector<double> myFGShapeLengths_aux;
int e_aux = 0;
Node* node = NULL;
double voltage = 0;
if (myCircuitStartNodePos != NULL) {
voltage = myCircuitStartNodePos->getVoltage();
GLHelper::setColor(scheme.getColor(MAX2(0.0, voltage - 400)));
}
Circuit* circuit = getCircuit();
lock();
for (auto it = myChargingVehicles.begin(); it != myChargingVehicles.end(); ++it) {
fromPos = (*it)->getPositionOnLane() - ((*it)->getVehicleType().getLength() / 2);
if (fromPos < 0) {
fromPos = 0;
};
myFGShape_aux = myFGShape;
myFGShape_aux = myFGShape_aux.getSubpart(
lane_aux.interpolateLanePosToGeometryPos(fromPos),
lane_aux.interpolateLanePosToGeometryPos(toPos));
myFGShapeRotations_aux.clear();
myFGShapeLengths_aux.clear();
myFGShapeRotations_aux.reserve(myFGShape.size() - 1);
myFGShapeLengths_aux.reserve(myFGShape.size() - 1);
e_aux = (int)myFGShape_aux.size() - 1;
for (int i = 0; i < e_aux; ++i) {
const Position& f_aux = myFGShape_aux[i];
const Position& s_aux = myFGShape_aux[i + 1];
myFGShapeLengths_aux.push_back(f_aux.distanceTo(s_aux));
myFGShapeRotations_aux.push_back((double)atan2((s_aux.x() - f_aux.x()), (f_aux.y() - s_aux.y())) * (double) 180.0 / (double)M_PI);
}
voltage = 0;
if (circuit != nullptr) {
circuit->lock();
node = circuit->getNode("pos_" + (*it)->getID());
if (node != nullptr) {
voltage = node->getVoltage();
}
circuit->unlock();
}
GLHelper::setColor(scheme.getColor(MAX2(0.0, voltage - 400)));
GLHelper::drawBoxLines(myFGShape_aux, myFGShapeRotations_aux, myFGShapeLengths_aux, exaggeration / 8, 0, 0.5);
toPos = fromPos;
}
unlock();
myFGShape_aux = myFGShape;
myFGShape_aux = myFGShape_aux.getSubpart(
lane_aux.interpolateLanePosToGeometryPos(getBeginLanePosition()),
lane_aux.interpolateLanePosToGeometryPos(toPos));
myFGShapeRotations_aux.clear();
myFGShapeLengths_aux.clear();
myFGShapeRotations_aux.reserve(myFGShape.size() - 1);
myFGShapeLengths_aux.reserve(myFGShape.size() - 1);
e_aux = (int)myFGShape_aux.size() - 1;
for (int i = 0; i < e_aux; ++i) {
const Position& f_aux = myFGShape_aux[i];
const Position& s_aux = myFGShape_aux[i + 1];
myFGShapeLengths_aux.push_back(f_aux.distanceTo(s_aux));
myFGShapeRotations_aux.push_back((double)atan2((s_aux.x() - f_aux.x()), (f_aux.y() - s_aux.y())) * (double) 180.0 / (double)M_PI);
}
GLHelper::drawBoxLines(myFGShape_aux, myFGShapeRotations_aux, myFGShapeLengths_aux, exaggeration / 8, 0, 0.5);
if (getElecHybridCount() > 0) {
GLHelper::setColor(redChargeOverheadWire);
} else if (myTractionSubstation != NULL && myTractionSubstation->getElecHybridCount() > 0) {
GLHelper::setColor(yellowCharge);
} else {
GLHelper::setColor(green);
}
GLHelper::drawBoxLines(myFGShape, myFGShapeRotations, myFGShapeLengths, exaggeration / 8, 0, -0.5);
if (s.scale * exaggeration >= 10 && myVoltageSource) {
GLHelper::pushMatrix();
const double lineAngle = s.getTextAngle(myFGSignRot);
glTranslated(myFGSignPos.x(), myFGSignPos.y(), 0);
glRotated(-lineAngle, 0, 0, 1);
GLHelper::drawText((toString(getTractionSubstation()->getSubstationVoltage()) + " V").c_str(), Position(1.2, 0), .1, 1.f, RGBColor(114, 210, 252), 0, FONS_ALIGN_LEFT);
GLHelper::popMatrix();
glTranslated(myFGSignPos.x(), myFGSignPos.y(), 0);
int noPoints = 9;
if (s.scale * exaggeration > 25) {
noPoints = MIN2((int)(9.0 + (s.scale * exaggeration) / 10.0), 36);
}
glScaled(exaggeration, exaggeration, 1);
GLHelper::drawFilledCircle((double) 1.1, noPoints);
glTranslated(0, 0, .1);
GLHelper::setColor(yellow);
GLHelper::drawFilledCircle((double) 0.9, noPoints);
if (s.scale * exaggeration >= 4.5) {
GLHelper::drawText("C", Position(), .1, 1.6, lightgray, myFGSignRot);
}
glTranslated(5, 0, 0);
}
GLHelper::popMatrix();
GLHelper::popName();
drawName(getCenteringBoundary().getCenter(), s.scale, s.addName);
}
GUIParameterTableWindow*
GUIOverheadWireClamp::getParameterWindow(GUIMainWindow& app, GUISUMOAbstractView&) {
GUIParameterTableWindow* ret = new GUIParameterTableWindow(app, *this);
ret->closeBuilding();
return ret;
}
GUIGLObjectPopupMenu*
GUIOverheadWireClamp::getPopUpMenu(GUIMainWindow& app, GUISUMOAbstractView& parent) {
GUIGLObjectPopupMenu* ret = new GUIGLObjectPopupMenu(app, parent, this);
buildPopupHeader(ret, app);
buildCenterPopupEntry(ret);
buildNameCopyPopupEntry(ret);
buildSelectionPopupEntry(ret);
buildShowParamsPopupEntry(ret);
buildPositionCopyEntry(ret, app);
return ret;
}
double
GUIOverheadWireClamp::getExaggeration(const GUIVisualizationSettings& s) const {
return s.addSize.getExaggeration(s, this);
}
Boundary
GUIOverheadWireClamp::getCenteringBoundary() const {
Boundary b = myFGShape.getBoxBoundary();
b.grow(20);
return b;
}
void
GUIOverheadWireClamp::drawGL(const GUIVisualizationSettings& s) const {
GLHelper::pushName(getGlID());
GLHelper::pushMatrix();
RGBColor lightgray(211, 211, 211, 255);
RGBColor green(76, 170, 50, 255);
RGBColor yellow(255, 235, 0, 255);
RGBColor yellowCharge(255, 180, 0, 255);
RGBColor redCharge(255, 51, 51, 255);
RGBColor redChargeOverheadWire(180, 0, 0, 255);
glTranslated(0, 0, getType());
GLHelper::setColor(redChargeOverheadWire);
const double exaggeration = getExaggeration(s);
PositionVector myFGShape_aux = myFGShape;
std::vector<double> myFGShapeRotations_aux;
std::vector<double> myFGShapeLengths_aux;
myFGShapeRotations_aux.clear();
myFGShapeLengths_aux.clear();
myFGShapeRotations_aux.reserve(myFGShape.size() - 1);
myFGShapeLengths_aux.reserve(myFGShape.size() - 1);
int e_aux = (int)myFGShape_aux.size() - 1;
for (int i = 0; i < e_aux; ++i) {
const Position& f_aux = myFGShape_aux[i];
const Position& s_aux = myFGShape_aux[i + 1];
myFGShapeLengths_aux.push_back(f_aux.distanceTo(s_aux));
myFGShapeRotations_aux.push_back((double)atan2((s_aux.x() - f_aux.x()), (f_aux.y() - s_aux.y())) * (double) 180.0 / (double)M_PI);
}
GLHelper::drawBoxLines(myFGShape_aux, myFGShapeRotations_aux, myFGShapeLengths_aux, exaggeration / 8, 0, 0.5);
GLHelper::popMatrix();
GLHelper::popName();
drawName(getCenteringBoundary().getCenter(), s.scale, s.addName);
}