void GLHelper::drawShapeDottedContour(const int type, const PositionVector& shape, const double width) { glPushMatrix(); // build contour using shapes of first and last lane shapes PositionVector contourFront = shape; // only add an contourback if width is greather of 0 if (width > 0) { PositionVector contourback = contourFront; contourFront.move2side(width); contourback.move2side(-width); contourback = contourback.reverse(); for (auto i : contourback) { contourFront.push_back(i); } contourFront.push_back(shape.front()); } // resample shape PositionVector resampledShape = contourFront.resample(1); // draw contour over shape glTranslated(0, 0, type + 2); // set custom line width glLineWidth(3); // draw contour drawLine(resampledShape, getDottedcontourColors((int)resampledShape.size())); //restore line width glLineWidth(1); glPopMatrix(); }
void GLHelper::drawShapeDottedContour(const int type, const PositionVector& frontShape, const double offsetFrontShape, const PositionVector& backShape, const double offsetBackShape) { glPushMatrix(); // build contour using shapes of first and last lane shapes PositionVector contourFront = frontShape; PositionVector contourback = backShape; contourFront.move2side(offsetFrontShape); contourback.move2side(offsetBackShape); contourback = contourback.reverse(); for (auto i : contourback) { contourFront.push_back(i); } contourFront.push_back(frontShape.front()); // resample shape PositionVector resampledShape = contourFront.resample(1); // draw contour over shape glTranslated(0, 0, type + 2); // set custom line width glLineWidth(3); // draw contour GLHelper::drawLine(resampledShape, getDottedcontourColors((int)resampledShape.size())); //restore line width glLineWidth(1); glPopMatrix(); }
GNEEdge* GNENet::addReversedEdge(GNEEdge* edge, GNEUndoList* undoList) { undoList->p_begin("add reversed edge"); GNEEdge* reversed = 0; if (edge->getNBEdge()->getLaneSpreadFunction() == LANESPREAD_RIGHT) { GNEEdge* reversed = createEdge(edge->getDest(), edge->getSource(), edge, undoList, "-" + edge->getID(), false, true); assert(reversed != 0); reversed->setAttribute(SUMO_ATTR_SHAPE, toString(edge->getNBEdge()->getInnerGeometry().reverse()), undoList); } else { // if the edge is centered it should probably connect somewhere else // make it easy to move and reconnect it PositionVector orig = edge->getNBEdge()->getGeometry(); PositionVector origInner = edge->getNBEdge()->getInnerGeometry(); const SUMOReal tentativeShift = edge->getNBEdge()->getTotalWidth() + 2; orig.move2side(-tentativeShift); origInner.move2side(-tentativeShift); GNEJunction* src = createJunction(orig.back(), undoList); GNEJunction* dest = createJunction(orig.front(), undoList); GNEEdge* reversed = createEdge(src, dest, edge, undoList, "-" + edge->getID(), false, true); assert(reversed != 0); reversed->setAttribute(SUMO_ATTR_SHAPE, toString(origInner.reverse()), undoList); // select the new edge and its nodes std::set<GUIGlID> toSelect; toSelect.insert(reversed->getGlID()); toSelect.insert(src->getGlID()); toSelect.insert(dest->getGlID()); undoList->add(new GNEChange_Selection(toSelect, gSelected.getSelected(), true), true); } undoList->p_end(); return reversed; }
// =========================================================================== // method definitions // =========================================================================== GUIContainerStop::GUIContainerStop(const std::string& id, const std::vector<std::string>& lines, MSLane& lane, SUMOReal frompos, SUMOReal topos) : MSStoppingPlace(id, lines, lane, frompos, topos), GUIGlObject_AbstractAdd("containerStop", GLO_TRIGGER, id) { myFGShape = lane.getShape(); myFGShape.move2side((SUMOReal) 1.65); myFGShape = myFGShape.getSubpart(frompos, 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((SUMOReal) atan2((s.x() - f.x()), (f.y() - s.y())) * (SUMOReal) 180.0 / (SUMOReal) PI); } PositionVector tmp = myFGShape; tmp.move2side(1.5); myFGSignPos = tmp.getLineCenter(); myFGSignRot = 0; if (tmp.length() != 0) { myFGSignRot = myFGShape.rotationDegreeAtOffset(SUMOReal((myFGShape.length() / 2.))); myFGSignRot -= 90; } }
PositionVector NWWriter_OpenDrive::getLeftLaneBorder(const NBEdge* edge, int laneIndex, double widthOffset) { const bool lefthand = OptionsCont::getOptions().getBool("lefthand"); if (laneIndex == -1) { // leftmost lane laneIndex = lefthand ? 0 : (int)edge->getNumLanes() - 1; } /// it would be tempting to use // PositionVector result = edge->getLaneShape(laneIndex); // (and the moveo2side) // However, the lanes in SUMO have a small lateral gap (SUMO_const_laneOffset) to account for markings // In OpenDRIVE this gap does not exists so we have to do all lateral // computations based on the reference line // This assumes that the 'stop line' for all lanes is colinear! const int leftmost = lefthand ? 0 : (int)edge->getNumLanes() - 1; widthOffset -= (edge->getLaneWidth(leftmost) / 2); // collect lane widths from left border of edge to left border of lane to connect to if (lefthand) { for (int i = leftmost; i < laneIndex; i++) { widthOffset += edge->getLaneWidth(i); } } else { for (int i = leftmost; i > laneIndex; i--) { widthOffset += edge->getLaneWidth(i); } } PositionVector result = edge->getLaneShape(leftmost); try { result.move2side(widthOffset); } catch (InvalidArgument&) { } return result; }
Position MSPerson::MSPersonStage::getEdgePosition(const MSEdge* e, SUMOReal at, SUMOReal offset) const { // @todo: well, definitely not the nicest way... Should be precomputed const MSLane* lane = e->getLanes()[0]; PositionVector shp = lane->getShape(); shp.move2side(offset); return shp.positionAtOffset(lane->interpolateLanePosToGeometryPos(at)); }
void NBRampsComputer::moveRampRight(NBEdge* ramp, int addedLanes) { if (ramp->getLaneSpreadFunction() != LANESPREAD_CENTER) { return; } try { PositionVector g = ramp->getGeometry(); SUMOReal factor = SUMO_const_laneWidthAndOffset * (SUMOReal)(addedLanes - 1) + SUMO_const_halfLaneAndOffset * (SUMOReal)(addedLanes % 2); g.move2side(factor); ramp->setGeometry(g); } catch (InvalidArgument&) { WRITE_WARNING("For edge '" + ramp->getID() + "': could not compute shape."); } }
void GNEConnection::drawGL(const GUIVisualizationSettings& s) const { // Check if connection must be drawed if (!myShapeDeprecated && (myNet->getViewNet()->getViewOptions().showConnections() || (myNet->getViewNet()->getEditModes().currentSupermode == GNE_SUPERMODE_DEMAND))) { // Push draw matrix 1 glPushMatrix(); // Push name glPushName(getGlID()); // Traslate matrix glTranslated(0, 0, GLO_JUNCTION + 0.1); // must draw on top of junction // Set color if (drawUsingSelectColor()) { // override with special colors (unless the color scheme is based on selection) GLHelper::setColor(s.selectedConnectionColor); } else if (mySpecialColor != nullptr) { GLHelper::setColor(*mySpecialColor); } else { // Set color depending of the link state GLHelper::setColor(GNEInternalLane::colorForLinksState(getLinkState())); } // draw connection checking whether it is not too small if isn't being drawn for selecting const double selectionScale = isAttributeCarrierSelected() ? s.selectionScale : 1; if ((s.scale * selectionScale < 5.) && !s.drawForSelecting) { // If it's small, draw a simple line GLHelper::drawLine(myShape); } else { // draw a list of lines const bool spreadSuperposed = s.scale >= 1 && s.spreadSuperposed && myFromLane->drawAsRailway(s) && getEdgeFrom()->getNBEdge()->isBidiRail(); PositionVector shape = myShape; if (spreadSuperposed) { shape.move2side(0.5); } GLHelper::drawBoxLines(shape, myShapeRotations, myShapeLengths, 0.2 * selectionScale); glTranslated(0, 0, 0.1); GLHelper::setColor(GLHelper::getColor().changedBrightness(51)); // check if internal junction marker has to be drawn if (myInternalJunctionMarker.size() > 0) { GLHelper::drawLine(myInternalJunctionMarker); } // check if dotted contour has to be drawn (not useful at high zoom) if (!s.drawForSelecting && (myNet->getViewNet()->getDottedAC() == this)) { GLHelper::drawShapeDottedContour(getType(), shape, 0.25); } } // Pop name glPopName(); // Pop draw matrix 1 glPopMatrix(); } }
void NBRampsComputer::moveRampRight(NBEdge* ramp, int addedLanes) { if (ramp->getLaneSpreadFunction() != LANESPREAD_CENTER) { return; } try { PositionVector g = ramp->getGeometry(); const SUMOReal offset = (0.5 * addedLanes * (ramp->getLaneWidth() == NBEdge::UNSPECIFIED_WIDTH ? SUMO_const_laneWidth : ramp->getLaneWidth())); g.move2side(offset); ramp->setGeometry(g); } catch (InvalidArgument&) { WRITE_WARNING("For edge '" + ramp->getID() + "': could not compute shape."); } }
void NBSign::writeAsPOI(OutputDevice& into, const NBEdge* edge) const { PositionVector shp = edge->getLanes()[0].shape; try { shp.move2side(3); } catch (InvalidArgument&) { // we do not write anything, maybe we should } Position pos = shp.positionAtOffset(myOffset); into.openTag(SUMO_TAG_POI); into.writeAttr(SUMO_ATTR_ID, edge->getID() + "." + toString(myOffset)); into.writeAttr(SUMO_ATTR_TYPE, SignTypeStrings.getString(myType)); switch (myType) { /// XXX @todo add default colors case SIGN_TYPE_SPEED: case SIGN_TYPE_SLOPE: case SIGN_TYPE_CITY: case SIGN_TYPE_INFO: into.writeAttr(SUMO_ATTR_COLOR, RGBColor::GREY); break; case SIGN_TYPE_YIELD: case SIGN_TYPE_STOP: case SIGN_TYPE_ALLWAY_STOP: case SIGN_TYPE_ON_RAMP: case SIGN_TYPE_RAIL_CROSSING: into.writeAttr(SUMO_ATTR_COLOR, RGBColor::RED); break; case SIGN_TYPE_PRIORITY: into.writeAttr(SUMO_ATTR_COLOR, RGBColor::YELLOW); break; case SIGN_TYPE_RIGHT_BEFORE_LEFT: into.writeAttr(SUMO_ATTR_COLOR, RGBColor(255, 153, 0, 255)); break; case SIGN_TYPE_ROUNDABOUT: into.writeAttr(SUMO_ATTR_COLOR, RGBColor::BLUE); break; } into.writeAttr(SUMO_ATTR_X, pos.x()); into.writeAttr(SUMO_ATTR_Y, pos.y()); into.writeAttr(SUMO_ATTR_ANGLE, 0); // XXX use road angle? // @todo add image resources and default images for all signs //into.writeAttr(SUMO_ATTR_IMGFILE, p->getImgFile()); //into.writeAttr(SUMO_ATTR_WIDTH, p->getWidth()); //into.writeAttr(SUMO_ATTR_HEIGHT, p->getHeight()); into.closeTag(); }
// =========================================================================== // method definitions // =========================================================================== GUIChargingStation::GUIChargingStation(const std::string& id, MSLane& lane, SUMOReal frompos, SUMOReal topos, SUMOReal chargingPower, SUMOReal efficiency, bool chargeInTransit, int chargeDelay) : MSChargingStation(id, lane, frompos, topos, chargingPower, efficiency, chargeInTransit, chargeDelay), GUIGlObject_AbstractAdd("chargingStation", GLO_TRIGGER, id) { myFGShape = lane.getShape(); myFGShape = myFGShape.getSubpart(frompos, 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((SUMOReal) atan2((s.x() - f.x()), (f.y() - s.y())) * (SUMOReal) 180.0 / (SUMOReal) PI); } PositionVector tmp = myFGShape; tmp.move2side(1.5); myFGSignPos = tmp.getLineCenter(); myFGSignRot = 0; if (tmp.length() != 0) { myFGSignRot = myFGShape.rotationDegreeAtOffset(SUMOReal((myFGShape.length() / 2.))); myFGSignRot -= 90; } }
// =========================================================================== // method definitions // =========================================================================== GUIParkingArea::GUIParkingArea(const std::string& id, const std::vector<std::string>& lines, MSLane& lane, SUMOReal frompos, SUMOReal topos, unsigned int capacity, SUMOReal width, SUMOReal length, SUMOReal angle) : MSParkingArea(id, lines, lane, frompos, topos, capacity, width, length, angle), GUIGlObject_AbstractAdd("parkingArea", GLO_TRIGGER, id) { myShapeRotations.reserve(myShape.size() - 1); myShapeLengths.reserve(myShape.size() - 1); int e = (int) myShape.size() - 1; for (int i = 0; i < e; ++i) { const Position& f = myShape[i]; const Position& s = myShape[i + 1]; myShapeLengths.push_back(f.distanceTo(s)); myShapeRotations.push_back((SUMOReal) atan2((s.x() - f.x()), (f.y() - s.y())) * (SUMOReal) 180.0 / (SUMOReal) PI); } PositionVector tmp = myShape; tmp.move2side(lane.getWidth() + myWidth); mySignPos = tmp.getLineCenter(); mySignRot = 0; if (tmp.length() != 0) { mySignRot = myShape.rotationDegreeAtOffset(SUMOReal((myShape.length() / 2.))); mySignRot -= 90; } }
// =========================================================================== // method definitions // =========================================================================== GUIParkingArea::GUIParkingArea(const std::string& id, const std::vector<std::string>& lines, MSLane& lane, double frompos, double topos, unsigned int capacity, double width, double length, double angle, const std::string& name) : MSParkingArea(id, lines, lane, frompos, topos, capacity, width, length, angle, name), GUIGlObject_AbstractAdd(GLO_PARKING_AREA, id) { const double offsetSign = MSNet::getInstance()->lefthand() ? -1 : 1; myShapeRotations.reserve(myShape.size() - 1); myShapeLengths.reserve(myShape.size() - 1); int e = (int) myShape.size() - 1; for (int i = 0; i < e; ++i) { const Position& f = myShape[i]; const Position& s = myShape[i + 1]; myShapeLengths.push_back(f.distanceTo(s)); myShapeRotations.push_back((double) atan2((s.x() - f.x()), (f.y() - s.y())) * (double) 180.0 / (double) M_PI); } PositionVector tmp = myShape; tmp.move2side((lane.getWidth() + myWidth) * offsetSign); mySignPos = tmp.getLineCenter(); mySignRot = 0; if (tmp.length() != 0) { mySignRot = myShape.rotationDegreeAtOffset(double((myShape.length() / 2.))); mySignRot -= 90; } }
void GNEContainerStop::updateGeometry() { // Clear all containers myShapeRotations.clear(); myShapeLengths.clear(); // Get value of option "lefthand" SUMOReal offsetSign = OptionsCont::getOptions().getBool("lefthand") ? -1 : 1; // Get shape of lane parent myShape = myLane->getShape(); // Move shape to side myShape.move2side(1.65 * offsetSign); // Cut shape using as delimitators from start position and end position myShape = myShape.getSubpart(myLane->getPositionRelativeToParametricLenght(myStartPos), myLane->getPositionRelativeToParametricLenght(myEndPos)); // Get number of parts of the shape int numberOfSegments = (int) myShape.size() - 1; // If number of segments is more than 0 if (numberOfSegments >= 0) { // Reserve memory (To improve efficiency) myShapeRotations.reserve(numberOfSegments); myShapeLengths.reserve(numberOfSegments); // For every part of the shape for (int i = 0; i < numberOfSegments; ++i) { // Obtain first position const Position& f = myShape[i]; // Obtain next position const Position& s = myShape[i + 1]; // Save distance between position into myShapeLengths myShapeLengths.push_back(f.distanceTo(s)); // Save rotation (angle) of the vector constructed by points f and s myShapeRotations.push_back((SUMOReal) atan2((s.x() - f.x()), (f.y() - s.y())) * (SUMOReal) 180.0 / (SUMOReal) PI); } } // Obtain a copy of the shape PositionVector tmpShape = myShape; // Move shape to side tmpShape.move2side(1.5 * offsetSign); // Get position of the sign mySignPos = tmpShape.getLineCenter(); // Set block icon position myBlockIconPosition = myShape.getLineCenter(); // Set block icon rotation, and using their rotation for sign setBlockIconRotation(myLane); // Refresh element (neccesary to avoid grabbing problems) myViewNet->getNet()->refreshAdditional(this); }
void NIXMLEdgesHandler::myEndElement(int element) { if (element == SUMO_TAG_EDGE && myCurrentEdge != 0) { if (!myIsUpdate) { try { if (!myEdgeCont.insert(myCurrentEdge)) { WRITE_ERROR("Duplicate edge occured. ID='" + myCurrentID + "'"); delete myCurrentEdge; } } catch (InvalidArgument& e) { WRITE_ERROR(e.what()); throw; } catch (...) { WRITE_ERROR("An important information is missing in edge '" + myCurrentID + "'."); } } if (mySplits.size() != 0) { std::vector<Split>::iterator i; NBEdge* e = myCurrentEdge; sort(mySplits.begin(), mySplits.end(), split_sorter()); unsigned int noLanesMax = e->getNumLanes(); // compute the node positions and sort the lanes for (i = mySplits.begin(); i != mySplits.end(); ++i) { (*i).gpos = e->getGeometry().positionAtLengthPosition((*i).pos); sort((*i).lanes.begin(), (*i).lanes.end()); noLanesMax = MAX2(noLanesMax, (unsigned int)(*i).lanes.size()); } // split the edge std::vector<int> currLanes; for (unsigned int l = 0; l < e->getNumLanes(); ++l) { currLanes.push_back(l); } std::string edgeid = e->getID(); SUMOReal seen = 0; for (i = mySplits.begin(); i != mySplits.end(); ++i) { const Split& exp = *i; assert(exp.lanes.size() != 0); if (exp.pos > 0 && e->getGeometry().length() + seen > exp.pos && exp.pos > seen) { std::string nid = edgeid + "." + toString(exp.nameid); NBNode* rn = new NBNode(nid, exp.gpos); if (myNodeCont.insert(rn)) { // split the edge std::string nid = myCurrentID + "." + toString(exp.nameid); std::string pid = e->getID(); myEdgeCont.splitAt(myDistrictCont, e, exp.pos - seen, rn, pid, nid, e->getNumLanes(), (unsigned int) exp.lanes.size()); seen = exp.pos; std::vector<int> newLanes = exp.lanes; NBEdge* pe = myEdgeCont.retrieve(pid); NBEdge* ne = myEdgeCont.retrieve(nid); // reconnect lanes pe->invalidateConnections(true); // new on right unsigned int rightMostP = currLanes[0]; unsigned int rightMostN = newLanes[0]; for (int l = 0; l < (int) rightMostP - (int) rightMostN; ++l) { pe->addLane2LaneConnection(0, ne, l, NBEdge::L2L_VALIDATED, true); } // new on left unsigned int leftMostP = currLanes.back(); unsigned int leftMostN = newLanes.back(); for (int l = 0; l < (int) leftMostN - (int) leftMostP; ++l) { pe->addLane2LaneConnection(pe->getNumLanes() - 1, ne, leftMostN - l - rightMostN, NBEdge::L2L_VALIDATED, true); } // all other connected for (unsigned int l = 0; l < noLanesMax; ++l) { if (find(currLanes.begin(), currLanes.end(), l) == currLanes.end()) { continue; } if (find(newLanes.begin(), newLanes.end(), l) == newLanes.end()) { continue; } pe->addLane2LaneConnection(l - rightMostP, ne, l - rightMostN, NBEdge::L2L_VALIDATED, true); } // move to next e = ne; currLanes = newLanes; } else { WRITE_WARNING("Error on parsing a split (edge '" + myCurrentID + "')."); } } else if (exp.pos == 0) { if (e->getNumLanes() < exp.lanes.size()) { e->incLaneNo((int) exp.lanes.size() - e->getNumLanes()); } else { e->decLaneNo(e->getNumLanes() - (int) exp.lanes.size()); } currLanes = exp.lanes; } else { WRITE_WARNING("Split at '" + toString(exp.pos) + "' lies beyond the edge's length (edge '" + myCurrentID + "')."); } } // patch lane offsets e = myEdgeCont.retrieve(edgeid); i = mySplits.begin(); if ((*i).pos != 0) { e = e->getToNode()->getOutgoingEdges()[0]; } for (; i != mySplits.end(); ++i) { unsigned int maxLeft = (*i).lanes.back(); SUMOReal offset = 0; if (maxLeft < noLanesMax) { if (e->getLaneSpreadFunction() == LANESPREAD_RIGHT) { offset = SUMO_const_laneWidthAndOffset * (noLanesMax - 1 - maxLeft); } else { offset = SUMO_const_halfLaneAndOffset * (noLanesMax - 1 - maxLeft); } } unsigned int maxRight = (*i).lanes.front(); if (maxRight > 0 && e->getLaneSpreadFunction() == LANESPREAD_CENTER) { offset -= SUMO_const_halfLaneAndOffset * maxRight; } if (offset != 0) { PositionVector g = e->getGeometry(); g.move2side(offset); e->setGeometry(g); } if (e->getToNode()->getOutgoingEdges().size() != 0) { e = e->getToNode()->getOutgoingEdges()[0]; } } } } }
void NWWriter_DlrNavteq::writeNodesUnsplitted(const OptionsCont& oc, NBNodeCont& nc, NBEdgeCont& ec, std::map<NBEdge*, std::string>& internalNodes) { // For "real" nodes we simply use the node id. // For internal nodes (geometry vectors describing edge geometry in the parlance of this format) // we use the id of the edge and do not bother with // compression (each direction gets its own internal node). OutputDevice& device = OutputDevice::getDevice(oc.getString("dlr-navteq-output") + "_nodes_unsplitted.txt"); writeHeader(device, oc); const GeoConvHelper& gch = GeoConvHelper::getFinal(); const bool haveGeo = gch.usingGeoProjection(); const double geoScale = pow(10.0f, haveGeo ? 5 : 2); // see NIImporter_DlrNavteq::GEO_SCALE device.setPrecision(oc.getInt("dlr-navteq.precision")); if (!haveGeo) { WRITE_WARNING("DlrNavteq node data will be written in (floating point) cartesian coordinates"); } // write format specifier device << "# NODE_ID\tIS_BETWEEN_NODE\tamount_of_geocoordinates\tx1\ty1\t[x2 y2 ... xn yn]\n"; // write header Boundary boundary = gch.getConvBoundary(); Position min(boundary.xmin(), boundary.ymin()); Position max(boundary.xmax(), boundary.ymax()); gch.cartesian2geo(min); min.mul(geoScale); gch.cartesian2geo(max); max.mul(geoScale); int multinodes = 0; for (std::map<std::string, NBEdge*>::const_iterator i = ec.begin(); i != ec.end(); ++i) { if ((*i).second->getGeometry().size() > 2) { multinodes++; } } device << "# [xmin_region] " << min.x() << "\n"; device << "# [xmax_region] " << max.x() << "\n"; device << "# [ymin_region] " << min.y() << "\n"; device << "# [ymax_region] " << max.y() << "\n"; device << "# [elements_multinode] " << multinodes << "\n"; device << "# [elements_normalnode] " << nc.size() << "\n"; device << "# [xmin] " << min.x() << "\n"; device << "# [xmax] " << max.x() << "\n"; device << "# [ymin] " << min.y() << "\n"; device << "# [ymax] " << max.y() << "\n"; // write normal nodes for (std::map<std::string, NBNode*>::const_iterator i = nc.begin(); i != nc.end(); ++i) { NBNode* n = (*i).second; Position pos = n->getPosition(); gch.cartesian2geo(pos); pos.mul(geoScale); device << n->getID() << "\t0\t1\t" << pos.x() << "\t" << pos.y() << "\n"; } // write "internal" nodes std::vector<std::string> avoid; std::set<std::string> reservedNodeIDs; const bool numericalIDs = oc.getBool("numerical-ids"); if (oc.isSet("reserved-ids")) { NBHelpers::loadPrefixedIDsFomFile(oc.getString("reserved-ids"), "node:", reservedNodeIDs); // backward compatibility NBHelpers::loadPrefixedIDsFomFile(oc.getString("reserved-ids"), "junction:", reservedNodeIDs); // selection format } if (numericalIDs) { avoid = nc.getAllNames(); std::vector<std::string> avoid2 = ec.getAllNames(); avoid.insert(avoid.end(), avoid2.begin(), avoid2.end()); avoid.insert(avoid.end(), reservedNodeIDs.begin(), reservedNodeIDs.end()); } IDSupplier idSupplier("", avoid); for (std::map<std::string, NBEdge*>::const_iterator i = ec.begin(); i != ec.end(); ++i) { NBEdge* e = (*i).second; PositionVector geom = e->getGeometry(); if (geom.size() > 2) { // the import NIImporter_DlrNavteq checks for the presence of a // negated edge id to determine spread type. We may need to do some // shifting to make this consistent const bool hasOppositeID = ec.getOppositeByID(e->getID()) != nullptr; if (e->getLaneSpreadFunction() == LANESPREAD_RIGHT && !hasOppositeID) { // need to write center-line geometry instead try { geom.move2side(e->getTotalWidth() / 2); } catch (InvalidArgument& exception) { WRITE_WARNING("Could not reconstruct shape for edge:'" + e->getID() + "' (" + exception.what() + ")."); } } else if (e->getLaneSpreadFunction() == LANESPREAD_CENTER && hasOppositeID) { // need to write left-border geometry instead try { geom.move2side(-e->getTotalWidth() / 2); } catch (InvalidArgument& exception) { WRITE_WARNING("Could not reconstruct shape for edge:'" + e->getID() + "' (" + exception.what() + ")."); } } std::string internalNodeID = e->getID(); if (internalNodeID == UNDEFINED || (nc.retrieve(internalNodeID) != nullptr) || reservedNodeIDs.count(internalNodeID) > 0 ) { // need to invent a new name to avoid clashing with the id of a 'real' node or a reserved name if (numericalIDs) { internalNodeID = idSupplier.getNext(); } else { internalNodeID += "_geometry"; } } internalNodes[e] = internalNodeID; device << internalNodeID << "\t1\t" << geom.size() - 2; for (int ii = 1; ii < (int)geom.size() - 1; ++ii) { Position pos = geom[(int)ii]; gch.cartesian2geo(pos); pos.mul(geoScale); device << "\t" << pos.x() << "\t" << pos.y(); } device << "\n"; } } device.close(); }
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 NIXMLEdgesHandler::myEndElement(int element) { if (element == SUMO_TAG_EDGE && myCurrentEdge != 0) { // add bike lane, wait until lanes are loaded to avoid building if it already exists if (myBikeLaneWidth != NBEdge::UNSPECIFIED_WIDTH) { myCurrentEdge->addBikeLane(myBikeLaneWidth); } // add sidewalk, wait until lanes are loaded to avoid building if it already exists if (mySidewalkWidth != NBEdge::UNSPECIFIED_WIDTH) { myCurrentEdge->addSidewalk(mySidewalkWidth); } if (!myIsUpdate) { try { if (!myEdgeCont.insert(myCurrentEdge)) { WRITE_ERROR("Duplicate edge occured. ID='" + myCurrentID + "'"); delete myCurrentEdge; } } catch (InvalidArgument& e) { WRITE_ERROR(e.what()); throw; } catch (...) { WRITE_ERROR("An important information is missing in edge '" + myCurrentID + "'."); } } if (mySplits.size() != 0) { std::vector<Split>::iterator i; NBEdge* e = myCurrentEdge; sort(mySplits.begin(), mySplits.end(), split_sorter()); unsigned int noLanesMax = e->getNumLanes(); // compute the node positions and sort the lanes for (i = mySplits.begin(); i != mySplits.end(); ++i) { sort((*i).lanes.begin(), (*i).lanes.end()); noLanesMax = MAX2(noLanesMax, (unsigned int)(*i).lanes.size()); } // split the edge std::vector<int> currLanes; for (unsigned int l = 0; l < e->getNumLanes(); ++l) { currLanes.push_back(l); } if (e->getNumLanes() != mySplits.back().lanes.size()) { // invalidate traffic light definitions loaded from a SUMO network // XXX it would be preferable to reconstruct the phase definitions heuristically e->getToNode()->invalidateTLS(myTLLogicCont); // if the number of lanes changes the connections should be // recomputed e->invalidateConnections(true); } std::string edgeid = e->getID(); SUMOReal seen = 0; for (i = mySplits.begin(); i != mySplits.end(); ++i) { const Split& exp = *i; assert(exp.lanes.size() != 0); if (exp.pos > 0 && e->getGeometry().length() + seen > exp.pos && exp.pos > seen) { if (myNodeCont.insert(exp.node)) { myNodeCont.markAsSplit(exp.node); // split the edge std::string pid = e->getID(); myEdgeCont.splitAt(myDistrictCont, e, exp.pos - seen, exp.node, pid, exp.node->getID(), e->getNumLanes(), (unsigned int) exp.lanes.size(), exp.speed); seen = exp.pos; std::vector<int> newLanes = exp.lanes; NBEdge* pe = myEdgeCont.retrieve(pid); NBEdge* ne = myEdgeCont.retrieve(exp.node->getID()); // reconnect lanes pe->invalidateConnections(true); // new on right unsigned int rightMostP = currLanes[0]; unsigned int rightMostN = newLanes[0]; for (int l = 0; l < (int) rightMostP - (int) rightMostN; ++l) { pe->addLane2LaneConnection(0, ne, l, NBEdge::L2L_VALIDATED, true); } // new on left unsigned int leftMostP = currLanes.back(); unsigned int leftMostN = newLanes.back(); for (int l = 0; l < (int) leftMostN - (int) leftMostP; ++l) { pe->addLane2LaneConnection(pe->getNumLanes() - 1, ne, leftMostN - l - rightMostN, NBEdge::L2L_VALIDATED, true); } // all other connected for (unsigned int l = 0; l < noLanesMax; ++l) { if (find(currLanes.begin(), currLanes.end(), l) == currLanes.end()) { continue; } if (find(newLanes.begin(), newLanes.end(), l) == newLanes.end()) { continue; } pe->addLane2LaneConnection(l - rightMostP, ne, l - rightMostN, NBEdge::L2L_VALIDATED, true); } // move to next e = ne; currLanes = newLanes; } else { WRITE_WARNING("Error on parsing a split (edge '" + myCurrentID + "')."); } } else if (exp.pos == 0) { if (e->getNumLanes() < exp.lanes.size()) { e->incLaneNo((int) exp.lanes.size() - e->getNumLanes()); } else { e->decLaneNo(e->getNumLanes() - (int) exp.lanes.size()); } currLanes = exp.lanes; // invalidate traffic light definition loaded from a SUMO network // XXX it would be preferable to reconstruct the phase definitions heuristically e->getFromNode()->invalidateTLS(myTLLogicCont); } else { WRITE_WARNING("Split at '" + toString(exp.pos) + "' lies beyond the edge's length (edge '" + myCurrentID + "')."); } } // patch lane offsets e = myEdgeCont.retrieve(edgeid); if (mySplits.front().pos != 0) { // add a dummy split at the beginning to ensure correct offset Split start; start.pos = 0; for (int lane = 0; lane < (int)e->getNumLanes(); ++lane) { start.lanes.push_back(lane); } mySplits.insert(mySplits.begin(), start); } i = mySplits.begin(); for (; i != mySplits.end(); ++i) { unsigned int maxLeft = (*i).lanes.back(); SUMOReal offset = 0; if (maxLeft < noLanesMax) { if (e->getLaneSpreadFunction() == LANESPREAD_RIGHT) { offset = SUMO_const_laneWidthAndOffset * (noLanesMax - 1 - maxLeft); } else { offset = SUMO_const_halfLaneAndOffset * (noLanesMax - 1 - maxLeft); } } unsigned int maxRight = (*i).lanes.front(); if (maxRight > 0 && e->getLaneSpreadFunction() == LANESPREAD_CENTER) { offset -= SUMO_const_halfLaneAndOffset * maxRight; } if (offset != 0) { PositionVector g = e->getGeometry(); g.move2side(offset); e->setGeometry(g); } if (e->getToNode()->getOutgoingEdges().size() != 0) { e = e->getToNode()->getOutgoingEdges()[0]; } } } } }