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

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.Collections.ObjectModel;
  19. using System.Text;
  20. namespace SharpMap.Geometries
  21. {
  22. /// <summary>
  23. /// A LinearRing is a LineString that is both closed and simple.
  24. /// </summary>
  25. public class LinearRing : LineString
  26. {
  27. /// <summary>
  28. /// Initializes an instance of a LinearRing from a set of vertices
  29. /// </summary>
  30. /// <param name="vertices"></param>
  31. public LinearRing(Collection<Point> vertices)
  32. : base(vertices)
  33. {
  34. }
  35. /// <summary>
  36. /// Initializes an instance of a LinearRing
  37. /// </summary>
  38. public LinearRing() : base()
  39. {
  40. }
  41. #region ICloneable Members
  42. /// <summary>
  43. /// Return a copy of this geometry
  44. /// </summary>
  45. /// <returns>Copy of Geometry</returns>
  46. public new LinearRing Clone()
  47. {
  48. LinearRing l = new LinearRing();
  49. for (int i = 0; i < this.Vertices.Count; i++)
  50. l.Vertices.Add(this.Vertices[i].Clone());
  51. return l;
  52. }
  53. #endregion
  54. /// <summary>
  55. /// Tests whether a ring is oriented counter-clockwise.
  56. /// </summary>
  57. /// <returns>Returns true if ring is oriented counter-clockwise.</returns>
  58. public bool IsCCW()
  59. {
  60. Point hip, p, prev, next;
  61. int hii, i;
  62. int nPts = this.Vertices.Count;
  63. // check that this is a valid ring - if not, simply return a dummy value
  64. if (nPts < 4) return false;
  65. // algorithm to check if a Ring is stored in CCW order
  66. // find highest point
  67. hip = this.Vertices[0];
  68. hii = 0;
  69. for (i = 1; i < nPts; i++)
  70. {
  71. p = this.Vertices[i];
  72. if (p.Y > hip.Y)
  73. {
  74. hip = p;
  75. hii = i;
  76. }
  77. }
  78. // find points on either side of highest
  79. int iPrev = hii - 1;
  80. if (iPrev < 0) iPrev = nPts - 2;
  81. int iNext = hii + 1;
  82. if (iNext >= nPts) iNext = 1;
  83. prev = this.Vertices[iPrev];
  84. next = this.Vertices[iNext];
  85. // translate so that hip is at the origin.
  86. // This will not affect the area calculation, and will avoid
  87. // finite-accuracy errors (i.e very small vectors with very large coordinates)
  88. // This also simplifies the discriminant calculation.
  89. double prev2x = prev.X - hip.X;
  90. double prev2y = prev.Y - hip.Y;
  91. double next2x = next.X - hip.X;
  92. double next2y = next.Y - hip.Y;
  93. // compute cross-product of vectors hip->next and hip->prev
  94. // (e.g. area of parallelogram they enclose)
  95. double disc = next2x * prev2y - next2y * prev2x;
  96. // If disc is exactly 0, lines are collinear.  There are two possible cases:
  97. // (1) the lines lie along the x axis in opposite directions
  98. // (2) the line lie on top of one another
  99. //  (2) should never happen, so we're going to ignore it!
  100. // (Might want to assert this)
  101. //  (1) is handled by checking if next is left of prev ==> CCW
  102. if (disc == 0.0)
  103. {
  104. // poly is CCW if prev x is right of next x
  105. return (prev.X > next.X);
  106. }
  107. else
  108. {
  109. // if area is positive, points are ordered CCW
  110. return (disc > 0.0);
  111. }
  112. }
  113. /// <summary>
  114. /// Returns the area of the LinearRing
  115. /// </summary>
  116. public double Area
  117. {
  118. get {
  119. if (this.Vertices.Count < 3)
  120. return 0;
  121. double sum = 0;
  122. double ax = this.Vertices[0].X;
  123. double ay = this.Vertices[0].Y;
  124. for(int i = 1; i < this.Vertices.Count - 1; i++)
  125. {
  126. double bx = this.Vertices[i].X;
  127. double by = this.Vertices[i].Y;
  128. double cx = this.Vertices[i + 1].X;
  129. double cy = this.Vertices[i + 1].Y;
  130. sum += ax * by - ay * bx +
  131. ay * cx - ax * cy +
  132. bx * cy - cx * by;
  133. }
  134. return Math.Abs(-sum / 2);
  135. }
  136. }
  137. /// <summary>
  138. /// Returns true of the Point 'p' is within the instance of this ring
  139. /// </summary>
  140. /// <param name="p"></param>
  141. /// <returns></returns>
  142. public bool IsPointWithin(Point p)
  143. {
  144. bool c = false;
  145. for (int i = 0; i < this.Vertices.Count; i++)
  146. for (int j = i + 1; j < this.Vertices.Count - 1; j++)
  147. {
  148. if ((((this.Vertices[i].Y <= p.Y) && (p.Y < this.Vertices[j].Y)) ||
  149.  ((this.Vertices[j].Y <= p.Y) && (p.Y < this.Vertices[i].Y))) &&
  150. (p.X < (this.Vertices[j].X - this.Vertices[i].X) * (p.Y - this.Vertices[i].Y) / (this.Vertices[j].Y - this.Vertices[i].Y) + this.Vertices[i].X))
  151. c = !c;
  152. }
  153. return c;
  154. }
  155. }
  156. }