/// <summary> /// Computes the signed area for a ring. The signed area is positive if the /// <list type="Table"> /// <listheader> /// <term>value</term> /// <description>meaning</description> /// </listheader> /// <item><term>> 0</term> /// <description>The ring is oriented clockwise (CW)</description></item> /// <item><term>< 0</term> /// <description>The ring is oriented counter clockwise (CCW)</description></item> /// <item><term>== 0</term> /// <description>The ring is degenerate or flat</description></item> /// </list> /// ring is oriented CW, negative if the ring is oriented CCW, and zero if the /// ring is degenerate or flat. /// </summary> /// <param name="ring">The coordinates forming the ring</param> /// <returns>The signed area of the ring</returns> public static double OfRingSigned(CoordinateSequence ring) { int n = ring.Count; if (n < 3) { return(0.0); } /** * Based on the Shoelace formula. * http://en.wikipedia.org/wiki/Shoelace_formula */ var p1 = ring.GetCoordinateCopy(0); var p2 = ring.GetCoordinateCopy(1); double x0 = p1.X; p2.X -= x0; double sum = 0.0; for (int i = 1; i < n - 1; i++) { double p0Y = p1.Y; p1.X = p2.X; p1.Y = p2.Y; ring.GetCoordinate(i + 1, p2); p2.X -= x0; sum += p1.X * (p0Y - p2.Y); } return(sum / 2.0); }
/// <summary> /// Computes the length of a <c>LineString</c> specified by a sequence of points. /// </summary> /// <param name="pts">The points specifying the <c>LineString</c></param> /// <returns>The length of the <c>LineString</c></returns> public static double OfLine(CoordinateSequence pts) { // optimized for processing CoordinateSequences int n = pts.Count; if (n <= 1) { return(0.0); } double len = 0.0; var p = pts.GetCoordinateCopy(0); double x0 = p.X; double y0 = p.Y; for (int i = 1; i < n; i++) { pts.GetCoordinate(i, p); double x1 = p.X; double y1 = p.Y; double dx = x1 - x0; double dy = y1 - y0; len += Math.Sqrt(dx * dx + dy * dy); x0 = x1; y0 = y1; } return(len); }
/// <summary> /// Computes the locations of the nearest points between this sequence /// and another sequence. /// The locations are presented in the same order as the input sequences. /// </summary> /// <returns>A pair of <see cref="GeometryLocation"/>s for the nearest points.</returns> public GeometryLocation[] NearestLocations(FacetSequence facetSeq) { bool isPoint = IsPoint; bool isPointOther = facetSeq.IsPoint; var locs = new GeometryLocation[2]; if (isPoint && isPointOther) { // DEVIATION (minor): JTS uses "new Coordinate(GetCoordinate(int))", which is worse // than "GetCoordinateCopy(int)" for two reasons: 1) doesn't copy M (or, in NTS, Z), // and 2) might allocate two Coordinate instances instead of one. var pt = _pts.GetCoordinateCopy(_start); var seqPt = facetSeq._pts.GetCoordinateCopy(facetSeq._start); locs[0] = new GeometryLocation(_geom, _start, pt); locs[1] = new GeometryLocation(facetSeq._geom, facetSeq._start, seqPt); } else if (isPoint) { var pt = _pts.GetCoordinateCopy(_start); ComputeDistancePointLine(pt, facetSeq, locs); } else if (isPointOther) { var seqPt = facetSeq._pts.GetCoordinateCopy(facetSeq._start); ComputeDistancePointLine(seqPt, this, locs); // unflip the locations (locs[0], locs[1]) = (locs[1], locs[0]); } else { ComputeDistanceLineLine(facetSeq, locs); } return(locs); }
/// <summary> /// Creates a new sequence based on a deep copy of the given <see cref="CoordinateSequence"/>. /// </summary> /// <param name="coordSeq">The coordinate sequence that will be copied</param> public CoordinateArraySequence(CoordinateSequence coordSeq) : base(coordSeq?.Count ?? 0, coordSeq?.Dimension ?? 2, coordSeq?.Measures ?? 0) { if (coordSeq == null) { Coordinates = new Coordinate[0]; return; } Coordinates = new Coordinate[coordSeq.Count]; for (int i = 0; i < Coordinates.Length; i++) { Coordinates[i] = coordSeq.GetCoordinateCopy(i); } }