载入中...
搜索中...
未找到
RoadNetwork.cpp
浏览该文件的文档.
16bool finite3(float x, float y, float z) { return std::isfinite(x) && std::isfinite(y) && std::isfinite(z); }
60 return a.inEdge == b.inEdge && a.inLane == b.inLane && a.outEdge == b.outEdge && a.outLane == b.outLane &&
107 auto turn = network.addLaneLink({incoming.value(), 0, outgoing.value(), 0, RoadLaneDirection::Forward,
132 auto incoming = network.addEdge(stem.value(), hub.value(), {P(0.f, 0.f, 24.f), P(0.f, 0.f, 0.f)}, lanes,
150 DiagnosticCode::InvalidArgument, "lanes in [1,4] required", curved ? "curve-uphill" : "sloped-t"));
162 curved ? std::vector<RoadControlPoint>{P(-22.f, 0.f, 12.f), P(-13.f, 1.4f, 14.f), P(-6.f, 3.f, 7.f),
166 curved ? std::vector<RoadControlPoint>{P(-20.f, 7.f, -14.f), P(-12.f, 6.4f, -16.f), P(-5.f, 5.f, -7.f),
171 auto exitEdge = network.addEdge(hub.value(), exit.value(), {P(0.f, 4.f, 0.f), P(24.f, 4.f, 0.f)},
186 if (!std::isfinite(style.speedLimitMps) || style.speedLimitMps <= 0.f || style.speedLimitMps > 200.f ||
222 DiagnosticCode::InvalidArgument, "node requires finite position and positive junctionRadius", "node"));
231 if (node.id == 0 || node.id == std::numeric_limits<std::uint32_t>::max() || findNodeIndex(node.id) >= 0)
233 Diagnostic::error(DiagnosticCode::AlreadyExists, "node id must be non-zero and unused", "node.id"));
234 if (!finite3(node.x, node.y, node.z) || !std::isfinite(node.junctionRadius) || node.junctionRadius <= 0.f)
236 DiagnosticCode::InvalidArgument, "node requires finite position and positive junctionRadius", "node"));
239 DiagnosticCode::InvalidArgument, "node junction control is outside supported bounds", "node.junctionControl"));
252 Diagnostic::error(DiagnosticCode::NotFound, "edge endpoints must reference live nodes", "edge"));
258 Diagnostic::error(DiagnosticCode::InvalidArgument, "edge needs at least two control points", "edge"));
278 DiagnosticCode::PreconditionViolation, "edge centerline must contain a non-degenerate segment", "edge"));
296 if (edge.id == 0 || edge.id == std::numeric_limits<std::uint32_t>::max() || findEdgeIndex(edge.id) >= 0)
298 Diagnostic::error(DiagnosticCode::AlreadyExists, "edge id must be non-zero and unused", "edge.id"));
301 Diagnostic::error(DiagnosticCode::NotFound, "edge endpoints must reference live nodes", "edge"));
304 Diagnostic::error(DiagnosticCode::PreconditionViolation, "edge endpoints must be distinct", "edge"));
307 Diagnostic::error(DiagnosticCode::InvalidArgument, "edge needs at least two control points", "edge"));
323 DiagnosticCode::PreconditionViolation, "edge centerline must contain a non-degenerate segment", "edge"));
416 return Result<int>::failure(Diagnostic::error(DiagnosticCode::NotFound, "unknown node", "nodeId"));
419 constexpr RoadLaneDirection directions[] = {RoadLaneDirection::Forward, RoadLaneDirection::Backward};
445 std::any_of(candidate.laneLinks_.begin(), candidate.laneLinks_.end(), [&](const auto& current) {
469 if (!finite3(node.x, node.y, node.z) || !std::isfinite(node.junctionRadius) || node.junctionRadius <= 0.f ||
479 Diagnostic::error(DiagnosticCode::InvariantViolation, "edge references a missing node", "edge"));
485 Diagnostic::error(DiagnosticCode::InvariantViolation, "edge has fewer than two samples", "edge"));
506 if (laneEntryNode(inEdge, link.inDirection) != laneExitNode(outEdge, link.outDirection) || link.inLane < 0 ||
522 if (idx < 0) return Result<void>::failure(Diagnostic::error(DiagnosticCode::NotFound, "unknown edge", "edgeId"));
535 if (index < 0) return Result<void>::failure(Diagnostic::error(DiagnosticCode::NotFound, "unknown node", "nodeId"));
538 Diagnostic::error(DiagnosticCode::InvalidArgument, "node position must be finite", "position"));
560 DiagnosticCode::InvariantViolation, "lane link is both active and blocked", "blockedLaneLink"));
577 if (index < 0) return Result<void>::failure(Diagnostic::error(DiagnosticCode::NotFound, "unknown node", "nodeId"));
580 DiagnosticCode::InvalidArgument, "junction radius must be finite and positive", "junctionRadius"));
588Result<void> RoadNetwork::setNodeJunctionControl(std::uint32_t nodeId, RoadJunctionControl control) {
590 if (index < 0) return Result<void>::failure(Diagnostic::error(DiagnosticCode::NotFound, "unknown node", "nodeId"));
593 DiagnosticCode::InvalidArgument, "junction control is outside supported bounds", "junctionControl"));
601Result<int> RoadNetwork::mergeNodes(std::uint32_t keepNodeId, std::uint32_t removeNodeId, float maxDistance) {
604 Diagnostic::error(DiagnosticCode::InvalidArgument, "merge nodes must be distinct", "removeNodeId"));
611 Diagnostic::error(DiagnosticCode::InvalidArgument, "merge distance must be finite and non-negative",
624 DiagnosticCode::PreconditionViolation, "merging nodes would create a self-loop edge", "removeNodeId"));
651Result<void> RoadNetwork::setEdgeControlPoints(std::uint32_t edgeId, std::vector<RoadControlPoint> controlPoints) {
653 if (index < 0) return Result<void>::failure(Diagnostic::error(DiagnosticCode::NotFound, "unknown edge", "edgeId"));
656 Diagnostic::error(DiagnosticCode::InvalidArgument, "edge needs at least two control points", "points"));
670 DiagnosticCode::PreconditionViolation, "edge centerline must contain a non-degenerate segment", "points"));
676Result<int> RoadNetwork::setEdgeLaneCounts(std::uint32_t edgeId, int lanesForward, int lanesBackward) {
678 if (idx < 0) return Result<int>::failure(Diagnostic::error(DiagnosticCode::NotFound, "unknown edge", "edgeId"));
679 auto profile = makeRoadProfile(edges_[static_cast<std::size_t>(idx)].style, lanesForward, lanesBackward);
691 candidate.laneLinks_.erase(std::remove_if(candidate.laneLinks_.begin(), candidate.laneLinks_.end(), invalid),
694 std::remove_if(candidate.blockedLaneLinks_.begin(), candidate.blockedLaneLinks_.end(), invalid),
706 if (index < 0) return Result<void>::failure(Diagnostic::error(DiagnosticCode::NotFound, "unknown edge", "edgeId"));
715 return direction == RoadLaneDirection::Forward ? RoadLaneDirection::Backward : RoadLaneDirection::Forward;
737 return Result<int>::failure(Diagnostic::error(DiagnosticCode::NotFound, "unknown edge", "edgeId"));
739 return Result<int>::failure(Diagnostic::error(DiagnosticCode::NotFound, "unknown node", "nodeId"));
745 DiagnosticCode::PreconditionViolation, "edge endpoint reconnect would create a self-loop", "nodeId"));
789 const auto incidentCount = std::count_if(edges_.begin(), edges_.end(), [&](const RoadEdge& candidate) {
799 Diagnostic::error(DiagnosticCode::InvariantViolation, "edge endpoint node is missing", "edgeId"));
821Result<RoadEdgeSplitResult> RoadNetwork::splitEdge(std::uint32_t edgeId, std::size_t controlPointIndex,
826Result<RoadEdgeSplitResult> RoadNetwork::splitEdgeAtSplineParameter(std::uint32_t edgeId, float parameter,
867Result<RoadEdgeSplitResult> RoadNetwork::splitEdge(std::uint32_t edgeId, std::size_t controlPointIndex,
877 DiagnosticCode::InvalidArgument, "edge split requires an interior control point", "controlPointIndex"));
880 Diagnostic::error(DiagnosticCode::InvalidArgument, "edge split radius must be positive", "junctionRadius"));
890 auto node = candidate.restoreNode({insertedNodeId, splitPoint.x, splitPoint.y, splitPoint.z, junctionRadius});
903 auto second = candidate.addEdge(insertedNodeId, original.to, std::move(continuation), original.lanesForward,
908 auto second = candidate.restoreEdge({continuationEdgeId, insertedNodeId, original.to, std::move(continuation),
929 {edgeId, lane, continuationEdgeId, lane, RoadLaneDirection::Forward, RoadLaneDirection::Forward});
934 {continuationEdgeId, lane, edgeId, lane, RoadLaneDirection::Backward, RoadLaneDirection::Backward});
945Result<RoadEdgeSplitResult> RoadNetwork::splitEdgeAtPosition(std::uint32_t edgeId, RoadControlPoint position,
950Result<RoadEdgeSplitResult> RoadNetwork::splitEdgeAtPosition(std::uint32_t edgeId, RoadControlPoint position,
957 if (!finite3(position.x, position.y, position.z) || !std::isfinite(maxDistance) || maxDistance < 0.f)
959 DiagnosticCode::InvalidArgument, "split position and snap distance must be finite", "position"));
983 const float px = position.x - projected.x, py = position.y - projected.y, pz = position.z - projected.z;
995 DiagnosticCode::PreconditionViolation, "position is outside the road snap distance", "maxDistance"));
1001 return splitEdgeAtSplineParameter(edgeId, bestParameter, junctionRadius, nodeId, secondEdgeId);
1006 if (index < 0) return Result<void>::failure(Diagnostic::error(DiagnosticCode::NotFound, "unknown edge", "edgeId"));
1024 if (index < 0) return Result<void>::failure(Diagnostic::error(DiagnosticCode::NotFound, "unknown node", "nodeId"));
1028 Diagnostic::error(DiagnosticCode::PreconditionViolation, "node must be isolated before removal", "nodeId"));
1050 if (idx < 0) return Result<RoadNode>::failure(Diagnostic::error(DiagnosticCode::NotFound, "unknown node", "id"));
1056 if (idx < 0) return Result<RoadEdge>::failure(Diagnostic::error(DiagnosticCode::NotFound, "unknown edge", "id"));
1063 Diagnostic::error(DiagnosticCode::InvalidArgument, "length>=8, lanes in [1,4] required", "straight"));
1079 Diagnostic::error(DiagnosticCode::InvalidArgument, "radius>=8, lanes in [1,4] required", "curve"));
1094 if (!std::isfinite(length) || length < 12.f || !std::isfinite(height) || height < 2.f || lanes < 1 || lanes > 4)
1115 Diagnostic::error(DiagnosticCode::InvalidArgument, "span>=16, lanes in [1,4] required", "cross"));
1138 auto e1 = network.addEdge(nN.value(), nC.value(), {P(0.f, 0.f, -half), P(0.f, 0.f, 0.f)}, lanes, 0, style);
1139 auto e2 = network.addEdge(nC.value(), nS.value(), {P(0.f, 0.f, 0.f), P(0.f, 0.f, half)}, lanes, 0, style);
1140 auto e3 = network.addEdge(nW.value(), nC.value(), {P(-half, 0.f, 0.f), P(0.f, 0.f, 0.f)}, lanes, 0, style);
1141 auto e4 = network.addEdge(nC.value(), nE.value(), {P(0.f, 0.f, 0.f), P(half, 0.f, 0.f)}, lanes, 0, style);
1153 Diagnostic::error(DiagnosticCode::InvalidArgument, "span>=16, lanes in [1,4] required", "tee"));
1192Result<RoadNetwork> RoadNetwork::makeFan(float span, int lanes, std::vector<float> armAnglesDeg,
1196 Diagnostic::error(DiagnosticCode::InvalidArgument, "span>=16, lanes in [1,4] required", "fan"));
1199 Diagnostic::error(DiagnosticCode::InvalidArgument, "fan needs at least two arm angles", "fan"));
1221 for (std::size_t index = 0; index < specs.size(); ++index) specs[index].intoHub = index % 2u == 0u;
1225 if (unique.empty() || std::fabs(spec.degrees - unique.back().degrees) > 1.f) unique.push_back(spec);
1226 if (unique.size() >= 2u && std::fabs(unique.front().degrees + 360.f - unique.back().degrees) <= 1.f)
1230 Diagnostic::error(DiagnosticCode::InvalidArgument, "fan needs at least two distinct arm angles", "fan"));
1284 auto node = network.addNode(std::cos(angle) * ringRadius, 0.f, std::sin(angle) * ringRadius, seamRadius);
1303 const RoadControlPoint p1 = P(p0.x - std::sin(a0) * handle, 0.f, p0.z + std::cos(a0) * handle);
1304 const RoadControlPoint p2 = P(p3.x + std::sin(a3) * handle, 0.f, p3.z - std::cos(a3) * handle);
1313 auto outer = network.addNode(std::cos(angle) * outerRadius, 0.f, std::sin(angle) * outerRadius, 2.f);
1315 auto approach = network.addEdge(outer.value(), ringNodes[static_cast<std::size_t>(i)], {{}, {}}, lanes, lanes,
1329Result<RoadNetwork> RoadNetwork::makeScene(const std::string& scene, float span, float bridgeHeight, int lanes,
1344 if (scene == "interchange" || scene.empty()) return makeInterchange(span, bridgeHeight, lanes, seed);
1351Result<RoadNetwork> RoadNetwork::makeInterchange(float span, float bridgeHeight, int lanes, std::uint32_t seed) {
1352 if (!std::isfinite(span) || span < 16.f || !std::isfinite(bridgeHeight) || bridgeHeight < 1.f || lanes < 1 ||
1355 DiagnosticCode::InvalidArgument, "span>=16, bridgeHeight>=1, lanes in [1,4] required", "interchange"));
1397 auto add = [&](std::uint32_t a, std::uint32_t b, std::vector<RoadControlPoint> pts, const RoadStyle& style) {
1442 for (const auto node : {nN.value(), nW.value(), nBridgeNW.value(), nBridgeSE.value(), nS.value(), nE.value()}) {
Stable, structured diagnostics shared by engine modules.
static Diagnostic error(DiagnosticCode code, std::string message, std::string path={}, DiagnosticDetails details={}, std::string source={})
Construct an error diagnostic with the standard error severity.
Definition Diagnostic.h:125
const T & value() const &
Borrow the value from a const lvalue after checking success.
Definition Result.h:308
static Result failure(Status status)
Construct a failed result from a structured status.
Definition Result.h:175
Owning directed road graph with lane connectivity.
Definition RoadNetwork.h:19
Result< int > reconnectEdgeEndpoint(std::uint32_t edgeId, bool fromEndpoint, std::uint32_t nodeId)
Reconnect one edge endpoint to an existing node and prune connections left at the old junction.
Definition RoadNetwork.cpp:732
Result< void > removeNode(std::uint32_t nodeId)
Remove an isolated node.
Definition RoadNetwork.cpp:1022
Result< void > unblockLaneLink(const RoadLaneConnection &link)
Remove one exact persistent lane-link prohibition.
Definition RoadNetwork.cpp:392
Result< void > setEdgeStyle(std::uint32_t edgeId, RoadStyle style)
Replace edge style atomically.
Definition RoadNetwork.cpp:520
Result< void > addLaneLink(RoadLaneConnection link)
Register one legal turn inside a shared junction node.
Definition RoadNetwork.cpp:356
static Result< RoadNetwork > makeStraight(float length=36.f, int lanes=2)
Scene 1: single flat straight segment (no junction).
Definition RoadNetwork.cpp:1060
static Result< RoadNetwork > makeCross(float span=32.f, int lanes=2)
Scene 4: simple ground-level 4-way cross (one junction disc).
Definition RoadNetwork.cpp:1112
Result< RoadEdgeSplitResult > splitEdgeAtSplineParameter(std::uint32_t edgeId, float parameter, float junctionRadius=6.f, std::uint32_t nodeId=0, std::uint32_t secondEdgeId=0)
Split at a normalized parameter on the same Catmull-Rom centerline used by road baking.
Definition RoadNetwork.cpp:826
Result< std::uint32_t > detachEdgeEndpoint(std::uint32_t edgeId, bool fromEndpoint)
Detach one edge endpoint onto a new coincident stable node.
Definition RoadNetwork.cpp:777
static Result< RoadNetwork > makeInterchange(float span=48.f, float bridgeHeight=8.f, int lanes=2, std::uint32_t seed=1)
Build a multi-level interchange demo graph (ground cross + elevated loop + ramps).
Definition RoadNetwork.cpp:1351
static Result< RoadNetwork > makeBridge(float length=36.f, float height=6.f, int lanes=2)
Scene 3: elevated straight with piers.
Definition RoadNetwork.cpp:1093
Result< void > removeLaneLink(const RoadLaneConnection &link)
Remove one exact lane-to-lane connection.
Definition RoadNetwork.cpp:403
Result< void > restoreNode(RoadNode node)
Restore a node with an explicit stable id for undo/import paths.
Definition RoadNetwork.cpp:230
Result< void > reverseEdge(std::uint32_t edgeId)
Atomically reverse one edge while preserving its physical lanes, links, and side-object intervals.
Definition RoadNetwork.cpp:704
Result< void > validate() const
Validate graph, endpoint and lane-link invariants without mutation.
Definition RoadNetwork.cpp:467
Result< RoadEdgeSplitResult > splitEdgeAtPosition(std::uint32_t edgeId, RoadControlPoint position, float maxDistance, float junctionRadius=6.f)
Project a world position onto the baked Catmull-Rom centerline and split at the nearest point.
Definition RoadNetwork.cpp:945
static Result< RoadNetwork > makeY(float span=32.f, int lanes=2)
Ground-level Y-junction with three arms separated by 120 degrees.
Definition RoadNetwork.cpp:1185
Result< void > setNodeJunctionRadius(std::uint32_t nodeId, float junctionRadius)
Replace one node's positive junction trim radius.
Definition RoadNetwork.cpp:575
static Result< RoadNetwork > makeFork(float span=32.f, int lanes=2)
Three-way scene with a 60-degree acute fork.
Definition RoadNetwork.cpp:1261
static Result< RoadNetwork > makeSkew(float span=32.f, int lanes=2)
Three-way scene with 135-degree skew corners.
Definition RoadNetwork.cpp:1265
Result< void > setNodeJunctionControl(std::uint32_t nodeId, RoadJunctionControl control)
Replace one node's authoritative traffic-control policy.
Definition RoadNetwork.cpp:588
Result< std::uint32_t > addEdge(std::uint32_t from, std::uint32_t to, std::vector< RoadControlPoint > controlPoints, int lanesForward=2, int lanesBackward=0, RoadStyle style={})
Insert a non-degenerate directed edge between two distinct live nodes.
Definition RoadNetwork.cpp:247
Result< void > setNodePosition(std::uint32_t nodeId, float x, float y, float z)
Move a node and atomically re-anchor every incident edge endpoint.
Definition RoadNetwork.cpp:533
static Result< RoadNetwork > makeRoundabout(float span=48.f, int lanes=1)
Build a four-entry roundabout from ordinary nodes, curved edges and lane links.
Definition RoadNetwork.cpp:1269
static Result< RoadNetwork > makeScene(const std::string &scene, float span=36.f, float bridgeHeight=6.f, int lanes=2, std::uint32_t seed=1)
Dispatch a named debug/demo scene.
Definition RoadNetwork.cpp:1329
Result< bool > blockLaneLink(RoadLaneConnection link)
Persistently forbid one exact legal lane connection and remove it if currently active.
Definition RoadNetwork.cpp:372
static Result< RoadNetwork > makeFan(float span, int lanes, std::vector< float > armAnglesDeg, std::vector< bool > intoHub={})
Build a ground-level N-way fan from absolute arm angles in degrees.
Definition RoadNetwork.cpp:1192
Result< RoadEdgeSplitResult > splitEdge(std::uint32_t edgeId, std::size_t controlPointIndex, float junctionRadius=6.f)
Split an edge at one authored interior control point as a single topology mutation.
Definition RoadNetwork.cpp:821
Result< int > connectAllTurns(std::uint32_t nodeId)
Auto-connect all forward and backward lane ports at one node.
Definition RoadNetwork.cpp:414
Result< std::uint32_t > addNode(float x, float y, float z, float junctionRadius=6.f)
Insert a junction node after validating finite coordinates.
Definition RoadNetwork.cpp:219
Result< void > setEdgeControlPoints(std::uint32_t edgeId, std::vector< RoadControlPoint > controlPoints)
Replace one edge spline while preserving its node-owned endpoint positions.
Definition RoadNetwork.cpp:651
Result< void > removeEdge(std::uint32_t edgeId)
Remove an edge and every lane link that references it.
Definition RoadNetwork.cpp:1004
static Result< RoadNetwork > makeTee(float span=32.f, int lanes=2)
Ground-level T-junction with an east-west through road and south stem.
Definition RoadNetwork.cpp:1150
static Result< RoadNetwork > makeCurve(float radius=18.f, int lanes=2)
Scene 2: gentle horizontal curve (no junction).
Definition RoadNetwork.cpp:1076
Result< void > restoreEdge(RoadEdge edge)
Restore an edge with an explicit stable id for undo/import paths.
Definition RoadNetwork.cpp:295
Result< int > setEdgeLaneCounts(std::uint32_t edgeId, int lanesForward, int lanesBackward)
Atomically replace directional lane counts and remove links that become out of range.
Definition RoadNetwork.cpp:676
Result< int > mergeNodes(std::uint32_t keepNodeId, std::uint32_t removeNodeId, float maxDistance)
Atomically merge one nearby endpoint node into another stable node.
Definition RoadNetwork.cpp:601
Definition RoadBake.cpp:17
Result< RoadProfile > makeRoadProfile(const RoadStyle &style, int lanesForward, int lanesBackward)
Build a mathematical road cross-section for the given lane counts.
Definition RoadProfile.cpp:50
RoadJunctionControl
Authoritative traffic-control policy applied to every approach of one junction node.
Definition RoadTypes.h:43
@ Signal
Every incoming approach is controlled by a traffic signal.
@ Uncontrolled
Edge trafficPriority resolves right-of-way without a mandatory stop.
@ Yield
Lower-priority approaches yield; equal-priority approaches all yield.
int mapLaneByLateralRank(int inLane, int inLaneCount, int outLaneCount)
Definition RoadNetwork.cpp:199
bool validJunctionControl(RoadJunctionControl control)
Definition RoadNetwork.cpp:205
RoadLaneDirection
Travel direction of a lane relative to the authored edge centerline.
Definition RoadTypes.h:79
@ Backward
Travels from RoadEdge::to to RoadEdge::from.
@ InvalidArgument
@ NotFound
@ PreconditionViolation
@ AlreadyExists
@ InvariantViolation
One authored control point on a road centerline (world space, Y-up).
Definition RoadTypes.h:12
Stable identities produced by one atomic edge split.
Definition RoadTypes.h:72
Directed centerline edge with optional reverse lanes.
Definition RoadTypes.h:61
std::vector< RoadControlPoint > controlPoints
Definition RoadTypes.h:65
One legal lane-to-lane connection inside a junction.
Definition RoadTypes.h:90
RoadLaneDirection outDirection
Definition RoadTypes.h:96
RoadLaneDirection inDirection
Definition RoadTypes.h:95
Cross-section and structural style for one road edge.
Definition RoadTypes.h:19
int trafficPriority
Higher incoming-road values win uncontrolled junction priority.
Definition RoadTypes.h:35