internal RoadCollection(RoadTopology topology, AssetLoadContext loadContext, HeightMap heightMap) : this() { // The map stores road segments with no connectivity: // - a segment is from point A to point B // - with a road type name // - and start and end curve types (angled, tight curve, broad curve). // The goal is to create road networks of connected road segments, // where a network has only a single road type. // A road network is composed of 2 or more nodes. // A network is a (potentially) cyclic graph. // A road node has > 1 and <= 4 edges connected to it. // A node can be part of multiple networks. // An edge can only exist in one network. var roadTemplateList = new RoadTemplateList(loadContext.AssetStore.RoadTemplates); var networks = RoadNetwork.BuildNetworks(topology, roadTemplateList); foreach (var network in networks) { _roads.Add(AddDisposable(new Road( loadContext, heightMap, network))); } }
public static IEnumerable <RoadNetwork> BuildNetworks(RoadTopology topology, RoadTemplateList roadTemplateList) { topology.AlignOrientation(); var edgeSegments = BuildEdgeSegments(topology); InsertNodeSegments(topology, edgeSegments); InsertEndCapSegments(edgeSegments, roadTemplateList); var networks = BuildNetworks(topology, edgeSegments); // sort networks in the order specified by roadTemplateList var sortedNetworks = roadTemplateList .Join( networks, t => t.InstanceId, n => n.Template.InstanceId, (t, n) => n); return(sortedNetworks); }
private static void InsertEndCapSegments(IReadOnlyDictionary <RoadTopologyEdge, StraightRoadSegment> edgeSegments, RoadTemplateList roadTemplateList) { foreach (var edge in edgeSegments.Reverse()) { // the end cap flag is only relevant when the edge is not connected to another edge on this end bool hasEndCapAtStart = edge.Key.StartType.HasFlag(RoadType.EndCap) && edge.Value.Start.To == null; bool hasEndCapAtEnd = edge.Key.EndType.HasFlag(RoadType.EndCap) && edge.Value.End.To == null; // single edges without any connected edges can only have one end cap (at the end position), even when the flag is present at both nodes if (hasEndCapAtEnd) { EndCapRoadSegment.CreateEndCap(GetIncomingRoadData(edge.Key.End, edge.Key), edge.Value.EndPosition, edge.Key.Template, edgeSegments, roadTemplateList); } else if (hasEndCapAtStart) { EndCapRoadSegment.CreateEndCap(GetIncomingRoadData(edge.Key.Start, edge.Key), edge.Value.StartPosition, edge.Key.Template, edgeSegments, roadTemplateList); } } }