void GLHelper::drawFilledPolyTesselated(const PositionVector& v, bool close) { if (v.size() == 0) { return; } GLUtesselator* tobj = gluNewTess(); gluTessCallback(tobj, GLU_TESS_VERTEX, (GLvoid(APIENTRY*)()) &glVertex3dv); gluTessCallback(tobj, GLU_TESS_BEGIN, (GLvoid(APIENTRY*)()) &glBegin); gluTessCallback(tobj, GLU_TESS_END, (GLvoid(APIENTRY*)()) &glEnd); gluTessCallback(tobj, GLU_TESS_COMBINE, (GLvoid(APIENTRY*)()) &combCallback); gluTessProperty(tobj, GLU_TESS_WINDING_RULE, GLU_TESS_WINDING_ODD); gluTessBeginPolygon(tobj, nullptr); gluTessBeginContour(tobj); double* points = new double[(v.size() + int(close)) * 3]; for (int i = 0; i != (int)v.size(); ++i) { points[3 * i] = v[i].x(); points[3 * i + 1] = v[i].y(); points[3 * i + 2] = 0; gluTessVertex(tobj, points + 3 * i, points + 3 * i); } if (close) { const int i = (int)v.size(); points[3 * i] = v[0].x(); points[3 * i + 1] = v[0].y(); points[3 * i + 2] = 0; gluTessVertex(tobj, points + 3 * i, points + 3 * i); } gluTessEndContour(tobj); gluTessEndPolygon(tobj); gluDeleteTess(tobj); delete[] points; }
void ShapeHandler::addPoly(const SUMOSAXAttributes& attrs) { bool ok = true; std::string id = attrs.get<std::string>(SUMO_ATTR_ID, 0, ok); // get the id, report an error if not given or empty... if (!ok) { return; } SUMOReal layer = attrs.getOpt<SUMOReal>(SUMO_ATTR_LAYER, id.c_str(), ok, Shape::DEFAULT_LAYER); bool fill = attrs.getOpt<bool>(SUMO_ATTR_FILL, id.c_str(), ok, false); std::string type = attrs.getOpt<std::string>(SUMO_ATTR_TYPE, id.c_str(), ok, Shape::DEFAULT_TYPE); std::string colorStr = attrs.get<std::string>(SUMO_ATTR_COLOR, id.c_str(), ok); RGBColor color = attrs.get<RGBColor>(SUMO_ATTR_COLOR, id.c_str(), ok); PositionVector shape = attrs.get<PositionVector>(SUMO_ATTR_SHAPE, id.c_str(), ok); if (attrs.getOpt<bool>(SUMO_ATTR_GEO, id.c_str(), ok, false)) { for (int i = 0; i < (int) shape.size(); i++) { GeoConvHelper::getFinal().x2cartesian_const(shape[i]); } } SUMOReal angle = attrs.getOpt<SUMOReal>(SUMO_ATTR_ANGLE, id.c_str(), ok, Shape::DEFAULT_ANGLE); std::string imgFile = attrs.getOpt<std::string>(SUMO_ATTR_IMGFILE, id.c_str(), ok, Shape::DEFAULT_IMG_FILE); if (imgFile != "" && !FileHelpers::isAbsolute(imgFile)) { imgFile = FileHelpers::getConfigurationRelative(getFileName(), imgFile); } if (shape.size() != 0) { if (!myShapeContainer.addPolygon(id, type, color, layer, angle, imgFile, shape, fill)) { WRITE_WARNING("Skipping redefinition of polygon '" + id + "'."); } } }
bool NBNetBuilder::transformCoordinates(PositionVector& from, bool includeInBoundary, GeoConvHelper* from_srs) { const SUMOReal maxLength = OptionsCont::getOptions().getFloat("geometry.max-segment-length"); if (maxLength > 0 && from.size() > 1) { // transformation to cartesian coordinates must happen before we can check segment length PositionVector copy = from; for (int i = 0; i < (int) from.size(); i++) { transformCoordinates(copy[i], false); } // check lengths and insert new points where needed (in the original // coordinate system) int inserted = 0; for (int i = 0; i < (int)copy.size() - 1; i++) { Position start = from[i + inserted]; Position end = from[i + inserted + 1]; SUMOReal length = copy[i].distanceTo(copy[i + 1]); const Position step = (end - start) * (maxLength / length); int steps = 0; while (length > maxLength) { length -= maxLength; steps++; from.insert(from.begin() + i + inserted + 1, start + (step * steps)); inserted++; } } // now perform the transformation again so that height mapping can be // performed for the new points } bool ok = true; for (int i = 0; i < (int) from.size(); i++) { ok = ok && transformCoordinates(from[i], includeInBoundary, from_srs); } return ok; }
void GLHelper::drawBoxLines(const PositionVector& geom1, const PositionVector& geom2, const std::vector<double>& rots, const std::vector<double>& lengths, double width) { int minS = (int) MIN4(rots.size(), lengths.size(), geom1.size(), geom2.size()); for (int i = 0; i < minS; i++) { GLHelper::drawBoxLine(geom1[i], geom2[i], rots[i], lengths[i], width); } }
void GLHelper::debugVertices(const PositionVector& shape, double size, double layer) { RGBColor color = RGBColor::randomHue(); for (int i = 0; i < (int)shape.size(); ++i) { GLHelper::drawText(toString(i), shape[i], layer, size, color, 0); } }
void NLHandler::addPoly(const SUMOSAXAttributes& attrs) { bool ok = true; std::string id = attrs.get<std::string>(SUMO_ATTR_ID, 0, ok); // get the id, report an error if not given or empty... if (!ok) { return; } SUMOReal layer = attrs.getOpt<SUMOReal>(SUMO_ATTR_LAYER, id.c_str(), ok, (SUMOReal)GLO_POLYGON); bool fill = attrs.getOpt<bool>(SUMO_ATTR_FILL, id.c_str(), ok, false); std::string type = attrs.getOpt<std::string>(SUMO_ATTR_TYPE, id.c_str(), ok, ""); std::string colorStr = attrs.get<std::string>(SUMO_ATTR_COLOR, id.c_str(), ok); RGBColor color = attrs.get<RGBColor>(SUMO_ATTR_COLOR, id.c_str(), ok); PositionVector shape = attrs.get<PositionVector>(SUMO_ATTR_SHAPE, id.c_str(), ok); SUMOReal angle = attrs.getOpt<SUMOReal>(SUMO_ATTR_ANGLE, id.c_str(), ok, Shape::DEFAULT_ANGLE); std::string imgFile = attrs.getOpt<std::string>(SUMO_ATTR_IMGFILE, id.c_str(), ok, Shape::DEFAULT_IMG_FILE); if (imgFile != "" && !FileHelpers::isAbsolute(imgFile)) { imgFile = FileHelpers::getConfigurationRelative(getFileName(), imgFile); } if (shape.size() != 0) { if (!myNet.getShapeContainer().addPolygon(id, type, color, layer, angle, imgFile, shape, fill)) { WRITE_ERROR("Polygon '" + id + "' already exists."); } } }
void GLHelper::drawShapeDottedContour(const int type, const PositionVector& frontShape, const double offsetFrontShape, const PositionVector& backShape, const double offsetBackShape) { glPushMatrix(); // build contour using shapes of first and last lane shapes PositionVector contourFront = frontShape; PositionVector contourback = backShape; contourFront.move2side(offsetFrontShape); contourback.move2side(offsetBackShape); contourback = contourback.reverse(); for (auto i : contourback) { contourFront.push_back(i); } contourFront.push_back(frontShape.front()); // resample shape PositionVector resampledShape = contourFront.resample(1); // draw contour over shape glTranslated(0, 0, type + 2); // set custom line width glLineWidth(3); // draw contour GLHelper::drawLine(resampledShape, getDottedcontourColors((int)resampledShape.size())); //restore line width glLineWidth(1); glPopMatrix(); }
void GLHelper::drawShapeDottedContour(const int type, const PositionVector& shape, const double width) { glPushMatrix(); // build contour using shapes of first and last lane shapes PositionVector contourFront = shape; // only add an contourback if width is greather of 0 if (width > 0) { PositionVector contourback = contourFront; contourFront.move2side(width); contourback.move2side(-width); contourback = contourback.reverse(); for (auto i : contourback) { contourFront.push_back(i); } contourFront.push_back(shape.front()); } // resample shape PositionVector resampledShape = contourFront.resample(1); // draw contour over shape glTranslated(0, 0, type + 2); // set custom line width glLineWidth(3); // draw contour drawLine(resampledShape, getDottedcontourColors((int)resampledShape.size())); //restore line width glLineWidth(1); glPopMatrix(); }
void GLHelper::drawShapeDottedContour(const int type, const Position& center, const double width, const double height, const double rotation, const double offsetX, const double offsetY) { glPushMatrix(); // create shape around center PositionVector shape; shape.push_back(Position(width / 2, height / 2)); shape.push_back(Position(width / -2, height / 2)); shape.push_back(Position(width / -2, height / -2)); shape.push_back(Position(width / 2, height / -2)); shape.push_back(Position(width / 2, height / 2)); // resample shape shape = shape.resample(1); // draw contour over shape glTranslated(center.x(), center.y(), type + 2); // set custom line width glLineWidth(3); // rotate glRotated(rotation, 0, 0, 1); // translate offset glTranslated(offsetX, offsetY, 0); // draw contour GLHelper::drawLine(shape, getDottedcontourColors((int)shape.size())); //restore line width glLineWidth(1); glPopMatrix(); }
void BinaryFormatter::writeAttr(std::ostream& into, const SumoXMLAttr attr, const PositionVector& val) { BinaryFormatter::writeAttrHeader(into, attr, BF_LIST); FileHelpers::writeInt(into, static_cast<int>(val.size())); for (PositionVector::const_iterator pos = val.begin(); pos != val.end(); ++pos) { writePosition(into, *pos); } }
void GLHelper::debugVertices(const PositionVector& shape, SUMOReal size, SUMOReal layer) { RGBColor color = RGBColor::fromHSV(RandHelper::rand(360), 1, 1); for (int i = 0; i < (int)shape.size(); ++i) { GLHelper::drawText(toString(i), shape[i], layer, size, color, 0); } }
void PositionVector::append(const PositionVector& v, SUMOReal sameThreshold) { if (size() > 0 && v.size() > 0 && back().distanceTo(v[0]) < sameThreshold) { copy(v.begin() + 1, v.end(), back_inserter(*this)); } else { copy(v.begin(), v.end(), back_inserter(*this)); } }
void NIVissimNodeCluster::buildNBNode(NBNodeCont& nc) { if (myConnectors.size() == 0) { return; // !!! Check, whether this can happen } // compute the position PositionVector crossings; IntVector::iterator i, j; // check whether this is a split of an edge only if (myAmEdgeSplit) { // !!! should be assert(myTLID==-1); for (i = myConnectors.begin(); i != myConnectors.end(); i++) { NIVissimConnection* c1 = NIVissimConnection::dictionary(*i); crossings.push_back_noDoublePos(c1->getFromGeomPosition()); } } else { // compute the places the connections cross for (i = myConnectors.begin(); i != myConnectors.end(); i++) { NIVissimAbstractEdge* c1 = NIVissimAbstractEdge::dictionary(*i); c1->buildGeom(); for (j = i + 1; j != myConnectors.end(); j++) { NIVissimAbstractEdge* c2 = NIVissimAbstractEdge::dictionary(*j); c2->buildGeom(); if (c1->crossesEdge(c2)) { crossings.push_back_noDoublePos(c1->crossesEdgeAtPoint(c2)); } } } // alternative way: compute via positions of crossings if (crossings.size() == 0) { for (i = myConnectors.begin(); i != myConnectors.end(); i++) { NIVissimConnection* c1 = NIVissimConnection::dictionary(*i); crossings.push_back_noDoublePos(c1->getFromGeomPosition()); crossings.push_back_noDoublePos(c1->getToGeomPosition()); } } } // get the position (center) Position pos = crossings.getPolygonCenter(); // build the node /* if(myTLID!=-1) { !!! NIVissimTL *tl = NIVissimTL::dictionary(myTLID); if(tl->getType()=="festzeit") { node = new NBNode(getNodeName(), pos.x(), pos.y(), "traffic_light"); } else { node = new NBNode(getNodeName(), pos.x(), pos.y(), "actuated_traffic_light"); } }*/ NBNode* node = new NBNode(getNodeName(), pos, NODETYPE_PRIORITY_JUNCTION); if (!nc.insert(node)) { delete node; throw 1; } myNBNode = node; }
void GLHelper::drawLine(const PositionVector& v) { glBegin(GL_LINES); int e = (int) v.size() - 1; for (int i = 0; i < e; ++i) { glVertex2d(v[i].x(), v[i].y()); glVertex2d(v[i + 1].x(), v[i + 1].y()); } glEnd(); }
void GLHelper::drawLine(const PositionVector& v, const std::vector<RGBColor>& cols) { glBegin(GL_LINES); int e = (int) v.size() - 1; for (int i = 0; i < e; ++i) { setColor(cols[i]); glVertex2d(v[i].x(), v[i].y()); glVertex2d(v[i + 1].x(), v[i + 1].y()); } glEnd(); }
void NWWriter_OpenDrive::writeElevationProfile(const PositionVector& shape, OutputDevice& device, const OutputDevice_String& elevationDevice) { // check if the shape is flat bool flat = true; double z = shape.size() == 0 ? 0 : shape[0].z(); for (int i = 1; i < (int)shape.size(); ++i) { if (fabs(shape[i].z() - z) > NUMERICAL_EPS) { flat = false; break; } } device << " <elevationProfile>\n"; if (flat) { device << " <elevation s=\"0\" a=\"" << z << "\" b=\"0\" c=\"0\" d=\"0\"/>\n"; } else { device << elevationDevice.getString(); } device << " </elevationProfile>\n"; }
void GLHelper::drawBoxLines(const PositionVector& geom, double width) { int e = (int) geom.size() - 1; for (int i = 0; i < e; i++) { const Position& f = geom[i]; const Position& s = geom[i + 1]; drawBoxLine(f, RAD2DEG(atan2((s.x() - f.x()), (f.y() - s.y()))), f.distanceTo(s), width); } }
bool PositionVector::operator==(const PositionVector& v2) const { if (size() == v2.size()) { for (int i = 0; i < (int)size(); i++) { if ((*this)[i] != v2[i]) { return false; } } return true; } else { return false; } }
void GLHelper::drawShapeDottedContour(const int type, const PositionVector& shape) { glPushMatrix(); // resample junction shape PositionVector resampledShape = shape.resample(1); // draw contour over shape glTranslated(0, 0, type + 0.1); // set custom line width glLineWidth(3); // draw contour GLHelper::drawLine(resampledShape, GLHelper::getDottedcontourColors((int)resampledShape.size())); //restore line width glLineWidth(1); glPopMatrix(); }
void NLHandler::addDistrict(const SUMOSAXAttributes& attrs) { bool ok = true; myCurrentIsBroken = false; // get the id, report an error if not given or empty... myCurrentDistrictID = attrs.get<std::string>(SUMO_ATTR_ID, 0, ok); if (!ok) { myCurrentIsBroken = true; return; } try { MSEdge* sink = myEdgeControlBuilder.buildEdge(myCurrentDistrictID + "-sink", MSEdge::EDGEFUNCTION_DISTRICT); if (!MSEdge::dictionary(myCurrentDistrictID + "-sink", sink)) { delete sink; throw InvalidArgument("Another edge with the id '" + myCurrentDistrictID + "-sink' exists."); } sink->initialize(new std::vector<MSLane*>()); MSEdge* source = myEdgeControlBuilder.buildEdge(myCurrentDistrictID + "-source", MSEdge::EDGEFUNCTION_DISTRICT); if (!MSEdge::dictionary(myCurrentDistrictID + "-source", source)) { delete source; throw InvalidArgument("Another edge with the id '" + myCurrentDistrictID + "-source' exists."); } source->initialize(new std::vector<MSLane*>()); if (attrs.hasAttribute(SUMO_ATTR_EDGES)) { std::vector<std::string> desc = attrs.getStringVector(SUMO_ATTR_EDGES); for (std::vector<std::string>::const_iterator i = desc.begin(); i != desc.end(); ++i) { MSEdge* edge = MSEdge::dictionary(*i); // check whether the edge exists if (edge == 0) { throw InvalidArgument("The edge '" + *i + "' within district '" + myCurrentDistrictID + "' is not known."); } source->addFollower(edge); edge->addFollower(sink); } } if (attrs.hasAttribute(SUMO_ATTR_SHAPE)) { PositionVector shape = attrs.get<PositionVector>(SUMO_ATTR_SHAPE, myCurrentDistrictID.c_str(), ok); if (shape.size() != 0) { if (!myNet.getShapeContainer().addPolygon(myCurrentDistrictID, "taz", RGBColor::parseColor("1.0,.33,.33"), 0, 0, "", shape, false)) { WRITE_WARNING("Skipping visualization of taz '" + myCurrentDistrictID + "', polygon already exists."); } } } } catch (InvalidArgument& e) { WRITE_ERROR(e.what()); myCurrentIsBroken = true; } }
// ---- the root/edge/lanes/lane - element void NLHandler::addLane(const SUMOSAXAttributes& attrs) { // omit internal edges if not wished and broken edges if (myCurrentIsInternalToSkip || myCurrentIsBroken) { return; } bool ok = true; // get the id, report an error if not given or empty... std::string id = attrs.get<std::string>(SUMO_ATTR_ID, 0, ok); if (!ok) { myCurrentIsBroken = true; return; } SUMOReal maxSpeed = attrs.get<SUMOReal>(SUMO_ATTR_SPEED, id.c_str(), ok); SUMOReal length = attrs.get<SUMOReal>(SUMO_ATTR_LENGTH, id.c_str(), ok); std::string allow; try { bool dummy; allow = attrs.getOpt<std::string>(SUMO_ATTR_ALLOW, id.c_str(), dummy, "", false); } catch (EmptyData e) { // !!! deprecated } std::string disallow = attrs.getOpt<std::string>(SUMO_ATTR_DISALLOW, id.c_str(), ok, ""); SUMOReal width = attrs.getOpt<SUMOReal>(SUMO_ATTR_WIDTH, id.c_str(), ok, SUMO_const_laneWidth); PositionVector shape = attrs.get<PositionVector>(SUMO_ATTR_SHAPE, id.c_str(), ok); if (shape.size() < 2) { WRITE_ERROR("Shape of lane '" + id + "' is broken.\n Can not build according edge."); myCurrentIsBroken = true; return; } SVCPermissions permissions = parseVehicleClasses(allow, disallow); myCurrentIsBroken |= !ok; if (!myCurrentIsBroken) { try { MSLane* lane = myEdgeControlBuilder.addLane(id, maxSpeed, length, shape, width, permissions); // insert the lane into the lane-dictionary, checking if (!MSLane::dictionary(id, lane)) { delete lane; WRITE_ERROR("Another lane with the id '" + id + "' exists."); myCurrentIsBroken = true; } myLastParameterised = lane; } catch (InvalidArgument& e) { WRITE_ERROR(e.what()); } } }
void GLHelper::drawFilledPoly(const PositionVector& v, bool close) { if (v.size() == 0) { return; } glPolygonMode(GL_FRONT_AND_BACK, GL_FILL); glBegin(GL_POLYGON); for (PositionVector::const_iterator i = v.begin(); i != v.end(); i++) { const Position& p = *i; glVertex2d(p.x(), p.y()); } if (close) { const Position& p = *(v.begin()); glVertex2d(p.x(), p.y()); } glEnd(); }
void NWWriter_OpenDrive::checkLaneGeometries(const NBEdge* e) { if (e->getNumLanes() > 1) { // compute 'stop line' of rightmost lane const PositionVector shape0 = e->getLaneShape(0); assert(shape0.size() >= 2); const Position& from = shape0[-2]; const Position& to = shape0[-1]; PositionVector stopLine; stopLine.push_back(to); stopLine.push_back(to - PositionVector::sideOffset(from, to, -1000.0)); // endpoints of all other lanes should be on the stop line for (int lane = 1; lane < e->getNumLanes(); ++lane) { const double dist = stopLine.distance2D(e->getLaneShape(lane)[-1]); if (dist > NUMERICAL_EPS) { WRITE_WARNING("Uneven stop line at lane '" + e->getLaneID(lane) + "' (dist=" + toString(dist) + ") cannot be represented in OpenDRIVE."); } } } }
double NWWriter_OpenDrive::writeGeomLines(const PositionVector& shape, OutputDevice& device, OutputDevice& elevationDevice, double offset) { for (int j = 0; j < (int)shape.size() - 1; ++j) { const Position& p = shape[j]; const Position& p2 = shape[j + 1]; const double hdg = shape.angleAt2D(j); const double length = p.distanceTo2D(p2); 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("line").closeTag(); device.closeTag(); elevationDevice << " <elevation s=\"" << offset << "\" a=\"" << p.z() << "\" b=\"" << (p2.z() - p.z()) / MAX2(POSITION_EPS, length) << "\" c=\"0\" d=\"0\"/>\n"; offset += length; } return offset; }
SUMOReal PositionVector::area() const { if (size() < 3) { return 0; } SUMOReal area = 0; PositionVector tmp = *this; if (!isClosed()) { // make sure its closed tmp.push_back(tmp[0]); } const int endIndex = (int)tmp.size() - 1; // http://en.wikipedia.org/wiki/Polygon for (int i = 0; i < endIndex; i++) { area += tmp[i].x() * tmp[i + 1].y() - tmp[i + 1].x() * tmp[i].y(); } if (area < 0) { // we whether we had cw or ccw order area *= -1; } return area / 2; }
void GLHelper::drawBoxLines(const PositionVector& geom, const std::vector<SUMOReal>& rots, const std::vector<SUMOReal>& lengths, SUMOReal width, int cornerDetail, SUMOReal offset) { // draw the lane int e = (int) geom.size() - 1; for (int i = 0; i < e; i++) { drawBoxLine(geom[i], rots[i], lengths[i], width, offset); } // draw the corner details if (cornerDetail > 0) { for (int i = 1; i < e; i++) { glPushMatrix(); glTranslated(geom[i].x(), geom[i].y(), 0.1); if (rightTurn(rots[i - 1], rots[i])) { // inside corner drawFilledCircle(MIN2(lengths[i], width - offset), cornerDetail); } else { // outside corner, make sure to only draw a segment of the circle SUMOReal angleBeg = -rots[i - 1]; SUMOReal angleEnd = 180 - rots[i]; // avoid drawing more than 360 degrees if (angleEnd - angleBeg > 360) { angleBeg += 360; } if (angleEnd - angleBeg < -360) { angleEnd += 360; } // for a left tur, draw the right way around if (angleEnd > angleBeg) { angleEnd -= 360; } drawFilledCircle(MIN2(lengths[i], width + offset), cornerDetail, angleBeg, angleEnd); } glEnd(); glPopMatrix(); } } }
void NIImporter_SUMO::addJunction(const SUMOSAXAttributes& attrs) { // get the id, report an error if not given or empty... bool ok = true; std::string id = attrs.getStringReporting(SUMO_ATTR_ID, 0, ok); if (!ok) { return; } if (id[0] == ':') { // internal node return; } SumoXMLNodeType type = attrs.getNodeType(ok); if (ok) { if (type == NODETYPE_DEAD_END_DEPRECATED) { // patch legacy type type = NODETYPE_DEAD_END; } } else { WRITE_WARNING("Unknown node type for junction '" + id + "'."); } Position pos = readPosition(attrs, id, ok); NILoader::transformCoordinates(pos, true, myLocation); // the network may have non-default edge geometry. // accurate reconstruction of legacy networks is not possible. We ought to warn about this if (attrs.hasAttribute(SUMO_ATTR_SHAPE)) { PositionVector shape = attrs.getShapeReporting(SUMO_ATTR_SHAPE, id.c_str(), ok, true); if (shape.size() > 0) { shape.push_back_noDoublePos(shape[0]); // need closed shape if (!shape.around(pos) && shape.distance(pos) > 1) { // MAGIC_THRESHOLD // WRITE_WARNING("Junction '" + id + "': distance between pos and shape is " + toString(shape.distance(pos))); mySuspectKeepShape = true; } } } NBNode* node = new NBNode(id, pos, type); if (!myNodeCont.insert(node)) { WRITE_ERROR("Problems on adding junction '" + id + "'."); delete node; return; } }
void GLHelper::drawBoxLines(const PositionVector& geom, const std::vector<double>& rots, const std::vector<double>& lengths, double width, int cornerDetail, double offset) { // draw the lane int e = (int) geom.size() - 1; for (int i = 0; i < e; i++) { drawBoxLine(geom[i], rots[i], lengths[i], width, offset); } // draw the corner details if (cornerDetail > 0) { for (int i = 1; i < e; i++) { glPushMatrix(); glTranslated(geom[i].x(), geom[i].y(), 0.1); double angleBeg = -rots[i - 1]; double angleEnd = 180 - rots[i]; if (rightTurn(rots[i - 1], rots[i])) { std::swap(angleBeg, angleEnd); } // only draw the missing piece angleBeg -= 90; angleEnd += 90; // avoid drawing more than 360 degrees if (angleEnd - angleBeg > 360) { angleBeg += 360; } if (angleEnd - angleBeg < -360) { angleEnd += 360; } // draw the right way around if (angleEnd > angleBeg) { angleEnd -= 360; } drawFilledCircle(width + offset, cornerDetail, angleBeg, angleEnd); glPopMatrix(); } } }
void GLHelper::drawBoxLines(const PositionVector& geom, const std::vector<double>& rots, const std::vector<double>& lengths, const std::vector<RGBColor>& cols, double width, int cornerDetail, double offset) { int e = (int) geom.size() - 1; for (int i = 0; i < e; i++) { setColor(cols[i]); drawBoxLine(geom[i], rots[i], lengths[i], width, offset); } if (cornerDetail > 0) { for (int i = 1; i < e; i++) { glPushMatrix(); setColor(cols[i]); glTranslated(geom[i].x(), geom[i].y(), 0); drawFilledCircle(width, cornerDetail); glEnd(); glPopMatrix(); } } }
void GLHelper::drawCrossTies(const PositionVector& geom, const std::vector<double>& rots, const std::vector<double>& lengths, double length, double spacing, double halfWidth, bool drawForSelecting) { glPushMatrix(); // draw on top of of the white area between the rails glTranslated(0, 0, 0.1); int e = (int) geom.size() - 1; for (int i = 0; i < e; ++i) { glPushMatrix(); glTranslated(geom[i].x(), geom[i].y(), 0.0); glRotated(rots[i], 0, 0, 1); // draw crossing depending if isn't being drawn for selecting if (!drawForSelecting) { for (double t = 0; t < lengths[i]; t += spacing) { glBegin(GL_QUADS); glVertex2d(-halfWidth, -t); glVertex2d(-halfWidth, -t - length); glVertex2d(halfWidth, -t - length); glVertex2d(halfWidth, -t); glEnd(); } } else { // only draw a single rectangle if it's being drawn only for selecting glBegin(GL_QUADS); glVertex2d(-halfWidth, 0); glVertex2d(-halfWidth, -lengths.back()); glVertex2d(halfWidth, -lengths.back()); glVertex2d(halfWidth, 0); glEnd(); } // pop three draw matrix glPopMatrix(); } glPopMatrix(); }