OsmMapImport.cs 9.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275
  1. using System;
  2. using System.ComponentModel;
  3. using System.Collections.Generic;
  4. using System.Diagnostics;
  5. using System.Text;
  6. using System.Xml;
  7. using System.Globalization;
  8. using System.Windows.Forms;
  9. namespace FastReport.Map.Import.Osm
  10. {
  11. internal class OsmMapImport : MapImport
  12. {
  13. #region Fields
  14. private MapObject map;
  15. private MapLayer layer;
  16. private XmlDocument document;
  17. private Dictionary<ulong, OsmNode> nodes;
  18. private Dictionary<ulong, OsmWay> ways;
  19. private Dictionary<ulong, OsmRelation> relations;
  20. private double normalScale;
  21. private BoundingBox realOsmBox;
  22. #endregion // Fields
  23. #region Constructors
  24. public OsmMapImport()
  25. {
  26. map = new MapObject();
  27. document = new XmlDocument();
  28. nodes = new Dictionary<ulong, OsmNode>();
  29. ways = new Dictionary<ulong, OsmWay>();
  30. relations = new Dictionary<ulong, OsmRelation>();
  31. normalScale = 0.0;
  32. realOsmBox = new BoundingBox();
  33. map.MercatorProjection = false;
  34. }
  35. #endregion // Constructors
  36. #region Private Methods
  37. private double CalculateNormalScale()
  38. {
  39. double scaleByWidth = map.Width / (realOsmBox.MaxX - realOsmBox.MinX);
  40. double scaleByHeight = map.Height / (realOsmBox.MaxY - realOsmBox.MinY);
  41. return scaleByWidth < scaleByHeight ? scaleByWidth : scaleByHeight;
  42. }
  43. private void NormalizeLayerBox()
  44. {
  45. layer.Box.MinX = 0.0;
  46. layer.Box.MinY = 0.0;
  47. layer.Box.MaxX = (realOsmBox.MaxX - realOsmBox.MinX) * normalScale;
  48. layer.Box.MaxY = (realOsmBox.MaxY - realOsmBox.MinY) * normalScale;
  49. }
  50. private double ConvertToDouble(string value)
  51. {
  52. return Double.Parse(value, CultureInfo.InvariantCulture);
  53. }
  54. private void LoadBounds()
  55. {
  56. XmlNode bounds = document.GetElementsByTagName("bounds")[0];
  57. realOsmBox.MinX = ConvertToDouble(bounds.Attributes["minlon"].Value);
  58. realOsmBox.MinY = ConvertToDouble(bounds.Attributes["minlat"].Value);
  59. realOsmBox.MaxX = ConvertToDouble(bounds.Attributes["maxlon"].Value);
  60. realOsmBox.MaxY = ConvertToDouble(bounds.Attributes["maxlat"].Value);
  61. normalScale = CalculateNormalScale();
  62. }
  63. private void NormalizeNodes()
  64. {
  65. foreach (OsmNode node in nodes.Values)
  66. {
  67. node.Lon = (node.Lon - realOsmBox.MinX) * normalScale;
  68. node.Lat = (node.Lat - realOsmBox.MinY) * normalScale;
  69. }
  70. }
  71. private void LoadNodes()
  72. {
  73. foreach (XmlNode node in document.GetElementsByTagName("node"))
  74. {
  75. ulong id = Convert.ToUInt64(node.Attributes["id"].Value);
  76. double lon = ConvertToDouble(node.Attributes["lon"].Value);
  77. double lat = ConvertToDouble(node.Attributes["lat"].Value);
  78. Dictionary<string, string> tags = new Dictionary<string, string>();
  79. foreach (XmlNode tagNode in node.ChildNodes)
  80. {
  81. if (tagNode.Name == "tag")
  82. {
  83. tags.Add(tagNode.Attributes["k"].Value, tagNode.Attributes["v"].Value);
  84. }
  85. }
  86. nodes.Add(id, new OsmNode(lat, lon, tags));
  87. }
  88. NormalizeNodes();
  89. }
  90. private void LoadWays()
  91. {
  92. foreach (XmlNode node in document.GetElementsByTagName("way"))
  93. {
  94. ulong id = Convert.ToUInt64(node.Attributes["id"].Value);
  95. List<ulong> refs = new List<ulong>();
  96. Dictionary<string, string> tags = new Dictionary<string, string>();
  97. foreach (XmlNode refNode in node.ChildNodes)
  98. {
  99. if (refNode.Name == "nd")
  100. {
  101. refs.Add(Convert.ToUInt64(refNode.Attributes["ref"].Value));
  102. }
  103. if (refNode.Name == "tag")
  104. {
  105. tags.Add(refNode.Attributes["k"].Value, refNode.Attributes["v"].Value);
  106. }
  107. }
  108. ways.Add(id, new OsmWay(refs, tags));
  109. }
  110. }
  111. private void LoadRelations()
  112. {
  113. foreach (XmlNode node in document.GetElementsByTagName("relation"))
  114. {
  115. ulong id = Convert.ToUInt64(node.Attributes["id"].Value);
  116. List<ulong> nodeRefs = new List<ulong>();
  117. List<ulong> wayRefs = new List<ulong>();
  118. foreach (XmlNode refNode in node.ChildNodes)
  119. {
  120. if (refNode.Name == "member")
  121. {
  122. switch (refNode.Attributes["type"].Value)
  123. {
  124. case "node":
  125. nodeRefs.Add(Convert.ToUInt64(refNode.Attributes["ref"].Value));
  126. break;
  127. case "way":
  128. wayRefs.Add(Convert.ToUInt64(refNode.Attributes["ref"].Value));
  129. break;
  130. }
  131. }
  132. }
  133. relations.Add(id, new OsmRelation(nodeRefs, wayRefs));
  134. }
  135. }
  136. private void ConvertWays()
  137. {
  138. List<ShapePolyLine> lines = new List<ShapePolyLine>();
  139. List<ShapePolygon> polygons = new List<ShapePolygon>();
  140. foreach (OsmWay way in ways.Values)
  141. {
  142. bool isPolygon = false;
  143. ShapePolygon shape = null;
  144. if (way.NodeRefs[0] == way.NodeRefs[way.NodeRefs.Count - 1])
  145. {
  146. shape = new ShapePolygon();
  147. isPolygon = true;
  148. }
  149. else
  150. {
  151. shape = new ShapePolyLine();
  152. isPolygon = false;
  153. }
  154. shape.Parts.Clear();
  155. PointD[] part = new PointD[way.NodeRefs.Count];
  156. shape.Parts.Add(part);
  157. for (int i = 0; i < way.NodeRefs.Count; i++)
  158. {
  159. PointD point = new PointD();
  160. point.X = nodes[way.NodeRefs[i]].Lon;
  161. point.Y = nodes[way.NodeRefs[i]].Lat;
  162. part[i] = point;
  163. nodes[way.NodeRefs[i]].HasParent = true;
  164. }
  165. foreach (KeyValuePair<string, string> tag in way.Tags)
  166. {
  167. shape.SpatialData.SetValue(tag.Key, tag.Value);
  168. }
  169. if (isPolygon)
  170. {
  171. polygons.Add((ShapePolygon)shape);
  172. }
  173. else
  174. {
  175. lines.Add((ShapePolyLine)shape);
  176. }
  177. }
  178. if (lines.Count > 0)
  179. {
  180. layer = new MapLayer();
  181. NormalizeLayerBox();
  182. layer.Type = LayerType.Line;
  183. map.Layers.Add(layer);
  184. foreach (ShapePolyLine line in lines)
  185. {
  186. line.Box = layer.Box;
  187. layer.Shapes.Add(line);
  188. }
  189. }
  190. if (polygons.Count > 0)
  191. {
  192. layer = new MapLayer();
  193. NormalizeLayerBox();
  194. layer.Type = LayerType.Polygon;
  195. map.Layers.Add(layer);
  196. foreach (ShapePolygon polygon in polygons)
  197. {
  198. polygon.Box = layer.Box;
  199. layer.Shapes.Add(polygon);
  200. }
  201. }
  202. }
  203. private void ConvertNodes()
  204. {
  205. layer = new MapLayer();
  206. NormalizeLayerBox();
  207. layer.Type = LayerType.Point;
  208. map.Layers.Add(layer);
  209. foreach (OsmNode node in nodes.Values)
  210. {
  211. if (!node.HasParent)
  212. {
  213. ShapePoint point = new ShapePoint();
  214. point.X = node.Lon;
  215. point.Y = node.Lat;
  216. foreach (KeyValuePair<string, string> tag in node.Tags)
  217. {
  218. point.SpatialData.SetValue(tag.Key, tag.Value);
  219. }
  220. layer.Shapes.Add(point);
  221. }
  222. }
  223. }
  224. private void LoadMap()
  225. {
  226. LoadBounds();
  227. LoadNodes();
  228. LoadWays();
  229. ConvertWays();
  230. ConvertNodes();
  231. }
  232. #endregion // Private Methods
  233. #region Public Methods
  234. public override void ImportMap(MapObject map, MapLayer layer, string filename)
  235. {
  236. try
  237. {
  238. this.map = map;
  239. this.layer = layer;
  240. document.Load(filename);
  241. LoadMap();
  242. }
  243. catch
  244. {
  245. if (!FastReport.Utils.Config.WebMode)
  246. {
  247. MessageBox.Show(new FastReport.Utils.MyRes("Messages").Get("WrongFileFormat") + ".");
  248. }
  249. }
  250. }
  251. #endregion // Public Methods
  252. }
  253. }