| #include "roadnet/roadnet.h" |
| #include "utility/config.h" |
| #include "vehicle/vehicle.h" |
|
|
| #include "rapidjson/document.h" |
| #include "rapidjson/filereadstream.h" |
|
|
| #include <iostream> |
| #include <algorithm> |
|
|
| using std::map; |
| using std::string; |
|
|
| namespace CityFlow { |
| static double getLengthOfPoints(const std::vector<Point> &points); |
|
|
| static Point getPointByDistance(const std::vector<Point> &points, double dis) { |
| dis = min2double(max2double(dis, 0), getLengthOfPoints(points)); |
| if (dis <= 0.0) |
| return points[0]; |
| for (size_t i = 1; i < points.size(); i++) { |
| double len = (points[i - 1] - points[i]).len(); |
| if (dis > len) |
| dis -= len; |
| else |
| return points[i - 1] + (points[i] - points[i - 1]) * (dis / len); |
| } |
| return points.back(); |
| } |
|
|
| static double getLengthOfPoints(const std::vector<Point> &points) { |
| double length = 0.0; |
| for (size_t i = 0; i + 1 < points.size(); i++) |
| length += (points[i + 1] - points[i]).len(); |
| return length; |
| } |
|
|
| Point RoadNet::getPoint(const Point &p1, const Point &p2, double a) { |
| return Point((p2.x - p1.x) * a + p1.x, (p2.y - p1.y) * a + p1.y); |
| } |
|
|
| bool RoadNet::loadFromJson(std::string jsonFileName) { |
| rapidjson::Document document; |
| if (!readJsonFromFile(jsonFileName, document)) { |
| std::cerr << "cannot open roadnet file" << std::endl; |
| return false; |
| } |
| |
| std::list<std::string> path; |
| if (!document.IsObject()) |
| throw JsonTypeError("roadnet config file", "object"); |
| try { |
| const rapidjson::Value &interValues = getJsonMemberArray("intersections", document); |
| const rapidjson::Value &roadValues = getJsonMemberArray("roads", document); |
|
|
| |
| roads.resize(roadValues.Size()); |
| intersections.resize(interValues.Size()); |
| for (rapidjson::SizeType i = 0; i < roadValues.Size(); i++) { |
| path.emplace_back("road[" + std::to_string(i) + "]"); |
| std::string id = getJsonMember<const char*>("id", roadValues[i]); |
| roadMap[id] = &roads[i]; |
| roads[i].id = id; |
| path.pop_back(); |
| } |
| assert(path.empty()); |
|
|
| for (rapidjson::SizeType i = 0; i < interValues.Size(); i++) { |
| path.emplace_back("intersection[" + std::to_string(i) + "]"); |
| std::string id = getJsonMember<const char*>("id", interValues[i]);; |
| interMap[id] = &intersections[i]; |
| intersections[i].id = id; |
| path.pop_back(); |
| } |
| assert(path.empty()); |
|
|
| |
| path.emplace_back("roads"); |
| for (rapidjson::SizeType i = 0; i < roadValues.Size(); i++) { |
| |
| path.emplace_back(roads[i].getId()); |
| const auto &curRoadValue = roadValues[i]; |
| if (!curRoadValue.IsObject()) { |
| throw JsonTypeError("road[" + std::to_string(i) + "]", "object"); |
| } |
| roads[i].startIntersection = interMap[getJsonMember<const char*>("startIntersection", curRoadValue)]; |
| roads[i].endIntersection = interMap[getJsonMember<const char*>("endIntersection", curRoadValue)]; |
| |
| |
| if (!roads[i].startIntersection) throw JsonFormatError("startIntersection does not exist."); |
| if (!roads[i].endIntersection) throw JsonFormatError("endIntersection does not exist."); |
|
|
| |
| const auto &lanesValue = getJsonMemberArray("lanes", curRoadValue); |
| int laneIndex = 0; |
| for (const auto &laneValue : lanesValue.GetArray()) { |
| path.emplace_back("lane[" + std::to_string(laneIndex) + "]"); |
| if (!laneValue.IsObject()) |
| throw JsonTypeError("lane", "object"); |
| double width = getJsonMember<double>("width", laneValue); |
| double maxSpeed = getJsonMember<double>("maxSpeed", laneValue); |
| roads[i].lanes.emplace_back(width, maxSpeed, laneIndex, &roads[i]); |
| laneIndex++; |
| path.pop_back(); |
| } |
|
|
| for (auto &lane : roads[i].lanes) { |
| drivableMap[lane.getId()] = &lane; |
| } |
|
|
| |
| const auto &pointsValue = getJsonMemberArray("points", curRoadValue); |
| for (const auto &pointValue : pointsValue.GetArray()) { |
| path.emplace_back("point[" + std::to_string(roads[i].points.size()) + "]"); |
| if (!pointValue.IsObject()) |
| throw JsonTypeError("point of road", "object"); |
| double x = getJsonMember<double>("x", pointValue); |
| double y = getJsonMember<double>("y", pointValue); |
| roads[i].points.emplace_back(x, y); |
| path.pop_back(); |
| } |
| path.pop_back(); |
| } |
| path.pop_back(); |
| assert(path.empty()); |
|
|
| for (rapidjson::SizeType i = 0; i < roadValues.Size(); i++) { |
| roads[i].initLanesPoints(); |
| } |
|
|
| |
| std::map<std::string, RoadLinkType> typeMap = {{"turn_left", turn_left}, |
| {"turn_right", turn_right}, |
| {"go_straight", go_straight}}; |
| path.emplace_back("intersections"); |
| for (rapidjson::SizeType i = 0; i < interValues.Size(); i++) { |
| path.emplace_back(intersections[i].getId()); |
| const auto &curInterValue = interValues[i]; |
| if (!curInterValue.IsObject()) { |
| throw JsonTypeError("intersection", "object"); |
| return false; |
| } |
|
|
| |
| const auto &pointValue = getJsonMemberObject("point", curInterValue); |
| intersections[i].isVirtual = getJsonMember<bool>("virtual", curInterValue); |
| double x = getJsonMember<double>("x", pointValue); |
| double y = getJsonMember<double>("y", pointValue); |
| intersections[i].point = Point(x, y); |
|
|
| |
| const auto &roadsValue = getJsonMemberArray("roads", curInterValue); |
| for (auto &roadNameValue : roadsValue.GetArray()) { |
| path.emplace_back("roads[" + std::to_string(intersections[i].roads.size()) + "]"); |
| std::string roadName = roadNameValue.GetString(); |
| if (!roadMap.count(roadName)) |
| throw JsonFormatError("No such road: " + roadName); |
| intersections[i].roads.push_back(roadMap[roadName]); |
| path.pop_back(); |
| } |
|
|
| |
| intersections[i].trafficLight.intersection = &intersections[i]; |
| if (intersections[i].isVirtual) { |
| path.pop_back(); |
| continue; |
| } |
|
|
| |
| intersections[i].width = getJsonMember<double>("width", curInterValue); |
|
|
| |
| const auto &roadLinksValue = getJsonMemberArray("roadLinks", curInterValue); |
| intersections[i].roadLinks.resize(roadLinksValue.Size()); |
| int roadLinkIndex = 0; |
| for (const auto &roadLinkValue : roadLinksValue.GetArray()) { |
| path.emplace_back("roadLinks[" + std::to_string(roadLinkIndex) + "]"); |
| if (!roadLinkValue.IsObject()) |
| throw JsonTypeError("roadLink", "object"); |
| RoadLink &roadLink = intersections[i].roadLinks[roadLinkIndex]; |
| roadLink.index = roadLinkIndex++; |
| roadLink.type = typeMap[getJsonMember<const char*>("type", roadLinkValue)]; |
| roadLink.startRoad = roadMap[getJsonMember<const char*>("startRoad", roadLinkValue)]; |
| roadLink.endRoad = roadMap[getJsonMember<const char*>("endRoad", roadLinkValue)]; |
|
|
| const auto &laneLinksValue = getJsonMemberArray("laneLinks", roadLinkValue); |
| roadLink.laneLinks.resize(laneLinksValue.Size()); |
| int laneLinkIndex = 0; |
| for (const auto &laneLinkValue : laneLinksValue.GetArray()) { |
| path.emplace_back("laneLinks[" + std::to_string(laneLinkIndex) + "]"); |
| if (!laneLinkValue.IsObject()) |
| throw JsonTypeError("laneLink", "object"); |
| LaneLink &laneLink = roadLink.laneLinks[laneLinkIndex++]; |
|
|
| int startLaneIndex = getJsonMember<int>("startLaneIndex", laneLinkValue); |
| int endLaneIndex = getJsonMember<int>("endLaneIndex", laneLinkValue); |
| if (startLaneIndex >= static_cast<int>(roadLink.startRoad->lanes.size()) || startLaneIndex < 0) |
| throw JsonFormatError("startLaneIndex out of range"); |
| if (endLaneIndex >= static_cast<int>(roadLink.endRoad->lanes.size()) || endLaneIndex < 0) |
| throw JsonFormatError("startLaneIndex out of range"); |
| Lane *startLane = &roadLink.startRoad->lanes[startLaneIndex]; |
| Lane *endLane = &roadLink.endRoad->lanes[endLaneIndex]; |
|
|
| auto iter = laneLinkValue.FindMember("points"); |
| if (iter != laneLinkValue.MemberEnd() && !iter->value.IsArray()) |
| throw JsonTypeError("points in laneLink", "array"); |
| if (iter != laneLinkValue.MemberEnd() && !iter->value.Empty()) |
| for (const auto &pValue : iter->value.GetArray()) { |
| laneLink.points.emplace_back(getJsonMember<double>("x", pValue), |
| getJsonMember<double>("y", pValue)); |
| } |
| else { |
| Point start = Point(startLane->getPointByDistance( |
| startLane->getLength() - startLane->getEndIntersection()->width)); |
| Point end = Point( |
| endLane->getPointByDistance(0.0 + endLane->getStartIntersection()->width)); |
| double len = (Point(end.x - start.x, end.y - start.y)).len(); |
| Point startDirection = startLane->getDirectionByDistance( |
| startLane->getLength() - startLane->getEndIntersection()->width); |
| Point endDirection = endLane->getDirectionByDistance( |
| 0.0 + endLane->getStartIntersection()->width); |
| double minGap = 5; |
| double gap1X = startDirection.x * len * 0.5; |
| double gap1Y = startDirection.y * len * 0.5; |
| double gap2X = -endDirection.x * len * 0.5; |
| double gap2Y = -endDirection.y * len * 0.5; |
| if (gap1X * gap1X + gap1Y * gap1Y < 25 && startLane->getEndIntersection()->width >= 5) { |
| gap1X = minGap * startDirection.x; |
| gap1Y = minGap * startDirection.y; |
| } |
| if (gap2X * gap2X + gap2Y * gap2Y < 25 && endLane->getStartIntersection()->width >= 5) { |
| gap2X = minGap * endDirection.x; |
| gap2Y = minGap * endDirection.y; |
| } |
| Point mid1 = Point(start.x + gap1X,start.y + gap1Y); |
| Point mid2 = Point(end.x + gap2X,end.y + gap2Y); |
| int numPoints = 10; |
| for (int i = 0; i <= numPoints; i++) { |
| Point p1 = getPoint(start, mid1, i / double(numPoints)); |
| Point p2 = getPoint(mid1, mid2, i / double(numPoints)); |
| Point p3 = getPoint(mid2, end, i / double(numPoints)); |
| Point p4 = getPoint(p1, p2, i / double(numPoints)); |
| Point p5 = getPoint(p2, p3, i / double(numPoints)); |
| Point p6 = getPoint(p4, p5, i / double(numPoints)); |
| laneLink.points.emplace_back(p6.x, p6.y); |
| } |
| } |
| laneLink.roadLink = &roadLink; |
|
|
| laneLink.startLane = startLane; |
| laneLink.endLane = endLane; |
| laneLink.length = getLengthOfPoints(laneLink.points); |
| startLane->laneLinks.push_back(&laneLink); |
| drivableMap.emplace(laneLink.getId(), &laneLink); |
| path.pop_back(); |
| } |
| roadLink.intersection = &intersections[i]; |
| path.pop_back(); |
| } |
|
|
| |
| const auto &trafficLightValue = getJsonMemberObject("trafficLight", curInterValue); |
| path.emplace_back("trafficLight"); |
| const auto &lightPhasesValue = getJsonMemberArray("lightphases", trafficLightValue); |
| for (const auto &lightPhaseValue : lightPhasesValue.GetArray()) { |
| path.emplace_back("lightphases[" + std::to_string(intersections[i].trafficLight.phases.size()) + "]"); |
| if (!lightPhaseValue.IsObject()) |
| throw JsonTypeError("lightphase", "object"); |
| LightPhase lightPhase; |
| lightPhase.time = getJsonMember<double>("time", lightPhaseValue); |
| lightPhase.roadLinkAvailable = std::vector<bool>(intersections[i].roadLinks.size(), false); |
| const auto& availableRoadLinksValue = |
| getJsonMemberArray("availableRoadLinks", lightPhaseValue); |
| for (rapidjson::SizeType index = 0; index < availableRoadLinksValue.Size(); index++) { |
| path.emplace_back("availableRoadLinks[" + std::to_string(index) + "]"); |
| if (!availableRoadLinksValue[index].IsInt()) |
| throw JsonTypeError("availableRoadLink", "int"); |
| size_t indexInRoadLinks = availableRoadLinksValue[index].GetUint(); |
| if (indexInRoadLinks >= lightPhase.roadLinkAvailable.size()) |
| throw JsonFormatError("index out of range"); |
| lightPhase.roadLinkAvailable[indexInRoadLinks] = true; |
| path.pop_back(); |
| } |
| intersections[i].trafficLight.phases.push_back(lightPhase); |
| path.pop_back(); |
| } |
| path.pop_back(); |
| intersections[i].trafficLight.init(0); |
|
|
| path.pop_back(); |
| } |
| path.pop_back(); |
| assert(path.empty()); |
| }catch (const JsonFormatError &e) { |
| std::cerr << "Error occurred when reading the roadnet file: " << std::endl; |
| for (const auto &node : path) { |
| std::cerr << "/" << node; |
| } |
| std::cerr << " " << e.what() << std::endl; |
| return false; |
| } |
|
|
| for (auto &intersection : intersections) |
| intersection.initCrosses(); |
| VehicleInfo vehicleTemplate; |
|
|
| for (auto &road : roads) |
| road.initLanesPoints(); |
|
|
| for (auto &road : roads) { |
| road.buildSegmentationByInterval((vehicleTemplate.len + vehicleTemplate.minGap) * MAX_NUM_CARS_ON_SEGMENT); |
| } |
|
|
| for (auto &road : roads) { |
| auto &roadLanes = road.getLanePointers(); |
| lanes.insert(lanes.end(), roadLanes.begin(), roadLanes.end()); |
| drivables.insert(drivables.end(), roadLanes.begin(), roadLanes.end()); |
| } |
| for (auto &intersection : intersections) { |
| auto &intersectionLaneLinks = intersection.getLaneLinks(); |
| laneLinks.insert(laneLinks.end(), intersectionLaneLinks.begin(), intersectionLaneLinks.end()); |
| drivables.insert(drivables.end(), intersectionLaneLinks.begin(), intersectionLaneLinks.end()); |
| } |
| return true; |
| } |
|
|
| rapidjson::Value RoadNet::convertToJson(rapidjson::Document::AllocatorType &allocator) { |
| rapidjson::Value jsonRoot(rapidjson::kObjectType); |
| |
| rapidjson::Value jsonNodes(rapidjson::kArrayType); |
| for (size_t i = 0; i < intersections.size(); ++i) { |
| rapidjson::Value jsonNode(rapidjson::kObjectType), jsonPoint(rapidjson::kArrayType); |
| rapidjson::Value idValue; |
| idValue.SetString(rapidjson::StringRef(intersections[i].id.c_str())); |
| jsonNode.AddMember("id", idValue, allocator); |
| jsonPoint.PushBack(intersections[i].point.x, allocator); |
| jsonPoint.PushBack(intersections[i].point.y, allocator); |
| jsonNode.AddMember("point", jsonPoint, allocator); |
| jsonNode.AddMember("virtual", intersections[i].isVirtual, allocator); |
| if (!intersections[i].isVirtual) { |
| jsonNode.AddMember("width", intersections[i].width, allocator); |
| } |
|
|
| rapidjson::Value jsonOutline(rapidjson::kArrayType); |
| for (auto &point: intersections[i].getOutline()) { |
| jsonOutline.PushBack(point.x, allocator); |
| jsonOutline.PushBack(point.y, allocator); |
| } |
| jsonNode.AddMember("outline", jsonOutline, allocator); |
| jsonNodes.PushBack(jsonNode, allocator); |
| } |
| jsonRoot.AddMember("nodes", jsonNodes, allocator); |
|
|
| |
| rapidjson::Value jsonEdges(rapidjson::kArrayType); |
| for (size_t i = 0; i < roads.size(); ++i) { |
| rapidjson::Value jsonEdge(rapidjson::kObjectType); |
| rapidjson::Value jsonPoints(rapidjson::kArrayType); |
| rapidjson::Value jsonLaneWidths(rapidjson::kArrayType); |
| rapidjson::Value jsonDirs(rapidjson::kArrayType); |
|
|
| rapidjson::Value idValue; |
| idValue.SetString(rapidjson::StringRef(roads[i].id.c_str())); |
| jsonEdge.AddMember("id", idValue, allocator); |
| rapidjson::Value startValue; |
| if (roads[i].startIntersection) |
| startValue.SetString(rapidjson::StringRef(roads[i].startIntersection->id.c_str())); |
| else |
| startValue.SetString("null"); |
| jsonEdge.AddMember("from", startValue, allocator); |
|
|
| rapidjson::Value endValue; |
| if (roads[i].endIntersection) |
| endValue.SetString(rapidjson::StringRef(roads[i].endIntersection->id.c_str())); |
| else |
| endValue.SetString("null"); |
| jsonEdge.AddMember("to", endValue, allocator); |
| for (size_t j = 0; j < roads[i].points.size(); ++j) { |
| rapidjson::Value jsonPoint(rapidjson::kArrayType); |
| jsonPoint.PushBack(roads[i].points[j].x, allocator); |
| jsonPoint.PushBack(roads[i].points[j].y, allocator); |
| jsonPoints.PushBack(jsonPoint, allocator); |
| } |
| jsonEdge.AddMember("points", jsonPoints, allocator); |
| jsonEdge.AddMember("nLane", static_cast<int>(roads[i].lanes.size()), allocator); |
| for (size_t j = 0; j < roads[i].lanes.size(); ++j) { |
| jsonLaneWidths.PushBack(roads[i].lanes[j].width, allocator); |
| } |
| jsonEdge.AddMember("laneWidths", jsonLaneWidths, allocator); |
| jsonEdges.PushBack(jsonEdge, allocator); |
| } |
| jsonRoot.AddMember("edges", jsonEdges, allocator); |
| return jsonRoot; |
| } |
|
|
| Point Drivable::getPointByDistance(double dis) const { |
| return CityFlow::getPointByDistance(points, dis); |
| } |
|
|
| Point Drivable::getDirectionByDistance(double dis) const { |
| double remain = dis; |
| for (int i = 0; i + 1 < (int) points.size(); i++) { |
| double len = (points[i + 1] - points[i]).len(); |
| if (remain < len) |
| return (points[i + 1] - points[i]).unit(); |
| else |
| remain -= len; |
| } |
| return (points[points.size() - 1] - points[points.size() - 2]).unit(); |
| } |
|
|
| Lane::Lane() { |
| width = 0; |
| maxSpeed = 0; |
| laneIndex = -1; |
| belongRoad = 0; |
| drivableType = LANE; |
| } |
|
|
| Lane::Lane(double width, double maxSpeed, int laneIndex, Road *belongRoad) { |
| this->width = width; |
| this->maxSpeed = maxSpeed; |
| this->laneIndex = laneIndex; |
| this->belongRoad = belongRoad; |
| drivableType = LANE; |
| } |
|
|
| bool Lane::available(const Vehicle *vehicle) const { |
| if (!vehicles.empty()) { |
| Vehicle *tail = vehicles.back(); |
| return tail->getDistance() > tail->getLen() + vehicle->getMinGap(); |
| } else { |
| return true; |
| } |
| } |
|
|
| bool Lane::canEnter(const Vehicle *vehicle) const { |
| if (!vehicles.empty()) { |
| Vehicle *tail = vehicles.back(); |
| return tail->getDistance() > tail->getLen() + vehicle->getLen() || |
| tail->getSpeed() >= 2; |
| } else { |
| return true; |
| } |
| } |
|
|
| std::vector<LaneLink *> Lane::getLaneLinksToRoad(const Road *road) const { |
| std::vector<LaneLink *> ret; |
| for (auto &laneLink : laneLinks) { |
| if (laneLink->getEndLane()->getBelongRoad() == road) |
| ret.push_back(laneLink); |
| } |
| return ret; |
| } |
|
|
| void Road::initLanesPoints() { |
| double dsum = 0.0; |
| std::vector<Point> roadPoints = this->points; |
|
|
| assert(roadPoints.size() >= 2); |
|
|
| if (!startIntersection->isVirtualIntersection()) { |
| double width = startIntersection->width; |
| Point p1 = roadPoints[0]; |
| Point p2 = roadPoints[1]; |
| roadPoints[0] = p1 + (p2 - p1).unit() * width; |
| } |
|
|
| if (!endIntersection->isVirtualIntersection()) { |
| double width = endIntersection->width; |
| Point p1 = roadPoints[roadPoints.size() - 2]; |
| Point p2 = roadPoints[roadPoints.size() - 1]; |
| roadPoints[roadPoints.size() - 1] = p2 - (p2 - p1).unit() * width; |
| } |
|
|
| for (Lane &lane : lanes) { |
| double dmin = dsum; |
| double dmax = dsum + lane.width; |
| lane.points.clear(); |
| for (int j = 0; j < (int) roadPoints.size(); j++) { |
| |
| std::vector<Point> &lanePoints = lane.points; |
| if (j == 0) { |
| Vector u = (roadPoints[1] - roadPoints[0]).unit(); |
| Vector v = -u.normal(); |
| Point startPoint = roadPoints[j] + v * ((dmin + dmax) / 2.0); |
| lanePoints.push_back(startPoint); |
| } else if (j + 1 == (int) roadPoints.size()) { |
| Vector u = (roadPoints[j] - roadPoints[j - 1]).unit(); |
| Vector v = -u.normal(); |
| Point endPoint = roadPoints[j] + v * ((dmin + dmax) / 2.0); |
| lanePoints.push_back(endPoint); |
| } else { |
| Vector u1 = (roadPoints[j + 1] - roadPoints[j]).unit(); |
| Vector u2 = (roadPoints[j] - roadPoints[j - 1]).unit(); |
| Vector u = (u1 + u2).unit(); |
| Vector v = -u.normal(); |
| Point interPoint = roadPoints[j] + v * ((dmin + dmax) / 2.0); |
| lanePoints.push_back(interPoint); |
| } |
| } |
| lane.length = getLengthOfPoints(lane.points); |
| dsum += lane.width; |
| } |
| } |
|
|
| const std::vector<Lane *> &Road::getLanePointers() { |
| if (lanePointers.size()) return lanePointers; |
| for (auto &lane : lanes) { |
| lanePointers.push_back(&lane); |
| } |
| return lanePointers; |
| } |
|
|
| void Intersection::initCrosses() { |
| std::vector<LaneLink *> allLaneLinks; |
| for (auto &roadLink : roadLinks) { |
| for (auto &laneLink : roadLink.getLaneLinks()) |
| allLaneLinks.push_back(&laneLink); |
| } |
| int n = (int) allLaneLinks.size(); |
|
|
| for (int i = 0; i < n; i++) { |
| for (int j = i + 1; j < n; j++) { |
| LaneLink *la = allLaneLinks[i]; |
| LaneLink *lb = allLaneLinks[j]; |
| std::vector<Point> &va = la->points; |
| std::vector<Point> &vb = lb->points; |
| double disa = 0.0; |
| for (int ia = 0; ia + 1 < (int) va.size(); ia++) { |
| double disb = 0.0; |
| for (int ib = 0; ib + 1 < (int) vb.size(); ib++) { |
| Point A1 = va[ia], A2 = va[ia + 1]; |
| Point B1 = vb[ib], B2 = vb[ib + 1]; |
| if (Point::sign(crossMultiply(A2 - A1, B2 - B1)) == 0) continue; |
| Point P = calcIntersectPoint(A1, A2, B1, B2); |
| if (onSegment(A1, A2, P) && onSegment(B1, B2, P)) { |
| Cross cross; |
| cross.laneLinks[0] = la; |
| cross.laneLinks[1] = lb; |
| cross.notifyVehicles[0] = nullptr; |
| cross.notifyVehicles[1] = nullptr; |
| cross.distanceOnLane[0] = disa + (P - A1).len(); |
| cross.distanceOnLane[1] = disb + (P - B1).len(); |
| cross.ang = calcAng(A2 - A1, B2 - B1); |
| |
| double w1 = la->getWidth(); |
| double w2 = lb->getWidth(); |
| double c1 = w1 / sin(cross.ang); |
| double c2 = w2 / sin(cross.ang); |
| double diag = (c1 * c1 + c2 * c2 + 2 * c1 * c2 * cos(cross.ang)) / 4; |
| cross.safeDistances[0] = sqrt(diag - w2 * w2 / 4); |
| cross.safeDistances[1] = sqrt(diag - w1 * w1 / 4); |
| this->crosses.push_back(cross); |
| goto FOUND; |
| } |
| disb += (vb[ib + 1] - vb[ib]).len(); |
| } |
| disa += (va[ia + 1] - va[ia]).len(); |
| } |
| FOUND:; |
| } |
| } |
| for (Cross &cross : this->crosses) { |
| cross.laneLinks[0]->getCrosses().push_back(&cross); |
| cross.laneLinks[1]->getCrosses().push_back(&cross); |
| } |
| for (auto laneLink : allLaneLinks) { |
| std::vector<Cross *> &crosses = laneLink->getCrosses(); |
| sort(crosses.begin(), crosses.end(), [laneLink](Cross *ca, Cross *cb) -> bool { |
| double da = ca->distanceOnLane[ca->laneLinks[0] != laneLink]; |
| double db = cb->distanceOnLane[cb->laneLinks[0] != laneLink]; |
| return da < db; |
| }); |
| } |
| } |
|
|
| const std::vector<LaneLink *> &Intersection::getLaneLinks() { |
| if (laneLinks.size() > 0) return laneLinks; |
| for (auto &roadLink : roadLinks) { |
| auto &roadLaneLinks = roadLink.getLaneLinkPointers(); |
| laneLinks.insert(laneLinks.end(), roadLaneLinks.begin(), roadLaneLinks.end()); |
| } |
| return laneLinks; |
| } |
|
|
| const std::vector<LaneLink *> &RoadLink::getLaneLinkPointers() { |
| if (laneLinkPointers.size() > 0) return laneLinkPointers; |
| for (auto &laneLink : laneLinks) { |
| laneLinkPointers.push_back(&laneLink); |
| } |
| return laneLinkPointers; |
| } |
|
|
| void Cross::notify(LaneLink *laneLink, Vehicle *vehicle, double notifyDistance) { |
| assert(laneLink == laneLinks[0] || laneLink == laneLinks[1]); |
| int i = (laneLink == laneLinks[0]) ? 0 : 1; |
| assert(notifyVehicles[i] == nullptr); |
| notifyVehicles[i] = vehicle; |
| notifyDistances[i] = notifyDistance; |
| } |
|
|
| bool Cross::canPass(const Vehicle *vehicle, const LaneLink *laneLink, double distanceToLaneLinkStart) const { |
| |
| assert(laneLink == laneLinks[0] || laneLink == laneLinks[1]); |
| int i = (laneLink == laneLinks[0]) ? 0 : 1; |
|
|
| Vehicle *foeVehicle = notifyVehicles[1 - i]; |
| RoadLinkType t1 = laneLinks[i]->getRoadLinkType(); |
| RoadLinkType t2 = laneLinks[1 - i]->getRoadLinkType(); |
| double d1 = distanceOnLane[i] - distanceToLaneLinkStart, d2 = notifyDistances[1 - i]; |
|
|
| if (foeVehicle == nullptr) return true; |
|
|
| if (!vehicle->canYield(d1)) return true; |
|
|
| int yield = 0; |
| if (!foeVehicle->canYield(d2)) yield = 1; |
|
|
| if (yield == 0) { |
| if (t1 > t2) { |
| yield = -1; |
| } else if (t1 < t2) { |
| if (d2 > 0) { |
| |
| int foeVehicleReachSteps = foeVehicle->getReachStepsOnLaneLink(d2, laneLinks[1 - i]); |
| int reachSteps = vehicle->getReachStepsOnLaneLink(d1, laneLinks[i]); |
| if (foeVehicleReachSteps > reachSteps) { |
| yield = -1; |
| } |
| } else { |
| if (d2 + foeVehicle->getLen() < 0) { |
| yield = -1; |
| } |
| } |
| if (yield == 0) yield = 1; |
| } else { |
| if (d2 > 0) { |
| int foeVehicleReachSteps = foeVehicle->getReachStepsOnLaneLink(d2, laneLinks[1 - i]); |
| int reachSteps = vehicle->getReachStepsOnLaneLink(d1, laneLinks[i]); |
| if (foeVehicleReachSteps > reachSteps) { |
| yield = -1; |
| } else if (foeVehicleReachSteps < reachSteps) { |
| yield = 1; |
| } else { |
| if (vehicle->getEnterLaneLinkTime() == foeVehicle->getEnterLaneLinkTime()) { |
| if (d1 == d2) { |
| yield = vehicle->getPriority() > foeVehicle->getPriority() ? -1 : 1; |
| } else { |
| yield = d1 < d2 ? -1 : 1; |
| } |
| } else { |
| yield = vehicle->getEnterLaneLinkTime() < foeVehicle->getEnterLaneLinkTime() ? -1 : 1; |
| } |
| } |
| } else { |
| yield = d2 + foeVehicle->getLen() < 0 ? -1 : 1; |
| } |
| } |
| } |
| assert(yield != 0); |
| if (yield == 1) { |
| Vehicle *fastPointer = foeVehicle; |
| Vehicle *slowPointer = foeVehicle; |
| while (fastPointer != nullptr && fastPointer->getBlocker() != nullptr) { |
| slowPointer = slowPointer->getBlocker(); |
| fastPointer = fastPointer->getBlocker()->getBlocker(); |
| if (slowPointer == fastPointer) { |
| |
| yield = -1; |
| break; |
| } |
| } |
| } |
| return yield == -1; |
| } |
|
|
| void RoadNet::reset() { |
| for (auto &road : roads) road.reset(); |
| for (auto &intersection : intersections) intersection.reset(); |
| } |
|
|
| void Road::reset() { |
| for (auto &lane : lanes) lane.reset(); |
| } |
|
|
| void Road::buildSegmentationByInterval(double interval) { |
| size_t numSegs = std::max((size_t) ceil(getLengthOfPoints(this->points) / interval), (size_t) 1); |
| for (Lane &lane : lanes) |
| lane.buildSegmentation(numSegs); |
| } |
|
|
| double Road::getWidth() const{ |
| double width = 0; |
| for (const auto &lane : getLanes()){ |
| width += lane.getWidth(); |
| } |
| return width; |
| } |
|
|
| double Road::getLength() const{ |
| double length = 0; |
| for (const auto &lane : getLanes()){ |
| length += lane.getLength(); |
| } |
| return length; |
| } |
|
|
| double Road::averageLength() const{ |
| double sum = 0; |
| size_t laneNum = getLanes().size(); |
| if (laneNum == 0) return 0; |
| for (const auto &lane : getLanes()){ |
| sum += lane.getLength(); |
| } |
| return sum / laneNum; |
| } |
|
|
| double Road::getAverageSpeed() const{ |
| int vehicleNum = 0; |
| double speedSum = 0; |
| for (const auto &lane : lanes) { |
| vehicleNum += lane.getHistoryVehicleNum(); |
| speedSum += lane.getHistoryAverageSpeed() * lane.getHistoryVehicleNum(); |
| } |
| return vehicleNum ? speedSum / vehicleNum : -1; |
| |
| } |
|
|
| double Road::getAverageDuration() const{ |
| double averageSpeed = getAverageSpeed(); |
| if (averageSpeed < 0) return -1; |
| return averageLength() / averageSpeed; |
| } |
|
|
| bool Road::connectedToRoad(const Road *road) const{ |
| for (const auto &lane : getLanes()) { |
| if (lane.getLaneLinksToRoad(road).size()) |
| return true; |
| } |
| return false; |
| } |
|
|
| void Intersection::reset() { |
| trafficLight.reset(); |
| for (auto &roadLink : roadLinks) roadLink.reset(); |
| for (auto &cross : crosses) cross.reset(); |
| } |
|
|
| std::vector<Point> Intersection::getOutline() { |
| |
| std::vector<Point> points; |
| points.push_back(getPosition()); |
| for (auto road : getRoads()){ |
| Vector roadDirect = road->getEndIntersection().getPosition() - road->getStartIntersection().getPosition(); |
| roadDirect = roadDirect.unit(); |
| Vector pDirect = roadDirect.normal(); |
| if (&road->getStartIntersection() == this) { |
| roadDirect = -roadDirect; |
| } |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| double roadWidth = road->getWidth(); |
| double deltaWidth = 0.5 * min2double(width, roadWidth); |
| deltaWidth = max2double(deltaWidth, 5); |
|
|
| Point pointA = getPosition() - roadDirect * width; |
| Point pointB = pointA - pDirect * roadWidth; |
| points.push_back(pointA); |
| points.push_back(pointB); |
|
|
| if (deltaWidth < road->averageLength()) { |
| Point pointA1 = pointA - roadDirect * deltaWidth; |
| Point pointB1 = pointB - roadDirect * deltaWidth; |
| points.push_back(pointA1); |
| points.push_back(pointB1); |
| } |
| } |
|
|
| auto minIter = std::min_element(points.begin(), points.end(), |
| [](const Point &a, const Point &b){ return a.y < b.y; }); |
|
|
| Point p0 = *minIter; |
| std::vector<Point> stack; |
| stack.push_back(p0); |
| points.erase(minIter); |
|
|
| std::sort(points.begin(), points.end(), |
| [&p0](const Point &a, const Point &b) |
| {return (a - p0).ang() < (b - p0).ang(); }); |
|
|
| for (size_t i = 0 ; i < points.size(); ++i) { |
| Point &point = points[i]; |
| Point p2 = stack[stack.size() - 1]; |
| if (stack.size() < 2) { |
| if (point.x != p2.x || point.y != p2.y) |
| stack.emplace_back(point); |
| continue; |
| } |
| Point p1 = stack[stack.size() - 2]; |
|
|
| while (stack.size() > 1 && crossMultiply(point - p2, p2 - p1) >= 0) { |
| p2 = p1; |
| stack.pop_back(); |
| if (stack.size() > 1) p1 = stack[stack.size() - 2]; |
| } |
| stack.emplace_back(point); |
| } |
|
|
| return stack; |
| } |
|
|
| bool Intersection::isImplicitIntersection() { |
| return trafficLight.getPhases().size() <= 1; |
| } |
|
|
| void RoadLink::reset() { |
| for (auto &laneLink : laneLinks) laneLink.reset(); |
| } |
|
|
| void LaneLink::reset() { |
| vehicles.clear(); |
| } |
|
|
| void Lane::reset() { |
| waitingBuffer.clear(); |
| vehicles.clear(); |
| } |
|
|
| std::vector<Vehicle *> Lane::getVehiclesBeforeDistance(double dis, size_t segmentIndex, double deltaDis) { |
| std::vector<Vehicle *> ret; |
| for (int i = segmentIndex; i >=0 ;i--) { |
| Segment * segment = getSegment(i); |
| auto &vehicles = segment->getVehicles(); |
| for(auto it = vehicles.begin(); it != vehicles.end(); ++it) { |
| Vehicle *vehicle = *(*it); |
| if (vehicle->getDistance() < dis - deltaDis) return ret; |
| if (vehicle->getDistance() < dis) ret.emplace_back(vehicle); |
| } |
| } |
| return ret; |
| } |
|
|
|
|
| void Lane::buildSegmentation(size_t numSegs) { |
| this->segments.resize((unsigned) numSegs); |
| for (size_t i = 0; i < numSegs; i++) { |
| segments[i].index = i; |
| segments[i].vehicles.clear(); |
| segments[i].belongLane = this; |
| segments[i].startPos = i * this->length / numSegs; |
| segments[i].endPos = (i + 1) * this->length / numSegs; |
| } |
| } |
|
|
| void Lane::initSegments() { |
| auto iter = this->vehicles.begin(); |
| auto end = this->vehicles.end(); |
| for (int i = (int) segments.size() - 1; i >= 0; i--) { |
| Segment &seg = segments[i]; |
| seg.vehicles.clear(); |
| while (iter != end && (*iter)->getDistance() >= seg.getStartPos()) { |
| seg.vehicles.push_back(iter); |
| (*iter)->setSegmentIndex(seg.index); |
| ++iter; |
| } |
| } |
| } |
|
|
| Vehicle *Lane::getVehicleBeforeDistance(double dis, size_t segmentIndex) const{ |
| for (int i = segmentIndex ; i >= 0 ; --i){ |
| auto vehs = getSegment(i)->getVehicles(); |
| for (auto itr = vehs.begin() ; itr != vehs.end(); ++itr){ |
| auto &vehicle = **itr; |
| if (vehicle->getDistance() < dis) return **itr; |
| } |
| } |
|
|
| return nullptr; |
| } |
|
|
| Vehicle *Lane::getVehicleAfterDistance(double dis, size_t segmentIndex) const{ |
| for (size_t i = segmentIndex ; i < getSegmentNum() ; ++i){ |
| auto vehs = getSegment(i)->getVehicles(); |
| for (auto itr = vehs.rbegin() ; itr != vehs.rend(); ++itr){ |
| auto &vehicle = **itr; |
| if (vehicle->getDistance() >= dis) return **itr; |
| } |
| } |
| return nullptr; |
| } |
|
|
| void Lane::updateHistory() { |
| double speedSum = historyVehicleNum * historyAverageSpeed; |
| while (history.size() > historyLen){ |
| historyVehicleNum -= history.front().vehicleNum; |
| speedSum -= history.front().vehicleNum * history.front().averageSpeed; |
| history.pop_front(); |
| } |
| double curSpeedSum = 0; |
| int vehicleNum = getVehicles().size(); |
| historyVehicleNum += vehicleNum; |
| for (auto vehicle : getVehicles()) |
| curSpeedSum += vehicle->getSpeed(); |
| speedSum += curSpeedSum; |
| history.emplace_back(vehicleNum, vehicleNum ? curSpeedSum / vehicleNum : 0); |
| historyAverageSpeed = historyVehicleNum ? speedSum / historyVehicleNum : 0; |
| } |
|
|
| int Lane::getHistoryVehicleNum() const{ |
| return historyVehicleNum; |
| } |
|
|
| double Lane::getHistoryAverageSpeed() const{ |
| return historyAverageSpeed; |
| } |
|
|
| void Cross::reset() { } |
|
|
| std::list<Vehicle *>::iterator Segment::findVehicle(Vehicle *vehicle) { |
| for (auto itr = vehicles.begin() ; itr != vehicles.end() ; ++itr) |
| if (**itr == vehicle) { |
| return *itr; |
| } |
| return belongLane->getVehicles().end(); |
| } |
|
|
| void Segment::removeVehicle(Vehicle *vehicle) { |
| for (auto itr = vehicles.begin() ; itr != vehicles.end() ; ++itr) |
| if (**itr == vehicle) { |
| vehicles.erase(itr); |
| return; |
| } |
| } |
|
|
| void Segment::insertVehicle(std::list<Vehicle *>::iterator &vehicle) { |
| auto itr = vehicles.begin(); |
| for (; itr != vehicles.end() && (**itr)->getDistance() > (*vehicle)->getDistance() ; ++itr); |
| vehicles.insert(itr, vehicle); |
| } |
|
|
| } |
|
|
|
|