void NLHandler::addPOI(const SUMOSAXAttributes& attrs) { bool ok = true; const SUMOReal INVALID_POSITION(-1000000); std::string id = attrs.get<std::string>(SUMO_ATTR_ID, 0, ok); SUMOReal x = attrs.getOpt<SUMOReal>(SUMO_ATTR_X, id.c_str(), ok, INVALID_POSITION); SUMOReal y = attrs.getOpt<SUMOReal>(SUMO_ATTR_Y, id.c_str(), ok, INVALID_POSITION); SUMOReal lon = attrs.getOpt<SUMOReal>(SUMO_ATTR_LON, id.c_str(), ok, INVALID_POSITION); SUMOReal lat = attrs.getOpt<SUMOReal>(SUMO_ATTR_LAT, id.c_str(), ok, INVALID_POSITION); SUMOReal lanePos = attrs.getOpt<SUMOReal>(SUMO_ATTR_POSITION, id.c_str(), ok, INVALID_POSITION); SUMOReal layer = attrs.getOpt<SUMOReal>(SUMO_ATTR_LAYER, id.c_str(), ok, (SUMOReal)GLO_POI); std::string type = attrs.getOpt<std::string>(SUMO_ATTR_TYPE, id.c_str(), ok, ""); std::string laneID = attrs.getOpt<std::string>(SUMO_ATTR_LANE, id.c_str(), ok, ""); RGBColor color = attrs.hasAttribute(SUMO_ATTR_COLOR) ? attrs.get<RGBColor>(SUMO_ATTR_COLOR, id.c_str(), ok) : RGBColor::RED; SUMOReal angle = attrs.getOpt<SUMOReal>(SUMO_ATTR_ANGLE, id.c_str(), ok, Shape::DEFAULT_ANGLE); std::string imgFile = attrs.getOpt<std::string>(SUMO_ATTR_IMGFILE, id.c_str(), ok, Shape::DEFAULT_IMG_FILE); if (imgFile != "" && !FileHelpers::isAbsolute(imgFile)) { imgFile = FileHelpers::getConfigurationRelative(getFileName(), imgFile); } SUMOReal width = attrs.getOpt<SUMOReal>(SUMO_ATTR_WIDTH, id.c_str(), ok, Shape::DEFAULT_IMG_WIDTH); SUMOReal height = attrs.getOpt<SUMOReal>(SUMO_ATTR_HEIGHT, id.c_str(), ok, Shape::DEFAULT_IMG_HEIGHT); if (!ok) { return; } Position pos(x, y); if (x == INVALID_POSITION || y == INVALID_POSITION) { // try computing x,y from lane,pos if (laneID != "") { MSLane* lane = MSLane::dictionary(laneID); if (lane == 0) { WRITE_ERROR("Lane '" + laneID + "' to place a poi '" + id + "'on is not known."); return; } if (lanePos < 0) { lanePos = lane->getLength() + lanePos; } pos = lane->geometryPositionAtOffset(lanePos); } else { // try computing x,y from lon,lat if (lat == INVALID_POSITION || lon == INVALID_POSITION) { WRITE_ERROR("Either (x,y), (lon,lat) or (lane,pos) must be specified for poi '" + id + "'."); return; } else if (!GeoConvHelper::getFinal().usingGeoProjection()) { WRITE_ERROR("(lon, lat) is specified for poi '" + id + "' but no geo-conversion is specified for the network."); return; } pos.set(lon, lat); GeoConvHelper::getFinal().x2cartesian_const(pos); } } if (!myNet.getShapeContainer().addPOI(id, type, color, layer, angle, imgFile, pos, width, height)) { WRITE_ERROR("PoI '" + id + "' already exists."); } }
void Person::moveToXY(const std::string& personID, const std::string& edgeID, const double x, const double y, double angle, const int keepRouteFlag) { MSPerson* p = getPerson(personID); bool keepRoute = (keepRouteFlag == 1); bool mayLeaveNetwork = (keepRouteFlag == 2); Position pos(x, y); #ifdef DEBUG_MOVEXY const double origAngle = angle; #endif // angle must be in [0,360] because it will be compared against those returned by naviDegree() // angle set to INVALID_DOUBLE_VALUE is ignored in the evaluated and later set to the angle of the matched lane if (angle != INVALID_DOUBLE_VALUE) { while (angle >= 360.) { angle -= 360.; } while (angle < 0.) { angle += 360.; } } Position currentPos = p->getPosition(); #ifdef DEBUG_MOVEXY std::cout << std::endl << "begin person " << p->getID() << " lanePos:" << p->getEdgePos() << " edge:" << Named::getIDSecure(p->getEdge()) << "\n"; std::cout << " want pos:" << pos << " edgeID:" << edgeID << " origAngle:" << origAngle << " angle:" << angle << " keepRoute:" << keepRoute << std::endl; #endif ConstMSEdgeVector edges; MSLane* lane = nullptr; double lanePos; double lanePosLat = 0; double bestDistance = std::numeric_limits<double>::max(); int routeOffset = 0; bool found = false; double maxRouteDistance = 100; ConstMSEdgeVector ev; ev.push_back(p->getEdge()); int routeIndex = 0; MSLane* currentLane = const_cast<MSLane*>(getSidewalk<MSEdge, MSLane>(p->getEdge())); switch (p->getStageType(0)) { case MSTransportable::MOVING_WITHOUT_VEHICLE: { MSPerson::MSPersonStage_Walking* s = dynamic_cast<MSPerson::MSPersonStage_Walking*>(p->getCurrentStage()); assert(s != 0); ev = s->getEdges(); routeIndex = (int)(s->getRouteStep() - s->getRoute().begin()); } break; default: break; } if (keepRoute) { // case a): vehicle is on its earlier route // we additionally assume it is moving forward (SUMO-limit); // note that the route ("edges") is not changed in this case found = Helper::moveToXYMap_matchingRoutePosition(pos, edgeID, ev, routeIndex, bestDistance, &lane, lanePos, routeOffset); } else { double speed = pos.distanceTo2D(p->getPosition()); // !!!veh->getSpeed(); found = Helper::moveToXYMap(pos, maxRouteDistance, mayLeaveNetwork, edgeID, angle, speed, ev, routeIndex, currentLane, p->getEdgePos(), true, bestDistance, &lane, lanePos, routeOffset, edges); } if ((found && bestDistance <= maxRouteDistance) || mayLeaveNetwork) { // compute lateral offset if (found) { const double perpDist = lane->getShape().distance2D(pos, false); if (perpDist != GeomHelper::INVALID_OFFSET) { lanePosLat = perpDist; if (!mayLeaveNetwork) { lanePosLat = MIN2(lanePosLat, 0.5 * (lane->getWidth() + p->getVehicleType().getWidth())); } // figure out whether the offset is to the left or to the right PositionVector tmp = lane->getShape(); try { tmp.move2side(-lanePosLat); // moved to left } catch (ProcessError&) { WRITE_WARNING("Could not determine position on lane '" + lane->getID() + " at lateral position " + toString(-lanePosLat) + "."); } //std::cout << " lane=" << lane->getID() << " posLat=" << lanePosLat << " shape=" << lane->getShape() << " tmp=" << tmp << " tmpDist=" << tmp.distance2D(pos) << "\n"; if (tmp.distance2D(pos) > perpDist) { lanePosLat = -lanePosLat; } } } if (found && !mayLeaveNetwork && MSGlobals::gLateralResolution < 0) { // mapped position may differ from pos pos = lane->geometryPositionAtOffset(lanePos, -lanePosLat); } assert((found && lane != 0) || (!found && lane == 0)); if (angle == INVALID_DOUBLE_VALUE) { if (lane != nullptr) { angle = GeomHelper::naviDegree(lane->getShape().rotationAtOffset(lanePos)); } else { // compute angle outside road network from old and new position angle = GeomHelper::naviDegree(p->getPosition().angleTo2D(pos)); } } switch (p->getStageType(0)) { case MSTransportable::MOVING_WITHOUT_VEHICLE: { Helper::setRemoteControlled(p, pos, lane, lanePos, lanePosLat, angle, routeOffset, edges, MSNet::getInstance()->getCurrentTimeStep()); break; } default: throw TraCIException("Command moveToXY is not supported for person '" + personID + "' while " + p->getCurrentStageDescription() + "."); } } else { if (lane == nullptr) { throw TraCIException("Could not map person '" + personID + "' no road found within " + toString(maxRouteDistance) + "m."); } else { throw TraCIException("Could not map person '" + personID + "' distance to road is " + toString(bestDistance) + "."); } } }
void GUIVehicle::drawAction_drawCarriageClass(const GUIVisualizationSettings& s, bool asImage) const { RGBColor current = GLHelper::getColor(); RGBColor darker = current.changedBrightness(-51); const double exaggeration = s.vehicleSize.getExaggeration(s, this); const double totalLength = getVType().getLength(); double upscaleLength = exaggeration; if (exaggeration > 1 && totalLength > 5) { // reduce the length/width ratio because this is not usefull at high zoom upscaleLength = MAX2(1.0, upscaleLength * (5 + sqrt(totalLength - 5)) / totalLength); } const double locomotiveLength = getVehicleType().getParameter().locomotiveLength * upscaleLength; if (exaggeration == 0) { return; } const double defaultLength = getVehicleType().getParameter().carriageLength * upscaleLength; const double carriageGap = getVehicleType().getParameter().carriageGap * upscaleLength; const double length = totalLength * upscaleLength; const double halfWidth = getVehicleType().getWidth() / 2.0 * exaggeration; glPopMatrix(); // undo initial translation and rotation const double xCornerCut = 0.3 * exaggeration; const double yCornerCut = 0.4 * exaggeration; // round to closest integer const int numCarriages = MAX2(1, 1 + (int)((length - locomotiveLength) / (defaultLength + carriageGap) + 0.5)); assert(numCarriages > 0); double carriageLengthWithGap = length / numCarriages; double carriageLength = carriageLengthWithGap - carriageGap; double firstCarriageLength = carriageLength; if (defaultLength != locomotiveLength && numCarriages > 1) { firstCarriageLength = locomotiveLength; carriageLengthWithGap = (length - locomotiveLength) / (numCarriages - 1); carriageLength = carriageLengthWithGap - carriageGap; } const int firstPassengerCarriage = defaultLength == locomotiveLength || numCarriages == 1 ? 0 : 1; const int totalSeats = getVType().getPersonCapacity() + getVType().getContainerCapacity(); const int seatsPerCarriage = (int)ceil(totalSeats / (numCarriages - firstPassengerCarriage)); // lane on which the carriage front is situated MSLane* lane = myLane; int routeIndex = getRoutePosition(); // lane on which the carriage back is situated MSLane* backLane = myLane; int backRouteIndex = routeIndex; // offsets of front and back double carriageOffset = myState.pos(); double carriageBackOffset = myState.pos() - firstCarriageLength; // handle seats int requiredSeats = getNumPassengers() + getNumContainers(); if (requiredSeats > 0) { mySeatPositions.clear(); } Position front, back; double angle = 0.; // draw individual carriages double curCLength = firstCarriageLength; //std::cout << SIMTIME << " veh=" << getID() << " curCLength=" << curCLength << " loc=" << locomotiveLength << " car=" << carriageLength << " tlen=" << totalLength << " len=" << length << "\n"; for (int i = 0; i < numCarriages; ++i) { if (i > 0) { curCLength = carriageLength; } while (carriageOffset < 0) { MSLane* prev = getPreviousLane(lane, routeIndex); if (prev != lane) { carriageOffset += prev->getLength(); } else { // no lane available for drawing. carriageOffset = 0; } lane = prev; } while (carriageBackOffset < 0) { MSLane* prev = getPreviousLane(backLane, backRouteIndex); if (prev != backLane) { carriageBackOffset += prev->getLength(); } else { // no lane available for drawing. carriageBackOffset = 0; } backLane = prev; } front = lane->geometryPositionAtOffset(carriageOffset); back = backLane->geometryPositionAtOffset(carriageBackOffset); if (front == back) { // no place for drawing available continue; } const double drawnCarriageLength = front.distanceTo2D(back); angle = atan2((front.x() - back.x()), (back.y() - front.y())) * (double) 180.0 / (double) M_PI; if (i >= firstPassengerCarriage) { computeSeats(front, back, seatsPerCarriage, exaggeration, requiredSeats); } glPushMatrix(); glTranslated(front.x(), front.y(), getType()); glRotated(angle, 0, 0, 1); if (!asImage || !GUIBaseVehicleHelper::drawAction_drawVehicleAsImage(s, getVType().getImgFile(), this, getVType().getWidth(), curCLength)) { switch (getVType().getGuiShape()) { case SVS_TRUCK_SEMITRAILER: case SVS_TRUCK_1TRAILER: if (i == 0) { GUIBaseVehicleHelper::drawAction_drawVehicleAsPoly(s, getVType().getGuiShape(), getVType().getWidth() * exaggeration, curCLength, i); } else { GLHelper::setColor(current); GLHelper::drawBoxLine(Position(0, 0), 180, curCLength, halfWidth); } break; default: { if (i == 0) { GLHelper::setColor(darker); } else { GLHelper::setColor(current); } // generic rail carriage glBegin(GL_TRIANGLE_FAN); glVertex2d(-halfWidth + xCornerCut, 0); glVertex2d(-halfWidth, yCornerCut); glVertex2d(-halfWidth, drawnCarriageLength - yCornerCut); glVertex2d(-halfWidth + xCornerCut, drawnCarriageLength); glVertex2d(halfWidth - xCornerCut, drawnCarriageLength); glVertex2d(halfWidth, drawnCarriageLength - yCornerCut); glVertex2d(halfWidth, yCornerCut); glVertex2d(halfWidth - xCornerCut, 0); glEnd(); } } } glPopMatrix(); carriageOffset -= (curCLength + carriageGap); carriageBackOffset -= carriageLengthWithGap; } if (getVType().getGuiShape() == SVS_RAIL_CAR) { glPushMatrix(); glTranslated(front.x(), front.y(), getType()); glRotated(angle, 0, 0, 1); drawAction_drawVehicleBlinker(curCLength); drawAction_drawVehicleBrakeLight(curCLength); glPopMatrix(); } // restore matrix glPushMatrix(); front = getPosition(); glTranslated(front.x(), front.y(), getType()); const double degAngle = RAD2DEG(getAngle() + M_PI / 2.); glRotated(degAngle, 0, 0, 1); glScaled(exaggeration, upscaleLength, 1); if (mySeatPositions.size() == 0) { mySeatPositions.push_back(back); } }