MapLayer.cs 36 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110
  1. using System;
  2. using System.IO;
  3. using System.ComponentModel;
  4. using System.Collections.Generic;
  5. using System.Diagnostics;
  6. using System.Text;
  7. using System.Drawing;
  8. using System.Drawing.Drawing2D;
  9. using System.Globalization;
  10. using FastReport.Utils;
  11. using FastReport.Data;
  12. using FastReport.Map.Import.Shp;
  13. using System.Drawing.Design;
  14. namespace FastReport.Map
  15. {
  16. /// <summary>
  17. /// Specifies the type of objects that layer contains.
  18. /// </summary>
  19. public enum LayerType
  20. {
  21. /// <summary>
  22. /// The layer contains points.
  23. /// </summary>
  24. Point,
  25. /// <summary>
  26. /// The layer contains lines.
  27. /// </summary>
  28. Line,
  29. /// <summary>
  30. /// The layer contains polygons.
  31. /// </summary>
  32. Polygon
  33. }
  34. /// <summary>
  35. /// Specifies the spatial source for the layer.
  36. /// </summary>
  37. public enum SpatialSource
  38. {
  39. /// <summary>
  40. /// Source is ESRI shapefile.
  41. /// </summary>
  42. ShpFile,
  43. /// <summary>
  44. /// Source is a latitude/longitude/name provided by an application.
  45. /// </summary>
  46. ApplicationData
  47. }
  48. /// <summary>
  49. /// Determines how map labels are displayed.
  50. /// </summary>
  51. public enum MapLabelKind
  52. {
  53. /// <summary>
  54. /// No label displayed.
  55. /// </summary>
  56. None,
  57. /// <summary>
  58. /// The shape name is displayed.
  59. /// </summary>
  60. Name,
  61. /// <summary>
  62. /// The value is displayed.
  63. /// </summary>
  64. Value,
  65. /// <summary>
  66. /// Both name and value displayed.
  67. /// </summary>
  68. NameAndValue
  69. }
  70. /// <summary>
  71. /// Represents a map layer.
  72. /// </summary>
  73. public class MapLayer : Base, IParent, ICustomTypeDescriptor
  74. {
  75. #region Fields
  76. private LayerType type;
  77. private SpatialSource spatialSource;
  78. private string shapefile;
  79. private bool visible;
  80. private BoundingBox box;
  81. private ShapeCollection shapes;
  82. private ShapeStyle defaultShapeStyle;
  83. private MapPalette palette;
  84. private DataSourceBase dataSource;
  85. private string filter;
  86. // used if SpatialSource is ShpFile
  87. private string spatialColumn;
  88. private string spatialValue;
  89. // used if SpatialSource is ApplicationData
  90. private string latitudeValue;
  91. private string longitudeValue;
  92. private string labelValue;
  93. //
  94. private string analyticalValue;
  95. private string labelColumn;
  96. private MapLabelKind labelKind;
  97. private string labelFormat;
  98. private TotalType function;
  99. private ColorRanges colorRanges;
  100. private SizeRanges sizeRanges;
  101. private float accuracy;
  102. private float labelsVisibleAtZoom;
  103. private string zoomPolygon;
  104. private SortedList<string, double> values;
  105. private SortedList<string, int> counts;
  106. #endregion // Fields
  107. #region Properties
  108. /// <summary>
  109. /// Gets or sets a type of layer.
  110. /// </summary>
  111. [Browsable(false)]
  112. public LayerType Type
  113. {
  114. get { return type; }
  115. set { type = value; }
  116. }
  117. /// <summary>
  118. /// Gets or sets the spatial source for the layer.
  119. /// </summary>
  120. [DefaultValue(SpatialSource.ShpFile)]
  121. [Category("Data")]
  122. public SpatialSource SpatialSource
  123. {
  124. get { return spatialSource; }
  125. set
  126. {
  127. spatialSource = value;
  128. if (value == SpatialSource.ApplicationData)
  129. {
  130. LabelColumn = "NAME";
  131. SpatialColumn = "LOCATION";
  132. Box.MinX = -180;
  133. Box.MaxX = 180;
  134. Box.MinY = -90;
  135. Box.MaxY = 83.623031;
  136. }
  137. }
  138. }
  139. /// <summary>
  140. /// Gets or sets the name of ESRI shapefile.
  141. /// </summary>
  142. public string Shapefile
  143. {
  144. get { return shapefile; }
  145. set { shapefile = value; }
  146. }
  147. /// <summary>
  148. /// Gets or sets the data source.
  149. /// </summary>
  150. [Category("Data")]
  151. public DataSourceBase DataSource
  152. {
  153. get { return dataSource; }
  154. set { dataSource = value; }
  155. }
  156. /// <summary>
  157. /// Gets or sets the datasource filter expression.
  158. /// </summary>
  159. [Category("Data")]
  160. [Editor("FastReport.TypeEditors.ExpressionEditor, FastReport", typeof(UITypeEditor))]
  161. public string Filter
  162. {
  163. get { return filter; }
  164. set { filter = value; }
  165. }
  166. /// <summary>
  167. /// Gets or sets spatial column name.
  168. /// </summary>
  169. /// <remarks>
  170. /// This property is used if the <see cref="SpatialSource"/> is set to <b>ShpFile</b>.
  171. /// </remarks>
  172. [Category("Data")]
  173. [Editor("FastReport.Map.SpatialColumnEditor, FastReport", typeof(UITypeEditor))]
  174. public string SpatialColumn
  175. {
  176. get { return spatialColumn; }
  177. set { spatialColumn = value; }
  178. }
  179. /// <summary>
  180. /// Gets or sets an expression that returns spatial value.
  181. /// </summary>
  182. /// <remarks>
  183. /// This property is used if the <see cref="SpatialSource"/> is set to <b>ShpFile</b>.
  184. /// </remarks>
  185. [Category("Data")]
  186. [Editor("FastReport.TypeEditors.ExpressionEditor, FastReport", typeof(UITypeEditor))]
  187. public string SpatialValue
  188. {
  189. get { return spatialValue; }
  190. set { spatialValue = value; }
  191. }
  192. /// <summary>
  193. /// Gets or sets an expression that returns latitude value.
  194. /// </summary>
  195. /// <remarks>
  196. /// This property is used if the <see cref="SpatialSource"/> is set to <b>ApplicationData</b>.
  197. /// </remarks>
  198. [Category("Data")]
  199. [Editor("FastReport.TypeEditors.ExpressionEditor, FastReport", typeof(UITypeEditor))]
  200. public string LatitudeValue
  201. {
  202. get { return latitudeValue; }
  203. set { latitudeValue = value; }
  204. }
  205. /// <summary>
  206. /// Gets or sets an expression that returns longitude value.
  207. /// </summary>
  208. /// <remarks>
  209. /// This property is used if the <see cref="SpatialSource"/> is set to <b>ApplicationData</b>.
  210. /// </remarks>
  211. [Category("Data")]
  212. [Editor("FastReport.TypeEditors.ExpressionEditor, FastReport", typeof(UITypeEditor))]
  213. public string LongitudeValue
  214. {
  215. get { return longitudeValue; }
  216. set { longitudeValue = value; }
  217. }
  218. /// <summary>
  219. /// Gets or sets an expression that returns label value.
  220. /// </summary>
  221. /// <remarks>
  222. /// This property is used if the <see cref="SpatialSource"/> is set to <b>ApplicationData</b>.
  223. /// </remarks>
  224. [Category("Data")]
  225. [Editor("FastReport.TypeEditors.ExpressionEditor, FastReport", typeof(UITypeEditor))]
  226. public string LabelValue
  227. {
  228. get { return labelValue; }
  229. set { labelValue = value; }
  230. }
  231. /// <summary>
  232. /// Gets or sets an expression that returns analytical value.
  233. /// </summary>
  234. [Category("Data")]
  235. [Editor("FastReport.TypeEditors.ExpressionEditor, FastReport", typeof(UITypeEditor))]
  236. public string AnalyticalValue
  237. {
  238. get { return analyticalValue; }
  239. set { analyticalValue = value; }
  240. }
  241. /// <summary>
  242. /// Gets or sets label's column name.
  243. /// </summary>
  244. [Category("Appearance")]
  245. [Editor("FastReport.Map.SpatialColumnEditor, FastReport", typeof(UITypeEditor))]
  246. public string LabelColumn
  247. {
  248. get { return labelColumn; }
  249. set { labelColumn = value; }
  250. }
  251. /// <summary>
  252. /// Gets or sets a value that determines how map labels are displayed.
  253. /// </summary>
  254. [DefaultValue(MapLabelKind.Name)]
  255. [Category("Appearance")]
  256. public MapLabelKind LabelKind
  257. {
  258. get { return labelKind; }
  259. set { labelKind = value; }
  260. }
  261. /// <summary>
  262. /// Gets or sets the format of label's value.
  263. /// </summary>
  264. [Category("Appearance")]
  265. public string LabelFormat
  266. {
  267. get { return labelFormat; }
  268. set { labelFormat = value; }
  269. }
  270. /// <summary>
  271. /// Gets or sets the map accuracy. Lower value is better, but slower.
  272. /// </summary>
  273. [DefaultValue(2f)]
  274. [Category("Appearance")]
  275. public float Accuracy
  276. {
  277. get { return accuracy; }
  278. set { accuracy = value; }
  279. }
  280. /// <summary>
  281. /// Gets or sets the value that determines the labels visiblity at a certain zoom value.
  282. /// </summary>
  283. [DefaultValue(1f)]
  284. [Category("Appearance")]
  285. public float LabelsVisibleAtZoom
  286. {
  287. get { return labelsVisibleAtZoom; }
  288. set { labelsVisibleAtZoom = value; }
  289. }
  290. /// <summary>
  291. /// Gets or sets the aggregate function.
  292. /// </summary>
  293. [Category("Data")]
  294. [DefaultValue(TotalType.Sum)]
  295. public TotalType Function
  296. {
  297. get { return function; }
  298. set { function = value; }
  299. }
  300. /// <summary>
  301. /// Gets or sets a value indicating that the layer is visible.
  302. /// </summary>
  303. [DefaultValue(true)]
  304. [Category("Behavior")]
  305. public bool Visible
  306. {
  307. get { return visible; }
  308. set { visible = value; }
  309. }
  310. /// <summary>
  311. /// Gets or sets a bounding box of layer.
  312. /// </summary>
  313. [Browsable(false)]
  314. public BoundingBox Box
  315. {
  316. get { return box; }
  317. set { box = value; }
  318. }
  319. /// <summary>
  320. /// Gets a collection of map objects.
  321. /// </summary>
  322. [Browsable(false)]
  323. public ShapeCollection Shapes
  324. {
  325. get { return shapes; }
  326. }
  327. /// <summary>
  328. /// Gets the default style of shapes in this layer.
  329. /// </summary>
  330. [Category("Appearance")]
  331. public ShapeStyle DefaultShapeStyle
  332. {
  333. get { return defaultShapeStyle; }
  334. }
  335. /// <summary>
  336. /// Gets or sets the palette used to highlight shapes.
  337. /// </summary>
  338. [Category("Appearance")]
  339. [DefaultValue(MapPalette.None)]
  340. public MapPalette Palette
  341. {
  342. get { return palette; }
  343. set { palette = value; }
  344. }
  345. /// <summary>
  346. /// Gets the color ranges used to highlight shapes based on analytical value.
  347. /// </summary>
  348. [Category("Appearance")]
  349. public ColorRanges ColorRanges
  350. {
  351. get { return colorRanges; }
  352. }
  353. /// <summary>
  354. /// Gets the size ranges used to draw points based on analytical value.
  355. /// </summary>
  356. [Category("Appearance")]
  357. public SizeRanges SizeRanges
  358. {
  359. get { return sizeRanges; }
  360. }
  361. /// <summary>
  362. /// Gets or sets the expression that returns the name of polygon to zoom.
  363. /// </summary>
  364. [Category("Data")]
  365. [Editor("FastReport.TypeEditors.ExpressionEditor, FastReport", typeof(UITypeEditor))]
  366. public string ZoomPolygon
  367. {
  368. get { return zoomPolygon; }
  369. set { zoomPolygon = value; }
  370. }
  371. /// <summary>
  372. /// Gets or sets the bounding box as a string.
  373. /// </summary>
  374. [Browsable(false)]
  375. public string BoxAsString
  376. {
  377. get { return Box.GetAsString(); }
  378. set { Box.SetAsString(value); }
  379. }
  380. /// <summary>
  381. /// Gets a reference to the Map object.
  382. /// </summary>
  383. [Browsable(false)]
  384. public MapObject Map
  385. {
  386. get { return Parent as MapObject; }
  387. }
  388. internal List<string> SpatialColumns
  389. {
  390. get
  391. {
  392. if (Shapes.Count > 0)
  393. return Shapes[0].SpatialData.GetKeys();
  394. return new List<string>();
  395. }
  396. }
  397. internal bool IsShapefileEmbedded
  398. {
  399. get { return String.IsNullOrEmpty(Shapefile); }
  400. }
  401. #endregion // Properties
  402. #region Public Methods
  403. /// <inheritdoc/>
  404. public override void Assign(Base source)
  405. {
  406. base.Assign(source);
  407. MapLayer src = source as MapLayer;
  408. Shapefile = src.Shapefile;
  409. Type = src.Type;
  410. SpatialSource = src.SpatialSource;
  411. DataSource = src.DataSource;
  412. Filter = src.Filter;
  413. SpatialColumn = src.SpatialColumn;
  414. SpatialValue = src.SpatialValue;
  415. Function = src.Function;
  416. LatitudeValue = src.LatitudeValue;
  417. LongitudeValue = src.LongitudeValue;
  418. LabelValue = src.LabelValue;
  419. AnalyticalValue = src.AnalyticalValue;
  420. LabelColumn = src.LabelColumn;
  421. LabelKind = src.LabelKind;
  422. LabelFormat = src.LabelFormat;
  423. Accuracy = src.Accuracy;
  424. LabelsVisibleAtZoom = src.LabelsVisibleAtZoom;
  425. Visible = src.Visible;
  426. ZoomPolygon = src.ZoomPolygon;
  427. Box.Assign(src.Box);
  428. DefaultShapeStyle.Assign(src.DefaultShapeStyle);
  429. Palette = src.Palette;
  430. ColorRanges.Assign(src.ColorRanges);
  431. SizeRanges.Assign(src.SizeRanges);
  432. }
  433. /// <summary>
  434. /// Draws the layer.
  435. /// </summary>
  436. /// <param name="e">The drawing parameters.</param>
  437. public void Draw(FRPaintEventArgs e)
  438. {
  439. if (Visible)
  440. {
  441. for (int i = 0; i < Shapes.Count; i++)
  442. {
  443. ShapeBase shape = Shapes[i];
  444. shape.ShapeIndex = i;
  445. shape.SetPrinting(IsPrinting);
  446. if (Map.IsDesigning || shape.Visible)
  447. shape.Draw(e);
  448. }
  449. if (LabelKind != MapLabelKind.None && (Map.Zoom >= LabelsVisibleAtZoom))
  450. {
  451. foreach (ShapeBase shape in Shapes)
  452. {
  453. if (Map.IsDesigning || shape.Visible)
  454. shape.DrawLabel(e);
  455. }
  456. }
  457. }
  458. }
  459. /// <summary>
  460. /// Finds the shape under cursor.
  461. /// </summary>
  462. /// <param name="point">The cursor coordinates.</param>
  463. /// <returns>The <b>ShapeBase</b> object if found.</returns>
  464. public ShapeBase HitTest(PointF point)
  465. {
  466. if (Visible)
  467. {
  468. foreach (ShapeBase shape in Shapes)
  469. {
  470. if (shape.HitTest(point))
  471. return shape;
  472. }
  473. }
  474. return null;
  475. }
  476. /// <inheritdoc/>
  477. public override void Serialize(FRWriter writer)
  478. {
  479. MapLayer c = writer.DiffObject as MapLayer;
  480. base.Serialize(writer);
  481. if (Shapefile != c.Shapefile)
  482. {
  483. // when saving to the report file, convert absolute path to the shapefile to relative path
  484. // (based on the reportfile path).
  485. string value = Shapefile;
  486. if (writer.SerializeTo == SerializeTo.Report && Report != null && !String.IsNullOrEmpty(Report.FileName))
  487. value = FileUtils.GetRelativePath(Shapefile, Path.GetDirectoryName(Report.FileName));
  488. writer.WriteStr("Shapefile", value);
  489. }
  490. if (Type != c.Type)
  491. writer.WriteValue("Type", Type);
  492. if (SpatialSource != c.SpatialSource)
  493. writer.WriteValue("SpatialSource", SpatialSource);
  494. if (DataSource != null)
  495. writer.WriteRef("DataSource", DataSource);
  496. if (Filter != c.Filter)
  497. writer.WriteStr("Filter", Filter);
  498. if (SpatialColumn != c.SpatialColumn)
  499. writer.WriteStr("SpatialColumn", SpatialColumn);
  500. if (SpatialValue != c.SpatialValue)
  501. writer.WriteStr("SpatialValue", SpatialValue);
  502. if (Function != c.Function)
  503. writer.WriteValue("Function", Function);
  504. if (LatitudeValue != c.LatitudeValue)
  505. writer.WriteStr("LatitudeValue", LatitudeValue);
  506. if (LongitudeValue != c.LongitudeValue)
  507. writer.WriteStr("LongitudeValue", LongitudeValue);
  508. if (LabelValue != c.LabelValue)
  509. writer.WriteStr("LabelValue", LabelValue);
  510. if (AnalyticalValue != c.AnalyticalValue)
  511. writer.WriteStr("AnalyticalValue", AnalyticalValue);
  512. if (LabelColumn != c.LabelColumn)
  513. writer.WriteStr("LabelColumn", LabelColumn);
  514. if (LabelKind != c.LabelKind)
  515. writer.WriteValue("LabelKind", LabelKind);
  516. if (LabelFormat != c.LabelFormat)
  517. writer.WriteStr("LabelFormat", LabelFormat);
  518. if (Accuracy != c.Accuracy)
  519. writer.WriteFloat("Accuracy", Accuracy);
  520. if (LabelsVisibleAtZoom != c.LabelsVisibleAtZoom)
  521. writer.WriteFloat("LabelsVisibleAtZoom", LabelsVisibleAtZoom);
  522. if (Visible != c.Visible)
  523. writer.WriteBool("Visible", Visible);
  524. if (ZoomPolygon != c.ZoomPolygon)
  525. writer.WriteStr("ZoomPolygon", ZoomPolygon);
  526. if (BoxAsString != c.BoxAsString)
  527. writer.WriteStr("BoxAsString", BoxAsString);
  528. DefaultShapeStyle.Serialize(writer, "DefaultShapeStyle", c.DefaultShapeStyle);
  529. if (Palette != c.Palette)
  530. writer.WriteValue("Palette", Palette);
  531. ColorRanges.Serialize(writer, "ColorRanges");
  532. SizeRanges.Serialize(writer, "SizeRanges");
  533. if (writer.SerializeTo == SerializeTo.Preview && !IsShapefileEmbedded)
  534. {
  535. // write children by itself
  536. foreach (ShapeBase shape in Shapes)
  537. {
  538. writer.Write(shape);
  539. }
  540. }
  541. }
  542. /// <summary>
  543. /// Creates unique names for all contained objects such as points, lines, polygons, etc.
  544. /// </summary>
  545. public void CreateUniqueNames()
  546. {
  547. if (Report != null)
  548. {
  549. FastNameCreator nameCreator = new FastNameCreator(Report.AllNamedObjects);
  550. if (String.IsNullOrEmpty(Name))
  551. nameCreator.CreateUniqueName(this);
  552. foreach (ShapeBase shape in Shapes)
  553. {
  554. if (String.IsNullOrEmpty(shape.Name))
  555. nameCreator.CreateUniqueName(shape);
  556. }
  557. }
  558. }
  559. /// <summary>
  560. /// Reduces the number of points in the shapes in this layer.
  561. /// </summary>
  562. /// <param name="accuracy">The accuracy value.</param>
  563. public void Simplify(double accuracy)
  564. {
  565. if (accuracy <= 0)
  566. return;
  567. foreach (ShapeBase shape in Shapes)
  568. {
  569. shape.Simplify(accuracy);
  570. }
  571. }
  572. private void Zoom_Shape(string value)
  573. {
  574. foreach (ShapeBase shape in Shapes)
  575. {
  576. if (shape.SpatialValue == value)
  577. {
  578. ShapePolygon shapePoly = shape as ShapePolygon;
  579. using (Bitmap bmp = new Bitmap(1, 1))
  580. using (Graphics g = Graphics.FromImage(bmp))
  581. using (GraphicCache cache = new GraphicCache())
  582. {
  583. FRPaintEventArgs args = new FRPaintEventArgs(g, 1, 1, cache);
  584. Map.OffsetX = 0;
  585. Map.OffsetY = 0;
  586. Map.Zoom = 1;
  587. Map.Draw(args);
  588. // this will calculate largestBoundsRect
  589. shapePoly.GetGraphicsPath(args).Dispose();
  590. RectangleF largestBoundsRect = shapePoly.largestBoundsRect;
  591. float distanceX = (Map.AbsLeft + Map.Width / 2) - (largestBoundsRect.Left + largestBoundsRect.Width / 2);
  592. float distanceY = (Map.AbsTop + Map.Height / 2) - (largestBoundsRect.Top + largestBoundsRect.Height / 2);
  593. float width = Map.Width - Map.Padding.Horizontal;
  594. float height = Map.Height - Map.Padding.Vertical;
  595. float zoomX = width / largestBoundsRect.Width;
  596. float zoomY = height / largestBoundsRect.Height;
  597. float zoom = Math.Min(zoomX, zoomY) * 0.95f;
  598. Map.OffsetX = distanceX;
  599. Map.OffsetY = distanceY;
  600. Map.Zoom = zoom;
  601. }
  602. break;
  603. }
  604. }
  605. }
  606. /// <summary>
  607. /// Loads the layer contents from ESRI shapefile (*.shp/*.dbf).
  608. /// </summary>
  609. /// <param name="fileName">The file name.</param>
  610. public void LoadShapefile(string fileName)
  611. {
  612. using (ShpMapImport import = new ShpMapImport())
  613. {
  614. import.ImportMap(Map, this, fileName);
  615. Simplify(0.03);
  616. CreateUniqueNames();
  617. }
  618. }
  619. /// <inheritdoc/>
  620. public override void OnAfterLoad()
  621. {
  622. // convert relative path to the shapefile to absolute path (based on the reportfile path).
  623. if (String.IsNullOrEmpty(Shapefile))
  624. return;
  625. Shapefile = Shapefile.Replace('\\', Path.DirectorySeparatorChar);
  626. if (!Path.IsPathRooted(Shapefile) && Report != null && !String.IsNullOrEmpty(Report.FileName))
  627. Shapefile = Path.GetDirectoryName(Report.FileName) + Path.DirectorySeparatorChar + Shapefile;
  628. LoadShapefile(Shapefile);
  629. }
  630. #endregion // Public Methods
  631. #region IParent Members
  632. /// <inheritdoc/>
  633. public bool CanContain(Base child)
  634. {
  635. return child is ShapeBase;
  636. }
  637. /// <inheritdoc/>
  638. public void GetChildObjects(ObjectCollection list)
  639. {
  640. if (IsShapefileEmbedded)
  641. {
  642. foreach (ShapeBase shape in Shapes)
  643. {
  644. list.Add(shape);
  645. }
  646. }
  647. }
  648. /// <inheritdoc/>
  649. public void AddChild(Base child)
  650. {
  651. Shapes.Add(child as ShapeBase);
  652. }
  653. /// <inheritdoc/>
  654. public void RemoveChild(Base child)
  655. {
  656. Shapes.Remove(child as ShapeBase);
  657. }
  658. /// <inheritdoc/>
  659. public int GetChildOrder(Base child)
  660. {
  661. return Shapes.IndexOf(child as ShapeBase);
  662. }
  663. /// <inheritdoc/>
  664. public void SetChildOrder(Base child, int order)
  665. {
  666. int oldOrder = child.ZOrder;
  667. if (oldOrder != -1 && order != -1 && oldOrder != order)
  668. {
  669. if (order > Shapes.Count)
  670. order = Shapes.Count;
  671. if (oldOrder <= order)
  672. order--;
  673. Shapes.Remove(child as ShapeBase);
  674. Shapes.Insert(order, child as ShapeBase);
  675. }
  676. }
  677. /// <inheritdoc/>
  678. public void UpdateLayout(float dx, float dy)
  679. {
  680. // do nothing
  681. }
  682. #endregion
  683. #region Report Engine
  684. internal void SaveState()
  685. {
  686. ColorRanges.SaveState();
  687. SizeRanges.SaveState();
  688. foreach (ShapeBase shape in Shapes)
  689. {
  690. shape.SaveState();
  691. }
  692. }
  693. internal void RestoreState()
  694. {
  695. ColorRanges.RestoreState();
  696. SizeRanges.RestoreState();
  697. foreach (ShapeBase shape in Shapes)
  698. {
  699. shape.RestoreState();
  700. }
  701. }
  702. internal void InitializeComponent()
  703. {
  704. foreach (ShapeBase shape in Shapes)
  705. {
  706. shape.InitializeComponent();
  707. }
  708. }
  709. internal void FinalizeComponent()
  710. {
  711. foreach (ShapeBase shape in Shapes)
  712. {
  713. shape.FinalizeComponent();
  714. }
  715. }
  716. /// <inheritdoc/>
  717. public override string[] GetExpressions()
  718. {
  719. List<string> expressions = new List<string>();
  720. if (!String.IsNullOrEmpty(Filter))
  721. expressions.Add(Filter);
  722. if (!String.IsNullOrEmpty(SpatialValue))
  723. expressions.Add(SpatialValue);
  724. if (!String.IsNullOrEmpty(LatitudeValue))
  725. expressions.Add(LatitudeValue);
  726. if (!String.IsNullOrEmpty(LongitudeValue))
  727. expressions.Add(LongitudeValue);
  728. if (!String.IsNullOrEmpty(LabelValue))
  729. expressions.Add(LabelValue);
  730. if (!String.IsNullOrEmpty(AnalyticalValue))
  731. expressions.Add(AnalyticalValue);
  732. if (!String.IsNullOrEmpty(ZoomPolygon))
  733. expressions.Add(ZoomPolygon);
  734. return expressions.ToArray();
  735. }
  736. internal void GetData()
  737. {
  738. InitializeData();
  739. if (DataSource != null)
  740. {
  741. DataSource.Init(Filter);
  742. DataSource.First();
  743. while (DataSource.HasMoreRows)
  744. {
  745. if (SpatialSource == SpatialSource.ShpFile)
  746. {
  747. if (!String.IsNullOrEmpty(SpatialValue) && !String.IsNullOrEmpty(AnalyticalValue))
  748. {
  749. object spatialValue = Report.Calc(SpatialValue);
  750. object analyticalValue = Report.Calc(AnalyticalValue);
  751. if (spatialValue != null && !(spatialValue is DBNull) &&
  752. analyticalValue != null && !(analyticalValue is DBNull))
  753. {
  754. AddValue(spatialValue.ToString(), Convert.ToDouble(analyticalValue));
  755. }
  756. }
  757. }
  758. else
  759. {
  760. if (!String.IsNullOrEmpty(LatitudeValue) && !String.IsNullOrEmpty(LongitudeValue) &&
  761. !String.IsNullOrEmpty(LabelValue) && !String.IsNullOrEmpty(AnalyticalValue))
  762. {
  763. object latitudeValue = Report.Calc(LatitudeValue);
  764. object longitudeValue = Report.Calc(LongitudeValue);
  765. object labelValue = Report.Calc(LabelValue);
  766. object analyticalValue = Report.Calc(AnalyticalValue);
  767. if (latitudeValue != null && !(latitudeValue is DBNull) &&
  768. longitudeValue != null && !(longitudeValue is DBNull) &&
  769. labelValue != null && !(labelValue is DBNull) &&
  770. analyticalValue != null && !(analyticalValue is DBNull))
  771. {
  772. AddValue(Convert.ToDouble(latitudeValue), Convert.ToDouble(longitudeValue), labelValue.ToString(), Convert.ToDouble(analyticalValue));
  773. }
  774. }
  775. }
  776. DataSource.Next();
  777. }
  778. }
  779. FinalizeData();
  780. }
  781. internal void InitializeData()
  782. {
  783. values.Clear();
  784. counts.Clear();
  785. if (SpatialSource == SpatialSource.ApplicationData)
  786. Shapes.Clear();
  787. }
  788. internal void FinalizeData()
  789. {
  790. double min = 1e10;
  791. double max = -1e10;
  792. IList<string> spatialValues = values.Keys;
  793. // finalize avg calculation, find min and max
  794. for (int i = 0; i < spatialValues.Count; i++)
  795. {
  796. string spatialValue = spatialValues[i];
  797. double analyticalValue = values[spatialValue];
  798. if (Function == TotalType.Avg)
  799. {
  800. analyticalValue = analyticalValue / counts[spatialValue];
  801. values[spatialValue] = analyticalValue;
  802. }
  803. if (analyticalValue < min)
  804. min = analyticalValue;
  805. if (analyticalValue > max)
  806. max = analyticalValue;
  807. }
  808. if (spatialValues.Count > 0)
  809. {
  810. ColorRanges.Fill(min, max);
  811. SizeRanges.Fill(min, max);
  812. }
  813. // set shape values
  814. foreach (ShapeBase shape in Shapes)
  815. {
  816. string spatialValue = shape.SpatialValue;
  817. if (values.ContainsKey(spatialValue))
  818. shape.Value = values[spatialValue];
  819. }
  820. if (!String.IsNullOrEmpty(ZoomPolygon))
  821. {
  822. object zoomShape = Report.Calc(ZoomPolygon);
  823. if (zoomShape != null && !(zoomShape is DBNull))
  824. Zoom_Shape(zoomShape.ToString());
  825. }
  826. }
  827. /// <summary>
  828. /// Adds application provided data.
  829. /// </summary>
  830. /// <param name="latitude">Latitude value.</param>
  831. /// <param name="longitude">Longitude value.</param>
  832. /// <param name="name">The name displayed as a label.</param>
  833. /// <param name="analyticalValue">Analytical value.</param>
  834. /// <remarks>
  835. /// Use this method if the <see cref="SpatialSource"/> is set to <b>ApplicationData</b>.
  836. /// </remarks>
  837. public void AddValue(double latitude, double longitude, string name, double analyticalValue)
  838. {
  839. string spatialValue = latitude.ToString(CultureInfo.InvariantCulture.NumberFormat) + "," +
  840. longitude.ToString(CultureInfo.InvariantCulture.NumberFormat);
  841. if (!values.ContainsKey(spatialValue))
  842. {
  843. ShapePoint point = new ShapePoint();
  844. point.X = longitude;
  845. point.Y = latitude;
  846. point.SpatialData.SetValue("NAME", name);
  847. point.SpatialData.SetValue("LOCATION", spatialValue);
  848. Shapes.Add(point);
  849. }
  850. AddValue(spatialValue, analyticalValue);
  851. }
  852. /// <summary>
  853. /// Adds a spatial/analytical value pair to the list.
  854. /// </summary>
  855. /// <param name="spatialValue">The spatial value.</param>
  856. /// <param name="analyticalValue">The analytical value.</param>
  857. /// <remarks>
  858. /// Use this method if the <see cref="SpatialSource"/> is set to <b>ShpFile</b>.
  859. /// </remarks>
  860. public void AddValue(string spatialValue, double analyticalValue)
  861. {
  862. if (!values.ContainsKey(spatialValue))
  863. {
  864. if (Function == TotalType.Count)
  865. analyticalValue = 1;
  866. values.Add(spatialValue, analyticalValue);
  867. counts.Add(spatialValue, 1);
  868. return;
  869. }
  870. double value = values[spatialValue];
  871. switch (Function)
  872. {
  873. case TotalType.Sum:
  874. case TotalType.Avg:
  875. value += analyticalValue;
  876. break;
  877. case TotalType.Max:
  878. if (analyticalValue > value)
  879. value = analyticalValue;
  880. break;
  881. case TotalType.Min:
  882. if (analyticalValue < value)
  883. value = analyticalValue;
  884. break;
  885. case TotalType.Count:
  886. value++;
  887. break;
  888. }
  889. values[spatialValue] = value;
  890. counts[spatialValue]++;
  891. }
  892. #endregion
  893. #region ICustomTypeDescriptor Members
  894. /// <inheritdoc/>
  895. public PropertyDescriptorCollection GetProperties()
  896. {
  897. return GetProperties(null);
  898. }
  899. /// <inheritdoc/>
  900. public PropertyDescriptorCollection GetProperties(Attribute[] attr)
  901. {
  902. PropertyDescriptorCollection typeProps = TypeDescriptor.GetProperties(this.GetType(), attr);
  903. PropertyDescriptorCollection properties = new PropertyDescriptorCollection(null);
  904. foreach (PropertyDescriptor desc in typeProps)
  905. {
  906. bool skip = false;
  907. if (SpatialSource == SpatialSource.ShpFile)
  908. {
  909. skip = desc.Name == "LatitudeValue" || desc.Name == "LongitudeValue" ||
  910. desc.Name == "LabelValue" || desc.Name == "LabelsVisibleAtZoom";
  911. }
  912. else if (SpatialSource == SpatialSource.ApplicationData)
  913. {
  914. skip = desc.Name == "SpatialColumn" || desc.Name == "SpatialValue" ||
  915. desc.Name == "LabelColumn" || desc.Name == "Accuracy";
  916. }
  917. if (!skip)
  918. properties.Add(desc);
  919. }
  920. return properties;
  921. }
  922. /// <inheritdoc/>
  923. public String GetClassName()
  924. {
  925. return TypeDescriptor.GetClassName(this, true);
  926. }
  927. /// <inheritdoc/>
  928. public AttributeCollection GetAttributes()
  929. {
  930. return TypeDescriptor.GetAttributes(this, true);
  931. }
  932. /// <inheritdoc/>
  933. public String GetComponentName()
  934. {
  935. return TypeDescriptor.GetComponentName(this, true);
  936. }
  937. /// <inheritdoc/>
  938. public TypeConverter GetConverter()
  939. {
  940. return TypeDescriptor.GetConverter(this, true);
  941. }
  942. /// <inheritdoc/>
  943. public EventDescriptor GetDefaultEvent()
  944. {
  945. return TypeDescriptor.GetDefaultEvent(this, true);
  946. }
  947. /// <inheritdoc/>
  948. public PropertyDescriptor GetDefaultProperty()
  949. {
  950. return TypeDescriptor.GetDefaultProperty(this, true);
  951. }
  952. /// <inheritdoc/>
  953. public object GetEditor(Type editorBaseType)
  954. {
  955. return TypeDescriptor.GetEditor(this, editorBaseType, true);
  956. }
  957. /// <inheritdoc/>
  958. public EventDescriptorCollection GetEvents(Attribute[] attributes)
  959. {
  960. return TypeDescriptor.GetEvents(this, attributes, true);
  961. }
  962. /// <inheritdoc/>
  963. public EventDescriptorCollection GetEvents()
  964. {
  965. return TypeDescriptor.GetEvents(this, true);
  966. }
  967. /// <inheritdoc/>
  968. public object GetPropertyOwner(PropertyDescriptor pd)
  969. {
  970. return this;
  971. }
  972. #endregion
  973. /// <summary>
  974. /// Initializes a new instance of the <see cref="MapLayer"/> class.
  975. /// </summary>
  976. public MapLayer()
  977. {
  978. visible = true;
  979. shapefile = "";
  980. shapes = new ShapeCollection(this);
  981. box = new BoundingBox();
  982. values = new SortedList<string, double>();
  983. counts = new SortedList<string, int>();
  984. function = TotalType.Sum;
  985. filter = "";
  986. spatialColumn = "";
  987. spatialValue = "";
  988. latitudeValue = "";
  989. longitudeValue = "";
  990. labelValue = "";
  991. analyticalValue = "";
  992. labelColumn = "";
  993. labelFormat = "";
  994. defaultShapeStyle = new ShapeStyle();
  995. colorRanges = new ColorRanges();
  996. sizeRanges = new SizeRanges();
  997. labelKind = MapLabelKind.Name;
  998. accuracy = 2;
  999. labelsVisibleAtZoom = 1;
  1000. zoomPolygon = "";
  1001. BaseName = "Layer";
  1002. SetFlags(Flags.CanShowChildrenInReportTree, false);
  1003. }
  1004. }
  1005. }