VectorRenderer.cs
上传用户:sex100000
上传日期:2013-11-09
资源大小:1377k
文件大小:15k
源码类别:

GIS编程

开发平台:

C#

  1. // Copyright 2005, 2006 - Morten Nielsen (www.iter.dk)
  2. //
  3. // This file is part of SharpMap.
  4. // SharpMap is free software; you can redistribute it and/or modify
  5. // it under the terms of the GNU Lesser General Public License as published by
  6. // the Free Software Foundation; either version 2 of the License, or
  7. // (at your option) any later version.
  8. // 
  9. // SharpMap is distributed in the hope that it will be useful,
  10. // but WITHOUT ANY WARRANTY; without even the implied warranty of
  11. // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  12. // GNU Lesser General Public License for more details.
  13. // You should have received a copy of the GNU Lesser General Public License
  14. // along with SharpMap; if not, write to the Free Software
  15. // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA 
  16. using System;
  17. using System.Collections.Generic;
  18. using System.Text;
  19. using System.Drawing.Drawing2D;
  20. namespace SharpMap.Rendering
  21. {
  22. /// <summary>
  23. /// This class renders individual geometry features to a graphics object using the settings of a map object.
  24. /// </summary>
  25. public class VectorRenderer
  26. {
  27. private static System.Drawing.Bitmap defaultsymbol = (System.Drawing.Bitmap)System.Drawing.Bitmap.FromStream(System.Reflection.Assembly.GetExecutingAssembly().GetManifestResourceStream("SharpMap.Styles.DefaultSymbol.png"));
  28. /// <summary>
  29. /// Renders a MultiLineString to the map.
  30. /// </summary>
  31. /// <param name="g">Graphics reference</param>
  32. /// <param name="lines">MultiLineString to be rendered</param>
  33. /// <param name="pen">Pen style used for rendering</param>
  34. /// <param name="map">Map reference</param>
  35. public static void DrawMultiLineString(System.Drawing.Graphics g, Geometries.MultiLineString lines, System.Drawing.Pen pen, SharpMap.Map map)
  36. {
  37. for (int i = 0; i < lines.LineStrings.Count; i++)
  38. DrawLineString(g, lines.LineStrings[i], pen, map);
  39. }
  40. /// <summary>
  41. /// Renders a LineString to the map.
  42. /// </summary>
  43. /// <param name="g">Graphics reference</param>
  44. /// <param name="line">LineString to render</param>
  45. /// <param name="pen">Pen style used for rendering</param>
  46. /// <param name="map">Map reference</param>
  47. public static void DrawLineString(System.Drawing.Graphics g, Geometries.LineString line, System.Drawing.Pen pen, SharpMap.Map map)
  48. {
  49. if (line.Vertices.Count > 1)
  50. {
  51. System.Drawing.Drawing2D.GraphicsPath gp = new System.Drawing.Drawing2D.GraphicsPath();
  52. gp.AddLines(line.TransformToImage(map));
  53. g.DrawPath(pen, gp);
  54. }
  55. }
  56. /// <summary>
  57. /// Renders a multipolygon byt rendering each polygon in the collection by calling DrawPolygon.
  58. /// </summary>
  59. /// <param name="g">Graphics reference</param>
  60. /// <param name="pols">MultiPolygon to render</param>
  61. /// <param name="brush">Brush used for filling (null or transparent for no filling)</param>
  62. /// <param name="pen">Outline pen style (null if no outline)</param>
  63. /// <param name="clip">Specifies whether polygon clipping should be applied</param>
  64. /// <param name="map">Map reference</param>
  65. public static void DrawMultiPolygon(System.Drawing.Graphics g, Geometries.MultiPolygon pols, System.Drawing.Brush brush, System.Drawing.Pen pen, bool clip, SharpMap.Map map)
  66. {
  67. for (int i = 0; i < pols.Polygons.Count; i++)
  68. DrawPolygon(g, pols.Polygons[i], brush, pen, clip, map);
  69. }
  70. /// <summary>
  71. /// Renders a polygon to the map.
  72. /// </summary>
  73. /// <param name="g">Graphics reference</param>
  74. /// <param name="pol">Polygon to render</param>
  75. /// <param name="brush">Brush used for filling (null or transparent for no filling)</param>
  76. /// <param name="pen">Outline pen style (null if no outline)</param>
  77. /// <param name="clip">Specifies whether polygon clipping should be applied</param>
  78. /// <param name="map">Map reference</param>
  79. public static void DrawPolygon(System.Drawing.Graphics g, SharpMap.Geometries.Polygon pol, System.Drawing.Brush brush, System.Drawing.Pen pen, bool clip, SharpMap.Map map)
  80. {
  81. if (pol.ExteriorRing == null)
  82. return;
  83. if (pol.ExteriorRing.Vertices.Count > 2)
  84. {
  85. //Use a graphics path instead of DrawPolygon. DrawPolygon has a problem with several interior holes
  86. System.Drawing.Drawing2D.GraphicsPath gp = new System.Drawing.Drawing2D.GraphicsPath();
  87. //Add the exterior polygon
  88. if (!clip)
  89. gp.AddPolygon(pol.ExteriorRing.TransformToImage(map));
  90. else
  91. gp.AddPolygon(clipPolygon(pol.ExteriorRing.TransformToImage(map), map.Size.Width, map.Size.Height));
  92. //Add the interior polygons (holes)
  93. for (int i = 0; i < pol.InteriorRings.Count; i++)
  94. if (!clip)
  95. gp.AddPolygon(pol.InteriorRings[i].TransformToImage(map));
  96. else
  97. gp.AddPolygon(clipPolygon(pol.InteriorRings[i].TransformToImage(map), map.Size.Width, map.Size.Height));
  98. // Only render inside of polygon if the brush isn't null or isn't transparent
  99. if (brush != null && brush != System.Drawing.Brushes.Transparent)
  100. g.FillPath(brush, gp);
  101. // Create an outline if a pen style is available
  102. if (pen != null)
  103. g.DrawPath(pen, gp);
  104. }
  105. }
  106. /// <summary>
  107. /// Renders a label to the map.
  108. /// </summary>
  109. /// <param name="g">Graphics reference</param>
  110. /// <param name="LabelPoint">Label placement</param>
  111. /// <param name="Offset">Offset of label in screen coordinates</param>
  112. /// <param name="font">Font used for rendering</param>
  113. /// <param name="forecolor">Font forecolor</param>
  114. /// <param name="backcolor">Background color</param>
  115. /// <param name="halo">Color of halo</param>
  116. /// <param name="rotation">Text rotation in degrees</param>
  117. /// <param name="text">Text to render</param>
  118. /// <param name="map">Map reference</param>
  119. public static void DrawLabel(System.Drawing.Graphics g, System.Drawing.PointF LabelPoint, System.Drawing.PointF Offset, System.Drawing.Font font, System.Drawing.Color forecolor, System.Drawing.Brush backcolor, System.Drawing.Pen halo, float rotation, string text, SharpMap.Map map)
  120. {
  121. System.Drawing.SizeF fontSize = g.MeasureString(text, font); //Calculate the size of the text
  122. LabelPoint.X += Offset.X; LabelPoint.Y += Offset.Y; //add label offset
  123. if (rotation != 0 && rotation != float.NaN)
  124. {
  125. g.TranslateTransform(LabelPoint.X, LabelPoint.Y);
  126. g.RotateTransform(rotation);
  127. g.TranslateTransform(-fontSize.Width / 2, -fontSize.Height / 2);
  128. if (backcolor != null && backcolor != System.Drawing.Brushes.Transparent)
  129. g.FillRectangle(backcolor, 0, 0, fontSize.Width * 0.74f + 1f, fontSize.Height * 0.74f);
  130. System.Drawing.Drawing2D.GraphicsPath path = new System.Drawing.Drawing2D.GraphicsPath();
  131. path.AddString(text, font.FontFamily, (int)font.Style, font.Size, new System.Drawing.Point(0, 0), null);
  132. if (halo != null)
  133. g.DrawPath(halo, path);
  134. g.FillPath(new System.Drawing.SolidBrush(forecolor), path);
  135. //g.DrawString(text, font, new System.Drawing.SolidBrush(forecolor), 0, 0);
  136. g.Transform = map.MapTransform;
  137. }
  138. else
  139. {
  140. if (backcolor != null && backcolor != System.Drawing.Brushes.Transparent)
  141. g.FillRectangle(backcolor, LabelPoint.X, LabelPoint.Y, fontSize.Width * 0.74f + 1, fontSize.Height * 0.74f);
  142. System.Drawing.Drawing2D.GraphicsPath path = new System.Drawing.Drawing2D.GraphicsPath();
  143. path.AddString(text, font.FontFamily, (int)font.Style, font.Size, LabelPoint, null);
  144. if (halo != null)
  145. g.DrawPath(halo, path);
  146. g.FillPath(new System.Drawing.SolidBrush(forecolor), path);
  147. //g.DrawString(text, font, new System.Drawing.SolidBrush(forecolor), LabelPoint.X, LabelPoint.Y);
  148. }
  149. }
  150. /*private System.Drawing.RectangleF GetPathEnvelope(System.Drawing.Drawing2D.GraphicsPath gp)
  151. {
  152. float minX = float.MaxValue; float minY = float.MaxValue;
  153. float maxX = float.MinValue; float maxY = float.MinValue;
  154. for(int i=0;i<gp.PointCount;i++)
  155. if(minX>gp.PathPoints[i].X)
  156. }*/
  157. /// <summary>
  158. /// Clips a polygon to the view.
  159. /// Based on UMN Mapserver renderer [This method is currently not used. It seems faster just to draw the outside points as well)
  160. /// </summary>
  161. /// <param name="vertices">vertices in image coordinates</param>
  162. /// <param name="width">Width of map in image coordinates</param>
  163. /// <param name="height">Height of map in image coordinates</param>
  164. /// <returns>Clipped polygon</returns>
  165. internal static System.Drawing.PointF[] clipPolygon(System.Drawing.PointF[] vertices, int width, int height)
  166. {
  167. float deltax, deltay, xin, xout, yin, yout;
  168. float tinx, tiny, toutx, touty, tin1, tin2, tout;
  169. float x1, y1, x2, y2;
  170. List<System.Drawing.PointF> line = new List<System.Drawing.PointF>();
  171. if (vertices.Length <= 1) /* nothing to clip */
  172. return vertices;
  173. /*
  174. ** Don't do any clip processing of shapes completely within the
  175. ** clip rectangle based on a comparison of bounds.   We could do 
  176. ** something similar for completely outside, but that rarely occurs
  177. ** since the spatial query at the layer read level has generally already
  178. ** discarded all shapes completely outside the rect.
  179. */
  180. // TODO
  181. //if (vertices.bounds.maxx <= width
  182. // && vertices.bounds.minx >= 0
  183. // && vertices.bounds.maxy <= height
  184. // && vertices.bounds.miny >= 0)
  185. // {
  186. // return vertices;
  187. // }
  188. //line.point = (pointObj*)malloc(sizeof(pointObj) * 2 * shape->line[j].numpoints + 1); /* worst case scenario, +1 allows us to duplicate the 1st and last point */
  189. //line.numpoints = 0;
  190. for (int i = 0; i < vertices.Length - 1; i++)
  191. {
  192. x1 = vertices[i].X;
  193. y1 = vertices[i].Y;
  194. x2 = vertices[i + 1].X;
  195. y2 = vertices[i + 1].Y;
  196. deltax = x2 - x1;
  197. if (deltax == 0)
  198. { // bump off of the vertical
  199. deltax = (x1 > 0) ? -float.MinValue : float.MinValue;
  200. }
  201. deltay = y2 - y1;
  202. if (deltay == 0)
  203. { // bump off of the horizontal
  204. deltay = (y1 > 0) ? -float.MinValue : float.MinValue;
  205. }
  206. if (deltax > 0)
  207. {   //  points to right
  208. xin = 0;
  209. xout = width;
  210. }
  211. else
  212. {
  213. xin = width;
  214. xout = 0;
  215. }
  216. if (deltay > 0)
  217. {   //  points up
  218. yin = 0;
  219. yout = height;
  220. }
  221. else
  222. {
  223. yin = height;
  224. yout = 0;
  225. }
  226. tinx = (xin - x1) / deltax;
  227. tiny = (yin - y1) / deltay;
  228. if (tinx < tiny)
  229. {   // hits x first
  230. tin1 = tinx;
  231. tin2 = tiny;
  232. }
  233. else
  234. {   // hits y first
  235. tin1 = tiny;
  236. tin2 = tinx;
  237. }
  238. if (1 >= tin1)
  239. {
  240. if (0 < tin1)
  241. line.Add(new System.Drawing.PointF(xin, yin));
  242. if (1 >= tin2)
  243. {
  244. toutx = (xout - x1) / deltax;
  245. touty = (yout - y1) / deltay;
  246. tout = (toutx < touty) ? toutx : touty;
  247. if (0 < tin2 || 0 < tout)
  248. {
  249. if (tin2 <= tout)
  250. {
  251. if (0 < tin2)
  252. {
  253. if (tinx > tiny)
  254. line.Add(new System.Drawing.PointF(xin, y1 + tinx * deltay));
  255. else
  256. line.Add(new System.Drawing.PointF(x1 + tiny * deltax, yin));
  257. }
  258. if (1 > tout)
  259. {
  260. if (toutx < touty)
  261. line.Add(new System.Drawing.PointF(xout, y1 + toutx * deltay));
  262. else
  263. line.Add(new System.Drawing.PointF(x1 + touty * deltax, yout));
  264. }
  265. else
  266. line.Add(new System.Drawing.PointF(x2, y2));
  267. }
  268. else
  269. {
  270. if (tinx > tiny)
  271. line.Add(new System.Drawing.PointF(xin, yout));
  272. else
  273. line.Add(new System.Drawing.PointF(xout, yin));
  274. }
  275. }
  276. }
  277. }
  278. }
  279. if (line.Count > 0)
  280. line.Add(new System.Drawing.PointF(line[0].Y, line[0].Y));
  281. return line.ToArray();
  282. }
  283. /// <summary>
  284. /// Renders a point to the map.
  285. /// </summary>
  286. /// <param name="g">Graphics reference</param>
  287. /// <param name="point">Point to render</param>
  288. /// <param name="symbol">Symbol to place over point</param>
  289. /// <param name="symbolscale">The amount that the symbol should be scaled. A scale of '1' equals to no scaling</param>
  290. /// <param name="offset">Symbol offset af scale=1</param>
  291. /// <param name="rotation">Symbol rotation in degrees</param>
  292. /// <param name="map">Map reference</param>
  293. public static void DrawPoint(System.Drawing.Graphics g, SharpMap.Geometries.Point point, System.Drawing.Bitmap symbol, float symbolscale, System.Drawing.PointF offset, float rotation, SharpMap.Map map)
  294. {
  295. if (point == null)
  296. return;
  297. if (symbol == null) //We have no point style - Use a default symbol
  298. symbol = defaultsymbol;
  299. System.Drawing.PointF pp = SharpMap.Utilities.Transform.WorldtoMap(point, map);
  300. Matrix startingTransform = g.Transform;
  301. if (rotation != 0 && !Single.IsNaN(rotation))
  302. {
  303. System.Drawing.PointF rotationCenter = System.Drawing.PointF.Add(pp, new System.Drawing.SizeF(symbol.Width / 2, symbol.Height / 2));
  304. Matrix transform = new Matrix();
  305. transform.RotateAt(rotation, rotationCenter);
  306. g.Transform = transform;
  307. if (symbolscale == 1f)
  308. g.DrawImageUnscaled(symbol, (int)(pp.X - symbol.Width / 2 + offset.X), (int)(pp.Y - symbol.Height / 2 + offset.Y));
  309. else
  310. {
  311. float width = symbol.Width * symbolscale;
  312. float height = symbol.Height * symbolscale;
  313. g.DrawImage(symbol, (int)pp.X - width / 2 + offset.X * symbolscale, (int)pp.Y - height / 2 + offset.Y * symbolscale, width, height);
  314. }
  315. g.Transform = startingTransform;
  316. }
  317. else
  318. {
  319. if (symbolscale == 1f)
  320. g.DrawImageUnscaled(symbol, (int)(pp.X - symbol.Width / 2 + offset.X), (int)(pp.Y - symbol.Height / 2 + offset.Y));
  321. else
  322. {
  323. float width = symbol.Width * symbolscale;
  324. float height = symbol.Height * symbolscale;
  325. g.DrawImage(symbol, (int)pp.X - width / 2 + offset.X * symbolscale, (int)pp.Y - height / 2 + offset.Y * symbolscale, width, height);
  326. }
  327. }
  328. }
  329. /// <summary>
  330. /// Renders a <see cref="SharpMap.Geometries.MultiPoint"/> to the map.
  331. /// </summary>
  332. /// <param name="g">Graphics reference</param>
  333. /// <param name="points">MultiPoint to render</param>
  334. /// <param name="symbol">Symbol to place over point</param>
  335. /// <param name="symbolscale">The amount that the symbol should be scaled. A scale of '1' equals to no scaling</param>
  336. /// <param name="offset">Symbol offset af scale=1</param>
  337. /// <param name="rotation">Symbol rotation in degrees</param>
  338. /// <param name="map">Map reference</param>
  339. public static void DrawMultiPoint(System.Drawing.Graphics g, Geometries.MultiPoint points, System.Drawing.Bitmap symbol, float symbolscale, System.Drawing.PointF offset, float rotation, SharpMap.Map map)
  340. {
  341. for (int i = 0; i < points.Points.Count; i++)
  342. DrawPoint(g, points.Points[i], symbol, symbolscale, offset, rotation, map);
  343. }
  344. }
  345. }