using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Xml.Serialization; using TransportGame.Utils; namespace TransportGame.Model.Road { [XmlRoot("roadNetwork")] public class RoadNetwork { private int lastNodeId = -1, lastSegmentId = -1; /// /// Gets the road nodes /// [XmlIgnore] public Dictionary Nodes { get; private set; } /// /// Gets the road segments for the articulation graph /// [XmlIgnore] public Dictionary ArticulationSegments { get; private set; } /// /// Gets the road segments for the intersection graph /// [XmlIgnore] public Dictionary IntersectionSegments { get; private set; } /// /// Gets or sets the nodes /// [XmlArray("nodes")] public RoadNode[] NodesArray { get { return Nodes.Values.ToArray(); } set { Nodes.Clear(); foreach (var node in value) { node.ParentNetwork = this; Nodes.Add(node.Id, node); } } } /// /// Gets or sets the segments /// [XmlArray("articulationGraph")] public RoadSegment[] ArticulationSegmentsArray { get { return ArticulationSegments.Values.ToArray(); } set { ArticulationSegments.Clear(); foreach (var segment in value) { segment.ParentNetwork = this; ArticulationSegments.Add(segment.Id, segment); } } } /// /// Gets or sets the segments /// [XmlArray("intersectionGraph")] public RoadSegment[] IntersectionSegmentsArray { get { return ArticulationSegments.Values.ToArray(); } set { ArticulationSegments.Clear(); foreach (var segment in value) { segment.ParentNetwork = this; ArticulationSegments.Add(segment.Id, segment); } } } /// /// Initializes the road network /// public RoadNetwork() { Nodes = new Dictionary(); ArticulationSegments = new Dictionary(); IntersectionSegments = new Dictionary(); } /// /// Creates a node and returns it /// /// Position /// public RoadNode CreateNode(Vector2 pos) { // Skip IDs that already exist while (Nodes.ContainsKey(++lastNodeId)) ; // Create node RoadNode node = new RoadNode() { Id = lastNodeId, ParentNetwork = this, Position = pos }; Nodes.Add(node.Id, node); return node; } /// /// Creates a node and returns it /// /// Created node public RoadNode CreateNode() { return CreateNode(Vector2.Zero); } /// /// Creates a segment and returns it /// /// Created segment public RoadSegment CreateArticulationSegment() { return CreateArticulationSegment(null, null); } /// /// Creates a segment and returns it /// /// First terminal /// Second terminal /// Created segment public RoadSegment CreateArticulationSegment(RoadNode term1, RoadNode term2) { // Skip IDs that already exist while (ArticulationSegments.ContainsKey(++lastSegmentId)) ; // Create segment RoadSegment segment = new RoadSegment() { Id = lastSegmentId, ParentNetwork = this, Terminal1 = term1, Terminal2 = term2 }; // Set links if (term1 != null) term1.ArticulationSegmentIds.Add(segment.Id); if (term2 != null) term2.ArticulationSegmentIds.Add(segment.Id); ArticulationSegments.Add(segment.Id, segment); return segment; } /// /// Creates an articulation segment /// /// First terminal /// Position of second terminal /// Road segment public RoadSegment CreateArticulationSegment(RoadNode term1, Vector2 term2pos) { var term2 = CreateNode(term2pos); return CreateArticulationSegment(term1, term2); } /// /// Creates an articulation segment /// /// Position of first terminal /// Second terminal /// Road segment public RoadSegment CreateArticulationSegment(Vector2 term1pos, RoadNode term2) { var term1 = CreateNode(term1pos); return CreateArticulationSegment(term1, term2); } /// /// Creates an articulation segment /// /// Position of first terminal /// Position of second terminal /// Road segment public RoadSegment CreateArticulationSegment(Vector2 term1pos, Vector2 term2pos) { var term1 = CreateNode(term1pos); var term2 = CreateNode(term2pos); return CreateArticulationSegment(term1, term2); } /// /// Creates a segment and returns it /// /// Created segment public RoadSegment CreateIntersectionSegment() { // Skip IDs that already exist while (IntersectionSegments.ContainsKey(++lastSegmentId)) ; // Create segment RoadSegment segment = new RoadSegment() { Id = lastSegmentId, ParentNetwork = this }; IntersectionSegments.Add(segment.Id, segment); return segment; } /// /// Splits an articulation segment in two segments /// /// /// /// Newly created road node public RoadNode SplitArticulationSegment(RoadSegment segment, Vector2 point) { // Get current terminals var term1 = segment.Terminal1; var term2 = segment.Terminal2; int l1 = segment.LanesTo1, l2 = segment.LanesTo2; // Create new terminal var newTerm = CreateNode(point); // Delete exinsting segment term1.ArticulationSegmentIds.Remove(segment.Id); term2.ArticulationSegmentIds.Remove(segment.Id); ArticulationSegments.Remove(segment.Id); // Create split segments var seg1 = CreateArticulationSegment(term1, newTerm); var seg2 = CreateArticulationSegment(newTerm, term2); seg1.LanesTo1 = seg2.LanesTo1 = l1; seg1.LanesTo2 = seg2.LanesTo2 = l2; return newTerm; } } }