void NWWriter_XML::writeEdgesAndConnections(const OptionsCont& oc, NBNodeCont& nc, NBEdgeCont& ec) { const GeoConvHelper& gch = GeoConvHelper::getFinal(); bool useGeo = oc.exists("proj.plain-geo") && oc.getBool("proj.plain-geo"); const bool geoAccuracy = useGeo || gch.usingInverseGeoProjection(); OutputDevice& edevice = OutputDevice::getDevice(oc.getString("plain-output-prefix") + ".edg.xml"); edevice.writeXMLHeader("edges", NWFrame::MAJOR_VERSION + " xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" xsi:noNamespaceSchemaLocation=\"http://sumo-sim.org/xsd/edges_file.xsd\""); OutputDevice& cdevice = OutputDevice::getDevice(oc.getString("plain-output-prefix") + ".con.xml"); cdevice.writeXMLHeader("connections", NWFrame::MAJOR_VERSION + " xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" xsi:noNamespaceSchemaLocation=\"http://sumo-sim.org/xsd/connections_file.xsd\""); bool noNames = !oc.getBool("output.street-names"); for (std::map<std::string, NBEdge*>::const_iterator i = ec.begin(); i != ec.end(); ++i) { // write the edge itself to the edges-files NBEdge* e = (*i).second; edevice.openTag(SUMO_TAG_EDGE); edevice.writeAttr(SUMO_ATTR_ID, e->getID()); edevice.writeAttr(SUMO_ATTR_FROM, e->getFromNode()->getID()); edevice.writeAttr(SUMO_ATTR_TO, e->getToNode()->getID()); if (!noNames && e->getStreetName() != "") { edevice.writeAttr(SUMO_ATTR_NAME, StringUtils::escapeXML(e->getStreetName())); } edevice.writeAttr(SUMO_ATTR_PRIORITY, e->getPriority()); // write the type if given if (e->getTypeID() != "") { edevice.writeAttr(SUMO_ATTR_TYPE, e->getTypeID()); } edevice.writeAttr(SUMO_ATTR_NUMLANES, e->getNumLanes()); if (!e->hasLaneSpecificSpeed()) { edevice.writeAttr(SUMO_ATTR_SPEED, e->getSpeed()); } // write non-default geometry if (!e->hasDefaultGeometry()) { PositionVector geom = e->getGeometry(); if (useGeo) { for (int i = 0; i < (int) geom.size(); i++) { gch.cartesian2geo(geom[i]); } } if (geoAccuracy) { edevice.setPrecision(GEO_OUTPUT_ACCURACY); } edevice.writeAttr(SUMO_ATTR_SHAPE, geom); if (geoAccuracy) { edevice.setPrecision(); } } // write the spread type if not default ("right") if (e->getLaneSpreadFunction() != LANESPREAD_RIGHT) { edevice.writeAttr(SUMO_ATTR_SPREADTYPE, toString(e->getLaneSpreadFunction())); } // write the length if it was specified if (e->hasLoadedLength()) { edevice.writeAttr(SUMO_ATTR_LENGTH, e->getLoadedLength()); } // some attributes can be set by edge default or per lane. Write as default if possible (efficiency) if (e->getLaneWidth() != NBEdge::UNSPECIFIED_WIDTH && !e->hasLaneSpecificWidth()) { edevice.writeAttr(SUMO_ATTR_WIDTH, e->getLaneWidth()); } if (e->getOffset() != NBEdge::UNSPECIFIED_OFFSET && !e->hasLaneSpecificOffset()) { edevice.writeAttr(SUMO_ATTR_OFFSET, e->getOffset()); } if (!e->needsLaneSpecificOutput()) { edevice.closeTag(); } else { for (unsigned int i = 0; i < e->getLanes().size(); ++i) { const NBEdge::Lane& lane = e->getLanes()[i]; edevice.openTag(SUMO_TAG_LANE); edevice.writeAttr(SUMO_ATTR_INDEX, i); // write allowed lanes NWWriter_SUMO::writePermissions(edevice, lane.permissions); NWWriter_SUMO::writePreferences(edevice, lane.preferred); // write other attributes if (lane.width != NBEdge::UNSPECIFIED_WIDTH && e->hasLaneSpecificWidth()) { edevice.writeAttr(SUMO_ATTR_WIDTH, lane.width); } if (lane.offset != NBEdge::UNSPECIFIED_OFFSET && e->hasLaneSpecificOffset()) { edevice.writeAttr(SUMO_ATTR_OFFSET, lane.offset); } if (e->hasLaneSpecificSpeed()) { edevice.writeAttr(SUMO_ATTR_SPEED, lane.speed); } edevice.closeTag(); } edevice.closeTag(); } // write this edge's connections to the connections-files e->sortOutgoingConnectionsByIndex(); const std::vector<NBEdge::Connection> connections = e->getConnections(); for (std::vector<NBEdge::Connection>::const_iterator c = connections.begin(); c != connections.end(); ++c) { NWWriter_SUMO::writeConnection(cdevice, *e, *c, false, NWWriter_SUMO::PLAIN); } if (connections.size() > 0) { cdevice << "\n"; } } // write loaded prohibitions to the connections-file for (std::map<std::string, NBNode*>::const_iterator i = nc.begin(); i != nc.end(); ++i) { NWWriter_SUMO::writeProhibitions(cdevice, i->second->getProhibitions()); } edevice.close(); cdevice.close(); }
int NWWriter_OpenDrive::writeInternalEdge(OutputDevice& device, OutputDevice& junctionDevice, const NBEdge* inEdge, int nodeID, int edgeID, int inEdgeID, int outEdgeID, int connectionID, const std::vector<NBEdge::Connection>& parallel, const bool isOuterEdge, const double straightThresh, const std::string& centerMark) { assert(parallel.size() != 0); const NBEdge::Connection& cLeft = parallel.back(); const NBEdge* outEdge = cLeft.toEdge; PositionVector begShape = getLeftLaneBorder(inEdge, cLeft.fromLane); PositionVector endShape = getLeftLaneBorder(outEdge, cLeft.toLane); //std::cout << "computing reference line for internal lane " << cLeft.getInternalLaneID() << " begLane=" << inEdge->getLaneShape(cLeft.fromLane) << " endLane=" << outEdge->getLaneShape(cLeft.toLane) << "\n"; double length; double laneOffset = 0; PositionVector fallBackShape; fallBackShape.push_back(begShape.back()); fallBackShape.push_back(endShape.front()); const bool turnaround = inEdge->isTurningDirectionAt(outEdge); bool ok = true; PositionVector init = NBNode::bezierControlPoints(begShape, endShape, turnaround, 25, 25, ok, 0, straightThresh); if (init.size() == 0) { length = fallBackShape.length2D(); // problem with turnarounds is known, method currently returns 'ok' (#2539) if (!ok) { WRITE_WARNING("Could not compute smooth shape from lane '" + inEdge->getLaneID(cLeft.fromLane) + "' to lane '" + outEdge->getLaneID(cLeft.toLane) + "'. Use option 'junctions.scurve-stretch' or increase radius of junction '" + inEdge->getToNode()->getID() + "' to fix this."); } else if (length <= NUMERICAL_EPS) { // left-curving geometry-like edges must use the right // side as reference line and shift begShape = getRightLaneBorder(inEdge, cLeft.fromLane); endShape = getRightLaneBorder(outEdge, cLeft.toLane); init = NBNode::bezierControlPoints(begShape, endShape, turnaround, 25, 25, ok, 0, straightThresh); if (init.size() != 0) { length = bezier(init, 12).length2D(); laneOffset = outEdge->getLaneWidth(cLeft.toLane); //std::cout << " internalLane=" << cLeft.getInternalLaneID() << " length=" << length << "\n"; } } } else { length = bezier(init, 12).length2D(); } junctionDevice << " <connection id=\"" << connectionID << "\" incomingRoad=\"" << inEdgeID << "\" connectingRoad=\"" << edgeID << "\" contactPoint=\"start\">\n"; device.openTag("road"); device.writeAttr("name", cLeft.id); device.setPrecision(8); // length requires higher precision device.writeAttr("length", MAX2(POSITION_EPS, length)); device.setPrecision(gPrecision); device.writeAttr("id", edgeID); device.writeAttr("junction", nodeID); device.openTag("link"); device.openTag("predecessor"); device.writeAttr("elementType", "road"); device.writeAttr("elementId", inEdgeID); device.writeAttr("contactPoint", "end"); device.closeTag(); device.openTag("successor"); device.writeAttr("elementType", "road"); device.writeAttr("elementId", outEdgeID); device.writeAttr("contactPoint", "start"); device.closeTag(); device.closeTag(); device.openTag("type").writeAttr("s", 0).writeAttr("type", "town").closeTag(); device.openTag("planView"); device.setPrecision(8); // geometry hdg requires higher precision OutputDevice_String elevationOSS(false, 3); elevationOSS.setPrecision(8); #ifdef DEBUG_SMOOTH_GEOM if (DEBUGCOND) { std::cout << "write planview for internal edge " << cLeft.id << " init=" << init << " fallback=" << fallBackShape << " begShape=" << begShape << " endShape=" << endShape << "\n"; } #endif if (init.size() == 0) { writeGeomLines(fallBackShape, device, elevationOSS); } else { writeGeomPP3(device, elevationOSS, init, length); } device.setPrecision(gPrecision); device.closeTag(); writeElevationProfile(fallBackShape, device, elevationOSS); device << " <lateralProfile/>\n"; device << " <lanes>\n"; if (laneOffset != 0) { device << " <laneOffset s=\"0\" a=\"" << laneOffset << "\" b=\"0\" c=\"0\" d=\"0\"/>\n"; } device << " <laneSection s=\"0\">\n"; writeEmptyCenterLane(device, centerMark, 0); device << " <right>\n"; for (int j = (int)parallel.size(); --j >= 0;) { const NBEdge::Connection& c = parallel[j]; const int fromIndex = c.fromLane - inEdge->getNumLanes(); const int toIndex = c.toLane - outEdge->getNumLanes(); device << " <lane id=\"-" << parallel.size() - j << "\" type=\"" << getLaneType(outEdge->getPermissions(c.toLane)) << "\" level=\"true\">\n"; device << " <link>\n"; device << " <predecessor id=\"" << fromIndex << "\"/>\n"; device << " <successor id=\"" << toIndex << "\"/>\n"; device << " </link>\n"; device << " <width sOffset=\"0\" a=\"" << outEdge->getLaneWidth(c.toLane) << "\" b=\"0\" c=\"0\" d=\"0\"/>\n"; std::string markType = "broken"; if (inEdge->isTurningDirectionAt(outEdge)) { markType = "none"; } else if (c.fromLane == 0 && c.toLane == 0 && isOuterEdge) { // solid road mark at the outer border markType = "solid"; } else if (isOuterEdge && j > 0 && (outEdge->getPermissions(parallel[j - 1].toLane) & ~(SVC_PEDESTRIAN | SVC_BICYCLE)) == 0) { // solid road mark to the left of sidewalk or bicycle lane markType = "solid"; } else if (!inEdge->getToNode()->geometryLike()) { // draw shorter road marks to indicate turning paths LinkDirection dir = inEdge->getToNode()->getDirection(inEdge, outEdge, OptionsCont::getOptions().getBool("lefthand")); if (dir == LINKDIR_LEFT || dir == LINKDIR_RIGHT || dir == LINKDIR_PARTLEFT || dir == LINKDIR_PARTRIGHT) { // XXX <type><line/><type> is not rendered by odrViewer so cannot be validated // device << " <type name=\"broken\" width=\"0.13\">\n"; // device << " <line length=\"0.5\" space=\"0.5\" tOffset=\"0\" sOffset=\"0\" rule=\"none\"/>\n"; // device << " </type>\n"; markType = "none"; } } device << " <roadMark sOffset=\"0\" type=\"" << markType << "\" weight=\"standard\" color=\"standard\" width=\"0.13\"/>\n"; device << " <speed sOffset=\"0\" max=\"" << c.vmax << "\"/>\n"; device << " </lane>\n"; junctionDevice << " <laneLink from=\"" << fromIndex << "\" to=\"" << toIndex << "\"/>\n"; connectionID++; } device << " </right>\n"; device << " </laneSection>\n"; device << " </lanes>\n"; device << " <objects/>\n"; device << " <signals/>\n"; device.closeTag(); junctionDevice << " </connection>\n"; return connectionID; }
bool NWWriter_OpenDrive::writeGeomSmooth(const PositionVector& shape, double speed, OutputDevice& device, OutputDevice& elevationDevice, double straightThresh, double& length) { #ifdef DEBUG_SMOOTH_GEOM if (DEBUGCOND) { std::cout << "writeGeomSmooth\n n=" << shape.size() << " shape=" << toString(shape) << "\n"; } #endif bool ok = true; const double longThresh = speed; // 16.0; // make user-configurable (should match the sampling rate of the source data) const double curveCutout = longThresh / 2; // 8.0; // make user-configurable (related to the maximum turning rate) // the length of the segment that is added for cutting a corner can be bounded by 2*curveCutout (prevent the segment to be classified as 'long') assert(longThresh >= 2 * curveCutout); assert(shape.size() > 2); // add intermediate points wherever there is a strong angular change between long segments // assume the geometry is simplified so as not to contain consecutive colinear points PositionVector shape2 = shape; double maxAngleDiff = 0; double offset = 0; for (int j = 1; j < (int)shape.size() - 1; ++j) { //const double hdg = shape.angleAt2D(j); const Position& p0 = shape[j - 1]; const Position& p1 = shape[j]; const Position& p2 = shape[j + 1]; const double dAngle = fabs(GeomHelper::angleDiff(p0.angleTo2D(p1), p1.angleTo2D(p2))); const double length1 = p0.distanceTo2D(p1); const double length2 = p1.distanceTo2D(p2); maxAngleDiff = MAX2(maxAngleDiff, dAngle); #ifdef DEBUG_SMOOTH_GEOM if (DEBUGCOND) { std::cout << " j=" << j << " dAngle=" << RAD2DEG(dAngle) << " length1=" << length1 << " length2=" << length2 << "\n"; } #endif if (dAngle > straightThresh && (length1 > longThresh || j == 1) && (length2 > longThresh || j == (int)shape.size() - 2)) { shape2.insertAtClosest(shape.positionAtOffset2D(offset + length1 - MIN2(length1 - POSITION_EPS, curveCutout))); shape2.insertAtClosest(shape.positionAtOffset2D(offset + length1 + MIN2(length2 - POSITION_EPS, curveCutout))); shape2.removeClosest(p1); } offset += length1; } const int numPoints = (int)shape2.size(); #ifdef DEBUG_SMOOTH_GEOM if (DEBUGCOND) { std::cout << " n=" << numPoints << " shape2=" << toString(shape2) << "\n"; } #endif if (maxAngleDiff < straightThresh) { length = writeGeomLines(shape2, device, elevationDevice, 0); #ifdef DEBUG_SMOOTH_GEOM if (DEBUGCOND) { std::cout << " special case: all lines. maxAngleDiff=" << maxAngleDiff << "\n"; } #endif return ok; } // write the long segments as lines, short segments as curves offset = 0; for (int j = 0; j < numPoints - 1; ++j) { const Position& p0 = shape2[j]; const Position& p1 = shape2[j + 1]; PositionVector line; line.push_back(p0); line.push_back(p1); const double lineLength = line.length2D(); if (lineLength >= longThresh) { offset = writeGeomLines(line, device, elevationDevice, offset); #ifdef DEBUG_SMOOTH_GEOM if (DEBUGCOND) { std::cout << " writeLine=" << toString(line) << "\n"; } #endif } else { // find control points PositionVector begShape; PositionVector endShape; if (j == 0 || j == numPoints - 2) { // keep the angle of the first/last segment but end at the front of the shape begShape = line; begShape.add(p0 - begShape.back()); } else if (j == 1 || p0.distanceTo2D(shape2[j - 1]) > longThresh) { // use the previous segment if it is long or the first one begShape.push_back(shape2[j - 1]); begShape.push_back(p0); } else { // end at p0 with mean angle of the previous and current segment begShape.push_back(shape2[j - 1]); begShape.push_back(p1); begShape.add(p0 - begShape.back()); } if (j == 0 || j == numPoints - 2) { // keep the angle of the first/last segment but start at the end of the shape endShape = line; endShape.add(p1 - endShape.front()); } else if (j == numPoints - 3 || p1.distanceTo2D(shape2[j + 2]) > longThresh) { // use the next segment if it is long or the final one endShape.push_back(p1); endShape.push_back(shape2[j + 2]); } else { // start at p1 with mean angle of the current and next segment endShape.push_back(p0); endShape.push_back(shape2[j + 2]); endShape.add(p1 - endShape.front()); } const double extrapolateLength = MIN2((double)25, lineLength / 4); PositionVector init = NBNode::bezierControlPoints(begShape, endShape, false, extrapolateLength, extrapolateLength, ok, 0, straightThresh); if (init.size() == 0) { // could not compute control points, write line offset = writeGeomLines(line, device, elevationDevice, offset); #ifdef DEBUG_SMOOTH_GEOM if (DEBUGCOND) { std::cout << " writeLine lineLength=" << lineLength << " begShape" << j << "=" << toString(begShape) << " endShape" << j << "=" << toString(endShape) << " init" << j << "=" << toString(init) << "\n"; } #endif } else { // write bezier const double curveLength = bezier(init, 12).length2D(); offset = writeGeomPP3(device, elevationDevice, init, curveLength, offset); #ifdef DEBUG_SMOOTH_GEOM if (DEBUGCOND) { std::cout << " writeCurve lineLength=" << lineLength << " curveLength=" << curveLength << " begShape" << j << "=" << toString(begShape) << " endShape" << j << "=" << toString(endShape) << " init" << j << "=" << toString(init) << "\n"; } #endif } } } length = offset; return ok; }
void PCLoaderDlrNavteq::loadPolyFile(const std::string& file, OptionsCont& oc, PCPolyContainer& toFill, PCTypeMap& tm) { // get the defaults RGBColor c = RGBColor::parseColor(oc.getString("color")); // attributes of the poly // parse int l = 0; LineReader lr(file); while (lr.hasMore()) { std::string line = lr.readLine(); ++l; // skip invalid/empty lines if (line.length() == 0 || line.find("#") != std::string::npos) { continue; } if (StringUtils::prune(line) == "") { continue; } // parse the poi StringTokenizer st(line, "\t"); std::vector<std::string> values = st.getVector(); if (values.size() < 6 || values.size() % 2 != 0) { throw ProcessError("Invalid dlr-navteq-polygon - line: '" + line + "'."); } std::string id = values[0]; std::string ort = values[1]; std::string type = values[2]; std::string name = values[3]; PositionVector vec; size_t index = 4; // now collect the positions while (values.size() > index) { std::string xpos = values[index]; std::string ypos = values[index + 1]; index += 2; SUMOReal x = TplConvert::_2SUMOReal(xpos.c_str()); SUMOReal y = TplConvert::_2SUMOReal(ypos.c_str()); Position pos(x, y); if (!GeoConvHelper::getProcessing().x2cartesian(pos)) { WRITE_WARNING("Unable to project coordinates for polygon '" + id + "'."); } vec.push_back(pos); } name = StringUtils::convertUmlaute(name); if (name == "noname" || toFill.containsPolygon(name)) { name = name + "#" + toString(toFill.getEnumIDFor(name)); } // check the polygon if (vec.size() == 0) { WRITE_WARNING("The polygon '" + id + "' is empty."); continue; } if (id == "") { WRITE_WARNING("The name of a polygon is missing; it will be discarded."); continue; } // patch the values bool fill = vec.front() == vec.back(); bool discard = oc.getBool("discard"); int layer = oc.getInt("layer"); RGBColor color; if (tm.has(type)) { const PCTypeMap::TypeDef& def = tm.get(type); name = def.prefix + name; type = def.id; color = def.color; fill = fill && def.allowFill; discard = def.discard; layer = def.layer; } else { name = oc.getString("prefix") + name; type = oc.getString("type"); color = c; } if (!discard) { Polygon* poly = new Polygon(name, type, color, vec, fill, (SUMOReal)layer); toFill.insert(name, poly, layer); } vec.clear(); } }
void GUIParkingArea::drawGL(const GUIVisualizationSettings& s) const { glPushName(getGlID()); glPushMatrix(); RGBColor grey(177, 184, 186, 171); RGBColor blue(83, 89, 172, 255); RGBColor red(255, 0, 0, 255); RGBColor green(0, 255, 0, 255); // draw the area glTranslated(0, 0, getType()); GLHelper::setColor(blue); GLHelper::drawBoxLines(myShape, myShapeRotations, myShapeLengths, myWidth / 2.); // draw details unless zoomed out to far const SUMOReal exaggeration = s.addSize.getExaggeration(s); if (s.scale * exaggeration >= 10) { // draw the lots glTranslated(0, 0, .1); std::map<unsigned int, LotSpaceDefinition >::const_iterator i; for (i = mySpaceOccupancies.begin(); i != mySpaceOccupancies.end(); i++) { glPushMatrix(); glTranslated((*i).second.myPosition.x(), (*i).second.myPosition.y(), (*i).second.myPosition.z()); glRotated((*i).second.myRotation, 0, 0, 1); Position pos = (*i).second.myPosition; PositionVector geom; SUMOReal w = (*i).second.myWidth / 2.; SUMOReal h = (*i).second.myLength; geom.push_back(Position(- w, + 0, 0.)); geom.push_back(Position(+ w, + 0, 0.)); geom.push_back(Position(+ w, + h, 0.)); geom.push_back(Position(- w, + h, 0.)); geom.push_back(Position(- w, + 0, 0.)); /* geom.push_back(Position(pos.x(), pos.y(), pos.z())); geom.push_back(Position(pos.x() + (*l).second.myWidth, pos.y(), pos.z())); geom.push_back(Position(pos.x() + (*l).second.myWidth, pos.y() - (*l).second.myLength, pos.z())); geom.push_back(Position(pos.x(), pos.y() - (*l).second.myLength, pos.z())); geom.push_back(Position(pos.x(), pos.y(), pos.z())); */ GLHelper::setColor((*i).second.vehicle == 0 ? green : red); GLHelper::drawBoxLines(geom, 0.1); glPopMatrix(); } GLHelper::setColor(blue); // draw the lines for (size_t i = 0; i != myLines.size(); ++i) { glPushMatrix(); glTranslated(mySignPos.x(), mySignPos.y(), 0); glRotated(180, 1, 0, 0); glRotated(mySignRot, 0, 0, 1); glPolygonMode(GL_FRONT_AND_BACK, GL_FILL); pfSetPosition(0, 0); pfSetScale(1.f); glScaled(exaggeration, exaggeration, 1); glTranslated(1.2, -(double)i, 0); pfDrawString(myLines[i].c_str()); glPopMatrix(); } // draw the sign glTranslated(mySignPos.x(), mySignPos.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((SUMOReal) 1.1, noPoints); glTranslated(0, 0, .1); GLHelper::setColor(grey); GLHelper::drawFilledCircle((SUMOReal) 0.9, noPoints); if (s.scale * exaggeration >= 4.5) { GLHelper::drawText("P", Position(), .1, 1.6 * exaggeration, blue, mySignRot); } } glPopMatrix(); glPopName(); drawName(getCenteringBoundary().getCenter(), s.scale, s.addName); for (std::vector<MSTransportable*>::const_iterator i = myWaitingTransportables.begin(); i != myWaitingTransportables.end(); ++i) { glTranslated(0, 1, 0); // make multiple containers viewable static_cast<GUIContainer*>(*i)->drawGL(s); } }
void GUIParkingArea::drawGL(const GUIVisualizationSettings& s) const { glPushName(getGlID()); glPushMatrix(); RGBColor grey(177, 184, 186, 171); RGBColor blue(83, 89, 172, 255); RGBColor red(255, 0, 0, 255); RGBColor green(0, 255, 0, 255); // draw the area glTranslated(0, 0, getType()); GLHelper::setColor(blue); GLHelper::drawBoxLines(myShape, myShapeRotations, myShapeLengths, myWidth / 2.); // draw details unless zoomed out to far const double exaggeration = s.addSize.getExaggeration(s); if (s.scale * exaggeration >= 1) { // draw the lots glTranslated(0, 0, .1); std::map<unsigned int, LotSpaceDefinition >::const_iterator i; for (i = mySpaceOccupancies.begin(); i != mySpaceOccupancies.end(); i++) { glPushMatrix(); glTranslated((*i).second.myPosition.x(), (*i).second.myPosition.y(), (*i).second.myPosition.z()); glRotated((*i).second.myRotation, 0, 0, 1); Position pos = (*i).second.myPosition; PositionVector geom; double w = (*i).second.myWidth / 2. - 0.1 * exaggeration; double h = (*i).second.myLength; geom.push_back(Position(- w, + 0, 0.)); geom.push_back(Position(+ w, + 0, 0.)); geom.push_back(Position(+ w, + h, 0.)); geom.push_back(Position(- w, + h, 0.)); geom.push_back(Position(- w, + 0, 0.)); /* geom.push_back(Position(pos.x(), pos.y(), pos.z())); geom.push_back(Position(pos.x() + (*l).second.myWidth, pos.y(), pos.z())); geom.push_back(Position(pos.x() + (*l).second.myWidth, pos.y() - (*l).second.myLength, pos.z())); geom.push_back(Position(pos.x(), pos.y() - (*l).second.myLength, pos.z())); geom.push_back(Position(pos.x(), pos.y(), pos.z())); */ GLHelper::setColor((*i).second.vehicle == 0 ? green : red); GLHelper::drawBoxLines(geom, 0.1 * exaggeration); glPopMatrix(); } GLHelper::setColor(blue); // draw the lines for (size_t i = 0; i != myLines.size(); ++i) { // push a new matrix for every line glPushMatrix(); // traslate and rotate glTranslated(mySignPos.x(), mySignPos.y(), 0); glRotated(180, 1, 0, 0); glRotated(mySignRot, 0, 0, 1); // draw line GLHelper::drawText(myLines[i].c_str(), Position(1.2, (double)i), .1, 1.f, RGBColor(76, 170, 50), 0, FONS_ALIGN_LEFT); // pop matrix for every line glPopMatrix(); } // draw the sign glTranslated(mySignPos.x(), mySignPos.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(grey); GLHelper::drawFilledCircle((double) 0.9, noPoints); if (s.scale * exaggeration >= 4.5) { GLHelper::drawText("P", Position(), .1, 1.6, blue, mySignRot); } } glPopMatrix(); if (s.addFullName.show && getMyName() != "") { GLHelper::drawText(getMyName(), mySignPos, GLO_MAX - getType(), s.addFullName.scaledSize(s.scale), s.addFullName.color, s.getTextAngle(mySignRot)); } glPopName(); drawName(getCenteringBoundary().getCenter(), s.scale, s.addName); for (std::vector<MSTransportable*>::const_iterator i = myWaitingTransportables.begin(); i != myWaitingTransportables.end(); ++i) { glTranslated(0, 1, 0); // make multiple containers viewable static_cast<GUIContainer*>(*i)->drawGL(s); } // draw parking vehicles (their lane might not be within drawing range. if it is, they are drawn twice) myLane.getVehiclesSecure(); for (std::set<const MSVehicle*>::const_iterator v = myLane.getParkingVehicles().begin(); v != myLane.getParkingVehicles().end(); ++v) { static_cast<const GUIVehicle* const>(*v)->drawGL(s); } myLane.releaseVehicles(); }
/* Test the method 'splitAt'*/ TEST_F(PositionVectorTest, test_method_splitAt) { PositionVector vec; vec.push_back(Position(0,0)); vec.push_back(Position(2,0)); vec.push_back(Position(5,0)); SUMOReal smallDiff = POSITION_EPS / 2; std::pair<PositionVector, PositionVector> result; // split in first segment result = vec.splitAt(1); EXPECT_DOUBLE_EQ(2, result.first.size()); EXPECT_DOUBLE_EQ(0, result.first[0].x()); EXPECT_DOUBLE_EQ(1, result.first[1].x()); EXPECT_DOUBLE_EQ(3, result.second.size()); EXPECT_DOUBLE_EQ(1, result.second[0].x()); EXPECT_DOUBLE_EQ(2, result.second[1].x()); EXPECT_DOUBLE_EQ(5, result.second[2].x()); // split in second segment result = vec.splitAt(4); EXPECT_DOUBLE_EQ(3, result.first.size()); EXPECT_DOUBLE_EQ(0, result.first[0].x()); EXPECT_DOUBLE_EQ(2, result.first[1].x()); EXPECT_DOUBLE_EQ(4, result.first[2].x()); EXPECT_DOUBLE_EQ(2, result.second.size()); EXPECT_DOUBLE_EQ(4, result.second[0].x()); EXPECT_DOUBLE_EQ(5, result.second[1].x()); // split close before inner point result = vec.splitAt(2 - smallDiff); EXPECT_DOUBLE_EQ(2, result.first.size()); EXPECT_DOUBLE_EQ(0, result.first[0].x()); EXPECT_DOUBLE_EQ(2, result.first[1].x()); EXPECT_DOUBLE_EQ(2, result.second.size()); EXPECT_DOUBLE_EQ(2, result.second[0].x()); EXPECT_DOUBLE_EQ(5 ,result.second[1].x()); // split close after inner point result = vec.splitAt(2 + smallDiff); EXPECT_DOUBLE_EQ(2, result.first.size()); EXPECT_DOUBLE_EQ(0, result.first[0].x()); EXPECT_DOUBLE_EQ(2, result.first[1].x()); EXPECT_DOUBLE_EQ(2, result.second.size()); EXPECT_DOUBLE_EQ(2, result.second[0].x()); EXPECT_DOUBLE_EQ(5 ,result.second[1].x()); // catch a bug vec.push_back(Position(6,0)); vec.push_back(Position(8,0)); // split at inner point result = vec.splitAt(5); EXPECT_DOUBLE_EQ(3, result.first.size()); EXPECT_DOUBLE_EQ(0, result.first[0].x()); EXPECT_DOUBLE_EQ(2, result.first[1].x()); EXPECT_DOUBLE_EQ(5, result.first[2].x()); EXPECT_DOUBLE_EQ(3, result.second.size()); EXPECT_DOUBLE_EQ(5, result.second[0].x()); EXPECT_DOUBLE_EQ(6 ,result.second[1].x()); EXPECT_DOUBLE_EQ(8 ,result.second[2].x()); // split short vector PositionVector vec2; vec2.push_back(Position(0,0)); vec2.push_back(Position(2,0)); result = vec2.splitAt(1); EXPECT_DOUBLE_EQ(2, result.first.size()); EXPECT_DOUBLE_EQ(0, result.first[0].x()); EXPECT_DOUBLE_EQ(1, result.first[1].x()); EXPECT_DOUBLE_EQ(2, result.second.size()); EXPECT_DOUBLE_EQ(1, result.second[0].x()); EXPECT_DOUBLE_EQ(2 ,result.second[1].x()); // split very short vector PositionVector vec3; vec3.push_back(Position(0,0)); vec3.push_back(Position(POSITION_EPS,0)); // supress expected warning MsgHandler::getWarningInstance()->removeRetriever(&OutputDevice::getDevice("stderr")); result = vec3.splitAt(smallDiff); MsgHandler::getWarningInstance()->addRetriever(&OutputDevice::getDevice("stderr")); EXPECT_DOUBLE_EQ(2, result.first.size()); EXPECT_DOUBLE_EQ(0, result.first[0].x()); EXPECT_DOUBLE_EQ(smallDiff, result.first[1].x()); EXPECT_DOUBLE_EQ(2, result.second.size()); EXPECT_DOUBLE_EQ(smallDiff, result.second[0].x()); EXPECT_DOUBLE_EQ(POSITION_EPS ,result.second[1].x()); }
void NBRampsComputer::buildOffRamp(NBNode* cur, NBNodeCont& nc, NBEdgeCont& ec, NBDistrictCont& dc, SUMOReal rampLength, bool dontSplit, std::set<NBEdge*>& incremented) { NBEdge* potHighway, *potRamp, *prev; getOffRampEdges(cur, &potHighway, &potRamp, &prev); // compute the number of lanes to append const unsigned int firstLaneNumber = potHighway->getNumLanes(); int toAdd = (potRamp->getNumLanes() + firstLaneNumber) - prev->getNumLanes(); NBEdge* first = prev; NBEdge* last = prev; NBEdge* curr = prev; if (toAdd > 0 && find(incremented.begin(), incremented.end(), prev) == incremented.end()) { SUMOReal currLength = 0; while (curr != 0 && currLength + curr->getGeometry().length() - POSITION_EPS < rampLength) { if (find(incremented.begin(), incremented.end(), curr) == incremented.end()) { curr->incLaneNo(toAdd); curr->invalidateConnections(true); incremented.insert(curr); moveRampRight(curr, toAdd); currLength += curr->getLength(); // !!! loaded length? last = curr; } NBNode* prevN = curr->getFromNode(); if (prevN->getIncomingEdges().size() == 1) { curr = prevN->getIncomingEdges()[0]; if (curr->getNumLanes() != firstLaneNumber) { // the number of lanes changes along the computation; we'll stop... curr = 0; } } else { // ambigous; and, in fact, what should it be? ...stop curr = 0; } } // check whether a further split is necessary if (curr != 0 && !dontSplit && currLength - POSITION_EPS < rampLength && curr->getNumLanes() == firstLaneNumber && find(incremented.begin(), incremented.end(), curr) == incremented.end()) { // there is enough place to build a ramp; do it bool wasFirst = first == curr; Position pos = curr->getGeometry().positionAtLengthPosition(curr->getGeometry().length() - (rampLength - currLength)); NBNode* rn = new NBNode(curr->getID() + "-AddedOffRampNode", pos); if (!nc.insert(rn)) { throw ProcessError("Ups - could not build on-ramp for edge '" + curr->getID() + "' (node could not be build)!"); } std::string name = curr->getID(); bool ok = ec.splitAt(dc, curr, rn, curr->getID(), curr->getID() + "-AddedOffRampEdge", curr->getNumLanes(), curr->getNumLanes() + toAdd); if (!ok) { WRITE_ERROR("Ups - could not build on-ramp for edge '" + curr->getID() + "'!"); return; } curr = ec.retrieve(name + "-AddedOffRampEdge"); curr->invalidateConnections(true); incremented.insert(curr); last = curr; moveRampRight(curr, toAdd); if (wasFirst) { first = curr; } } } // set connections from added ramp to ramp/highway if (!first->addLane2LaneConnections(potRamp->getNumLanes(), potHighway, 0, MIN2(first->getNumLanes() - 1, potHighway->getNumLanes()), NBEdge::L2L_VALIDATED, true)) { throw ProcessError("Could not set connection!"); } if (!first->addLane2LaneConnections(0, potRamp, 0, potRamp->getNumLanes(), NBEdge::L2L_VALIDATED, false)) { throw ProcessError("Could not set connection!"); } // patch ramp geometry PositionVector p = potRamp->getGeometry(); p.pop_front(); p.push_front(first->getLaneShape(0)[-1]); potRamp->setGeometry(p); // set connections from previous highway to added ramp NBNode* prevN = last->getFromNode(); if (prevN->getIncomingEdges().size() == 1) { NBEdge* prev = prevN->getIncomingEdges()[0];//const EdgeVector& o1 = cont->getToNode()->getOutgoingEdges(); if (prev->getNumLanes() < last->getNumLanes()) { last->addLane2LaneConnections(last->getNumLanes() - prev->getNumLanes(), last, 0, prev->getNumLanes(), NBEdge::L2L_VALIDATED); } } }
PositionVector PositionVector::convexHull() const { PositionVector ret = *this; ret.sortAsPolyCWByAngle(); return simpleHull_2D(ret); }
// =========================================================================== // method definitions // =========================================================================== // --------------------------------------------------------------------------- // static methods // --------------------------------------------------------------------------- void NWWriter_OpenDrive::writeNetwork(const OptionsCont& oc, NBNetBuilder& nb) { // check whether an opendrive-file shall be generated if (!oc.isSet("opendrive-output")) { return; } const NBNodeCont& nc = nb.getNodeCont(); const NBEdgeCont& ec = nb.getEdgeCont(); const bool origNames = oc.getBool("output.original-names"); const SUMOReal straightThresh = DEG2RAD(oc.getFloat("opendrive-output.straight-threshold")); // some internal mapping containers int nodeID = 1; int edgeID = nc.size() * 10; // distinct from node ids StringBijection<int> edgeMap; StringBijection<int> nodeMap; // OutputDevice& device = OutputDevice::getDevice(oc.getString("opendrive-output")); device << "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n"; device.openTag("OpenDRIVE"); time_t now = time(0); std::string dstr(ctime(&now)); const Boundary& b = GeoConvHelper::getFinal().getConvBoundary(); // write header device.openTag("header"); device.writeAttr("revMajor", "1"); device.writeAttr("revMinor", "4"); device.writeAttr("name", ""); device.writeAttr("version", "1.00"); device.writeAttr("date", dstr.substr(0, dstr.length() - 1)); device.writeAttr("north", b.ymax()); device.writeAttr("south", b.ymin()); device.writeAttr("east", b.xmax()); device.writeAttr("west", b.xmin()); /* @note obsolete in 1.4 device.writeAttr("maxRoad", ec.size()); device.writeAttr("maxJunc", nc.size()); device.writeAttr("maxPrg", 0); */ device.closeTag(); // write normal edges (road) for (std::map<std::string, NBEdge*>::const_iterator i = ec.begin(); i != ec.end(); ++i) { const NBEdge* e = (*i).second; // buffer output because some fields are computed out of order OutputDevice_String elevationOSS(false, 3); elevationOSS.setPrecision(8); OutputDevice_String planViewOSS(false, 2); planViewOSS.setPrecision(8); SUMOReal length = 0; planViewOSS.openTag("planView"); planViewOSS.setPrecision(8); // geometry hdg requires higher precision // for the shape we need to use the leftmost border of the leftmost lane const std::vector<NBEdge::Lane>& lanes = e->getLanes(); PositionVector ls = getLeftLaneBorder(e); #ifdef DEBUG_SMOOTH_GEOM if (DEBUGCOND) { std::cout << "write planview for edge " << e->getID() << "\n"; } #endif if (ls.size() == 2 || e->getPermissions() == SVC_PEDESTRIAN) { // foot paths may contain sharp angles length = writeGeomLines(ls, planViewOSS, elevationOSS); } else { bool ok = writeGeomSmooth(ls, e->getSpeed(), planViewOSS, elevationOSS, straightThresh, length); if (!ok) { WRITE_WARNING("Could not compute smooth shape for edge '" + e->getID() + "'."); } } planViewOSS.closeTag(); device.openTag("road"); device.writeAttr("name", StringUtils::escapeXML(e->getStreetName())); device.setPrecision(8); // length requires higher precision device.writeAttr("length", MAX2(POSITION_EPS, length)); device.setPrecision(OUTPUT_ACCURACY); device.writeAttr("id", getID(e->getID(), edgeMap, edgeID)); device.writeAttr("junction", -1); const bool hasSucc = e->getConnections().size() > 0; const bool hasPred = e->getIncomingEdges().size() > 0; if (hasPred || hasSucc) { device.openTag("link"); if (hasPred) { device.openTag("predecessor"); device.writeAttr("elementType", "junction"); device.writeAttr("elementId", getID(e->getFromNode()->getID(), nodeMap, nodeID)); device.closeTag(); } if (hasSucc) { device.openTag("successor"); device.writeAttr("elementType", "junction"); device.writeAttr("elementId", getID(e->getToNode()->getID(), nodeMap, nodeID)); device.closeTag(); } device.closeTag(); } device.openTag("type").writeAttr("s", 0).writeAttr("type", "town").closeTag(); device << planViewOSS.getString(); writeElevationProfile(ls, device, elevationOSS); device << " <lateralProfile/>\n"; device << " <lanes>\n"; device << " <laneSection s=\"0\">\n"; writeEmptyCenterLane(device, "solid", 0.13); device << " <right>\n"; for (int j = e->getNumLanes(); --j >= 0;) { device << " <lane id=\"-" << e->getNumLanes() - j << "\" type=\"" << getLaneType(e->getPermissions(j)) << "\" level=\"true\">\n"; device << " <link/>\n"; // this could be used for geometry-link junctions without u-turn, // predecessor and sucessors would be lane indices, // road predecessor / succesfors would be of type 'road' rather than // 'junction' //device << " <predecessor id=\"-1\"/>\n"; //device << " <successor id=\"-1\"/>\n"; //device << " </link>\n"; device << " <width sOffset=\"0\" a=\"" << e->getLaneWidth(j) << "\" b=\"0\" c=\"0\" d=\"0\"/>\n"; std::string markType = "broken"; if (j == 0) { markType = "solid"; } device << " <roadMark sOffset=\"0\" type=\"" << markType << "\" weight=\"standard\" color=\"standard\" width=\"0.13\"/>\n"; device << " <speed sOffset=\"0\" max=\"" << lanes[j].speed << "\"/>\n"; device << " </lane>\n"; } device << " </right>\n"; device << " </laneSection>\n"; device << " </lanes>\n"; device << " <objects/>\n"; device << " <signals/>\n"; if (origNames) { device << " <userData code=\"sumoId\" value=\"" << e->getID() << "\"/>\n"; } device.closeTag(); checkLaneGeometries(e); } device.lf(); // write junction-internal edges (road). In OpenDRIVE these are called 'paths' or 'connecting roads' for (std::map<std::string, NBNode*>::const_iterator i = nc.begin(); i != nc.end(); ++i) { NBNode* n = (*i).second; const std::vector<NBEdge*>& incoming = (*i).second->getIncomingEdges(); for (std::vector<NBEdge*>::const_iterator j = incoming.begin(); j != incoming.end(); ++j) { const NBEdge* inEdge = *j; const std::vector<NBEdge::Connection>& elv = inEdge->getConnections(); for (std::vector<NBEdge::Connection>::const_iterator k = elv.begin(); k != elv.end(); ++k) { const NBEdge::Connection& c = *k; const NBEdge* outEdge = c.toEdge; if (outEdge == 0) { continue; } const SUMOReal width = c.toEdge->getLaneWidth(c.toLane); const PositionVector begShape = getLeftLaneBorder(inEdge, c.fromLane); const PositionVector endShape = getLeftLaneBorder(outEdge, c.toLane); //std::cout << "computing reference line for internal lane " << c.getInternalLaneID() << " begLane=" << inEdge->getLaneShape(c.fromLane) << " endLane=" << outEdge->getLaneShape(c.toLane) << "\n"; SUMOReal length; PositionVector fallBackShape; fallBackShape.push_back(begShape.back()); fallBackShape.push_back(endShape.front()); const bool turnaround = inEdge->isTurningDirectionAt(outEdge); bool ok = true; PositionVector init = NBNode::bezierControlPoints(begShape, endShape, turnaround, 25, 25, ok, 0, straightThresh); if (init.size() == 0) { length = fallBackShape.length2D(); // problem with turnarounds is known, method currently returns 'ok' (#2539) if (!ok) { WRITE_WARNING("Could not compute smooth shape from lane '" + inEdge->getLaneID(c.fromLane) + "' to lane '" + outEdge->getLaneID(c.toLane) + "'. Use option 'junctions.scurve-stretch' or increase radius of junction '" + inEdge->getToNode()->getID() + "' to fix this."); } } else { length = bezier(init, 12).length2D(); } device.openTag("road"); device.writeAttr("name", c.getInternalLaneID()); device.setPrecision(8); // length requires higher precision device.writeAttr("length", MAX2(POSITION_EPS, length)); device.setPrecision(OUTPUT_ACCURACY); device.writeAttr("id", getID(c.getInternalLaneID(), edgeMap, edgeID)); device.writeAttr("junction", getID(n->getID(), nodeMap, nodeID)); device.openTag("link"); device.openTag("predecessor"); device.writeAttr("elementType", "road"); device.writeAttr("elementId", getID(inEdge->getID(), edgeMap, edgeID)); device.writeAttr("contactPoint", "end"); device.closeTag(); device.openTag("successor"); device.writeAttr("elementType", "road"); device.writeAttr("elementId", getID(outEdge->getID(), edgeMap, edgeID)); device.writeAttr("contactPoint", "start"); device.closeTag(); device.closeTag(); device.openTag("type").writeAttr("s", 0).writeAttr("type", "town").closeTag(); device.openTag("planView"); device.setPrecision(8); // geometry hdg requires higher precision OutputDevice_String elevationOSS(false, 3); #ifdef DEBUG_SMOOTH_GEOM if (DEBUGCOND) { std::cout << "write planview for internal edge " << c.getInternalLaneID() << " init=" << init << " fallback=" << fallBackShape << "\n"; } #endif if (init.size() == 0) { writeGeomLines(fallBackShape, device, elevationOSS); } else { writeGeomPP3(device, elevationOSS, init, length); } device.setPrecision(OUTPUT_ACCURACY); device.closeTag(); writeElevationProfile(fallBackShape, device, elevationOSS); device << " <lateralProfile/>\n"; device << " <lanes>\n"; device << " <laneSection s=\"0\">\n"; writeEmptyCenterLane(device, "none", 0); device << " <right>\n"; device << " <lane id=\"-1\" type=\"" << getLaneType(outEdge->getPermissions(c.toLane)) << "\" level=\"true\">\n"; device << " <link>\n"; device << " <predecessor id=\"-" << inEdge->getNumLanes() - c.fromLane << "\"/>\n"; device << " <successor id=\"-" << outEdge->getNumLanes() - c.toLane << "\"/>\n"; device << " </link>\n"; device << " <width sOffset=\"0\" a=\"" << width << "\" b=\"0\" c=\"0\" d=\"0\"/>\n"; device << " <roadMark sOffset=\"0\" type=\"none\" weight=\"standard\" color=\"standard\" width=\"0.13\"/>\n"; device << " </lane>\n"; device << " </right>\n"; device << " </laneSection>\n"; device << " </lanes>\n"; device << " <objects/>\n"; device << " <signals/>\n"; device.closeTag(); } } } // write junctions (junction) for (std::map<std::string, NBNode*>::const_iterator i = nc.begin(); i != nc.end(); ++i) { NBNode* n = (*i).second; const std::vector<NBEdge*>& incoming = n->getIncomingEdges(); // check if any connections must be written int numConnections = 0; for (std::vector<NBEdge*>::const_iterator j = incoming.begin(); j != incoming.end(); ++j) { numConnections += (int)((*j)->getConnections().size()); } if (numConnections == 0) { continue; } device << " <junction name=\"" << n->getID() << "\" id=\"" << getID(n->getID(), nodeMap, nodeID) << "\">\n"; int index = 0; for (std::vector<NBEdge*>::const_iterator j = incoming.begin(); j != incoming.end(); ++j) { const NBEdge* inEdge = *j; const std::vector<NBEdge::Connection>& elv = inEdge->getConnections(); for (std::vector<NBEdge::Connection>::const_iterator k = elv.begin(); k != elv.end(); ++k) { const NBEdge::Connection& c = *k; const NBEdge* outEdge = c.toEdge; if (outEdge == 0) { continue; } device << " <connection id=\"" << index << "\" incomingRoad=\"" << getID(inEdge->getID(), edgeMap, edgeID) << "\" connectingRoad=\"" << getID(c.getInternalLaneID(), edgeMap, edgeID) << "\" contactPoint=\"start\">\n"; device << " <laneLink from=\"-" << inEdge->getNumLanes() - c.fromLane << "\" to=\"-1" // every connection has its own edge << "\"/>\n"; device << " </connection>\n"; ++index; } } device << " </junction>\n"; } device.closeTag(); device.close(); }
void NIImporter_OpenStreetMap::insertEdge(Edge* e, int index, NBNode* from, NBNode* to, const std::vector<int> &passed, NBEdgeCont& ec, NBTypeCont& tc) { // patch the id std::string id = e->id; if (index >= 0) { id = id + "#" + toString(index); } // convert the shape PositionVector shape; for (std::vector<int>::const_iterator i = passed.begin(); i != passed.end(); ++i) { NIOSMNode* n = myOSMNodes.find(*i)->second; Position pos(n->lon, n->lat); if (!NILoader::transformCoordinates(pos, true)) { throw ProcessError("Unable to project coordinates for edge " + id + "."); } shape.push_back_noDoublePos(pos); } std::string type = e->myHighWayType; if (!tc.knows(type)) { if (type.find(compoundTypeSeparator) != std::string::npos) { // this edge has a combination type which does not yet exist in the TypeContainer StringTokenizer tok = StringTokenizer(type, compoundTypeSeparator); std::set<std::string> types; while (tok.hasNext()) { std::string t = tok.next(); if (tc.knows(t)) { types.insert(t); } else { WRITE_WARNING("Discarding edge " + id + " with type \"" + type + "\" (unknown compound \"" + t + "\")."); return; } } if (types.size() == 2 && types.count("railway.tram") == 1) { // compound types concern mostly the special case of tram tracks on a normal road. // in this case we simply discard the tram information since the default for road is to allow all vclasses types.erase("railway.tram"); std::string otherCompound = *(types.begin()); // XXX if otherCompound does not allow all vehicles (e.g. SVC_DELIVERY), tram will still not be allowed type = otherCompound; } else { // other cases not implemented yet WRITE_WARNING("Discarding edge " + id + " with unknown type \"" + type + "\"."); return; } } else { // we do not know the type -> something else, ignore //WRITE_WARNING("Discarding edge " + id + " with unknown type \"" + type + "\"."); return; } } // otherwise it is not an edge and will be ignored int noLanes = tc.getNumLanes(type); SUMOReal speed = tc.getSpeed(type); bool defaultsToOneWay = tc.getIsOneWay(type); SUMOVehicleClasses allowedClasses = tc.getAllowedClasses(type); SUMOVehicleClasses disallowedClasses = tc.getDisallowedClasses(type); // check directions bool addSecond = true; if (e->myIsOneWay == "true" || e->myIsOneWay == "yes" || e->myIsOneWay == "1" || (defaultsToOneWay && e->myIsOneWay != "no" && e->myIsOneWay != "false" && e->myIsOneWay != "0")) { addSecond = false; } // if we had been able to extract the number of lanes, override the highway type default if (e->myNoLanes >= 0) { if (!addSecond) { noLanes = e->myNoLanes; } else { noLanes = e->myNoLanes / 2; } } // if we had been able to extract the maximum speed, override the type's default if (e->myMaxSpeed != MAXSPEED_UNGIVEN) { speed = (SUMOReal)(e->myMaxSpeed / 3.6); } if (noLanes != 0 && speed != 0) { if (e->myIsOneWay != "" && e->myIsOneWay != "false" && e->myIsOneWay != "no" && e->myIsOneWay != "true" && e->myIsOneWay != "yes" && e->myIsOneWay != "-1" && e->myIsOneWay != "1") { WRITE_WARNING("New value for oneway found: " + e->myIsOneWay); } LaneSpreadFunction lsf = addSecond ? LANESPREAD_RIGHT : LANESPREAD_CENTER; if (e->myIsOneWay != "-1") { NBEdge* nbe = new NBEdge(id, from, to, type, speed, noLanes, tc.getPriority(type), tc.getWidth(type), NBEdge::UNSPECIFIED_OFFSET, shape, e->streetName, lsf); nbe->setVehicleClasses(allowedClasses, disallowedClasses); if (!ec.insert(nbe)) { delete nbe; throw ProcessError("Could not add edge '" + id + "'."); } } if (addSecond) { if (e->myIsOneWay != "-1") { id = "-" + id; } NBEdge* nbe = new NBEdge(id, to, from, type, speed, noLanes, tc.getPriority(type), tc.getWidth(type), NBEdge::UNSPECIFIED_OFFSET, shape.reverse(), e->streetName, lsf); nbe->setVehicleClasses(allowedClasses, disallowedClasses); if (!ec.insert(nbe)) { delete nbe; throw ProcessError("Could not add edge '-" + id + "'."); } } } }
void GNEJunction::drawGL(const GUIVisualizationSettings& s) const { glPushName(getGlID()); SUMOReal selectionScale = gSelected.isSelected(getType(), getGlID()) ? s.selectionScale : 1; if (s.scale * selectionScale * myMaxSize < 1.) { // draw something simple so that selection still works GLHelper::drawBoxLine(myNBNode.getPosition(), 0, 1, 1); } else { // node shape has been computed and is valid for drawing const bool drawShape = myNBNode.getShape().size() > 0 && s.drawJunctionShape; const bool drawBubble = (!drawShape || myNBNode.getShape().area() < 4) && s.drawJunctionShape; // magic threshold if (drawShape) { glPushMatrix(); setColor(s, false); glTranslated(0, 0, getType()); PositionVector shape = myNBNode.getShape(); shape.closePolygon(); if (selectionScale > 1) { shape.scaleRelative(selectionScale); } if (s.scale * selectionScale * myMaxSize < 40.) { GLHelper::drawFilledPoly(shape, true); } else { GLHelper::drawFilledPolyTesselated(shape, true); } glPopMatrix(); } if (drawBubble) { glPushMatrix(); setColor(s, true); Position pos = myNBNode.getPosition(); glTranslated(pos.x(), pos.y(), getType() - 0.05); GLHelper::drawFilledCircle(myMaxSize * selectionScale, 32); glPopMatrix(); } if (s.editMode == GNE_MODE_TLS && myNBNode.isTLControlled() && !myAmTLSSelected) { // decorate in tls mode if (!TLSDecalInitialized) { FXImage* i = new FXGIFImage(myNet->getApp(), tlslogo, IMAGE_KEEP | IMAGE_SHMI | IMAGE_SHMP); TLSDecalGlID = GUITexturesHelper::add(i); TLSDecalInitialized = true; delete i; } glPushMatrix(); Position pos = myNBNode.getPosition(); glTranslated(pos.x(), pos.y(), getType() + 0.1); glColor3d(1, 1, 1); const SUMOReal halfWidth = 32 / s.scale; const SUMOReal halfHeight = 64 / s.scale; GUITexturesHelper::drawTexturedBox(TLSDecalGlID, -halfWidth, -halfHeight, halfWidth, halfHeight); glPopMatrix(); } // draw crossings if (s.editMode != GNE_MODE_TLS) { for (std::vector<GNECrossing*>::const_iterator it = myCrossings.begin(); it != myCrossings.end(); it++) { (*it)->drawGL(s); } } // (optional) draw name @todo expose this setting drawName(myNBNode.getPosition(), s.scale, s.junctionName); } glPopName(); }
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 GNEConnection::updateGeometry(bool updateGrid) { // Get shape of from and to lanes NBEdge::Connection& nbCon = getNBEdgeConnection(); if (myShapeDeprecated) { // first check if object has to be removed from grid (SUMOTree) if (updateGrid) { myNet->removeGLObjectFromGrid(this); } // Clear containers myShape.clear(); myShapeRotations.clear(); myShapeLengths.clear(); PositionVector laneShapeFrom; if ((int)getEdgeFrom()->getNBEdge()->getLanes().size() > nbCon.fromLane) { laneShapeFrom = getEdgeFrom()->getNBEdge()->getLanes().at(nbCon.fromLane).shape; } else { return; } PositionVector laneShapeTo; if ((int)nbCon.toEdge->getLanes().size() > nbCon.toLane) { laneShapeTo = nbCon.toEdge->getLanes().at(nbCon.toLane).shape; } else { return; } // Calculate shape of connection depending of the size of Junction shape // value obtanied from GNEJunction::drawgl if (nbCon.customShape.size() != 0) { myShape = nbCon.customShape; } else if (getEdgeFrom()->getNBEdge()->getToNode()->getShape().area() > 4) { if (nbCon.shape.size() != 0) { myShape = nbCon.shape; // only append via shape if it exists if (nbCon.haveVia) { myShape.append(nbCon.viaShape); } } else { // Calculate shape so something can be drawn immidiately myShape = getEdgeFrom()->getNBEdge()->getToNode()->computeSmoothShape( laneShapeFrom, laneShapeTo, NUM_POINTS, getEdgeFrom()->getNBEdge()->getTurnDestination() == nbCon.toEdge, (double) 5. * (double) getEdgeFrom()->getNBEdge()->getNumLanes(), (double) 5. * (double) nbCon.toEdge->getNumLanes()); } } else { myShape.clear(); myShape.push_back(laneShapeFrom.positionAtOffset(MAX2(0.0, laneShapeFrom.length() - 1))); myShape.push_back(laneShapeTo.positionAtOffset(MIN2(1.0, laneShapeFrom.length()))); } // check if internal junction marker must be calculated if (nbCon.haveVia && (nbCon.shape.size() != 0)) { // create marker for interal junction waiting position (contPos) const double orthoLength = 0.5; Position pos = nbCon.shape.back(); myInternalJunctionMarker = nbCon.shape.getOrthogonal(pos, 10, true, 0.1); if (myInternalJunctionMarker.length() < orthoLength) { myInternalJunctionMarker.extrapolate(orthoLength - myInternalJunctionMarker.length()); } } else { myInternalJunctionMarker.clear(); } // Obtain lengths and shape rotations int segments = (int) myShape.size() - 1; if (segments >= 0) { myShapeRotations.reserve(segments); myShapeLengths.reserve(segments); for (int i = 0; i < segments; ++i) { const Position& f = myShape[i]; const Position& s = myShape[i + 1]; myShapeLengths.push_back(f.distanceTo2D(s)); myShapeRotations.push_back((double) atan2((s.x() - f.x()), (f.y() - s.y())) * (double) 180.0 / (double)M_PI); } } // mark connection as non-deprecated myShapeDeprecated = false; // last step is to check if object has to be added into grid (SUMOTree) again if (updateGrid) { myNet->addGLObjectIntoGrid(this); } } }
bool NIVissimTL::NIVissimTLSignal::isWithin(const PositionVector& poly) const { return poly.around(getPosition()); }
// ------------ Adding items to the container void PositionVector::push_back(const PositionVector& p) { copy(p.begin(), p.end(), back_inserter(*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 PositionVector::move2side(SUMOReal amount) { if (size() < 2) { return; } PositionVector shape; for (int i = 0; i < static_cast<int>(size()); i++) { if (i == 0) { Position from = (*this)[i]; Position to = (*this)[i + 1]; std::pair<SUMOReal, SUMOReal> offsets = GeomHelper::getNormal90D_CW(from, to, amount); shape.push_back(Position(from.x() - offsets.first, from.y() - offsets.second, from.z())); } else if (i == static_cast<int>(size()) - 1) { Position from = (*this)[i - 1]; Position to = (*this)[i]; std::pair<SUMOReal, SUMOReal> offsets = GeomHelper::getNormal90D_CW(from, to, amount); shape.push_back(Position(to.x() - offsets.first, to.y() - offsets.second, to.z())); } else { Position from = (*this)[i - 1]; Position me = (*this)[i]; Position to = (*this)[i + 1]; Line fromMe(from, me); fromMe.extrapolateBy2D(me.distanceTo2D(to)); const double extrapolateDev = fromMe.p2().distanceTo2D(to); if (fabs(extrapolateDev) < POSITION_EPS) { // parallel case, just shift the middle point std::pair<SUMOReal, SUMOReal> off = GeomHelper::getNormal90D_CW(from, to, amount); shape.push_back(Position(me.x() - off.first, me.y() - off.second, me.z())); continue; } if (fabs(extrapolateDev - 2 * me.distanceTo2D(to)) < POSITION_EPS) { // counterparallel case, just shift the middle point Line fromMe(from, me); fromMe.extrapolateBy2D(amount); shape.push_back(fromMe.p2()); continue; } std::pair<SUMOReal, SUMOReal> offsets = GeomHelper::getNormal90D_CW(from, me, amount); std::pair<SUMOReal, SUMOReal> offsets2 = GeomHelper::getNormal90D_CW(me, to, amount); Line l1( Position(from.x() - offsets.first, from.y() - offsets.second), Position(me.x() - offsets.first, me.y() - offsets.second)); l1.extrapolateBy2D(100); Line l2( Position(me.x() - offsets2.first, me.y() - offsets2.second), Position(to.x() - offsets2.first, to.y() - offsets2.second)); l2.extrapolateBy2D(100); if (l1.intersects(l2)) { shape.push_back(l1.intersectsAt(l2)); } else { throw InvalidArgument("no line intersection"); } } } /* ContType newCont; std::pair<SUMOReal, SUMOReal> p; Position newPos; // first point newPos = (*(begin())); p = GeomHelper::getNormal90D_CW(*(begin()), *(begin()+1), amount); newPos.add(p.first, p.second); newCont.push_back(newPos); // middle points for(const_iterator i=begin()+1; i!=end()-1; i++) { std::pair<SUMOReal, SUMOReal> oldp = p; newPos = *i; newPos.add(p.first, p.second); newCont.push_back(newPos); p = GeomHelper::getNormal90D_CW(*i, *(i+1), amount); // Position newPos(*i); // newPos.add((p.first+oldp.first)/2.0, (p.second+oldp.second)/2.0); // newCont.push_back(newPos); } // last point newPos = (*(end()-1)); newPos.add(p.first, p.second); newCont.push_back(newPos); myCont = newCont; */ *this = shape; }
void PCLoaderXML::myStartElement(int element, const SUMOSAXAttributes& attrs) { if (element != SUMO_TAG_POI && element != SUMO_TAG_POLY) { return; } if (element == SUMO_TAG_POI) { bool ok = true; // get the id, report an error if not given or empty... std::string id = attrs.getStringReporting(SUMO_ATTR_ID, 0, ok); SUMOReal x = attrs.getSUMORealReporting(SUMO_ATTR_X, id.c_str(), ok); SUMOReal y = attrs.getSUMORealReporting(SUMO_ATTR_Y, id.c_str(), ok); std::string type = attrs.getOptStringReporting(SUMO_ATTR_TYPE, id.c_str(), ok, myOptions.getString("type")); if (!ok) { return; } Position pos(x, y); if (!GeoConvHelper::getProcessing().x2cartesian(pos)) { WRITE_WARNING("Unable to project coordinates for POI '" + id + "'."); } // patch the values bool discard = myOptions.getBool("discard"); SUMOReal layer = (SUMOReal)myOptions.getInt("layer"); RGBColor color; if (myTypeMap.has(type)) { const PCTypeMap::TypeDef& def = myTypeMap.get(type); id = def.prefix + id; type = def.id; color = RGBColor::parseColor(def.color); discard = def.discard; layer = (SUMOReal)def.layer; } else { id = myOptions.getString("prefix") + id; color = RGBColor::parseColor(myOptions.getString("color")); } layer = attrs.getOptSUMORealReporting(SUMO_ATTR_LAYER, id.c_str(), ok, layer); if (attrs.hasAttribute(SUMO_ATTR_COLOR)) { color = attrs.getColorReporting(id.c_str(), ok); } SUMOReal angle = attrs.getOptSUMORealReporting(SUMO_ATTR_ANGLE, id.c_str(), ok, Shape::DEFAULT_ANGLE); std::string imgFile = attrs.getOptStringReporting(SUMO_ATTR_IMGFILE, id.c_str(), ok, Shape::DEFAULT_IMG_FILE); if (imgFile != "" && !FileHelpers::isAbsolute(imgFile)) { imgFile = FileHelpers::getConfigurationRelative(getFileName(), imgFile); } SUMOReal imgWidth = attrs.getOptSUMORealReporting(SUMO_ATTR_WIDTH, id.c_str(), ok, Shape::DEFAULT_IMG_WIDTH); SUMOReal imgHeight = attrs.getOptSUMORealReporting(SUMO_ATTR_HEIGHT, id.c_str(), ok, Shape::DEFAULT_IMG_HEIGHT); if (!ok) { return; } if (!discard) { bool ignorePrunning = false; if (OptionsCont::getOptions().isInStringVector("prune.keep-list", id)) { ignorePrunning = true; } PointOfInterest* poi = new PointOfInterest(id, type, color, pos, layer, angle, imgFile, imgWidth, imgHeight); if (!myCont.insert(id, poi, (int)layer, ignorePrunning)) { WRITE_ERROR("POI '" + id + "' could not be added."); delete poi; } } } if (element == SUMO_TAG_POLY) { bool discard = myOptions.getBool("discard"); SUMOReal layer = (SUMOReal)myOptions.getInt("layer"); bool ok = true; std::string id = attrs.getOptStringReporting(SUMO_ATTR_ID, myCurrentID.c_str(), ok, ""); std::string type = attrs.getOptStringReporting(SUMO_ATTR_TYPE, myCurrentID.c_str(), ok, myOptions.getString("type")); if (!ok) { return; } RGBColor color; if (myTypeMap.has(type)) { const PCTypeMap::TypeDef& def = myTypeMap.get(type); id = def.prefix + id; type = def.id; color = RGBColor::parseColor(def.color); discard = def.discard; layer = (SUMOReal)def.layer; } else { id = myOptions.getString("prefix") + id; color = RGBColor::parseColor(myOptions.getString("color")); } layer = attrs.getOptSUMORealReporting(SUMO_ATTR_LAYER, id.c_str(), ok, layer); if (attrs.hasAttribute(SUMO_ATTR_COLOR)) { color = attrs.getColorReporting(id.c_str(), ok); } SUMOReal angle = attrs.getOptSUMORealReporting(SUMO_ATTR_ANGLE, id.c_str(), ok, Shape::DEFAULT_ANGLE); std::string imgFile = attrs.getOptStringReporting(SUMO_ATTR_IMGFILE, id.c_str(), ok, Shape::DEFAULT_IMG_FILE); if (imgFile != "" && !FileHelpers::isAbsolute(imgFile)) { imgFile = FileHelpers::getConfigurationRelative(getFileName(), imgFile); } bool fill = attrs.getOptBoolReporting(SUMO_ATTR_FILL, id.c_str(), ok, false); if (!ok) { return; } if (!discard) { bool ignorePrunning = false; if (OptionsCont::getOptions().isInStringVector("prune.keep-list", id)) { ignorePrunning = true; } myCurrentID = id; myCurrentType = type; myCurrentColor = color; myCurrentIgnorePrunning = ignorePrunning; myCurrentLayer = layer; PositionVector pshape = attrs.getShapeReporting(SUMO_ATTR_SHAPE, myCurrentID.c_str(), ok, false); if (!ok) { return; } PositionVector shape; for (PositionVector::ContType::const_iterator i = pshape.begin(); i != pshape.end(); ++i) { Position pos((*i)); if (!GeoConvHelper::getProcessing().x2cartesian(pos)) { WRITE_WARNING("Unable to project coordinates for polygon '" + myCurrentID + "'."); } shape.push_back(pos); } Polygon* poly = new Polygon(myCurrentID, myCurrentType, myCurrentColor, shape, fill, layer, angle, imgFile); if (!myCont.insert(myCurrentID, poly, (int)myCurrentLayer, myCurrentIgnorePrunning)) { WRITE_ERROR("Polygon '" + myCurrentID + "' could not be added."); delete poly; } } } }
int NBHeightMapper::loadShapeFile(const std::string& file) { #ifdef HAVE_GDAL #if GDAL_VERSION_MAJOR < 2 OGRRegisterAll(); OGRDataSource* ds = OGRSFDriverRegistrar::Open(file.c_str(), FALSE); #else GDALAllRegister(); GDALDataset* ds = (GDALDataset*)GDALOpenEx(file.c_str(), GDAL_OF_VECTOR | GA_ReadOnly, NULL, NULL, NULL); #endif if (ds == NULL) { throw ProcessError("Could not open shape file '" + file + "'."); } // begin file parsing OGRLayer* layer = ds->GetLayer(0); layer->ResetReading(); // triangle coordinates are stored in WGS84 and later matched with network coordinates in WGS84 // build coordinate transformation OGRSpatialReference* sr_src = layer->GetSpatialRef(); OGRSpatialReference sr_dest; sr_dest.SetWellKnownGeogCS("WGS84"); OGRCoordinateTransformation* toWGS84 = OGRCreateCoordinateTransformation(sr_src, &sr_dest); if (toWGS84 == 0) { WRITE_WARNING("Could not create geocoordinates converter; check whether proj.4 is installed."); } int numFeatures = 0; OGRFeature* feature; layer->ResetReading(); while ((feature = layer->GetNextFeature()) != NULL) { OGRGeometry* geom = feature->GetGeometryRef(); assert(geom != 0); // @todo gracefull handling of shapefiles with unexpected contents or any error handling for that matter assert(std::string(geom->getGeometryName()) == std::string("POLYGON")); // try transform to wgs84 geom->transform(toWGS84); OGRLinearRing* cgeom = ((OGRPolygon*) geom)->getExteriorRing(); // assume TIN with with 4 points and point0 == point3 assert(cgeom->getNumPoints() == 4); PositionVector corners; for (int j = 0; j < 3; j++) { Position pos((double) cgeom->getX(j), (double) cgeom->getY(j), (double) cgeom->getZ(j)); corners.push_back(pos); myBoundary.add(pos); } addTriangle(corners); numFeatures++; /* OGRwkbGeometryType gtype = geom->getGeometryType(); switch (gtype) { case wkbPolygon: { break; } case wkbPoint: { WRITE_WARNING("got wkbPoint"); break; } case wkbLineString: { WRITE_WARNING("got wkbLineString"); break; } case wkbMultiPoint: { WRITE_WARNING("got wkbMultiPoint"); break; } case wkbMultiLineString: { WRITE_WARNING("got wkbMultiLineString"); break; } case wkbMultiPolygon: { WRITE_WARNING("got wkbMultiPolygon"); break; } default: WRITE_WARNING("Unsupported shape type occurred"); break; } */ OGRFeature::DestroyFeature(feature); } #if GDAL_VERSION_MAJOR < 2 OGRDataSource::DestroyDataSource(ds); #else GDALClose(ds); #endif OCTDestroyCoordinateTransformation(toWGS84); OGRCleanupAll(); return numFeatures; #else UNUSED_PARAMETER(file); WRITE_ERROR("Cannot load shape file since SUMO was compiled without GDAL support."); return 0; #endif }
/* Test the method 'scaleSize'.*/ TEST_F(PositionVectorTest, test_method_scaleSize) { PositionVector square; square.push_back(Position(0,0)); square.push_back(Position(1,0)); square.push_back(Position(1,1)); square.push_back(Position(0,1)); square.push_back(Position(0,0)); EXPECT_DOUBLE_EQ(square.area(), 1); square.scaleSize(3); EXPECT_DOUBLE_EQ(square.area(), 9); PositionVector expected; expected.push_back(Position(-1,-1)); expected.push_back(Position(2,-1)); expected.push_back(Position(2,2)); expected.push_back(Position(-1,2)); expected.push_back(Position(-1,-1)); EXPECT_EQ(expected.getCentroid(), square.getCentroid()); for (size_t i = 0; i < square.size(); i++) { EXPECT_DOUBLE_EQ(expected[i].x(), square[i].x()); EXPECT_DOUBLE_EQ(expected[i].y(), square[i].y()); } }
void PCLoaderArcView::load(const std::string& file, OptionsCont& oc, PCPolyContainer& toFill, PCTypeMap&) { #ifdef HAVE_GDAL GeoConvHelper& geoConvHelper = GeoConvHelper::getProcessing(); // get defaults std::string prefix = oc.getString("prefix"); std::string type = oc.getString("type"); RGBColor color = RGBColor::parseColor(oc.getString("color")); int layer = oc.getInt("layer"); std::string idField = oc.getString("shapefile.id-column"); // start parsing std::string shpName = file + ".shp"; OGRRegisterAll(); OGRDataSource* poDS = OGRSFDriverRegistrar::Open(shpName.c_str(), FALSE); if (poDS == NULL) { throw ProcessError("Could not open shape description '" + shpName + "'."); } // begin file parsing OGRLayer* poLayer = poDS->GetLayer(0); poLayer->ResetReading(); // build coordinate transformation OGRSpatialReference* origTransf = poLayer->GetSpatialRef(); OGRSpatialReference destTransf; // use wgs84 as destination destTransf.SetWellKnownGeogCS("WGS84"); OGRCoordinateTransformation* poCT = OGRCreateCoordinateTransformation(origTransf, &destTransf); if (poCT == NULL) { if (oc.isSet("shapefile.guess-projection")) { OGRSpatialReference origTransf2; origTransf2.SetWellKnownGeogCS("WGS84"); poCT = OGRCreateCoordinateTransformation(&origTransf2, &destTransf); } if (poCT == 0) { WRITE_WARNING("Could not create geocoordinates converter; check whether proj.4 is installed."); } } OGRFeature* poFeature; poLayer->ResetReading(); while ((poFeature = poLayer->GetNextFeature()) != NULL) { // read in edge attributes std::string id = poFeature->GetFieldAsString(idField.c_str()); id = StringUtils::prune(id); if (id == "") { throw ProcessError("Missing id under '" + idField + "'"); } id = prefix + id; // read in the geometry OGRGeometry* poGeometry = poFeature->GetGeometryRef(); if (poGeometry != 0) { // try transform to wgs84 poGeometry->transform(poCT); } OGRwkbGeometryType gtype = poGeometry->getGeometryType(); switch (gtype) { case wkbPoint: { OGRPoint* cgeom = (OGRPoint*) poGeometry; Position pos((SUMOReal) cgeom->getX(), (SUMOReal) cgeom->getY()); if (!geoConvHelper.x2cartesian(pos)) { WRITE_ERROR("Unable to project coordinates for POI '" + id + "'."); } PointOfInterest* poi = new PointOfInterest(id, type, pos, color); if (!toFill.insert(id, poi, layer)) { WRITE_ERROR("POI '" + id + "' could not been added."); delete poi; } } break; case wkbLineString: { OGRLineString* cgeom = (OGRLineString*) poGeometry; PositionVector shape; for (int j = 0; j < cgeom->getNumPoints(); j++) { Position pos((SUMOReal) cgeom->getX(j), (SUMOReal) cgeom->getY(j)); if (!geoConvHelper.x2cartesian(pos)) { WRITE_ERROR("Unable to project coordinates for polygon '" + id + "'."); } shape.push_back_noDoublePos(pos); } Polygon* poly = new Polygon(id, type, color, shape, false); if (!toFill.insert(id, poly, layer)) { WRITE_ERROR("Polygon '" + id + "' could not been added."); delete poly; } } break; case wkbPolygon: { OGRLinearRing* cgeom = ((OGRPolygon*) poGeometry)->getExteriorRing(); PositionVector shape; for (int j = 0; j < cgeom->getNumPoints(); j++) { Position pos((SUMOReal) cgeom->getX(j), (SUMOReal) cgeom->getY(j)); if (!geoConvHelper.x2cartesian(pos)) { WRITE_ERROR("Unable to project coordinates for polygon '" + id + "'."); } shape.push_back_noDoublePos(pos); } Polygon* poly = new Polygon(id, type, color, shape, true); if (!toFill.insert(id, poly, layer)) { WRITE_ERROR("Polygon '" + id + "' could not been added."); delete poly; } } break; case wkbMultiPoint: { OGRMultiPoint* cgeom = (OGRMultiPoint*) poGeometry; for (int i = 0; i < cgeom->getNumGeometries(); ++i) { OGRPoint* cgeom2 = (OGRPoint*) cgeom->getGeometryRef(i); Position pos((SUMOReal) cgeom2->getX(), (SUMOReal) cgeom2->getY()); std::string tid = id + "#" + toString(i); if (!geoConvHelper.x2cartesian(pos)) { WRITE_ERROR("Unable to project coordinates for POI '" + tid + "'."); } PointOfInterest* poi = new PointOfInterest(tid, type, pos, color); if (!toFill.insert(tid, poi, layer)) { WRITE_ERROR("POI '" + tid + "' could not been added."); delete poi; } } } break; case wkbMultiLineString: { OGRMultiLineString* cgeom = (OGRMultiLineString*) poGeometry; for (int i = 0; i < cgeom->getNumGeometries(); ++i) { OGRLineString* cgeom2 = (OGRLineString*) cgeom->getGeometryRef(i); PositionVector shape; std::string tid = id + "#" + toString(i); for (int j = 0; j < cgeom2->getNumPoints(); j++) { Position pos((SUMOReal) cgeom2->getX(j), (SUMOReal) cgeom2->getY(j)); if (!geoConvHelper.x2cartesian(pos)) { WRITE_ERROR("Unable to project coordinates for polygon '" + tid + "'."); } shape.push_back_noDoublePos(pos); } Polygon* poly = new Polygon(tid, type, color, shape, false); if (!toFill.insert(tid, poly, layer)) { WRITE_ERROR("Polygon '" + tid + "' could not been added."); delete poly; } } } break; case wkbMultiPolygon: { OGRMultiPolygon* cgeom = (OGRMultiPolygon*) poGeometry; for (int i = 0; i < cgeom->getNumGeometries(); ++i) { OGRLinearRing* cgeom2 = ((OGRPolygon*) cgeom->getGeometryRef(i))->getExteriorRing(); PositionVector shape; std::string tid = id + "#" + toString(i); for (int j = 0; j < cgeom2->getNumPoints(); j++) { Position pos((SUMOReal) cgeom2->getX(j), (SUMOReal) cgeom2->getY(j)); if (!geoConvHelper.x2cartesian(pos)) { WRITE_ERROR("Unable to project coordinates for polygon '" + tid + "'."); } shape.push_back_noDoublePos(pos); } Polygon* poly = new Polygon(tid, type, color, shape, true); if (!toFill.insert(tid, poly, layer)) { WRITE_ERROR("Polygon '" + tid + "' could not been added."); delete poly; } } } break; default: WRITE_WARNING("Unsupported shape type occured (id='" + id + "')."); break; } OGRFeature::DestroyFeature(poFeature); } PROGRESS_DONE_MESSAGE(); #else WRITE_ERROR("SUMO was compiled without GDAL support."); #endif }
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]; } } } } }
void ROVehicle::saveAsXML(OutputDevice& os, OutputDevice* const typeos, bool asAlternatives, OptionsCont& options) const { if (typeos != nullptr && getType() != nullptr && !getType()->saved) { getType()->write(*typeos); getType()->saved = true; } if (getType() != nullptr && !getType()->saved) { getType()->write(os); getType()->saved = asAlternatives; } const bool writeTrip = options.exists("write-trips") && options.getBool("write-trips"); const bool writeGeoTrip = writeTrip && options.getBool("write-trips.geo"); // write the vehicle (new style, with included routes) getParameter().write(os, options, writeTrip ? SUMO_TAG_TRIP : SUMO_TAG_VEHICLE); // save the route if (writeTrip) { const ConstROEdgeVector edges = myRoute->getFirstRoute()->getEdgeVector(); const ROEdge* from = nullptr; const ROEdge* to = nullptr; if (edges.size() > 0) { if (edges.front()->isTazConnector()) { if (edges.size() > 1) { from = edges[1]; } } else { from = edges[0]; } if (edges.back()->isTazConnector()) { if (edges.size() > 1) { to = edges[edges.size() - 2]; } } else { to = edges[edges.size() - 1]; } } if (from != nullptr) { if (writeGeoTrip) { Position fromPos = from->getLanes()[0]->getShape().positionAtOffset2D(0); if (GeoConvHelper::getFinal().usingGeoProjection()) { os.setPrecision(gPrecisionGeo); GeoConvHelper::getFinal().cartesian2geo(fromPos); os.writeAttr(SUMO_ATTR_FROMLONLAT, fromPos); os.setPrecision(gPrecision); } else { os.writeAttr(SUMO_ATTR_FROMXY, fromPos); } } else { os.writeAttr(SUMO_ATTR_FROM, from->getID()); } } if (to != nullptr) { if (writeGeoTrip) { Position toPos = to->getLanes()[0]->getShape().positionAtOffset2D(to->getLanes()[0]->getShape().length2D()); if (GeoConvHelper::getFinal().usingGeoProjection()) { os.setPrecision(gPrecisionGeo); GeoConvHelper::getFinal().cartesian2geo(toPos); os.writeAttr(SUMO_ATTR_TOLONLAT, toPos); os.setPrecision(gPrecision); } else { os.writeAttr(SUMO_ATTR_TOXY, toPos); } } else { os.writeAttr(SUMO_ATTR_TO, to->getID()); } } if (getParameter().via.size() > 0) { if (writeGeoTrip) { PositionVector viaPositions; for (const std::string& viaID : getParameter().via) { const ROEdge* viaEdge = RONet::getInstance()->getEdge(viaID); assert(viaEdge != nullptr); Position viaPos = viaEdge->getLanes()[0]->getShape().positionAtOffset2D(viaEdge->getLanes()[0]->getShape().length2D() / 2); viaPositions.push_back(viaPos); } if (GeoConvHelper::getFinal().usingGeoProjection()) { for (int i = 0; i < (int)viaPositions.size(); i++) { GeoConvHelper::getFinal().cartesian2geo(viaPositions[i]); } os.setPrecision(gPrecisionGeo); os.writeAttr(SUMO_ATTR_VIALONLAT, viaPositions); os.setPrecision(gPrecision); } else { os.writeAttr(SUMO_ATTR_VIAXY, viaPositions); } } else { os.writeAttr(SUMO_ATTR_VIA, getParameter().via); } } } else { myRoute->writeXMLDefinition(os, this, asAlternatives, options.getBool("exit-times")); } for (std::vector<SUMOVehicleParameter::Stop>::const_iterator stop = getParameter().stops.begin(); stop != getParameter().stops.end(); ++stop) { stop->write(os); } getParameter().writeParams(os); os.closeTag(); }
void NWWriter_OpenDrive::writeNormalEdge(OutputDevice& device, const NBEdge* e, int edgeID, int fromNodeID, int toNodeID, const bool origNames, const double straightThresh) { // buffer output because some fields are computed out of order OutputDevice_String elevationOSS(false, 3); elevationOSS.setPrecision(8); OutputDevice_String planViewOSS(false, 2); planViewOSS.setPrecision(8); double length = 0; planViewOSS.openTag("planView"); // for the shape we need to use the leftmost border of the leftmost lane const std::vector<NBEdge::Lane>& lanes = e->getLanes(); PositionVector ls = getLeftLaneBorder(e); #ifdef DEBUG_SMOOTH_GEOM if (DEBUGCOND) { std::cout << "write planview for edge " << e->getID() << "\n"; } #endif if (ls.size() == 2 || e->getPermissions() == SVC_PEDESTRIAN) { // foot paths may contain sharp angles length = writeGeomLines(ls, planViewOSS, elevationOSS); } else { bool ok = writeGeomSmooth(ls, e->getSpeed(), planViewOSS, elevationOSS, straightThresh, length); if (!ok) { WRITE_WARNING("Could not compute smooth shape for edge '" + e->getID() + "'."); } } planViewOSS.closeTag(); device.openTag("road"); device.writeAttr("name", StringUtils::escapeXML(e->getStreetName())); device.setPrecision(8); // length requires higher precision device.writeAttr("length", MAX2(POSITION_EPS, length)); device.setPrecision(gPrecision); device.writeAttr("id", edgeID); device.writeAttr("junction", -1); if (fromNodeID != INVALID_ID || toNodeID != INVALID_ID) { device.openTag("link"); if (fromNodeID != INVALID_ID) { device.openTag("predecessor"); device.writeAttr("elementType", "junction"); device.writeAttr("elementId", fromNodeID); device.closeTag(); } if (toNodeID != INVALID_ID) { device.openTag("successor"); device.writeAttr("elementType", "junction"); device.writeAttr("elementId", toNodeID); device.closeTag(); } device.closeTag(); } device.openTag("type").writeAttr("s", 0).writeAttr("type", "town").closeTag(); device << planViewOSS.getString(); writeElevationProfile(ls, device, elevationOSS); device << " <lateralProfile/>\n"; device << " <lanes>\n"; device << " <laneSection s=\"0\">\n"; const std::string centerMark = e->getPermissions(e->getNumLanes() - 1) == 0 ? "none" : "solid"; writeEmptyCenterLane(device, centerMark, 0.13); device << " <right>\n"; for (int j = e->getNumLanes(); --j >= 0;) { device << " <lane id=\"-" << e->getNumLanes() - j << "\" type=\"" << getLaneType(e->getPermissions(j)) << "\" level=\"true\">\n"; device << " <link/>\n"; // this could be used for geometry-link junctions without u-turn, // predecessor and sucessors would be lane indices, // road predecessor / succesfors would be of type 'road' rather than // 'junction' //device << " <predecessor id=\"-1\"/>\n"; //device << " <successor id=\"-1\"/>\n"; //device << " </link>\n"; device << " <width sOffset=\"0\" a=\"" << e->getLaneWidth(j) << "\" b=\"0\" c=\"0\" d=\"0\"/>\n"; std::string markType = "broken"; if (j == 0) { markType = "solid"; } else if (j > 0 && (e->getPermissions(j - 1) & ~(SVC_PEDESTRIAN | SVC_BICYCLE)) == 0) { // solid road mark to the left of sidewalk or bicycle lane markType = "solid"; } else if (e->getPermissions(j) == 0) { // solid road mark to the right of a forbidden lane markType = "solid"; } device << " <roadMark sOffset=\"0\" type=\"" << markType << "\" weight=\"standard\" color=\"standard\" width=\"0.13\"/>\n"; device << " <speed sOffset=\"0\" max=\"" << lanes[j].speed << "\"/>\n"; device << " </lane>\n"; } device << " </right>\n"; device << " </laneSection>\n"; device << " </lanes>\n"; device << " <objects/>\n"; device << " <signals/>\n"; if (origNames) { device << " <userData code=\"sumoId\" value=\"" << e->getID() << "\"/>\n"; } device.closeTag(); checkLaneGeometries(e); }
// Assume that a class is already given for the object: // Position with coordinates {SUMOReal x, y;} PositionVector simpleHull_2D(const PositionVector& V) { if (V.size() < 3) { throw ProcessError(); } // initialize a deque D[] from bottom to top so that the // 1st three vertices of V[] are a counterclockwise triangle int n = (int) V.size(); std::vector<Position> D(2 * n + 1); int bot = n - 2, top = bot + 3; // initial bottom and top deque indices D[bot] = D[top] = V[2]; // 3rd vertex is at both bot and top if (isLeft(V[0], V[1], V[2]) > 0) { D[bot + 1] = V[0]; D[bot + 2] = V[1]; // ccw vertices are: 2,0,1,2 } else { D[bot + 1] = V[1]; D[bot + 2] = V[0]; // ccw vertices are: 2,1,0,2 } // compute the hull on the deque D[] for (int i = 3; i < n; i++) { // process the rest of vertices // test if next vertex is inside the deque hull if (bot >= (int) D.size() || top - 1 >= (int) D.size() || i >= (int) V.size()) { throw ProcessError(); } if ((isLeft(D[bot], D[bot + 1], V[i]) > 0) && (isLeft(D[top - 1], D[top], V[i]) > 0)) { continue; // skip an interior vertex } // incrementally add an exterior vertex to the deque hull // get the rightmost tangent at the deque bot while (isLeft(D[bot], D[bot + 1], V[i]) <= 0) { ++bot; // remove bot of deque if (bot >= (int) D.size()) { throw ProcessError(); } } if (bot == 0) { throw ProcessError(); } D[--bot] = V[i]; // insert V[i] at bot of deque if (top == 0 || top >= (int) D.size()) { throw ProcessError(); } // get the leftmost tangent at the deque top while (isLeft(D[top - 1], D[top], V[i]) <= 0) { --top; // pop top of deque if (top == 0 || top >= (int) D.size()) { throw ProcessError(); } } if (top + 1 >= (int) D.size()) { throw ProcessError(); } D[++top] = V[i]; // push V[i] onto top of deque } // transcribe deque D[] to the output hull array H[] int h; // hull vertex counter PositionVector H; for (h = 0; h <= (top - bot); h++) { if (bot + h >= (int) D.size()) { throw ProcessError(); } H.push_back_noDoublePos(D[bot + h]); } return H; }
double NWWriter_OpenDrive::writeGeomPP3( OutputDevice& device, OutputDevice& elevationDevice, PositionVector init, double length, double offset) { assert(init.size() == 3 || init.size() == 4); // avoid division by 0 length = MAX2(POSITION_EPS, length); const Position p = init.front(); const double hdg = init.angleAt2D(0); // backup elevation values const PositionVector initZ = init; // translate to u,v coordinates init.add(-p.x(), -p.y(), -p.z()); init.rotate2D(-hdg); // parametric coefficients double aU, bU, cU, dU; double aV, bV, cV, dV; double aZ, bZ, cZ, dZ; // unfactor the Bernstein polynomials of degree 2 (or 3) and collect the coefficients if (init.size() == 3) { //f(x, a, b ,c) = a + (2*b - 2*a)*x + (a - 2*b + c)*x*x aU = init[0].x(); bU = 2 * init[1].x() - 2 * init[0].x(); cU = init[0].x() - 2 * init[1].x() + init[2].x(); dU = 0; aV = init[0].y(); bV = 2 * init[1].y() - 2 * init[0].y(); cV = init[0].y() - 2 * init[1].y() + init[2].y(); dV = 0; // elevation is not parameteric on [0:1] but on [0:length] aZ = initZ[0].z(); bZ = (2 * initZ[1].z() - 2 * initZ[0].z()) / length; cZ = (initZ[0].z() - 2 * initZ[1].z() + initZ[2].z()) / (length * length); dZ = 0; } else { // f(x, a, b, c, d) = a + (x*((3*b) - (3*a))) + ((x*x)*((3*a) + (3*c) - (6*b))) + ((x*x*x)*((3*b) - (3*c) - a + d)) aU = init[0].x(); bU = 3 * init[1].x() - 3 * init[0].x(); cU = 3 * init[0].x() - 6 * init[1].x() + 3 * init[2].x(); dU = -init[0].x() + 3 * init[1].x() - 3 * init[2].x() + init[3].x(); aV = init[0].y(); bV = 3 * init[1].y() - 3 * init[0].y(); cV = 3 * init[0].y() - 6 * init[1].y() + 3 * init[2].y(); dV = -init[0].y() + 3 * init[1].y() - 3 * init[2].y() + init[3].y(); // elevation is not parameteric on [0:1] but on [0:length] aZ = initZ[0].z(); bZ = (3 * initZ[1].z() - 3 * initZ[0].z()) / length; cZ = (3 * initZ[0].z() - 6 * initZ[1].z() + 3 * initZ[2].z()) / (length * length); dZ = (-initZ[0].z() + 3 * initZ[1].z() - 3 * initZ[2].z() + initZ[3].z()) / (length * length * length); } device.openTag("geometry"); device.writeAttr("s", offset); device.writeAttr("x", p.x()); device.writeAttr("y", p.y()); device.writeAttr("hdg", hdg); device.writeAttr("length", length); device.openTag("paramPoly3"); device.writeAttr("aU", aU); device.writeAttr("bU", bU); device.writeAttr("cU", cU); device.writeAttr("dU", dU); device.writeAttr("aV", aV); device.writeAttr("bV", bV); device.writeAttr("cV", cV); device.writeAttr("dV", dV); device.closeTag(); device.closeTag(); // write elevation elevationDevice.openTag("elevation"); elevationDevice.writeAttr("s", offset); elevationDevice.writeAttr("a", aZ); elevationDevice.writeAttr("b", bZ); elevationDevice.writeAttr("c", cZ); elevationDevice.writeAttr("d", dZ); elevationDevice.closeTag(); return offset + length; }
void PCLoaderVisum::load(const std::string& file, OptionsCont& oc, PCPolyContainer& toFill, PCTypeMap& tm) { GeoConvHelper& geoConvHelper = GeoConvHelper::getProcessing(); std::string what; std::map<long, Position> punkte; std::map<long, PositionVector> kanten; std::map<long, PositionVector> teilflaechen; std::map<long, long> flaechenelemente; NamedColumnsParser lineParser; LineReader lr(file); while (lr.hasMore()) { std::string line = lr.readLine(); // reset if current is over if (line.length() == 0 || line[0] == '*' || line[0] == '$') { what = ""; } // read items if (what == "$PUNKT") { lineParser.parseLine(line); long id = TplConvert<char>::_2long(lineParser.get("ID").c_str()); SUMOReal x = TplConvert<char>::_2SUMOReal(lineParser.get("XKOORD").c_str()); SUMOReal y = TplConvert<char>::_2SUMOReal(lineParser.get("YKOORD").c_str()); Position pos(x, y); if (!geoConvHelper.x2cartesian(pos)) { WRITE_WARNING("Unable to project coordinates for point '" + toString(id) + "'."); } punkte[id] = pos; continue; } else if (what == "$KANTE") { lineParser.parseLine(line); long id = TplConvert<char>::_2long(lineParser.get("ID").c_str()); long fromID = TplConvert<char>::_2long(lineParser.get("VONPUNKTID").c_str()); long toID = TplConvert<char>::_2long(lineParser.get("NACHPUNKTID").c_str()); PositionVector vec; vec.push_back(punkte[fromID]); vec.push_back(punkte[toID]); kanten[id] = vec; continue; } else if (what == "$ZWISCHENPUNKT") { lineParser.parseLine(line); long id = TplConvert<char>::_2long(lineParser.get("KANTEID").c_str()); int index = TplConvert<char>::_2int(lineParser.get("INDEX").c_str()); SUMOReal x = TplConvert<char>::_2SUMOReal(lineParser.get("XKOORD").c_str()); SUMOReal y = TplConvert<char>::_2SUMOReal(lineParser.get("YKOORD").c_str()); Position pos(x, y); if (!geoConvHelper.x2cartesian(pos)) { WRITE_WARNING("Unable to project coordinates for edge '" + toString(id) + "'."); } kanten[id].insertAt(index, pos); continue; } else if (what == "$TEILFLAECHENELEMENT") { lineParser.parseLine(line); long id = TplConvert<char>::_2long(lineParser.get("TFLAECHEID").c_str()); int index = TplConvert<char>::_2int(lineParser.get("INDEX").c_str()); index = 0; /// hmmmm - assume it's sorted... long kid = TplConvert<char>::_2long(lineParser.get("KANTEID").c_str()); int dir = TplConvert<char>::_2int(lineParser.get("RICHTUNG").c_str()); if (teilflaechen.find(id) == teilflaechen.end()) { teilflaechen[id] = PositionVector(); } if (dir == 0) { for (int i = 0; i < (int) kanten[kid].size(); ++i) { teilflaechen[id].push_back_noDoublePos(kanten[kid][i]); } } else { for (int i = (int) kanten[kid].size() - 1; i >= 0; --i) { teilflaechen[id].push_back_noDoublePos(kanten[kid][i]); } } continue; } else if (what == "$FLAECHENELEMENT") { lineParser.parseLine(line); long id = TplConvert<char>::_2long(lineParser.get("FLAECHEID").c_str()); long tid = TplConvert<char>::_2long(lineParser.get("TFLAECHEID").c_str()); int enklave = TplConvert<char>::_2int(lineParser.get("ENKLAVE").c_str()); // !!! unused enklave = 0; flaechenelemente[id] = tid; continue; } // set if read if (line[0] == '$') { what = ""; if (line.find("$PUNKT") == 0) { what = "$PUNKT"; } else if (line.find("$KANTE") == 0) { what = "$KANTE"; } else if (line.find("$ZWISCHENPUNKT") == 0) { what = "$ZWISCHENPUNKT"; } else if (line.find("$TEILFLAECHENELEMENT") == 0) { what = "$TEILFLAECHENELEMENT"; } else if (line.find("$FLAECHENELEMENT") == 0) { what = "$FLAECHENELEMENT"; } if (what != "") { lineParser.reinit(line.substr(what.length() + 1)); } } } // do some more sane job... RGBColor c = RGBColor::parseColor(oc.getString("color")); std::map<std::string, std::string> typemap; // load the pois/polys lr.reinit(); bool parsingCategories = false; bool parsingPOIs = false; bool parsingDistrictsDirectly = false; PositionVector vec; std::string polyType, lastID; bool first = true; while (lr.hasMore()) { std::string line = lr.readLine(); // do not parse empty lines if (line.length() == 0) { continue; } // do not parse comment lines if (line[0] == '*') { continue; } if (line[0] == '$') { // reset parsing on new entry type parsingCategories = false; parsingPOIs = false; parsingDistrictsDirectly = false; polyType = ""; } if (parsingCategories) { // parse the category StringTokenizer st(line, ";"); std::string catid = st.next(); std::string catname = st.next(); typemap[catid] = catname; } if (parsingPOIs) { // parse the poi // $POI:Nr;CATID;CODE;NAME;Kommentar;XKoord;YKoord; StringTokenizer st(line, ";"); std::string num = st.next(); std::string catid = st.next(); std::string code = st.next(); std::string name = st.next(); std::string comment = st.next(); std::string xpos = st.next(); std::string ypos = st.next(); // process read values SUMOReal x = TplConvert<char>::_2SUMOReal(xpos.c_str()); SUMOReal y = TplConvert<char>::_2SUMOReal(ypos.c_str()); Position pos(x, y); if (!geoConvHelper.x2cartesian(pos)) { WRITE_WARNING("Unable to project coordinates for POI '" + num + "'."); } std::string type = typemap[catid]; // check the poi name = num; // patch the values bool discard = oc.getBool("discard"); int layer = oc.getInt("layer"); RGBColor color; if (tm.has(type)) { const PCTypeMap::TypeDef& def = tm.get(type); name = def.prefix + name; type = def.id; color = RGBColor::parseColor(def.color); discard = def.discard; layer = def.layer; } else { name = oc.getString("prefix") + name; type = oc.getString("type"); color = c; } if (!discard) { PointOfInterest* poi = new PointOfInterest(name, type, pos, color); if (!toFill.insert(name, poi, layer)) { WRITE_ERROR("POI '" + name + "' could not been added."); delete poi; } } } // poly if (polyType != "") { StringTokenizer st(line, ";"); std::string id = st.next(); std::string type; if (!first && lastID != id) { // we have parsed a polygon completely RGBColor color; int layer = oc.getInt("layer"); bool discard = oc.getBool("discard"); if (tm.has(polyType)) { const PCTypeMap::TypeDef& def = tm.get(polyType); id = def.prefix + id; type = def.id; color = RGBColor::parseColor(def.color); discard = def.discard; layer = def.layer; } else { id = oc.getString("prefix") + id; type = oc.getString("type"); color = c; } if (!discard) { Polygon* poly = new Polygon(id, type, color, vec, false); if (!toFill.insert(id, poly, 1)) { WRITE_ERROR("Polygon '" + id + "' could not been added."); delete poly; } } vec.clear(); } lastID = id; first = false; // parse current poly std::string index = st.next(); std::string xpos = st.next(); std::string ypos = st.next(); Position pos2D((SUMOReal) atof(xpos.c_str()), (SUMOReal) atof(ypos.c_str())); if (!geoConvHelper.x2cartesian(pos2D)) { WRITE_WARNING("Unable to project coordinates for polygon '" + id + "'."); } vec.push_back(pos2D); } // district refering a shape if (parsingDistrictsDirectly) { //$BEZIRK:NR CODE NAME TYPNR XKOORD YKOORD FLAECHEID BEZART IVANTEIL_Q IVANTEIL_Z OEVANTEIL METHODEANBANTEILE ZWERT1 ZWERT2 ZWERT3 ISTINAUSWAHL OBEZNR NOM_COM COD_COM StringTokenizer st(line, ";"); std::string num = st.next(); std::string code = st.next(); std::string name = st.next(); st.next(); // typntr std::string xpos = st.next(); std::string ypos = st.next(); long id = TplConvert<char>::_2long(st.next().c_str()); // patch the values std::string type = "district"; name = num; bool discard = oc.getBool("discard"); int layer = oc.getInt("layer"); RGBColor color; if (tm.has(type)) { const PCTypeMap::TypeDef& def = tm.get(type); name = def.prefix + name; type = def.id; color = RGBColor::parseColor(def.color); discard = def.discard; layer = def.layer; } else { name = oc.getString("prefix") + name; type = oc.getString("type"); color = c; } if (!discard) { if (teilflaechen[flaechenelemente[id]].size() > 0) { Polygon* poly = new Polygon(name, type, color, teilflaechen[flaechenelemente[id]], false); if (!toFill.insert(name, poly, layer)) { WRITE_ERROR("Polygon '" + name + "' could not been added."); delete poly; } } else { SUMOReal x = TplConvert<char>::_2SUMOReal(xpos.c_str()); SUMOReal y = TplConvert<char>::_2SUMOReal(ypos.c_str()); Position pos(x, y); if (!geoConvHelper.x2cartesian(pos)) { WRITE_WARNING("Unable to project coordinates for POI '" + name + "'."); } PointOfInterest* poi = new PointOfInterest(name, type, pos, color); if (!toFill.insert(name, poi, layer)) { WRITE_ERROR("POI '" + name + "' could not been added."); delete poi; } } } } if (line.find("$POIKATEGORIEDEF:") == 0 || line.find("$POIKATEGORIE:") == 0) { // ok, got categories, begin parsing from next line parsingCategories = true; } if (line.find("$POI:") == 0) { // ok, got pois, begin parsing from next line parsingPOIs = true; } if (line.find("$BEZIRK") == 0 && line.find("FLAECHEID") != std::string::npos) { // ok, have a district header, and it seems like districts would reference shapes... parsingDistrictsDirectly = true; } if (line.find("$BEZIRKPOLY") != std::string::npos) { polyType = "district"; } if (line.find("$GEBIETPOLY") != std::string::npos) { polyType = "area"; } } }
void NIImporter_ArcView::load() { #ifdef HAVE_GDAL PROGRESS_BEGIN_MESSAGE("Loading data from '" + mySHPName + "'"); #if GDAL_VERSION_MAJOR < 2 OGRRegisterAll(); OGRDataSource* poDS = OGRSFDriverRegistrar::Open(mySHPName.c_str(), FALSE); #else GDALAllRegister(); GDALDataset* poDS = (GDALDataset*)GDALOpenEx(mySHPName.c_str(), GDAL_OF_VECTOR | GA_ReadOnly, NULL, NULL, NULL); #endif if (poDS == NULL) { WRITE_ERROR("Could not open shape description '" + mySHPName + "'."); return; } // begin file parsing OGRLayer* poLayer = poDS->GetLayer(0); poLayer->ResetReading(); // build coordinate transformation OGRSpatialReference* origTransf = poLayer->GetSpatialRef(); OGRSpatialReference destTransf; // use wgs84 as destination destTransf.SetWellKnownGeogCS("WGS84"); OGRCoordinateTransformation* poCT = OGRCreateCoordinateTransformation(origTransf, &destTransf); if (poCT == NULL) { if (myOptions.isSet("shapefile.guess-projection")) { OGRSpatialReference origTransf2; origTransf2.SetWellKnownGeogCS("WGS84"); poCT = OGRCreateCoordinateTransformation(&origTransf2, &destTransf); } if (poCT == 0) { WRITE_WARNING("Could not create geocoordinates converter; check whether proj.4 is installed."); } } OGRFeature* poFeature; poLayer->ResetReading(); while ((poFeature = poLayer->GetNextFeature()) != NULL) { // read in edge attributes std::string id, name, from_node, to_node; if (!getStringEntry(poFeature, "shapefile.street-id", "LINK_ID", true, id)) { WRITE_ERROR("Needed field '" + id + "' (from node id) is missing."); } if (id == "") { WRITE_ERROR("Could not obtain edge id."); return; } getStringEntry(poFeature, "shapefile.street-id", "ST_NAME", true, name); name = StringUtils::replace(name, "&", "&"); if (!getStringEntry(poFeature, "shapefile.from-id", "REF_IN_ID", true, from_node)) { WRITE_ERROR("Needed field '" + from_node + "' (from node id) is missing."); } if (!getStringEntry(poFeature, "shapefile.to-id", "NREF_IN_ID", true, to_node)) { WRITE_ERROR("Needed field '" + to_node + "' (to node id) is missing."); } if (from_node == "" || to_node == "") { from_node = toString(myRunningNodeID++); to_node = toString(myRunningNodeID++); } std::string type; if (myOptions.isSet("shapefile.type-id") && poFeature->GetFieldIndex(myOptions.getString("shapefile.type-id").c_str()) >= 0) { type = poFeature->GetFieldAsString(myOptions.getString("shapefile.type-id").c_str()); } else if (poFeature->GetFieldIndex("ST_TYP_AFT") >= 0) { type = poFeature->GetFieldAsString("ST_TYP_AFT"); } SUMOReal width = myTypeCont.getWidth(type); SUMOReal speed = getSpeed(*poFeature, id); int nolanes = getLaneNo(*poFeature, id, speed); int priority = getPriority(*poFeature, id); if (nolanes == 0 || speed == 0) { if (myOptions.getBool("shapefile.use-defaults-on-failure")) { nolanes = myTypeCont.getNumLanes(""); speed = myTypeCont.getSpeed(""); } else { OGRFeature::DestroyFeature(poFeature); WRITE_ERROR("The description seems to be invalid. Please recheck usage of types."); return; } } if (mySpeedInKMH) { speed = speed / (SUMOReal) 3.6; } // read in the geometry OGRGeometry* poGeometry = poFeature->GetGeometryRef(); OGRwkbGeometryType gtype = poGeometry->getGeometryType(); assert(gtype == wkbLineString); UNUSED_PARAMETER(gtype); // ony used for assertion OGRLineString* cgeom = (OGRLineString*) poGeometry; if (poCT != 0) { // try transform to wgs84 cgeom->transform(poCT); } PositionVector shape; for (int j = 0; j < cgeom->getNumPoints(); j++) { Position pos((SUMOReal) cgeom->getX(j), (SUMOReal) cgeom->getY(j)); if (!NBNetBuilder::transformCoordinate(pos)) { WRITE_WARNING("Unable to project coordinates for edge '" + id + "'."); } shape.push_back_noDoublePos(pos); } // build from-node NBNode* from = myNodeCont.retrieve(from_node); if (from == 0) { Position from_pos = shape[0]; from = myNodeCont.retrieve(from_pos); if (from == 0) { from = new NBNode(from_node, from_pos); if (!myNodeCont.insert(from)) { WRITE_ERROR("Node '" + from_node + "' could not be added"); delete from; continue; } } } // build to-node NBNode* to = myNodeCont.retrieve(to_node); if (to == 0) { Position to_pos = shape[-1]; to = myNodeCont.retrieve(to_pos); if (to == 0) { to = new NBNode(to_node, to_pos); if (!myNodeCont.insert(to)) { WRITE_ERROR("Node '" + to_node + "' could not be added"); delete to; continue; } } } if (from == to) { WRITE_WARNING("Edge '" + id + "' connects identical nodes, skipping."); continue; } // retrieve the information whether the street is bi-directional std::string dir; int index = poFeature->GetDefnRef()->GetFieldIndex("DIR_TRAVEL"); if (index >= 0 && poFeature->IsFieldSet(index)) { dir = poFeature->GetFieldAsString(index); } // add positive direction if wanted if (dir == "B" || dir == "F" || dir == "" || myOptions.getBool("shapefile.all-bidirectional")) { if (myEdgeCont.retrieve(id) == 0) { LaneSpreadFunction spread = dir == "B" || dir == "FALSE" ? LANESPREAD_RIGHT : LANESPREAD_CENTER; NBEdge* edge = new NBEdge(id, from, to, type, speed, nolanes, priority, width, NBEdge::UNSPECIFIED_OFFSET, shape, name, id, spread); myEdgeCont.insert(edge); checkSpread(edge); } } // add negative direction if wanted if (dir == "B" || dir == "T" || myOptions.getBool("shapefile.all-bidirectional")) { if (myEdgeCont.retrieve("-" + id) == 0) { LaneSpreadFunction spread = dir == "B" || dir == "FALSE" ? LANESPREAD_RIGHT : LANESPREAD_CENTER; NBEdge* edge = new NBEdge("-" + id, to, from, type, speed, nolanes, priority, width, NBEdge::UNSPECIFIED_OFFSET, shape.reverse(), name, id, spread); myEdgeCont.insert(edge); checkSpread(edge); } } // OGRFeature::DestroyFeature(poFeature); } #if GDAL_VERSION_MAJOR < 2 OGRDataSource::DestroyDataSource(poDS); #else GDALClose(poDS); #endif PROGRESS_DONE_MESSAGE(); #else WRITE_ERROR("SUMO was compiled without GDAL support."); #endif }
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); }