namespace OsmReader { using System; using System.Collections.Generic; using System.ComponentModel; using System.Data; using System.Drawing; using System.IO; using System.Linq; using System.Text; using System.Threading; using System.Windows.Forms; using System.Xml.Serialization; using OsmReader.OsmData; using OsmReader.OsmData.Elements; using OpenTraffic.Model; public partial class OsmReaderForm : Form { private Dictionary nodeDict = null; private Dictionary crossPoints = null; private List startPoints = null; private List endPoints = null; private List links = null; private List linkSegments = null; private double minLat = double.MaxValue; private double minLon = double.MaxValue; private double maxLat = double.MinValue; private double maxLon = double.MinValue; private bool showMotorway = true; private bool showTrunk = false; private bool showPrimary = false; private bool showSecondary = false; private bool showTertiary = false; private bool showResidential = false; private bool showMini_roundabout = false; private bool showUnclassified = false; private int showCrossPoints = 0; private bool showEndPoints = false; private Osm osm = null; [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Performance", "CA1823:AvoidUnusedPrivateFields")] private Font f1 = new Font("Arial", 10); private TrafficModel trafficModel; /// /// /// /// public OsmReaderForm(TrafficModel trafficModel, ITrafficModelEditor iTrafficModelEditor1) { this.trafficModel = trafficModel; InitializeComponent(); crossPointsComboBox.SelectedIndex = 0; } /// /// Load data from file. /// /// /// private void button2_Click(object sender, EventArgs e) { Cursor oldCursor = null; if (openFileDialog1.ShowDialog() == System.Windows.Forms.DialogResult.OK) { try { oldCursor = Cursor.Current; Cursor.Current = Cursors.WaitCursor; XmlSerializer serializer = new XmlSerializer(typeof(Osm)); using (FileStream stream = new FileStream(openFileDialog1.FileName, FileMode.Open)) { this.osm = (Osm)serializer.Deserialize(stream); } } finally { if (oldCursor != null) { Cursor.Current = oldCursor; } } } } /// /// Present data. /// /// /// private void button3_Click(object sender, EventArgs e) { Cursor oldCursor = null; try { oldCursor = Cursor.Current; Cursor.Current = Cursors.WaitCursor; if (this.osm != null) { printOsmInfo(); this.nodeDict = getCoordinateNodes(osm); this.startPoints = new List(); this.endPoints = new List(); this.crossPoints = getCrossPoints(); this.linkSegments = new List(); this.links = new List(); foreach (OsmWay way in osm.way) { bool road = checkRoadVisibility(way); if (road && way.nd != null) { processRoad(way); } else { // appendText("Type not supported: way=" + way.ToString() + ", way.Type=" + way.Type + "\r\n"); } } identifyExtraEndPoints(); appendText("linkSegments = " + (linkSegments != null ? linkSegments.Count.ToString() : "null") + "\r\n"); appendText("links = " + (links != null ? links.Count.ToString() : "null") + "\r\n"); appendText("startPoints = " + startPoints.Count + "\r\n"); appendText("crossPoints = " + crossPoints.Count + "\r\n"); appendText("endPoints = " + endPoints.Count + "\r\n"); /* KeyValuePair[] kvpa = this.nodeDict.ToArray(); for (int i = 0; i < kvpa.Length; i++) { for (int j = i+1; j < kvpa.Length; j++) { if (kvpa[i].Value.CloseTo(kvpa[j].Value, 5)) { appendText(kvpa[i].Value.id + " is close to " + kvpa[j].Value.id + " \r\n"); } } } */ printLinks(links); printCrossPoints(); } } finally { if (oldCursor != null) { Cursor.Current = oldCursor; } } } private void printCrossPoints() { dataGridView2.Rows.Clear(); foreach (KeyValuePair kvp in this.crossPoints) { int n1 = dataGridView2.Rows.Add(); DataGridViewCellCollection cells = dataGridView2.Rows[n1].Cells; cells["spId"].Value = kvp.Value.id.ToString(); cells["spLat"].Value = kvp.Value.lat.ToString(); cells["spLon"].Value = kvp.Value.lon.ToString(); cells["spLinks"].Value = kvp.Value.links.ToString(); cells["spIn"].Value = kvp.Value.inLinks.ToString(); cells["spOut"].Value = kvp.Value.outLinks.ToString(); } } /// /// Take care of end points from several sources. /// private void identifyExtraEndPoints() { foreach (KeyValuePair kvp in this.crossPoints) { if (kvp.Value.inLinks == 0 && kvp.Value.outLinks > 0 && !startPoints.Contains(kvp.Value.id)) { appendText("Add start " + kvp.Value + "\r\n"); startPoints.Add(kvp.Value.id); } if (kvp.Value.outLinks == 0 && kvp.Value.inLinks > 0 && !endPoints.Contains(kvp.Value.id)) { appendText("Add end " + kvp.Value + "\r\n"); endPoints.Add(kvp.Value.id); } } } private void processRoad(OsmWay way) { OsmNode oldNode = null; OsmNode startNode = null; double sumDistance = 0; OsmNode node = null; foreach (OsmNd nd in way.nd) { if (nodeDict.ContainsKey(nd.reference)) { node = nodeDict[nd.reference]; if (minLat > node.lat) minLat = node.lat; if (minLon > node.lon) minLon = node.lon; if (maxLat < node.lat) maxLat = node.lat; if (maxLon < node.lon) maxLon = node.lon; if (oldNode != null) { double d = OsmNode.calcDistance(oldNode, node); linkSegments.Add(new Link(way, oldNode, node, d)); sumDistance += d; if (crossPoints.ContainsKey(nd.reference)) { startNode.outLinks++; node.inLinks++; links.Add(new Link(way, startNode, node, sumDistance)); startNode = node; sumDistance = 0; } } else { if (!crossPoints.ContainsKey(nd.reference) && !startPoints.Contains(nd.reference)) { startPoints.Add(nd.reference); if (!way.Oneway) { if (!endPoints.Contains(nd.reference)) { endPoints.Add(nd.reference); } } } startNode = node; } oldNode = node; } else { // appendText("Not found in list of nodes: way=" + way.ToString() + ", node=" + nd.reference + "\r\n"); } } if (node != null && !startNode.Equals(node)) { startNode.outLinks++; node.inLinks++; links.Add(new Link(way, startNode, node, sumDistance)); } startNode = oldNode; sumDistance = 0; if (oldNode != null) { if (!crossPoints.ContainsKey(oldNode.id) && !startPoints.Contains(oldNode.id) && !endPoints.Contains(oldNode.id)) { endPoints.Add(oldNode.id); if (!way.Oneway) { if (!startPoints.Contains(oldNode.id)) { startPoints.Add(oldNode.id); } } } } } private void printOsmInfo() { appendText("attribution = " + osm.attribution + "\r\n"); appendText("copyright = " + osm.copyright + "\r\n"); appendText("generator = " + osm.generator + "\r\n"); appendText("license = " + osm.license + "\r\n"); appendText("version = " + osm.version + "\r\n"); appendText("bounds = " + (osm.bounds != null ? osm.bounds.ToString() : "null") + "\r\n"); appendText("node = " + (osm.node != null ? osm.node.Count.ToString() : "null") + "\r\n"); appendText("way = " + (osm.way != null ? osm.way.Count.ToString() : "null") + "\r\n"); appendText("relation = " + (osm.relation != null ? osm.relation.Count.ToString() : "null") + "\r\n"); } [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Globalization", "CA1308:NormalizeStringsToUppercase")] private bool checkRoadVisibility(OsmWay way) { bool road = false; if (way.WayType != null) { switch (way.WayType.ToLowerInvariant()) { case "motorway": case "motorway_junction": case "motorway_link": road = this.showMotorway; break; case "trunk": case "trunk_link": road = this.showTrunk; break; case "primary": case "primary_link": road = this.showPrimary; break; case "secondary": case "secondary_link": road = this.showSecondary; break; case "tertiary": case "tertiary_link": road = this.showTertiary; break; case "residential": case "living_street": road = this.showResidential; break; case "mini_roundabout": road = this.showMini_roundabout; break; case "unclassified": case "road": road = this.showUnclassified; break; } } return road; } private delegate void appendTextFunc(string txt); private void appendText(string txt) { if (this.textBox1.InvokeRequired) { try { this.Invoke(new appendTextFunc(this.appendText), new object[] { txt }); } catch (ThreadAbortException) { throw; } catch (System.Reflection.TargetParameterCountException ex) { MessageBox.Show( "Exception: " + ex.Message + "\r\n", "Error", MessageBoxButtons.OK, MessageBoxIcon.Stop); } catch (System.ObjectDisposedException) { // Ignore. } } else { textBox1.AppendText(txt); } } private delegate void printLinksFunc(List links1); private void printLinks(List links1) { if (this.dataGridView1.InvokeRequired) { try { this.Invoke(new printLinksFunc(this.printLinks), new object[] { links1 }); } catch (ThreadAbortException) { throw; } catch (System.Reflection.TargetParameterCountException ex) { MessageBox.Show( "Exception: " + ex.Message + "\r\n", "Error", MessageBoxButtons.OK, MessageBoxIcon.Stop); } catch (System.ObjectDisposedException) { // Ignore. } } else { int n = 0; if (links1 != null) { foreach (Link l1 in links1) { n++; // appendText("link[" + n + "] = " + l1 + "\r\n"); int n1 = this.dataGridView1.Rows.Add(); DataGridViewCellCollection cells = this.dataGridView1.Rows[n1].Cells; cells["refCol"].Value = l1.way.Ref; cells["nameCol"].Value = l1.way.Name; cells["typeCol"].Value = l1.way.WayType; cells["startLocCol"].Value = l1.startNode.lat.ToString("0.0000") + " : " + l1.startNode.lon.ToString("0.0000"); cells["endLocCol"].Value = l1.endNode.lat.ToString("0.0000") + " : " + l1.endNode.lon.ToString("0.0000"); cells["lengthCol"].Value = l1.length.ToString("0.0"); cells["maxSpeedCol"].Value = l1.way.Maxspeed; cells["oneWayCol"].Value = l1.way.Oneway; } } pictureBox1.Invalidate(); } } private Dictionary getCrossPoints() { Dictionary crossPoints1 = new Dictionary(); foreach (OsmWay way in osm.way) { if (way.nd != null && checkRoadVisibility(way)) { foreach (OsmNd nd in way.nd) { if (crossPoints1.ContainsKey(nd.reference)) { crossPoints1[nd.reference]++; } else { crossPoints1.Add(nd.reference, 1); } } } } Dictionary crossNodes = new Dictionary(); foreach (KeyValuePair kvp in crossPoints1) { if (kvp.Value > 1 && nodeDict.ContainsKey(kvp.Key)) { OsmNode node = nodeDict[kvp.Key]; node.links = kvp.Value; node.inLinks = 0; node.outLinks = 0; crossNodes.Add(kvp.Key, node); } } return crossNodes; } private static Dictionary getCoordinateNodes(Osm osm) { Dictionary nodeDict = new Dictionary(); foreach (OsmNode node in osm.node) { nodeDict.Add(node.id, node); } return nodeDict; } private void pictureBox1_Paint(object sender, PaintEventArgs e) { if (this.linkSegments != null && this.minLat < double.MaxValue && this.minLon < double.MaxValue && this.maxLat > double.MinValue && this.maxLon > double.MinValue) { Graphics g = e.Graphics; double diffLat = this.maxLat - this.minLat; double diffLon = this.maxLon - this.minLon; int margin = 90; int height = pictureBox1.ClientSize.Height - (margin * 2); int width = pictureBox1.ClientSize.Width - (margin * 2); drawLinks(g, diffLat, diffLon, margin, height, width); if (this.showEndPoints) { drawStartPoints(g, diffLat, diffLon, margin, height, width); drawEndPoints(g, diffLat, diffLon, margin, height, width); } } } private void drawLinks(Graphics g, double diffLat, double diffLon, int margin, int height, int width) { using (Pen pen1 = new Pen(Color.Magenta, 1)) { using (Pen pen2 = new Pen(Color.Black, 1)) { foreach (Link l1 in this.linkSegments) { using (Pen pen = new Pen(l1.way.DrawColor, 1)) { int y0Val = (int)(height - ((l1.startNode.lat - this.minLat) / diffLat * height)) + margin; int x0Val = (int)((l1.startNode.lon - this.minLon) / diffLon * width) + margin; int y1Val = (int)(height - ((l1.endNode.lat - this.minLat) / diffLat * height)) + margin; int x1Val = (int)((l1.endNode.lon - this.minLon) / diffLon * width) + margin; g.DrawLine(pen, x0Val, y0Val, x1Val, y1Val); if (this.showCrossPoints > 0 && this.crossPoints.ContainsKey(l1.endNode.id)) { drawCrossPoints(g, diffLat, diffLon, margin, height, width, pen1, pen2, l1); } } } } } } private void drawCrossPoints(Graphics g, double diffLat, double diffLon, int margin, int height, int width, Pen pen1, Pen pen2, Link l1) { if (this.crossPoints[l1.endNode.id].links > this.showCrossPoints) { if (this.crossPoints[l1.endNode.id].links > 2) { drawCross(g, diffLat, diffLon, margin, height, width, pen2, l1.endNode, 4); } else { drawCross(g, diffLat, diffLon, margin, height, width, pen1, l1.endNode, 4); } } } private void drawEndPoints(Graphics g, double diffLat, double diffLon, int margin, int height, int width) { if (this.endPoints != null) { using (Pen pen = new Pen(Color.LightSalmon, 2)) { foreach (long id in this.endPoints) { OsmNode n1 = this.nodeDict[id]; bool nearPoint = checkIfNear(n1); if (!this.crossPoints.ContainsKey(id) || (!nearPoint && n1.outLinks == 0)) { drawCircle(g, diffLat, diffLon, margin, height, width, pen, n1, 6); } } } } } private void drawStartPoints(Graphics g, double diffLat, double diffLon, int margin, int height, int width) { if (this.startPoints != null) { using (Pen pen = new Pen(Color.LightGreen, 2)) { foreach (long id in this.startPoints) { OsmNode n1 = this.nodeDict[id]; bool nearPoint = checkIfNear(n1); if (!this.crossPoints.ContainsKey(id) || (!nearPoint && n1.inLinks == 0)) { drawCircle(g, diffLat, diffLon, margin, height, width, pen, n1, 4); } } } } } private bool checkIfNear(OsmNode n1) { bool nearPoint = false; foreach (OsmNode n2 in this.crossPoints.Values) { if (!n1.Equals(n2) && n1.CloseTo(n2, 5)) { nearPoint = true; break; } } return nearPoint; } private void drawCross(Graphics g, double diffLat, double diffLon, int margin, int height, int width, Pen pen, OsmNode n1, int sz) { if (n1.lat >= this.minLat && n1.lat <= this.maxLat && n1.lon >= this.minLon && n1.lon <= this.maxLon) { int w = sz * 2; int y0Val = (int)(height - ((n1.lat - this.minLat) / diffLat * height)) + margin - sz; int x0Val = (int)((n1.lon - this.minLon) / diffLon * width) + margin - sz; g.DrawLine(pen, x0Val, y0Val + sz, x0Val + w, y0Val + sz); g.DrawLine(pen, x0Val + sz, y0Val, x0Val + sz, y0Val + w); } } private void drawCircle(Graphics g, double diffLat, double diffLon, int margin, int height, int width, Pen pen, OsmNode n1, int sz) { if (n1.lat >= this.minLat && n1.lat <= this.maxLat && n1.lon >= this.minLon && n1.lon <= this.maxLon) { int w = sz * 2 + 1; int y0Val = (int)(height - ((n1.lat - this.minLat) / diffLat * height)) + margin - sz; int x0Val = (int)((n1.lon - this.minLon) / diffLon * width) + margin - sz; g.DrawEllipse(pen, new Rectangle(x0Val, y0Val, w, w)); // g.DrawString(n1.id.ToString(), f1, Brushes.Black, x0Val, y0Val+8); } } private void motorwayCheckBox_CheckedChanged(object sender, EventArgs e) { this.showMotorway = ((CheckBox)sender).Checked; } private void trunkCheckBox_CheckedChanged(object sender, EventArgs e) { this.showTrunk = ((CheckBox)sender).Checked; } private void primaryCheckBox_CheckedChanged(object sender, EventArgs e) { this.showPrimary = ((CheckBox)sender).Checked; } private void secondaryCheckBox_CheckedChanged(object sender, EventArgs e) { this.showSecondary = ((CheckBox)sender).Checked; } private void tertiaryCheckBox_CheckedChanged(object sender, EventArgs e) { this.showTertiary = ((CheckBox)sender).Checked; } private void residentialCheckBox_CheckedChanged(object sender, EventArgs e) { this.showResidential = ((CheckBox)sender).Checked; } private void mini_roundaboutCheckBox_CheckedChanged(object sender, EventArgs e) { this.showMini_roundabout = ((CheckBox)sender).Checked; } private void unclassifiedCheckBox_CheckedChanged(object sender, EventArgs e) { this.showUnclassified = ((CheckBox)sender).Checked; } private void endPointsCheckBox_CheckedChanged(object sender, EventArgs e) { this.showEndPoints = ((CheckBox)sender).Checked; } private void crossPointsComboBox_SelectedIndexChanged(object sender, EventArgs e) { this.showCrossPoints = ((ComboBox)sender).SelectedIndex; } } }