00001
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024 #ifdef _MSC_VER
00025 #include <windows_config.h>
00026 #else
00027 #include <config.h>
00028 #endif
00029
00030 #include <cmath>
00031 #include <vector>
00032 #include <string>
00033 #include <utils/common/StringUtils.h>
00034 #include <utils/common/SUMOVehicleParameter.h>
00035 #include <microsim/MSVehicle.h>
00036 #include "GUINet.h"
00037 #include "GUIVehicle.h"
00038 #include <gui/GUIApplicationWindow.h>
00039 #include <utils/gui/windows/GUISUMOAbstractView.h>
00040 #include <gui/GUIGlobals.h>
00041 #include <utils/gui/div/GUIParameterTableWindow.h>
00042 #include <utils/gui/windows/GUIAppEnum.h>
00043 #include <microsim/logging/CastingFunctionBinding.h>
00044 #include <microsim/logging/FunctionBinding.h>
00045 #include <microsim/MSVehicleControl.h>
00046 #include <utils/gui/div/GUIGlobalSelection.h>
00047 #include <utils/common/RandHelper.h>
00048 #include <microsim/MSAbstractLaneChangeModel.h>
00049 #include <utils/gui/div/GLHelper.h>
00050 #include <foreign/polyfonts/polyfonts.h>
00051
00052
00053 #ifdef CHECK_MEMORY_LEAKS
00054 #include <foreign/nvwa/debug_new.h>
00055 #endif // CHECK_MEMORY_LEAKS
00056
00057
00058
00059
00060
00061 FXDEFMAP(GUIVehicle::GUIVehiclePopupMenu) GUIVehiclePopupMenuMap[]= {
00062 FXMAPFUNC(SEL_COMMAND, MID_SHOW_ALLROUTES, GUIVehicle::GUIVehiclePopupMenu::onCmdShowAllRoutes),
00063 FXMAPFUNC(SEL_COMMAND, MID_HIDE_ALLROUTES, GUIVehicle::GUIVehiclePopupMenu::onCmdHideAllRoutes),
00064 FXMAPFUNC(SEL_COMMAND, MID_SHOW_CURRENTROUTE, GUIVehicle::GUIVehiclePopupMenu::onCmdShowCurrentRoute),
00065 FXMAPFUNC(SEL_COMMAND, MID_HIDE_CURRENTROUTE, GUIVehicle::GUIVehiclePopupMenu::onCmdHideCurrentRoute),
00066 FXMAPFUNC(SEL_COMMAND, MID_SHOW_BEST_LANES, GUIVehicle::GUIVehiclePopupMenu::onCmdShowBestLanes),
00067 FXMAPFUNC(SEL_COMMAND, MID_HIDE_BEST_LANES, GUIVehicle::GUIVehiclePopupMenu::onCmdHideBestLanes),
00068 FXMAPFUNC(SEL_COMMAND, MID_START_TRACK, GUIVehicle::GUIVehiclePopupMenu::onCmdStartTrack),
00069 FXMAPFUNC(SEL_COMMAND, MID_STOP_TRACK, GUIVehicle::GUIVehiclePopupMenu::onCmdStopTrack),
00070 };
00071
00072
00073 FXIMPLEMENT(GUIVehicle::GUIVehiclePopupMenu, GUIGLObjectPopupMenu, GUIVehiclePopupMenuMap, ARRAYNUMBER(GUIVehiclePopupMenuMap))
00074
00075
00076
00077
00078
00079
00080
00081
00082
00083 double vehiclePoly_PassengerCarBody[] = { .5,0, 0,0, 0,.3, 0.08,.44, 0.25,.5, 0.95,.5, 1.,.4, 1.,-.4, 0.95,-.5, 0.25,-.5, 0.08,-.44, 0,-.3, 0,0, -10000 };
00084 double vehiclePoly_PassengerCarBodyFront[] = { 0.1,0, 0.025,0, 0.025,0.25, 0.27,0.4, 0.27,-.4, 0.025,-0.25, 0.025,0, -10000 };
00085 double vehiclePoly_PassengerFrontGlass[] = { 0.35,0, 0.3,0, 0.3,0.4, 0.43,0.3, 0.43,-0.3, 0.3,-0.4, 0.3,0, -10000 };
00086 double vehiclePoly_PassengerSedanRightGlass[] = { 0.36,-.43, 0.34,-.47, 0.77,-.47, 0.67,-.37, 0.45,-.37, 0.34,-.47, -10000 };
00087 double vehiclePoly_PassengerSedanLeftGlass[] = { 0.36,.43, 0.34,.47, 0.77,.47, 0.67,.37, 0.45,.37, 0.34,.47, -10000 };
00088 double vehiclePoly_PassengerSedanBackGlass[] = { 0.80,0, 0.70,0, 0.70,0.3, 0.83,0.4, 0.83,-.4, 0.70,-.3, 0.70,0, -10000 };
00089 double vehiclePoly_PassengerHatchbackRightGlass[] = { 0.36,-.43, 0.34,-.47, 0.94,-.47, 0.80,-.37, 0.45,-.37, 0.34,-.47, -10000 };
00090 double vehiclePoly_PassengerHatchbackLeftGlass[] = { 0.36,.43, 0.34,.47, 0.94,.47, 0.80,.37, 0.45,.37, 0.34,.47, -10000 };
00091 double vehiclePoly_PassengerHatchbackBackGlass[] = { 0.92,0, 0.80,0, 0.80,0.3, 0.95,0.4, 0.95,-.4, 0.80,-.3, 0.80,0, -10000 };
00092 double vehiclePoly_PassengerWagonRightGlass[] = { 0.36,-.43, 0.34,-.47, 0.94,-.47, 0.87,-.37, 0.45,-.37, 0.34,-.47, -10000 };
00093 double vehiclePoly_PassengerWagonLeftGlass[] = { 0.36,.43, 0.34,.47, 0.94,.47, 0.87,.37, 0.45,.37, 0.34,.47, -10000 };
00094 double vehiclePoly_PassengerWagonBackGlass[] = { 0.92,0, 0.90,0, 0.90,0.3, 0.95,0.4, 0.95,-.4, 0.90,-.3, 0.90,0, -10000 };
00095
00096 double vehiclePoly_PassengerVanBody[] = { .5,0, 0,0, 0,.4, 0.1,.5, 0.97,.5, 1.,.47, 1.,-.47, 0.97,-.5, 0.1,-.5, 0,-.4, 0,0, -10000 };
00097 double vehiclePoly_PassengerVanBodyFront[] = { 0.1,0, 0.025,0, 0.025,0.25, 0.13,0.4, 0.13,-.4, 0.025,-0.25, 0.025,0, -10000 };
00098 double vehiclePoly_PassengerVanFrontGlass[] = { 0.21,0, 0.16,0, 0.16,0.4, 0.29,0.3, 0.29,-0.3, 0.16,-0.4, 0.16,0, -10000 };
00099 double vehiclePoly_PassengerVanRightGlass[] = { 0.36,-.43, 0.20,-.47, 0.98,-.47, 0.91,-.37, 0.31,-.37, 0.20,-.47, -10000 };
00100 double vehiclePoly_PassengerVanLeftGlass[] = { 0.36,.43, 0.20,.47, 0.98,.47, 0.91,.37, 0.31,.37, 0.20,.47, -10000 };
00101 double vehiclePoly_PassengerVanBackGlass[] = { 0.95,0, 0.94,0, 0.94,0.3, 0.98,0.4, 0.98,-.4, 0.94,-.3, 0.94,0, -10000 };
00102
00103 double vehiclePoly_DeliveryMediumRightGlass[] = { 0.21,-.43, 0.20,-.47, 0.38,-.47, 0.38,-.37, 0.31,-.37, 0.20,-.47, -10000 };
00104 double vehiclePoly_DeliveryMediumLeftGlass[] = { 0.21,.43, 0.20,.47, 0.38,.47, 0.38,.37, 0.31,.37, 0.20,.47, -10000 };
00105
00106 double vehiclePoly_TransportBody[] = { .5,0, 0,0, 0,.45, 0.05,.5, 2.25,.5, 2.25,-.5, 0.05,-.5, 0,-.45, 0,0, -10000 };
00107 double vehiclePoly_TransportFrontGlass[] = { 0.1,0, 0.05,0, 0.05,0.45, 0.25,0.4, 0.25,-.4, 0.05,-0.45, 0.05,0, -10000 };
00108 double vehiclePoly_TransportRightGlass[] = { 0.36,-.47, 0.10,-.48, 1.25,-.48, 1.25,-.4, 0.3,-.4, 0.10,-.48, -10000 };
00109 double vehiclePoly_TransportLeftGlass[] = { 0.36,.47, 0.10,.48, 1.25,.48, 1.25,.4, 0.3,.4, 0.10,.48, -10000 };
00110
00111 double vehiclePoly_EVehicleBody[] = { .5,0, 0,0, 0,.3, 0.08,.44, 0.25,.5, 0.75,.5, .92,.44, 1,.3, 1,-.3, .92,-.44, .75,-.5, .25,-.5, 0.08,-.44, 0,-.3, 0,0, -1000 };
00112 double vehiclePoly_EVehicleFrontGlass[] = { .5,0, 0.05,.05, 0.05,.25, 0.13,.39, 0.3,.45, 0.70,.45, .87,.39, .95,.25, .95,-.25, .87,-.39, .70,-.45, .3,-.45, 0.13,-.39, 0.05,-.25, 0.05,0.05, -1000 };
00113
00114 double vehiclePoly_EVehicleBackGlass[] = { 0.65,0, 0.9,0, 0.9,0.4, 0.57,0.3, 0.57,-0.3, 0.9,-0.4, 0.9,0, -10000 };
00115
00116
00117
00118
00119
00120
00121
00122
00123 GUIVehicle::GUIVehiclePopupMenu::GUIVehiclePopupMenu(
00124 GUIMainWindow &app, GUISUMOAbstractView &parent,
00125 GUIGlObject &o)
00126 : GUIGLObjectPopupMenu(app, parent, o) {
00127 }
00128
00129
00130 GUIVehicle::GUIVehiclePopupMenu::~GUIVehiclePopupMenu() throw() {}
00131
00132
00133 long
00134 GUIVehicle::GUIVehiclePopupMenu::onCmdShowAllRoutes(FXObject*,FXSelector,void*) {
00135 assert(myObject->getType()==GLO_VEHICLE);
00136 myParent->showRoute(static_cast<GUIVehicle*>(myObject), -1);
00137 return 1;
00138 }
00139
00140
00141 long
00142 GUIVehicle::GUIVehiclePopupMenu::onCmdHideAllRoutes(FXObject*,FXSelector,void*) {
00143 assert(myObject->getType()==GLO_VEHICLE);
00144 myParent->hideRoute(static_cast<GUIVehicle*>(myObject), -1);
00145 return 1;
00146 }
00147
00148
00149 long
00150 GUIVehicle::GUIVehiclePopupMenu::onCmdShowCurrentRoute(FXObject*,FXSelector,void*) {
00151 assert(myObject->getType()==GLO_VEHICLE);
00152 myParent->showRoute(static_cast<GUIVehicle*>(myObject), 0);
00153 return 1;
00154 }
00155
00156
00157 long
00158 GUIVehicle::GUIVehiclePopupMenu::onCmdShowBestLanes(FXObject*,FXSelector,void*) {
00159 assert(myObject->getType()==GLO_VEHICLE);
00160 myParent->showBestLanes(static_cast<GUIVehicle*>(myObject));
00161 return 1;
00162 }
00163
00164
00165 long
00166 GUIVehicle::GUIVehiclePopupMenu::onCmdHideCurrentRoute(FXObject*,FXSelector,void*) {
00167 assert(myObject->getType()==GLO_VEHICLE);
00168 myParent->hideRoute(static_cast<GUIVehicle*>(myObject), 0);
00169 return 1;
00170 }
00171
00172 long
00173 GUIVehicle::GUIVehiclePopupMenu::onCmdHideBestLanes(FXObject*,FXSelector,void*) {
00174 assert(myObject->getType()==GLO_VEHICLE);
00175 myParent->hideBestLanes(static_cast<GUIVehicle*>(myObject));
00176 return 1;
00177 }
00178
00179 long
00180 GUIVehicle::GUIVehiclePopupMenu::onCmdStartTrack(FXObject*,FXSelector,void*) {
00181 assert(myObject->getType()==GLO_VEHICLE);
00182 myParent->startTrack(static_cast<GUIVehicle*>(myObject)->getGlID());
00183 return 1;
00184 }
00185
00186 long
00187 GUIVehicle::GUIVehiclePopupMenu::onCmdStopTrack(FXObject*,FXSelector,void*) {
00188 assert(myObject->getType()==GLO_VEHICLE);
00189 myParent->stopTrack();
00190 return 1;
00191 }
00192
00193
00194
00195
00196
00197 GUIVehicle::GUIVehicle(GUIGlObjectStorage &idStorage,
00198 SUMOVehicleParameter* pars, const MSRoute* route,
00199 const MSVehicleType* type,
00200 int vehicleIndex) throw(ProcessError)
00201 : MSVehicle(pars, route, type, vehicleIndex),
00202 GUIGlObject(idStorage, "vehicle:"+pars->id) {
00203 myIntCORNMap[MSCORN::CORN_VEH_BLINKER] = 0;
00204 }
00205
00206
00207 GUIVehicle::~GUIVehicle() throw() {
00208
00209 if (myLock.locked()) {
00210 myLock.unlock();
00211 }
00212 }
00213
00214
00215 GUIGLObjectPopupMenu *
00216 GUIVehicle::getPopUpMenu(GUIMainWindow &app,
00217 GUISUMOAbstractView &parent) throw() {
00218 GUIGLObjectPopupMenu *ret = new GUIVehiclePopupMenu(app, parent, *this);
00219 buildPopupHeader(ret, app);
00220 buildCenterPopupEntry(ret);
00221 buildNameCopyPopupEntry(ret);
00222 buildSelectionPopupEntry(ret);
00223
00224 if (parent.amShowingRouteFor(this, 0)) {
00225 new FXMenuCommand(ret, "Hide Current Route", 0, ret, MID_HIDE_CURRENTROUTE);
00226 } else {
00227 new FXMenuCommand(ret, "Show Current Route", 0, ret, MID_SHOW_CURRENTROUTE);
00228 }
00229 if (parent.amShowingRouteFor(this, -1)) {
00230 new FXMenuCommand(ret, "Hide All Routes", 0, ret, MID_HIDE_ALLROUTES);
00231 } else {
00232 new FXMenuCommand(ret, "Show All Routes", 0, ret, MID_SHOW_ALLROUTES);
00233 }
00234 if (parent.amShowingBestLanesFor(this)) {
00235 new FXMenuCommand(ret, "Hide Best Lanes", 0, ret, MID_HIDE_BEST_LANES);
00236 } else {
00237 new FXMenuCommand(ret, "Show Best Lanes", 0, ret, MID_SHOW_BEST_LANES);
00238 }
00239 new FXMenuSeparator(ret);
00240 int trackedID = parent.getTrackedID();
00241 if (trackedID<0||(size_t)trackedID!=getGlID()) {
00242 new FXMenuCommand(ret, "Start Tracking", 0, ret, MID_START_TRACK);
00243 } else {
00244 new FXMenuCommand(ret, "Stop Tracking", 0, ret, MID_STOP_TRACK);
00245 }
00246 new FXMenuSeparator(ret);
00247
00248 buildShowParamsPopupEntry(ret);
00249 buildPositionCopyEntry(ret, false);
00250 return ret;
00251 }
00252
00253
00254 GUIParameterTableWindow *
00255 GUIVehicle::getParameterWindow(GUIMainWindow &app,
00256 GUISUMOAbstractView &) throw() {
00257 GUIParameterTableWindow *ret =
00258 new GUIParameterTableWindow(app, *this, 15);
00259
00260 ret->mkItem("type [NAME]", false, myType->getID());
00261 if (getParameter().repetitionNumber>0) {
00262 ret->mkItem("left same route [#]", false, (unsigned int) getParameter().repetitionNumber);
00263 }
00264 if (getParameter().repetitionOffset>0) {
00265 ret->mkItem("emission period [s]", false, time2string(getParameter().repetitionOffset));
00266 }
00267 ret->mkItem("waiting time [s]", true,
00268 new FunctionBinding<GUIVehicle, SUMOReal>(this, &MSVehicle::getWaitingSeconds));
00269 ret->mkItem("last lane change [s]", true,
00270 new FunctionBinding<GUIVehicle, SUMOReal>(this, &GUIVehicle::getLastLaneChangeOffset));
00271 ret->mkItem("desired depart [s]", false, time2string(getDesiredDepart()));
00272 ret->mkItem("position [m]", true,
00273 new FunctionBinding<GUIVehicle, SUMOReal>(this, &GUIVehicle::getPositionOnLane));
00274 ret->mkItem("speed [m/s]", true,
00275 new FunctionBinding<GUIVehicle, SUMOReal>(this, &GUIVehicle::getSpeed));
00276 ret->mkItem("CO2 (HBEFA) [g/s]", true,
00277 new FunctionBinding<GUIVehicle, SUMOReal>(this, &GUIVehicle::getHBEFA_CO2Emissions));
00278 ret->mkItem("CO (HBEFA) [g/s]", true,
00279 new FunctionBinding<GUIVehicle, SUMOReal>(this, &GUIVehicle::getHBEFA_COEmissions));
00280 ret->mkItem("HC (HBEFA) [g/s]", true,
00281 new FunctionBinding<GUIVehicle, SUMOReal>(this, &GUIVehicle::getHBEFA_HCEmissions));
00282 ret->mkItem("NOx (HBEFA) [g/s]", true,
00283 new FunctionBinding<GUIVehicle, SUMOReal>(this, &GUIVehicle::getHBEFA_NOxEmissions));
00284 ret->mkItem("PMx (HBEFA) [g/s]", true,
00285 new FunctionBinding<GUIVehicle, SUMOReal>(this, &GUIVehicle::getHBEFA_PMxEmissions));
00286 ret->mkItem("fuel (HBEFA) [l/s]", true,
00287 new FunctionBinding<GUIVehicle, SUMOReal>(this, &GUIVehicle::getHBEFA_FuelConsumption));
00288 ret->mkItem("noise (Harmonoise) [dB]", true,
00289 new FunctionBinding<GUIVehicle, SUMOReal>(this, &GUIVehicle::getHarmonoise_NoiseEmissions));
00290
00291 ret->closeBuilding();
00292 return ret;
00293 }
00294
00295
00296 const std::string &
00297 GUIVehicle::getMicrosimID() const throw() {
00298 return getID();
00299 }
00300
00301
00302 bool
00303 GUIVehicle::active() const throw() {
00304 return isOnRoad();
00305 }
00306
00307
00308 void
00309 GUIVehicle::setRemoved() {
00310 myLane = 0;
00311 }
00312
00313
00314 Boundary
00315 GUIVehicle::getCenteringBoundary() const throw() {
00316 Boundary b;
00317 b.add(getPosition());
00318 b.grow(20);
00319 return b;
00320 }
00321
00322
00323
00324
00325
00326
00327
00328
00329
00330
00331 inline void
00332 drawAction_drawVehicleAsTrianglePlus(const GUIVehicle &veh, SUMOReal upscale) {
00333 SUMOReal length = veh.getVehicleType().getLength();
00334 glPushMatrix();
00335 glScaled(upscale, upscale, 1);
00336 if (length<8) {
00337 glScaled(1, length, 1);
00338 glBegin(GL_TRIANGLES);
00339 glVertex2d(0, 0);
00340 glVertex2d(0-1.25, 1);
00341 glVertex2d(0+1.25, 1);
00342 glEnd();
00343 } else {
00344 glBegin(GL_TRIANGLES);
00345 glVertex2d(0, 0);
00346 glVertex2d(0-1.25, 0+2);
00347 glVertex2d(0+1.25, 0+2);
00348 glVertex2d(0-1.25, 2);
00349 glVertex2d(0-1.25, length);
00350 glVertex2d(0+1.25, length);
00351 glVertex2d(0+1.25, 2);
00352 glVertex2d(0-1.25, 2);
00353 glVertex2d(0+1.25, length);
00354 glEnd();
00355 }
00356 glPopMatrix();
00357 }
00358
00359 inline void
00360 drawAction_drawVehicleAsBoxPlus(const GUIVehicle &veh, SUMOReal upscale) {
00361 SUMOReal length = veh.getVehicleType().getLength();
00362 SUMOReal offset = veh.getVehicleType().getGuiOffset();
00363 glPushMatrix();
00364 glRotated(90, 0, 0, 1);
00365
00366 glScaled(1, veh.getVehicleType().getGuiWidth(), 1.);
00367 glScaled(upscale, upscale, 1);
00368 glBegin(GL_TRIANGLE_FAN);
00369 glVertex2d((length-offset)/2., 0);
00370 glVertex2d(offset, 0);
00371 glVertex2d(offset, -.4);
00372 glVertex2d(offset+.1, -.5);
00373 glVertex2d(length, -.5);
00374 glVertex2d(length, .5);
00375 glVertex2d(offset+.1, .5);
00376 glVertex2d(offset, .4);
00377 glVertex2d(offset, 0);
00378 glEnd();
00379 glPopMatrix();
00380 }
00381
00382
00383 void
00384 drawPoly(double *poses, SUMOReal offset) {
00385 glPushMatrix();
00386 glTranslated(0, 0, offset*.01);
00387 glPolygonOffset(0, offset);
00388 glBegin(GL_TRIANGLE_FAN);
00389 int i = 0;
00390 while (poses[i]>-999) {
00391 glVertex2d(poses[i],poses[i+1]);
00392 i = i + 2;
00393 }
00394 glEnd();
00395 glPopMatrix();
00396 }
00397
00398
00399 inline void
00400 drawAction_drawVehicleAsPoly(const GUIVehicle &veh, SUMOReal upscale) {
00401 GLdouble current[4], lighter[4];
00402 glGetDoublev(GL_CURRENT_COLOR, current);
00403 lighter[0] = current[0]+.2;
00404 if (lighter[0]>1) lighter[0] = 1;
00405 lighter[1] = current[1]+.2;
00406 if (lighter[1]>1) lighter[1] = 1;
00407 lighter[2] = current[2]+.2;
00408 if (lighter[2]>1) lighter[2] = 1;
00409 lighter[3] = current[3]+.2;
00410 if (lighter[3]>1) lighter[3] = 1;
00411
00412
00413 SUMOReal length = veh.getVehicleType().getLength();
00414 glPushMatrix();
00415 glRotated(90, 0, 0, 1);
00416 glTranslated(veh.getVehicleType().getGuiOffset(), 0, 0);
00417 glScaled(length-veh.getVehicleType().getGuiOffset(), veh.getVehicleType().getGuiWidth(), 1.);
00418 glScaled(upscale, upscale, 1);
00419 SUMOVehicleShape shape = veh.getVehicleType().getGuiShape();
00420 switch (shape) {
00421 case SVS_UNKNOWN:
00422 drawPoly(vehiclePoly_PassengerCarBody, -4);
00423 glColor3dv(lighter);
00424 drawPoly(vehiclePoly_PassengerCarBodyFront, -4.5);
00425 glColor3d(0, 0, 0);
00426 drawPoly(vehiclePoly_PassengerFrontGlass, -4.5);
00427 break;
00428 case SVS_PEDESTRIAN:
00429
00430 glTranslated(0, 0, -.045);
00431 GLHelper::drawFilledCircle(1);
00432 glTranslated(0, 0, .045);
00433 glScaled(.7, 2, 1);
00434 glTranslated(0, 0, -.04);
00435 glColor3dv(lighter);
00436 GLHelper::drawFilledCircle(1);
00437 glTranslated(0, 0, .04);
00438 break;
00439 case SVS_BICYCLE:
00440 case SVS_MOTORCYCLE: {
00441 SUMOReal offset = 0;
00442 glPushMatrix();
00443 glTranslated(.5, 0, 0);
00444 glScaled(.25/(length-veh.getVehicleType().getGuiOffset()), 1, 1.);
00445 glTranslated(0, 0, -.045);
00446 GLHelper::drawFilledCircle(1);
00447 glScaled(.7, 2, 1);
00448 glTranslated(0, 0, .045);
00449 glTranslated(0, 0, -.04);
00450 glColor3dv(lighter);
00451 GLHelper::drawFilledCircle(1);
00452 glTranslated(0, 0, .04);
00453 glPopMatrix();
00454 }
00455 break;
00456 case SVS_PASSENGER:
00457 case SVS_PASSENGER_SEDAN:
00458 case SVS_PASSENGER_HATCHBACK:
00459 case SVS_PASSENGER_WAGON:
00460 drawPoly(vehiclePoly_PassengerCarBody, -4);
00461 glColor3dv(lighter);
00462 drawPoly(vehiclePoly_PassengerCarBodyFront, -4.5);
00463 glColor3d(0, 0, 0);
00464 drawPoly(vehiclePoly_PassengerFrontGlass, -4.5);
00465 break;
00466 case SVS_PASSENGER_VAN:
00467 drawPoly(vehiclePoly_PassengerVanBody, -4);
00468 glColor3dv(lighter);
00469 drawPoly(vehiclePoly_PassengerVanBodyFront, -4.5);
00470 glColor3d(0, 0, 0);
00471 drawPoly(vehiclePoly_PassengerVanFrontGlass, -4.5);
00472 drawPoly(vehiclePoly_PassengerVanRightGlass, -4.5);
00473 drawPoly(vehiclePoly_PassengerVanLeftGlass, -4.5);
00474 drawPoly(vehiclePoly_PassengerVanBackGlass, -4.5);
00475 break;
00476 case SVS_DELIVERY:
00477 drawPoly(vehiclePoly_PassengerVanBody, -4);
00478 glColor3dv(lighter);
00479 drawPoly(vehiclePoly_PassengerVanBodyFront, -4.5);
00480 glColor3d(0, 0, 0);
00481 drawPoly(vehiclePoly_PassengerVanFrontGlass, -4.5);
00482 drawPoly(vehiclePoly_DeliveryMediumRightGlass, -4.5);
00483 drawPoly(vehiclePoly_DeliveryMediumLeftGlass, -4.5);
00484 break;
00485 case SVS_TRANSPORT:
00486 case SVS_TRANSPORT_SEMITRAILER:
00487 case SVS_TRANSPORT_1TRAILER:
00488 glScaled(1./(length-veh.getVehicleType().getGuiOffset()), 1, 1.);
00489 drawPoly(vehiclePoly_TransportBody, -4);
00490 glColor3d(0, 0, 0);
00491 drawPoly(vehiclePoly_TransportFrontGlass, -4.5);
00492 drawPoly(vehiclePoly_TransportRightGlass, -4.5);
00493 drawPoly(vehiclePoly_TransportLeftGlass, -4.5);
00494 break;
00495 case SVS_BUS:
00496 case SVS_BUS_CITY: {
00497 SUMOReal ml = length - veh.getVehicleType().getGuiOffset();
00498 glScaled(1./(length-veh.getVehicleType().getGuiOffset()), 1, 1.);
00499 glTranslated(0, 0, -.04);
00500 glBegin(GL_TRIANGLE_FAN);
00501 glVertex2d(ml/2., 0);
00502 glVertex2d(0, 0);
00503 glVertex2d(0, -.45);
00504 glVertex2d(0+.05, -.5);
00505 glVertex2d(ml-.05, -.5);
00506 glVertex2d(ml, -.45);
00507 glVertex2d(ml, .45);
00508 glVertex2d(ml-.05, .5);
00509 glVertex2d(0+.05, .5);
00510 glVertex2d(0, .45);
00511 glVertex2d(0, 0);
00512 glEnd();
00513 glTranslated(0, 0, .04);
00514
00515 glTranslated(0, 0, -.045);
00516 glColor3d(0, 0, 0);
00517 glBegin(GL_QUADS);
00518 glVertex2d(0+.05, .48);
00519 glVertex2d(0+.05, -.48);
00520 glVertex2d(0+.15, -.48);
00521 glVertex2d(0+.15, .48);
00522
00523 glVertex2d(ml-.1, .45);
00524 glVertex2d(ml-.1, -.45);
00525 glVertex2d(ml-.05, -.45);
00526 glVertex2d(ml-.05, .45);
00527
00528 glVertex2d(0+.20, .49);
00529 glVertex2d(0+.20, .45);
00530 glVertex2d(ml-.20, .45);
00531 glVertex2d(ml-.20, .49);
00532
00533 glVertex2d(0+.20, -.49);
00534 glVertex2d(0+.20, -.45);
00535 glVertex2d(ml-.20, -.45);
00536 glVertex2d(ml-.20, -.49);
00537
00538 glEnd();
00539 glTranslated(0, 0, .045);
00540 }
00541 break;
00542 case SVS_BUS_OVERLAND:
00543 glScaled(1./(length-veh.getVehicleType().getGuiOffset()), 1, 1.);
00544 glTranslated(0, 0, -.04);
00545 glBegin(GL_TRIANGLE_FAN);
00546 glVertex2d(length/2., 0);
00547 glVertex2d(0, 0);
00548 glVertex2d(0, -.45);
00549 glVertex2d(.05, -.5);
00550 glVertex2d(length-.05, -.5);
00551 glVertex2d(length, -.45);
00552 glVertex2d(length, .45);
00553 glVertex2d(length-.05, .5);
00554 glVertex2d(.05, .5);
00555 glVertex2d(0, .45);
00556 glVertex2d(0, 0);
00557 glEnd();
00558 glTranslated(0, 0, .04);
00559 break;
00560 case SVS_RAIL:
00561 break;
00562 case SVS_RAIL_LIGHT:
00563 break;
00564 case SVS_RAIL_CITY:
00565 break;
00566 case SVS_RAIL_SLOW:
00567 break;
00568 case SVS_RAIL_FAST:
00569 break;
00570 case SVS_RAIL_CARGO:
00571 break;
00572 case SVS_E_VEHICLE:
00573 drawPoly(vehiclePoly_EVehicleBody, -4);
00574 glColor3d(0, 0, 0);
00575 drawPoly(vehiclePoly_EVehicleFrontGlass, -4.5);
00576 glTranslated(0, 0, -.048);
00577 glColor3dv(current);
00578 glBegin(GL_QUADS);
00579 glVertex2d(.3, .5);
00580 glVertex2d(.35, .5);
00581 glVertex2d(.35, -.5);
00582 glVertex2d(.3, -.5);
00583
00584 glVertex2d(.3, -.05);
00585 glVertex2d(.7, -.05);
00586 glVertex2d(.7, .05);
00587 glVertex2d(.3, .05);
00588
00589 glVertex2d(.7, .5);
00590 glVertex2d(.65, .5);
00591 glVertex2d(.65, -.5);
00592 glVertex2d(.7, -.5);
00593 glEnd();
00594 glTranslated(0, 0, .048);
00595
00596 break;
00597 default:
00598 drawPoly(vehiclePoly_PassengerCarBody, -4);
00599 glColor3d(1, 1, 1);
00600 drawPoly(vehiclePoly_PassengerCarBodyFront, -4.5);
00601 glColor3d(0, 0, 0);
00602 drawPoly(vehiclePoly_PassengerFrontGlass, -4.5);
00603 break;
00604 }
00605
00606 switch (shape) {
00607 case SVS_PEDESTRIAN:
00608 break;
00609 case SVS_BICYCLE:
00610
00611 glBegin(GL_TRIANGLE_FAN);
00612 glVertex2d(1/2., 0);
00613 glVertex2d(0, 0);
00614 glVertex2d(0, -.03);
00615 glVertex2d(0+.05, -.05);
00616 glVertex2d(1-.05, -.05);
00617 glVertex2d(1, -.03);
00618 glVertex2d(1, .03);
00619 glVertex2d(1-.05, .05);
00620 glVertex2d(0+.05, .05);
00621 glVertex2d(0, .03);
00622 glVertex2d(0, 0);
00623 glEnd();
00624 break;
00625 case SVS_MOTORCYCLE:
00626
00627 glBegin(GL_TRIANGLE_FAN);
00628 glVertex2d(1/2., 0);
00629 glVertex2d(0, 0);
00630 glVertex2d(0, -.03);
00631 glVertex2d(0+.05, -.2);
00632 glVertex2d(1-.05, -.2);
00633 glVertex2d(1, -.03);
00634 glVertex2d(1, .03);
00635 glVertex2d(1-.05, .2);
00636 glVertex2d(0+.05, .2);
00637 glVertex2d(0, .03);
00638 glVertex2d(0, 0);
00639 glEnd();
00640 break;
00641 case SVS_PASSENGER:
00642 case SVS_PASSENGER_SEDAN:
00643 drawPoly(vehiclePoly_PassengerSedanRightGlass, -4.5);
00644 drawPoly(vehiclePoly_PassengerSedanLeftGlass, -4.5);
00645 drawPoly(vehiclePoly_PassengerSedanBackGlass, -4.5);
00646 break;
00647 case SVS_PASSENGER_HATCHBACK:
00648 drawPoly(vehiclePoly_PassengerHatchbackRightGlass, -4.5);
00649 drawPoly(vehiclePoly_PassengerHatchbackLeftGlass, -4.5);
00650 drawPoly(vehiclePoly_PassengerHatchbackBackGlass, -4.5);
00651 break;
00652 case SVS_PASSENGER_WAGON:
00653 drawPoly(vehiclePoly_PassengerWagonRightGlass, -4.5);
00654 drawPoly(vehiclePoly_PassengerWagonLeftGlass, -4.5);
00655 drawPoly(vehiclePoly_PassengerWagonBackGlass, -4.5);
00656 break;
00657 case SVS_PASSENGER_VAN:
00658 case SVS_DELIVERY:
00659 break;
00660 case SVS_TRANSPORT:
00661 glColor3dv(current);
00662 GLHelper::drawBoxLine(Position2D(2.3, 0), 90., length-veh.getVehicleType().getGuiOffset()-2.3, .5);
00663 break;
00664 case SVS_TRANSPORT_SEMITRAILER:
00665 glColor3dv(current);
00666 GLHelper::drawBoxLine(Position2D(2.8, 0), 90., length-veh.getVehicleType().getGuiOffset()-2.8, .5);
00667 break;
00668 case SVS_TRANSPORT_1TRAILER: {
00669 glColor3dv(current);
00670 SUMOReal l = length-veh.getVehicleType().getGuiOffset()-2.3;
00671 l = l/2.;
00672 GLHelper::drawBoxLine(Position2D(2.3, 0), 90., l, .5);
00673 GLHelper::drawBoxLine(Position2D(2.3+l+.5, 0), 90., l-.5, .5);
00674 break;
00675 }
00676 case SVS_BUS:
00677 case SVS_BUS_CITY:
00678 case SVS_BUS_CITY_FLEXIBLE:
00679 case SVS_BUS_OVERLAND:
00680 case SVS_RAIL:
00681 case SVS_RAIL_LIGHT:
00682 case SVS_RAIL_CITY:
00683 case SVS_RAIL_SLOW:
00684 case SVS_RAIL_FAST:
00685 case SVS_RAIL_CARGO:
00686 case SVS_E_VEHICLE:
00687 break;
00688 default:
00689 drawPoly(vehiclePoly_PassengerSedanRightGlass, -4.5);
00690 drawPoly(vehiclePoly_PassengerSedanLeftGlass, -4.5);
00691 drawPoly(vehiclePoly_PassengerSedanBackGlass, -4.5);
00692 break;
00693 }
00694
00695
00696
00697
00698
00699
00700
00701
00702
00703
00704
00705
00706
00707
00708
00709
00710
00711
00712
00713
00714
00715
00716
00717
00718
00719
00720
00721
00722
00723
00724
00725
00726
00727
00728
00729
00730
00731
00732
00733
00734
00735
00736
00737
00738
00739
00740
00741
00742
00743
00744
00745
00746
00747
00748
00749
00750
00751
00752
00753
00754
00755
00756
00757
00758
00759
00760
00761
00762
00763 glPopMatrix();
00764 }
00765
00766
00767 #define BLINKER_POS_FRONT .5
00768 #define BLINKER_POS_BACK .5
00769
00770 inline void
00771 drawAction_drawVehicleBlinker(const GUIVehicle &veh) {
00772 double dir = (double) veh.getCORNIntValue(MSCORN::CORN_VEH_BLINKER)*veh.getVehicleType().getGuiWidth()*.5;
00773 if (dir==0) {
00774 return;
00775 }
00776 if (veh.getVehicleType().getGuiWidth()<.5) {
00777 return;
00778 }
00779 glColor3d(1.f, .8f, 0);
00780 glPushMatrix();
00781 glTranslated(dir, BLINKER_POS_FRONT+veh.getVehicleType().getGuiOffset(), 0);
00782 GLHelper::drawFilledCircle(.5, 6);
00783 glPopMatrix();
00784 glPushMatrix();
00785 glTranslated(dir, veh.getVehicleType().getLength()-BLINKER_POS_BACK, 0);
00786 GLHelper::drawFilledCircle(.5, 6);
00787 glPopMatrix();
00788 }
00789
00790
00791 inline void
00792 drawAction_drawVehicleName(const GUIVehicle &veh, SUMOReal size) {
00793 glPushMatrix();
00794 glTranslated(0, veh.getVehicleType().getLength() / 2., 0);
00795 glTranslated(0, 0, -.07);
00796 glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
00797 pfSetPosition(0, 0);
00798 pfSetScale(size);
00799 SUMOReal w = pfdkGetStringWidth(veh.getMicrosimID().c_str());
00800 glRotated(180, 0, 1, 0);
00801 glTranslated(-w/2., 0.4, 0);
00802 pfDrawString(veh.getMicrosimID().c_str());
00803 glPopMatrix();
00804 }
00805
00806
00807 void
00808 GUIVehicle::drawGL(const GUIVisualizationSettings &s) const throw() {
00809 glPushMatrix();
00810 Position2D p1 = myLane->getShape().positionAtLengthPosition(myState.pos());
00811 Position2D p2 = myFurtherLanes.size()>0
00812 ? myFurtherLanes.front()->getShape().positionAtLengthPosition(myFurtherLanes.front()->getPartialOccupatorEnd())
00813 : myLane->getShape().positionAtLengthPosition(myState.pos()-myType->getLength());
00814 glTranslated(p1.x(), p1.y(), 0);
00815 glRotated(atan2(p1.x()-p2.x(), p2.y()-p1.y())*180./PI, 0, 0, 1);
00816
00817 glTranslated(0, 0, -.04);
00818
00819 s.vehicleColorer.setGlColor(*this);
00820
00821 if (s.needsGlID) {
00822 glPushName(getGlID());
00823 }
00824
00825
00826
00827
00828
00829
00830
00831
00832
00833
00834
00835 SUMOReal upscale = s.vehicleExaggeration;
00836 switch (s.vehicleQuality) {
00837 case 0:
00838 drawAction_drawVehicleAsTrianglePlus(*this, upscale);
00839 break;
00840 case 1:
00841 drawAction_drawVehicleAsBoxPlus(*this, upscale);
00842 break;
00843 case 2:
00844 default:
00845 drawAction_drawVehicleAsPoly(*this, upscale);
00846 break;
00847 }
00848 glTranslated(0, 0, .04);
00849
00850 if (s.showBlinker) {
00851 glTranslated(0, 0, -.05);
00852 drawAction_drawVehicleBlinker(*this);
00853 glTranslated(0, 0, .05);
00854 }
00855
00856 if (s.drawLaneChangePreference) {
00857
00858
00859
00860
00861
00862
00863
00864
00865
00866
00867
00868
00869
00870
00871
00872
00873
00874
00875
00876
00877
00878
00879 }
00880
00881 if (true) {
00882
00883
00884
00885
00886
00887
00888
00889
00890
00891
00892
00893
00894
00895
00896
00897
00898
00899
00900
00901 }
00902 if (s.drawVehicleName) {
00903 glTranslated(0, 0, -.06);
00904
00905 glColor3d(s.vehicleNameColor.red(), s.vehicleNameColor.green(), s.vehicleNameColor.blue());
00906 drawAction_drawVehicleName(*this, s.vehicleNameSize / s.scale);
00907 glTranslated(0, 0, .06);
00908 }
00909
00910 if (s.needsGlID) {
00911 glPopName();
00912 }
00913 glPopMatrix();
00914 }
00915
00916
00917 const std::vector<MSVehicle::LaneQ> &
00918 GUIVehicle::getBestLanes() const throw() {
00919 myLock.lock();
00920 const std::vector<MSVehicle::LaneQ> &ret = MSVehicle::getBestLanes();
00921 myLock.unlock();
00922 return ret;
00923 }
00924
00925
00926 void
00927 GUIVehicle::setBlinkerInformation() {
00928 if (hasCORNIntValue(MSCORN::CORN_VEH_BLINKER)) {
00929 int blinker = 0;
00930 int state = getLaneChangeModel().getState();
00931 if ((state&LCA_LEFT)!=0) {
00932 blinker = 1;
00933 } else if ((state&LCA_RIGHT)!=0) {
00934 blinker = -1;
00935 } else {
00936 const MSLane &lane = getLane();
00937 MSLinkCont::const_iterator link = lane.succLinkSec(*this, 1, lane, getBestLanesContinuation());
00938 if (link!=lane.getLinkCont().end()&&lane.getLength()-getPositionOnLane()<lane.getMaxSpeed()*(SUMOReal) 7.) {
00939 switch ((*link)->getDirection()) {
00940 case MSLink::LINKDIR_TURN:
00941 case MSLink::LINKDIR_LEFT:
00942 case MSLink::LINKDIR_PARTLEFT:
00943 blinker = 1;
00944 break;
00945 case MSLink::LINKDIR_RIGHT:
00946 case MSLink::LINKDIR_PARTRIGHT:
00947 blinker = -1;
00948 break;
00949 default:
00950 break;
00951 }
00952 }
00953 }
00954 myIntCORNMap[MSCORN::CORN_VEH_BLINKER] = blinker;
00955 }
00956 }
00957
00958
00959 void
00960 GUIVehicle::initShapes() throw() {
00961 }
00962
00963
00964 GUIVehicle::Colorer::Colorer() {
00965 mySchemes.push_back(GUIColorScheme("uniform", RGBColor(1,1,0), "", true));
00966 mySchemes.push_back(GUIColorScheme("given/assigned vehicle color", RGBColor(1,1,0), "", true));
00967 mySchemes.push_back(GUIColorScheme("given/assigned type color", RGBColor(1,1,0), "", true));
00968 mySchemes.push_back(GUIColorScheme("given/assigned route color", RGBColor(1,1,0), "", true));
00969 mySchemes.push_back(GUIColorScheme("depart position as HSV", RGBColor(1,1,0), "", true));
00970 mySchemes.push_back(GUIColorScheme("arrival position as HSV", RGBColor(1,1,0), "", true));
00971 mySchemes.push_back(GUIColorScheme("direction/distance as HSV", RGBColor(1,1,0), "", true));
00972 mySchemes.push_back(GUIColorScheme("by speed", RGBColor(1,0,0)));
00973 mySchemes.back().addColor(RGBColor(0,0,1), (SUMOReal)(150.0/3.6));
00974 mySchemes.push_back(GUIColorScheme("by waiting time", RGBColor(0,0,1)));
00975 mySchemes.back().addColor(RGBColor(1,0,0), (SUMOReal)(5*60));
00976 mySchemes.push_back(GUIColorScheme("by time since last lanechange", RGBColor(1,1,1)));
00977 mySchemes.back().addColor(RGBColor(.5,.5,.5), (SUMOReal)(5*60));
00978 mySchemes.push_back(GUIColorScheme("by max speed", RGBColor(1,0,0)));
00979 mySchemes.back().addColor(RGBColor(0,0,1), (SUMOReal)(150.0/3.6));
00980
00981 mySchemes.push_back(GUIColorScheme("by CO2 emissions (HBEFA)", RGBColor(0,1,0)));
00982 mySchemes.back().addColor(RGBColor(1,0,0), (SUMOReal)5.);
00983 mySchemes.push_back(GUIColorScheme("by CO emissions (HBEFA)", RGBColor(0,1,0)));
00984 mySchemes.back().addColor(RGBColor(1,0,0), (SUMOReal)0.05);
00985 mySchemes.push_back(GUIColorScheme("by PMx emissions (HBEFA)", RGBColor(0,1,0)));
00986 mySchemes.back().addColor(RGBColor(1,0,0), (SUMOReal).005);
00987 mySchemes.push_back(GUIColorScheme("by NOx emissions (HBEFA)", RGBColor(0,1,0)));
00988 mySchemes.back().addColor(RGBColor(1,0,0), (SUMOReal).125);
00989 mySchemes.push_back(GUIColorScheme("by HC emissions (HBEFA)", RGBColor(0,1,0)));
00990 mySchemes.back().addColor(RGBColor(1,0,0), (SUMOReal).02);
00991 mySchemes.push_back(GUIColorScheme("by fuel consumption (HBEFA)", RGBColor(0,1,0)));
00992 mySchemes.back().addColor(RGBColor(1,0,0), (SUMOReal).005);
00993 mySchemes.push_back(GUIColorScheme("by noise emissions (Harmonoise)", RGBColor(0,1,0)));
00994 mySchemes.back().addColor(RGBColor(1,0,0), (SUMOReal)100.);
00995 mySchemes.push_back(GUIColorScheme("by reroute number", RGBColor(1,0,0)));
00996 mySchemes.back().addColor(RGBColor(1,1,0), (SUMOReal)1.);
00997 mySchemes.back().addColor(RGBColor(1,1,1), (SUMOReal)10.);
00998 }
00999
01000
01001 bool
01002 GUIVehicle::Colorer::setFunctionalColor(const GUIVehicle& vehicle) const {
01003 switch (myActiveScheme) {
01004 case 1:
01005 vehicle.setOwnDefinedColor();
01006 return true;
01007 case 2:
01008 vehicle.setOwnTypeColor();
01009 return true;
01010 case 3:
01011 vehicle.setOwnRouteColor();
01012 return true;
01013 case 4: {
01014 Position2D p = vehicle.getRoute().getEdges()[0]->getLanes()[0]->getShape()[0];
01015 const Boundary &b = ((GUINet*) MSNet::getInstance())->getBoundary();
01016 Position2D center = b.getCenter();
01017 SUMOReal hue = 180. + atan2(center.x()-p.x(), center.y()-p.y()) * 180. / PI;
01018 SUMOReal sat = p.distanceTo(center) / center.distanceTo(Position2D(b.xmin(), b.ymin()));
01019 RGBColor c = RGBColor::fromHSV(hue, sat, 1.);
01020 glColor3d(c.red(), c.green(), c.blue());
01021 return true;
01022 }
01023 case 5: {
01024 Position2D p = vehicle.getRoute().getEdges().back()->getLanes()[0]->getShape()[-1];
01025 const Boundary &b = ((GUINet*) MSNet::getInstance())->getBoundary();
01026 Position2D center = b.getCenter();
01027 SUMOReal hue = 180. + atan2(center.x()-p.x(), center.y()-p.y()) * 180. / PI;
01028 SUMOReal sat = p.distanceTo(center) / center.distanceTo(Position2D(b.xmin(), b.ymin()));
01029 RGBColor c = RGBColor::fromHSV(hue, sat, 1.);
01030 glColor3d(c.red(), c.green(), c.blue());
01031 return true;
01032 }
01033 case 6: {
01034 Position2D pb = vehicle.getRoute().getEdges()[0]->getLanes()[0]->getShape()[0];
01035 Position2D pe = vehicle.getRoute().getEdges().back()->getLanes()[0]->getShape()[-1];
01036 const Boundary &b = ((GUINet*) MSNet::getInstance())->getBoundary();
01037 SUMOReal hue = 180. + atan2(pb.x()-pe.x(), pb.y()-pe.y()) * 180. / PI;
01038 Position2D minp(b.xmin(), b.ymin());
01039 Position2D maxp(b.xmax(), b.ymax());
01040 SUMOReal sat = pb.distanceTo(pe) / minp.distanceTo(maxp);
01041 RGBColor c = RGBColor::fromHSV(hue, sat, 1.);
01042 glColor3d(c.red(), c.green(), c.blue());
01043 return true;
01044 }
01045 }
01046 return false;
01047 }
01048
01049
01050 SUMOReal
01051 GUIVehicle::Colorer::getColorValue(const GUIVehicle& vehicle) const {
01052 switch (myActiveScheme) {
01053 case 7:
01054 return vehicle.getSpeed();
01055 case 8:
01056 return vehicle.getWaitingSeconds();
01057 case 9:
01058 return vehicle.getLastLaneChangeOffset();
01059 case 10:
01060 return vehicle.getMaxSpeed();
01061 case 11:
01062 return vehicle.getHBEFA_CO2Emissions();
01063 case 12:
01064 return vehicle.getHBEFA_COEmissions();
01065 case 13:
01066 return vehicle.getHBEFA_PMxEmissions();
01067 case 14:
01068 return vehicle.getHBEFA_NOxEmissions();
01069 case 15:
01070 return vehicle.getHBEFA_HCEmissions();
01071 case 16:
01072 return vehicle.getHBEFA_FuelConsumption();
01073 case 17:
01074 return vehicle.getHarmonoise_NoiseEmissions();
01075 case 18:
01076 if (!vehicle.hasCORNIntValue(MSCORN::CORN_VEH_NUMBERROUTE)) {
01077 return -1;
01078 }
01079 return vehicle.getCORNIntValue(MSCORN::CORN_VEH_NUMBERROUTE);
01080 }
01081 return 0;
01082 }
01083
01084
01085
01086