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

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 SharpMap.Styles;
  20. namespace SharpMap.Rendering.Thematics
  21. {
  22. /// <summary>
  23. /// The GradientTheme class defines a gradient color thematic rendering of features based by a numeric attribute.
  24. /// </summary>
  25. public class GradientTheme : ITheme
  26. {
  27. /// <summary>
  28. /// Initializes a new instance of the GradientTheme class
  29. /// </summary>
  30. /// <remarks>
  31. /// <para>The gradient theme interpolates linearly between two styles based on a numerical attribute in the datasource.
  32. /// This is useful for scaling symbols, line widths, line and fill colors from numerical attributes.</para>
  33. /// <para>Colors are interpolated between two colors, but if you want to interpolate through more colors (fx. a rainbow),
  34. /// set the <see cref="TextColorBlend"/>, <see cref="LineColorBlend"/> and <see cref="FillColorBlend"/> properties
  35. /// to a custom <see cref="ColorBlend"/>.
  36. /// </para>
  37. /// <para>The following properties are scaled (properties not mentioned here are not interpolated):
  38. /// <list type="table">
  39. /// <listheader><term>Property</term><description>Remarks</description></listheader>
  40. /// <item><term><see cref="System.Drawing.Color"/></term><description>Red, Green, Blue and Alpha values are linearly interpolated.</description></item>
  41. /// <item><term><see cref="System.Drawing.Pen"/></term><description>The color, width, color of pens are interpolated. MiterLimit,StartCap,EndCap,LineJoin,DashStyle,DashPattern,DashOffset,DashCap,CompoundArray, and Alignment are switched in the middle of the min/max values.</description></item>
  42. /// <item><term><see cref="System.Drawing.SolidBrush"/></term><description>SolidBrush color are interpolated. Other brushes are not supported.</description></item>
  43. /// <item><term><see cref="SharpMap.Styles.VectorStyle"/></term><description>MaxVisible, MinVisible, Line, Outline, Fill and SymbolScale are scaled linearly. Symbol, EnableOutline and Enabled switch in the middle of the min/max values.</description></item>
  44. /// <item><term><see cref="SharpMap.Styles.LabelStyle"/></term><description>FontSize, BackColor, ForeColor, MaxVisible, MinVisible, Offset are scaled linearly. All other properties use min-style.</description></item>
  45. /// </list>
  46. /// </para>
  47. /// <example>
  48. /// Creating a rainbow colorblend showing colors from red, through yellow, green and blue depicting 
  49. /// the population density of a country.
  50. /// <code lang="C#">
  51. /// //Create two vector styles to interpolate between
  52. /// SharpMap.Styles.VectorStyle min = new SharpMap.Styles.VectorStyle();
  53. /// SharpMap.Styles.VectorStyle max = new SharpMap.Styles.VectorStyle();
  54. /// min.Outline.Width = 1f; //Outline width of the minimum value
  55. /// max.Outline.Width = 3f; //Outline width of the maximum value
  56. /// //Create a theme interpolating population density between 0 and 400
  57. /// SharpMap.Rendering.Thematics.GradientTheme popdens = new SharpMap.Rendering.Thematics.GradientTheme("PopDens", 0, 400, min, max);
  58. /// //Set the fill-style colors to be a rainbow blend from red to blue.
  59. /// popdens.FillColorBlend = SharpMap.Rendering.Thematics.ColorBlend.Rainbow5;
  60. /// myVectorLayer.Theme = popdens;
  61. /// </code>
  62. /// </example>
  63. /// </remarks>
  64. /// <param name="columnName">Name of column to extract the attribute</param>
  65. /// <param name="minValue">Minimum value</param>
  66. /// <param name="maxValue">Maximum value</param>
  67. /// <param name="minStyle">Color for minimum value</param>
  68. /// <param name="maxStyle">Color for maximum value</param>
  69. public GradientTheme(string columnName, double minValue, double maxValue, SharpMap.Styles.IStyle minStyle, SharpMap.Styles.IStyle maxStyle)
  70. {
  71. _ColumnName = columnName;
  72. _min = minValue;
  73. _max = maxValue;
  74. _maxStyle = maxStyle;
  75. _minStyle = minStyle;
  76. }
  77. private string _ColumnName;
  78. /// <summary>
  79. /// Gets or sets the column name from where to get the attribute value
  80. /// </summary>
  81. public string ColumnName
  82. {
  83. get { return _ColumnName; }
  84. set { _ColumnName = value; }
  85. }
  86. private double _min;
  87. /// <summary>
  88. /// Gets or sets the minimum value of the gradient
  89. /// </summary>
  90. public double Min
  91. {
  92. get { return _min; }
  93. set { _min = value; }
  94. }
  95. private double _max;
  96. /// <summary>
  97. /// Gets or sets the maximum value of the gradient
  98. /// </summary>
  99. public double Max
  100. {
  101. get { return _max; }
  102. set { _max = value; }
  103. }
  104. private SharpMap.Styles.IStyle _minStyle;
  105. /// <summary>
  106. /// Gets or sets the <see cref="SharpMap.Styles.IStyle">style</see> for the minimum value
  107. /// </summary>
  108. public SharpMap.Styles.IStyle MinStyle
  109. {
  110. get { return _minStyle; }
  111. set { _minStyle = value; }
  112. }
  113. private SharpMap.Styles.IStyle _maxStyle;
  114. /// <summary>
  115. /// Gets or sets the <see cref="SharpMap.Styles.IStyle">style</see> for the maximum value
  116. /// </summary>
  117. public SharpMap.Styles.IStyle MaxStyle
  118. {
  119. get { return _maxStyle; }
  120. set { _maxStyle = value; }
  121. }
  122. private ColorBlend _TextColorBlend;
  123. /// <summary>
  124. /// Gets or sets the <see cref="SharpMap.Rendering.Thematics.ColorBlend"/> used on labels
  125. /// </summary>
  126. public ColorBlend TextColorBlend
  127. {
  128. get { return _TextColorBlend; }
  129. set { _TextColorBlend = value; }
  130. }
  131. private ColorBlend _LineColorBlend;
  132. /// <summary>
  133. /// Gets or sets the <see cref="SharpMap.Rendering.Thematics.ColorBlend"/> used on lines
  134. /// </summary>
  135. public ColorBlend LineColorBlend
  136. {
  137. get { return _LineColorBlend; }
  138. set { _LineColorBlend = value; }
  139. }
  140. private ColorBlend _FillColorBlend;
  141. /// <summary>
  142. /// Gets or sets the <see cref="SharpMap.Rendering.Thematics.ColorBlend"/> used as Fill
  143. /// </summary>
  144. public ColorBlend FillColorBlend
  145. {
  146. get { return _FillColorBlend; }
  147. set { _FillColorBlend = value; }
  148. }
  149. #region ITheme Members
  150. /// <summary>
  151. /// Returns the style based on a numeric DataColumn, where style
  152. /// properties are linearly interpolated between max and min values.
  153. /// </summary>
  154. /// <param name="row">Feature</param>
  155. /// <returns><see cref="SharpMap.Styles.IStyle">Style</see> calculated by a linear interpolation between the min/max styles</returns>
  156. public SharpMap.Styles.IStyle GetStyle(SharpMap.Data.FeatureDataRow row)
  157. {
  158. double attr = 0;
  159. try { attr = Convert.ToDouble(row[this._ColumnName]); }
  160. catch { throw new ApplicationException("Invalid Attribute type in Gradient Theme - Couldn't parse attribute (must be numerical)"); }
  161. if (_minStyle.GetType() != _maxStyle.GetType())
  162. throw new ArgumentException("MinStyle and MaxStyle must be of the same type");
  163. switch (MinStyle.GetType().FullName)
  164. {
  165. case "SharpMap.Styles.VectorStyle":
  166. return CalculateVectorStyle(MinStyle as VectorStyle, MaxStyle as VectorStyle, attr);
  167. case "SharpMap.Styles.LabelStyle":
  168. return CalculateLabelStyle(MinStyle as LabelStyle, MaxStyle as LabelStyle, attr);
  169. default:
  170. throw new ArgumentException("Only SharpMap.Styles.VectorStyle and SharpMap.Styles.LabelStyle are supported for the gradient theme");
  171. }
  172. }
  173. private VectorStyle CalculateVectorStyle(SharpMap.Styles.VectorStyle min, SharpMap.Styles.VectorStyle max, double value)
  174. {
  175. VectorStyle style = new VectorStyle();
  176. double dFrac = Fraction(value);
  177. float fFrac = Convert.ToSingle(dFrac);
  178. style.Enabled = (dFrac>0.5 ? min.Enabled : max.Enabled);
  179. style.EnableOutline = (dFrac>0.5 ? min.EnableOutline : max.EnableOutline);
  180. if (_FillColorBlend != null)
  181. style.Fill = new System.Drawing.SolidBrush(_FillColorBlend.GetColor(fFrac));
  182. else if (min.Fill != null && max.Fill != null)
  183. style.Fill = InterpolateBrush(min.Fill, max.Fill, value);
  184. if (min.Line != null && max.Line != null)
  185. style.Line = InterpolatePen(min.Line, max.Line, value);
  186. if (_LineColorBlend != null)
  187. style.Line.Color = _LineColorBlend.GetColor(fFrac);
  188. if(min.Outline!=null && max.Outline != null)
  189. style.Outline = InterpolatePen(min.Outline, max.Outline,value);
  190. style.MinVisible = InterpolateDouble(min.MinVisible, max.MinVisible, value);
  191. style.MaxVisible = InterpolateDouble(min.MaxVisible, max.MaxVisible, value);
  192. style.Symbol = (dFrac > 0.5 ? min.Symbol : max.Symbol);
  193. style.SymbolOffset = (dFrac > 0.5 ? min.SymbolOffset : max.SymbolOffset); //We don't interpolate the offset but let it follow the symbol instead
  194. style.SymbolScale = InterpolateFloat(min.SymbolScale, max.SymbolScale, value);
  195. return style;
  196. }
  197. private LabelStyle CalculateLabelStyle(SharpMap.Styles.LabelStyle min, SharpMap.Styles.LabelStyle max, double value)
  198. {
  199. LabelStyle style = new LabelStyle();
  200. style.CollisionDetection = min.CollisionDetection;
  201. style.Enabled = InterpolateBool(min.Enabled, max.Enabled,value);
  202. float FontSize = InterpolateFloat(min.Font.Size,max.Font.Size,value);
  203. style.Font = new System.Drawing.Font(min.Font.FontFamily,FontSize,min.Font.Style);
  204. if (min.BackColor != null && max.BackColor != null)
  205. style.BackColor = InterpolateBrush(min.BackColor, max.BackColor, value);
  206. if (_TextColorBlend != null)
  207. style.ForeColor = _LineColorBlend.GetColor(Convert.ToSingle(Fraction(value)));
  208. else 
  209. style.ForeColor = InterpolateColor(min.ForeColor, max.ForeColor, value);
  210. if (min.Halo != null && max.Halo != null)
  211. style.Halo = InterpolatePen(min.Halo,max.Halo, value);
  212. style.MinVisible = InterpolateDouble(min.MinVisible,max.MinVisible,value);
  213. style.MaxVisible = InterpolateDouble(min.MaxVisible, max.MaxVisible, value);
  214. style.Offset = new System.Drawing.PointF(InterpolateFloat(min.Offset.X, max.Offset.X, value), InterpolateFloat(min.Offset.Y, max.Offset.Y, value));
  215. return style;
  216. }
  217. private double Fraction(double attr)
  218. {
  219. if (attr < _min) return 0;
  220. if (attr > _max) return 1;
  221. return (attr - _min) / (_max - _min);
  222. }
  223. private bool InterpolateBool(bool min, bool max, double attr)
  224. {
  225. double frac = Fraction(attr);
  226. if (frac > 0.5) return max;
  227. else return min;
  228. }
  229. private float InterpolateFloat(float min, float max, double attr)
  230. {
  231. return Convert.ToSingle((max - min) * Fraction(attr) + min);
  232. }
  233. private double InterpolateDouble(double min, double max, double attr)
  234. {
  235. return (max - min) * Fraction(attr) + min;
  236. }
  237. private System.Drawing.SolidBrush InterpolateBrush(System.Drawing.Brush min, System.Drawing.Brush max, double attr)
  238. {
  239. if (min.GetType() != typeof(System.Drawing.SolidBrush) || max.GetType() != typeof(System.Drawing.SolidBrush))
  240. throw (new ArgumentException("Only SolidBrush brushes are supported in GradientTheme"));
  241. return new System.Drawing.SolidBrush(InterpolateColor((min as System.Drawing.SolidBrush).Color, (max as System.Drawing.SolidBrush).Color, attr));
  242. }
  243. private System.Drawing.Pen InterpolatePen(System.Drawing.Pen min, System.Drawing.Pen max, double attr)
  244. {
  245. if (min.PenType!= System.Drawing.Drawing2D.PenType.SolidColor|| max.PenType != System.Drawing.Drawing2D.PenType.SolidColor)
  246. throw (new ArgumentException("Only SolidColor pens are supported in GradientTheme"));
  247. System.Drawing.Pen pen = new System.Drawing.Pen(InterpolateColor(min.Color, max.Color, attr),InterpolateFloat(min.Width, max.Width,attr));
  248. double frac = Fraction(attr);
  249. pen.MiterLimit = InterpolateFloat(min.MiterLimit, max.MiterLimit, attr);
  250. pen.StartCap = (frac > 0.5 ? max.StartCap : min.StartCap);
  251. pen.EndCap = (frac > 0.5 ? max.EndCap : min.EndCap);
  252. pen.LineJoin = (frac > 0.5 ? max.LineJoin : min.LineJoin);
  253. pen.DashStyle = (frac > 0.5 ? max.DashStyle : min.DashStyle);
  254. if(min.DashStyle==System.Drawing.Drawing2D.DashStyle.Custom && max.DashStyle==System.Drawing.Drawing2D.DashStyle.Custom)
  255. pen.DashPattern = (frac > 0.5 ? max.DashPattern : min.DashPattern);
  256. pen.DashOffset = (frac > 0.5 ? max.DashOffset : min.DashOffset);
  257. pen.DashCap = (frac > 0.5 ? max.DashCap : min.DashCap);
  258. if(min.CompoundArray.Length>0 && max.CompoundArray.Length>0)
  259. pen.CompoundArray = (frac > 0.5 ? max.CompoundArray : min.CompoundArray);
  260. pen.Alignment = (frac > 0.5 ? max.Alignment : min.Alignment);
  261. //pen.CustomStartCap = (frac > 0.5 ? max.CustomStartCap : min.CustomStartCap);  //Throws ArgumentException
  262. //pen.CustomEndCap = (frac > 0.5 ? max.CustomEndCap : min.CustomEndCap);  //Throws ArgumentException
  263. return pen;
  264. }
  265. private System.Drawing.Color InterpolateColor(System.Drawing.Color minCol, System.Drawing.Color maxCol, double attr)
  266. {
  267. double frac = Fraction(attr);
  268. if (frac==1)
  269. return maxCol;
  270. else if (frac==0)
  271. return minCol;
  272. else
  273. {
  274. double r = (maxCol.R - minCol.R) * frac + minCol.R;
  275. double g = (maxCol.G - minCol.G) * frac + minCol.G;
  276. double b = (maxCol.B - minCol.B) * frac + minCol.B;
  277. double a = (maxCol.A - minCol.A) * frac + minCol.A;
  278. if (r > 255) r = 255;
  279. if (g > 255) g = 255;
  280. if (b > 255) b = 255;
  281. if (a > 255) a = 255;
  282. return System.Drawing.Color.FromArgb((int)a, (int)r, (int)g, (int)b);
  283. }
  284. }
  285. #endregion
  286. }
  287. }