using GeoAPI.Geometries; using GisSharpBlog.NetTopologySuite.Geometries; namespace GisSharpBlog.NetTopologySuite.Simplify { /// /// Simplifies a line (sequence of points) using /// the standard Douglas-Peucker algorithm. /// public class DouglasPeuckerLineSimplifier { private readonly ICoordinate[] pts; private bool[] usePt; private readonly LineSegment seg = new LineSegment(); /// /// /// /// public DouglasPeuckerLineSimplifier(ICoordinate[] pts) { this.pts = pts; } /// /// /// public double DistanceTolerance { get; set; } /// /// /// /// /// /// public static ICoordinate[] Simplify(ICoordinate[] pts, double distanceTolerance) { DouglasPeuckerLineSimplifier simp = new DouglasPeuckerLineSimplifier(pts); simp.DistanceTolerance = distanceTolerance; return simp.Simplify(); } /// /// /// /// public ICoordinate[] Simplify() { usePt = new bool[pts.Length]; for (int i = 0; i < pts.Length; i++) { usePt[i] = true; } SimplifySection(0, pts.Length - 1); CoordinateList coordList = new CoordinateList(); for (int i = 0; i < pts.Length; i++) { if (usePt[i]) { coordList.Add(new Coordinate(pts[i])); } } return coordList.ToCoordinateArray(); } /// /// /// /// /// private void SimplifySection(int i, int j) { if ((i + 1) == j) { return; } seg.P0 = pts[i]; seg.P1 = pts[j]; double maxDistance = -1.0; int maxIndex = i; for (int k = i + 1; k < j; k++) { double distance = seg.Distance(pts[k]); if (distance > maxDistance) { maxDistance = distance; maxIndex = k; } } if (maxDistance <= DistanceTolerance) { for (int k = i + 1; k < j; k++) { usePt[k] = false; } } else { SimplifySection(i, maxIndex); SimplifySection(maxIndex, j); } } } }