#include <config.h>
#include <foreign/fontstash/fontstash.h>
#include <gui/GUIApplicationWindow.h>
#include <gui/GUIGlobals.h>
#include <microsim/MSEdge.h>
#include <microsim/MSLane.h>
#include <microsim/MSNet.h>
#include <microsim/MSParkingArea.h>
#include <microsim/logging/FunctionBinding.h>
#include <utils/common/MsgHandler.h>
#include <utils/common/ToString.h>
#include <utils/geom/Boundary.h>
#include <utils/geom/GeomHelper.h>
#include <utils/geom/PositionVector.h>
#include <utils/gui/div/GLHelper.h>
#include <utils/gui/div/GUIGlobalSelection.h>
#include <utils/gui/div/GUIParameterTableWindow.h>
#include <utils/gui/globjects/GLIncludes.h>
#include <utils/gui/globjects/GUIGLObjectPopupMenu.h>
#include <utils/gui/windows/GUIAppEnum.h>
#include "GUINet.h"
#include "GUIEdge.h"
#include "GUIPerson.h"
#include "GUIChargingStation.h"
GUIChargingStation::GUIChargingStation(const std::string& id, MSLane& lane, double frompos, double topos, const std::string& name,
double chargingPower, double efficiency, bool chargeInTransit, SUMOTime chargeDelay,
const std::string& chargeType, SUMOTime waitingTime) :
MSChargingStation(id, lane, frompos, topos, name, chargingPower, efficiency, chargeInTransit, chargeDelay, chargeType, waitingTime),
GUIGlObject_AbstractAdd(GLO_CHARGING_STATION, id, GUIIconSubSys::getIcon(GUIIcon::CHARGINGSTATION)) {
initAppearance(lane, frompos, topos);
}
GUIChargingStation::GUIChargingStation(const std::string& id, MSParkingArea* parkingArea, const std::string& name,
double chargingPower, double efficiency, bool chargeInTransit, SUMOTime chargeDelay,
const std::string& chargeType, SUMOTime waitingTime) :
MSChargingStation(id, parkingArea, name, chargingPower, efficiency, chargeInTransit, chargeDelay, chargeType, waitingTime),
GUIGlObject_AbstractAdd(GLO_CHARGING_STATION, id, GUIIconSubSys::getIcon(GUIIcon::CHARGINGSTATION)) {
initAppearance(const_cast<MSLane&>(parkingArea->getLane()), parkingArea->getBeginLanePosition(), parkingArea->getEndLanePosition());
}
GUIChargingStation::~GUIChargingStation() {
}
GUIParameterTableWindow*
GUIChargingStation::getParameterWindow(GUIMainWindow& app, GUISUMOAbstractView&) {
GUIParameterTableWindow* ret = new GUIParameterTableWindow(app, *this);
ret->mkItem(TL("name"), false, getMyName());
ret->mkItem(TL("begin position [m]"), false, myBegPos);
ret->mkItem(TL("end position [m]"), false, myEndPos);
ret->mkItem(TL("stopped vehicles [#]"), true, new FunctionBinding<GUIChargingStation, int>(this, &MSStoppingPlace::getStoppedVehicleNumber));
ret->mkItem(TL("last free pos [m]"), true, new FunctionBinding<GUIChargingStation, double>(this, &MSStoppingPlace::getLastFreePos));
ret->mkItem(TL("charging power [W]"), false, myChargingPower);
ret->mkItem(TL("charging efficiency [#]"), false, myEfficiency);
ret->mkItem(TL("charge in transit [true/false]"), false, myChargeInTransit);
ret->mkItem(TL("charge delay [s]"), false, STEPS2TIME(myChargeDelay));
ret->mkItem(TL("charge type"), false, chargeTypeToString(myChargeType));
ret->mkItem(TL("waiting time [s]"), false, STEPS2TIME(myWaitingTime));
ret->closeBuilding();
return ret;
}
GUIGLObjectPopupMenu*
GUIChargingStation::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
GUIChargingStation::getExaggeration(const GUIVisualizationSettings& s) const {
return s.addSize.getExaggeration(s, this);
}
Boundary
GUIChargingStation::getCenteringBoundary() const {
Boundary b = myFGShape.getBoxBoundary();
b.grow(20);
return b;
}
void
GUIChargingStation::drawGL(const GUIVisualizationSettings& s) const {
GLHelper::pushName(getGlID());
GLHelper::pushMatrix();
glTranslated(0, 0, getType());
RGBColor csColor = (myChargingVehicle)? s.colorSettings.chargingStationColorCharge : s.colorSettings.chargingStationColor;
GLHelper::setColor(csColor);
const double exaggeration = getExaggeration(s);
if(myParkingArea != nullptr) {
const std::vector<MSParkingArea::LotSpaceDefinition>& spaces = myParkingArea->getSpaceOccupancies();
for(const auto& space : spaces) {
GLHelper::drawBoxLine(space.position, space.rotation - 180., space.length, 0.5 * space.width);
}
GLHelper::pushMatrix();
glTranslated(0, 0, .1);
for(const auto& space : spaces) {
GLHelper::drawSpaceOccupancies(exaggeration, space.position, space.rotation,
space.width, space.length, space.vehicle ? true : false);
}
GLHelper::popMatrix();
} else {
GLHelper::drawBoxLines(myFGShape, myFGShapeRotations, myFGShapeLengths, MIN2(1.0, exaggeration));
}
GLHelper::setColor(csColor);
if (s.drawDetail(10, exaggeration)) {
GLHelper::pushMatrix();
const double rotSign = MSGlobals::gLefthand ? 1 : -1;
const double lineAngle = s.getTextAngle(myFGSignRot);
glTranslated(myFGSignPos.x(), myFGSignPos.y(), 0.2);
glRotated(-lineAngle, 0, 0, 1);
const double textOffset = s.flippedTextAngle(rotSign * myFGSignRot) ? -0.5 : -0.1;
GLHelper::drawText((toString(myChargingPower) + " W").c_str(), Position(1.2, textOffset), .1, 1.f, s.colorSettings.chargingStationColor, 0, FONS_ALIGN_LEFT);
GLHelper::popMatrix();
GLHelper::pushMatrix();
glTranslated(myFGSignPos.x(), myFGSignPos.y(), 0.2);
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(s.colorSettings.chargingStationColorSign);
GLHelper::drawFilledCircle((double) 0.9, noPoints);
GLHelper::drawText("C", Position(), .1, 1.6, s.colorSettings.chargingStationColor, myFGSignRot);
GLHelper::popMatrix();
}
if (s.addFullName.show(this) && getMyName() != "") {
GLHelper::drawTextSettings(s.addFullName, getMyName(), myFGSignPos, s.scale, s.getTextAngle(myFGSignRot), GLO_MAX - getType());
}
GLHelper::popMatrix();
GLHelper::popName();
drawName(getCenteringBoundary().getCenter(), s.scale, s.addName, s.angle);
}
void
GUIChargingStation::initAppearance(MSLane& lane, double frompos, double topos) {
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 = (myParkingArea != nullptr) ? myParkingArea->getShape() : myFGShape;
const double rotSign = MSGlobals::gLefthand ? -1 : 1;
const double offset = (myParkingArea != nullptr)? lane.getWidth() : 1.5;
tmp.move2side(offset * rotSign);
myFGSignPos = tmp.getLineCenter();
myFGSignRot = 0;
if (tmp.length() != 0) {
myFGSignRot = myFGShape.rotationDegreeAtOffset(double((tmp.length() / 2.)));
myFGSignRot -= 90 * rotSign;
}
}
const std::string
GUIChargingStation::getOptionalName() const {
return myName;
}