/// <summary> /// Returns true if the given coordinate is contained in this ring. /// /// See: http://geomalgorithms.com/a03-_inclusion.html /// </summary> /// <param name="coordinate"></param> /// <returns></returns> public bool Contains(GeoCoordinate coordinate) { int number = 0; if (this.Coordinates[0] == coordinate) { // the given point is one of the corners. return(true); } // loop over all edges and calculate if they possibly intersect. for (int idx = 0; idx < this.Coordinates.Count - 1; idx++) { if (this.Coordinates[idx + 1] == coordinate) { // the given point is one of the corners. return(true); } bool idxRight = this.Coordinates[idx].Longitude > coordinate.Longitude; bool idx1Right = this.Coordinates[idx + 1].Longitude > coordinate.Longitude; if (idxRight || idx1Right) { // at least on of the coordinates is to the right of the point to calculate for. if ((this.Coordinates[idx].Latitude <= coordinate.Latitude && this.Coordinates[idx + 1].Latitude >= coordinate.Latitude) && !(this.Coordinates[idx].Latitude == coordinate.Latitude && this.Coordinates[idx + 1].Latitude == coordinate.Latitude)) { // idx is lower than idx+1 if (idxRight && idx1Right) { // no need for the left/right algorithm the result is already known. number++; } else { // one of the coordinates is not to the 'right' now we need the left/right algorithm. LineF2D localLine = new LineF2D(this.Coordinates[idx], this.Coordinates[idx + 1]); if (localLine.PositionOfPoint(coordinate) == LinePointPosition.Left) { number++; } } } else if ((this.Coordinates[idx].Latitude >= coordinate.Latitude && this.Coordinates[idx + 1].Latitude <= coordinate.Latitude) && !(this.Coordinates[idx].Latitude == coordinate.Latitude && this.Coordinates[idx + 1].Latitude == coordinate.Latitude)) { // idx is higher than idx+1 if (idxRight && idx1Right) { // no need for the left/right algorithm the result is already known. number--; } else { // one of the coordinates is not to the 'right' now we need the left/right algorithm. LineF2D localLine = new LineF2D(this.Coordinates[idx], this.Coordinates[idx + 1]); if (localLine.PositionOfPoint(coordinate) == LinePointPosition.Right) { number--; } } } } } return(number != 0); }
public void LineDistance2DTest() { double delta = 0.000000000000001; // create the line to test. PointF2D a = new PointF2D(0, 0); PointF2D b = new PointF2D(1, 1); LineF2D line = new LineF2D(a, b); // calculate the results double sqrt_2 = (double)System.Math.Sqrt(2); double sqrt_2_div_2 = (double)System.Math.Sqrt(2) / 2.0f; // the point to test to. PointF2D c = new PointF2D(1, 0); Assert.AreEqual(line.Distance(c), sqrt_2_div_2, delta, string.Format("Point distance should be {0}f!", sqrt_2_div_2)); // the point to test to. c = new PointF2D(0, 1); Assert.AreEqual(line.Distance(c), sqrt_2_div_2, delta, string.Format("Point distance should be {0}f!", sqrt_2_div_2)); // the point to test to. c = new PointF2D(2, 2); Assert.AreEqual(line.Distance(c), 0.0f, delta, "Point distance should be 0.0f!"); // the point to test to. c = new PointF2D(2, 3); Assert.AreEqual(line.Distance(c), sqrt_2_div_2, delta, string.Format("Point distance should be {0}f!", sqrt_2_div_2)); // the point to test to. c = new PointF2D(3, 2); Assert.AreEqual(line.Distance(c), sqrt_2_div_2, delta, string.Format("Point distance should be {0}f!", sqrt_2_div_2)); // Segments tests. line = new LineF2D(a, b, true, true); // the point to test to. c = new PointF2D(1, 0); Assert.AreEqual(line.Distance(c), sqrt_2_div_2, delta, string.Format("Point distance should be {0}f!", sqrt_2_div_2)); // the point to test to. c = new PointF2D(0, 1); Assert.AreEqual(line.Distance(c), sqrt_2_div_2, delta, string.Format("Point distance should be {0}f!", sqrt_2_div_2)); // the point to test to. c = new PointF2D(2, 2); Assert.AreEqual(line.Distance(c), sqrt_2, delta, string.Format("Point distance should be {0}!", sqrt_2)); // the point to test to. c = new PointF2D(2, 1); Assert.AreEqual(line.Distance(c), 1, delta, string.Format("Point distance should be {0}f!", 1)); // the point to test to. c = new PointF2D(1, 2); Assert.AreEqual(line.Distance(c), 1, delta, string.Format("Point distance should be {0}f!", 1)); }
/// <summary> /// Simplify the specified points using epsilon. /// </summary> /// <param name="points">Points.</param> /// <param name="epsilon">Epsilon.</param> /// <param name="first">First.</param> /// <param name="last">Last.</param> public static PointF2D[] SimplifyBetween(PointF2D[] points, double epsilon, int first, int last) { if (points == null) { throw new ArgumentNullException("points"); } if (epsilon <= 0) { throw new ArgumentOutOfRangeException("epsilon"); } if (first > last) { throw new ArgumentException(string.Format("first[{0}] must be smaller or equal than last[{1}]!", first, last)); } if (first + 1 != last) { // find point with the maximum distance. double maxDistance = 0; int foundIndex = -1; // create the line between first-last. LineF2D line = new LineF2D(points[first], points [last]); for (int idx = first + 1; idx < last; idx++) { double distance = line.Distance(points[idx]); if (distance > maxDistance) { // larger distance found. maxDistance = distance; foundIndex = idx; } } if (foundIndex > 0 && maxDistance > epsilon) // a point was found and it is far enough. { PointF2D[] before = SimplifyCurve.SimplifyBetween(points, epsilon, first, foundIndex); PointF2D[] after = SimplifyCurve.SimplifyBetween(points, epsilon, foundIndex, last); // build result. PointF2D[] result = new PointF2D[before.Length + after.Length - 1]; for (int idx = 0; idx < before.Length - 1; idx++) { result [idx] = before [idx]; } for (int idx = 0; idx < after.Length; idx++) { result [idx + before.Length - 1] = after [idx]; } return(result); } } return(new PointF2D[] { points[first], points[last] }); }
public static PointF2D[] SimplifyBetween(PointF2D[] points, double epsilon, int first, int last) { if (points == null) { throw new ArgumentNullException("points"); } if (epsilon <= 0.0) { throw new ArgumentOutOfRangeException("epsilon"); } if (first > last) { throw new ArgumentException(string.Format("first[{0}] must be smaller or equal than last[{1}]!", new object[2] { (object)first, (object)last })); } if (first + 1 != last) { double num1 = 0.0; int num2 = -1; LineF2D lineF2D = new LineF2D(points[first], points[last]); for (int index = first + 1; index < last; ++index) { double num3 = lineF2D.Distance(points[index]); if (num3 > num1) { num1 = num3; num2 = index; } } if (num2 > 0 && num1 > epsilon) { PointF2D[] pointF2DArray1 = SimplifyCurve.SimplifyBetween(points, epsilon, first, num2); PointF2D[] pointF2DArray2 = SimplifyCurve.SimplifyBetween(points, epsilon, num2, last); PointF2D[] pointF2DArray3 = new PointF2D[pointF2DArray1.Length + pointF2DArray2.Length - 1]; for (int index = 0; index < pointF2DArray1.Length - 1; ++index) { pointF2DArray3[index] = pointF2DArray1[index]; } for (int index = 0; index < pointF2DArray2.Length; ++index) { pointF2DArray3[index + pointF2DArray1.Length - 1] = pointF2DArray2[index]; } return(pointF2DArray3); } } return(new PointF2D[2] { points[first], points[last] }); }
public void LinePosition2DTest() { PointF2D a = new PointF2D(0, 0); PointF2D b = new PointF2D(1, 1); LineF2D line = new LineF2D(a, b); // test where the position lie. Assert.AreEqual(line.PositionOfPoint(new PointF2D(0, 0.5f)), LinePointPosition.Left, "Point position should be right!"); Assert.AreEqual(line.PositionOfPoint(new PointF2D(0.5f, 0.5f)), LinePointPosition.On, "Point position should be on!"); Assert.AreEqual(line.PositionOfPoint(new PointF2D(0.5f, 0)), LinePointPosition.Right, "Point position should be left!"); }
public void LineSegmentIntersectionTests() { // double segments. LineF2D segment1 = new LineF2D(0, 0, 5, 0, true); LineF2D segment2 = new LineF2D(0, 0, 0, 5, true); LineF2D segment3 = new LineF2D(0, 3, 3, 0, true); LineF2D segment4 = new LineF2D(1, 1, 2, 2, true); LineF2D segment5 = new LineF2D(3, 3, 4, 4, true); LineF2D segment6 = new LineF2D(3, 1, 3, -1, true); PrimitiveF2D primitive = segment1.Intersection(segment2); Assert.IsNotNull(primitive); Assert.IsInstanceOf <PointF2D>(primitive); Assert.AreEqual(new PointF2D(0, 0), primitive as PointF2D); primitive = segment1.Intersection(segment3); Assert.IsNotNull(primitive); Assert.IsInstanceOf <PointF2D>(primitive); Assert.AreEqual(new PointF2D(3, 0), primitive as PointF2D); primitive = segment2.Intersection(segment3); Assert.IsNotNull(primitive); Assert.IsInstanceOf <PointF2D>(primitive); Assert.AreEqual(new PointF2D(0, 3), primitive as PointF2D); primitive = segment3.Intersection(segment4); Assert.IsNotNull(primitive); Assert.IsInstanceOf <PointF2D>(primitive); Assert.AreEqual(new PointF2D(1.5, 1.5), primitive as PointF2D); primitive = segment5.Intersection(segment1); Assert.IsNull(primitive); primitive = segment5.Intersection(segment2); Assert.IsNull(primitive); primitive = segment5.Intersection(segment3); Assert.IsNull(primitive); primitive = segment5.Intersection(segment4); Assert.IsNull(primitive); primitive = segment5.Intersection(segment6); Assert.IsNull(primitive); primitive = segment6.Intersection(segment3); Assert.IsNotNull(primitive); Assert.IsInstanceOf <PointF2D>(primitive); Assert.AreEqual(new PointF2D(3, 0), primitive as PointF2D); primitive = segment6.Intersection(segment1); Assert.IsNotNull(primitive); Assert.IsInstanceOf <PointF2D>(primitive); Assert.AreEqual(new PointF2D(3, 0), primitive as PointF2D); primitive = segment6.Intersection(segment3); Assert.IsNotNull(primitive); Assert.IsInstanceOf <PointF2D>(primitive); Assert.AreEqual(new PointF2D(3, 0), primitive as PointF2D); // half segments. LineF2D segment7 = new LineF2D(1.5, 2, 1.5, 0, true, false); // only closed upwards. LineF2D segment9 = new LineF2D(1.5, 2, 1.5, 4, true, false); // only closed downwards. LineF2D segment8 = new LineF2D(1.5, 1, 1.5, 0, true, false); // only closed upwards. LineF2D segment10 = new LineF2D(1.5, 1, 1.5, 4, true, false); // only closed downwards. primitive = segment7.Intersection(segment3); Assert.IsNotNull(primitive); Assert.IsInstanceOf <PointF2D>(primitive); Assert.AreEqual(new PointF2D(1.5, 1.5), primitive as PointF2D); primitive = segment3.Intersection(segment7); Assert.IsNotNull(primitive); Assert.IsInstanceOf <PointF2D>(primitive); Assert.AreEqual(new PointF2D(1.5, 1.5), primitive as PointF2D); primitive = segment9.Intersection(segment3); Assert.IsNull(primitive); primitive = segment3.Intersection(segment9); Assert.IsNull(primitive); primitive = segment10.Intersection(segment3); Assert.IsNotNull(primitive); Assert.IsInstanceOf <PointF2D>(primitive); Assert.AreEqual(new PointF2D(1.5, 1.5), primitive as PointF2D); primitive = segment3.Intersection(segment10); Assert.IsNotNull(primitive); Assert.IsInstanceOf <PointF2D>(primitive); Assert.AreEqual(new PointF2D(1.5, 1.5), primitive as PointF2D); primitive = segment8.Intersection(segment3); Assert.IsNull(primitive); primitive = segment3.Intersection(segment8); Assert.IsNull(primitive); LineF2D segment11 = new LineF2D(-1, 1, 0, 1, true, false); LineF2D segment12 = new LineF2D(0, 3, 3, 0, true, true); primitive = segment11.Intersection(segment12); Assert.IsNotNull(primitive); Assert.IsInstanceOf <PointF2D>(primitive); Assert.AreEqual(new PointF2D(2, 1), primitive as PointF2D); primitive = segment12.Intersection(segment11); Assert.IsNotNull(primitive); Assert.IsInstanceOf <PointF2D>(primitive); Assert.AreEqual(new PointF2D(2, 1), primitive as PointF2D); }
/// <summary> /// Returns true if the given coordinate is contained in this ring. /// /// See: http://geomalgorithms.com/a03-_inclusion.html /// </summary> /// <param name="X"></param> /// <param name="Y"></param> /// <param name="coordinate"></param> public static bool Contains(List <double> X, List <double> Y, double[] coordinate) { int number = 0; if (X[0] == coordinate[0] && Y[0] == coordinate[1]) { // the given point is one of the corners. return(true); } // loop over all edges and calculate if they possibly intersect. for (int idx = 0; idx < X.Count - 1; idx++) { if (X[idx + 1] == coordinate[0] && Y[idx + 1] == coordinate[1]) { // the given point is one of the corners. return(true); } bool idxRight = X[idx] > coordinate[0]; bool idx1Right = X[idx + 1] > coordinate[0]; if (idxRight || idx1Right) { // at least one of the coordinates is to the right of the point to calculate for. if ((Y[idx] <= coordinate[1] && Y[idx + 1] >= coordinate[1]) && !(Y[idx] == coordinate[1] && Y[idx + 1] == coordinate[1])) { // idx is lower than idx+1 if (idxRight && idx1Right) { // no need for the left/right algorithm the result is already known. number++; } else { // one of the coordinates is not to the 'right' now we need the left/right algorithm. LineF2D localLine = new LineF2D( new PointF2D(X[idx], Y[idx]), new PointF2D(X[idx + 1], Y[idx + 1])); if (localLine.PositionOfPoint(new PointF2D(coordinate)) == LinePointPosition.Left) { number++; } } } else if ((Y[idx] >= coordinate[1] && Y[idx + 1] <= coordinate[1]) && !(Y[idx] == coordinate[1] && Y[idx + 1] == coordinate[1])) { // idx is higher than idx+1 if (idxRight && idx1Right) { // no need for the left/right algorithm the result is already known. number--; } else { // one of the coordinates is not to the 'right' now we need the left/right algorithm. LineF2D localLine = new LineF2D( new PointF2D(X[idx], Y[idx]), new PointF2D(X[idx + 1], Y[idx + 1])); if (localLine.PositionOfPoint(new PointF2D(coordinate)) == LinePointPosition.Right) { number--; } } } } } return(number != 0); }
public void LineDistance2DSegmentTest() { double delta = 0.000000000000001; // create the line to test. PointF2D a = new PointF2D(0, 0); PointF2D b = new PointF2D(1, 1); LineF2D line = new LineF2D(a, b,true,true); // calculate the results double sqrt_2 = (double)System.Math.Sqrt(2); double sqrt_2_div_2 = (double)System.Math.Sqrt(2) / 2.0f; // the point to test to. PointF2D c = new PointF2D(1, 0); Assert.AreEqual(line.Distance(c), sqrt_2_div_2, delta, string.Format("Point distance should be {0}f!", sqrt_2_div_2)); // the point to test to. c = new PointF2D(0, 1); Assert.AreEqual(line.Distance(c), sqrt_2_div_2, delta, string.Format("Point distance should be {0}f!", sqrt_2_div_2)); // the point to test to. c = new PointF2D(2, 2); Assert.AreEqual(line.Distance(c), sqrt_2, delta); // the point to test to. c = new PointF2D(2, 3); Assert.AreEqual(line.Distance(c), 2.23606797749979, delta, string.Format("Point distance should be {0}f!", sqrt_2_div_2)); // the point to test to. c = new PointF2D(3, 2); Assert.AreEqual(line.Distance(c), 2.23606797749979, delta, string.Format("Point distance should be {0}f!", sqrt_2_div_2)); // the point to test to. c = new PointF2D(1, 0); Assert.AreEqual(line.Distance(c), sqrt_2_div_2, delta, string.Format("Point distance should be {0}f!", sqrt_2_div_2)); // the point to test to. c = new PointF2D(0, 1); Assert.AreEqual(line.Distance(c), sqrt_2_div_2, delta, string.Format("Point distance should be {0}f!", sqrt_2_div_2)); // the point to test to. c = new PointF2D(2, 2); Assert.AreEqual(line.Distance(c), sqrt_2, delta, string.Format("Point distance should be {0}!", sqrt_2)); // the point to test to. c = new PointF2D(2, 1); Assert.AreEqual(line.Distance(c), 1, delta, string.Format("Point distance should be {0}f!", 1)); // the point to test to. c = new PointF2D(1, 2); Assert.AreEqual(line.Distance(c), 1, delta, string.Format("Point distance should be {0}f!", 1)); // the point to test to. c = new PointF2D(-1, -1); Assert.AreEqual(line.Distance(c), sqrt_2, delta, string.Format("Point distance should be {0}f!", 1)); // the point to test to. c = new PointF2D(1, -1); Assert.AreEqual(line.Distance(c), sqrt_2, delta, string.Format("Point distance should be {0}f!", 1)); }
public static double[][] SimplifyBetween(double[][] points, double epsilon, int first, int last) { if (points == null) { throw new ArgumentNullException("points"); } if (points.Length != 2) { throw new ArgumentException(); } if (epsilon < 0.0) { throw new ArgumentOutOfRangeException("epsilon"); } if (first > last) { throw new ArgumentException(string.Format("first[{0}] must be smaller or equal than last[{1}]!", new object[2] { (object)first, (object)last })); } if (epsilon == 0.0) { return(points); } if (first == last) { return new double[2][] { new double[1] { points[0][first] }, new double[1] { points[1][first] } } } ; if (points[0][first] == points[0][last] && points[1][first] == points[1][last]) { double[][] numArray1 = SimplifyCurve.SimplifyBetween(points, epsilon, first, last - 1); double[][] numArray2 = new double[2][] { new double[numArray1[0].Length + 1], new double[numArray1[0].Length + 1] }; for (int index = 0; index < numArray1[0].Length; ++index) { numArray2[0][index] = numArray1[0][index]; numArray2[1][index] = numArray1[1][index]; } numArray2[0][numArray1[0].Length] = points[0][last]; numArray2[1][numArray1[0].Length] = points[1][last]; return(numArray2); } if (first + 1 != last) { double num1 = 0.0; int num2 = -1; LineF2D lineF2D = new LineF2D(new PointF2D(points[0][first], points[1][first]), new PointF2D(points[0][last], points[1][last])); for (int index = first + 1; index < last; ++index) { double num3 = lineF2D.Distance(new PointF2D(points[0][index], points[1][index])); if (num3 > num1) { num1 = num3; num2 = index; } } if (num2 > 0 && num1 > epsilon) { double[][] numArray1 = SimplifyCurve.SimplifyBetween(points, epsilon, first, num2); double[][] numArray2 = SimplifyCurve.SimplifyBetween(points, epsilon, num2, last); double[][] numArray3 = new double[2][] { new double[numArray1[0].Length + numArray2[0].Length - 1], new double[numArray1[0].Length + numArray2[0].Length - 1] }; for (int index = 0; index < numArray1[0].Length - 1; ++index) { numArray3[0][index] = numArray1[0][index]; numArray3[1][index] = numArray1[1][index]; } for (int index = 0; index < numArray2[0].Length; ++index) { numArray3[0][index + numArray1[0].Length - 1] = numArray2[0][index]; numArray3[1][index + numArray1[0].Length - 1] = numArray2[1][index]; } return(numArray3); } } return(new double[2][] { new double[2] { points[0][first], points[0][last] }, new double[2] { points[1][first], points[1][last] } }); }
/// <summary> /// Simplify the specified points using epsilon. /// </summary> /// <param name="points">Points.</param> /// <param name="epsilon">Epsilon.</param> /// <param name="first">First.</param> /// <param name="last">Last.</param> public static double[][] SimplifyBetween(double[][] points, double epsilon, int first, int last) { if (points == null) { throw new ArgumentNullException("points"); } if (points.Length != 2) { throw new ArgumentException(); } if (epsilon < 0) { throw new ArgumentOutOfRangeException("epsilon"); } if (first > last) { throw new ArgumentException(string.Format("first[{0}] must be smaller or equal than last[{1}]!", first, last)); } if (epsilon == 0) { // no simplification is possible. return(points); } if (first == last) { // first and last are equal, no simplification possible. return(new double[][] { new double[] { points[0][first] }, new double[] { points[1][first] } }); } double[][] result; // check for identical first and last points. if (points[0][first] == points[0][last] && points[1][first] == points[1][last]) { // first and last point are indentical. double[][] before = SimplifyCurve.SimplifyBetween(points, epsilon, first, last - 1); // build result. result = new double[2][]; result[0] = new double[before[0].Length + 1]; result[1] = new double[before[0].Length + 1]; for (int idx = 0; idx < before[0].Length; idx++) { result[0][idx] = before[0][idx]; result[1][idx] = before[1][idx]; } result[0][before[0].Length] = points[0][last]; result[1][before[0].Length] = points[1][last]; return(result); } if (first + 1 != last) { // find point with the maximum distance. double maxDistance = 0; int foundIndex = -1; // create the line between first-last. LineF2D line = new LineF2D(new PointF2D( points[0][first], points[1][first]), new PointF2D( points[0][last], points[1][last])); for (int idx = first + 1; idx < last; idx++) { double distance = line.Distance(new PointF2D( points[0][idx], points[1][idx])); if (distance > maxDistance) { // larger distance found. maxDistance = distance; foundIndex = idx; } } if (foundIndex > 0 && maxDistance > epsilon) { // a point was found and it is far enough. double[][] before = SimplifyCurve.SimplifyBetween(points, epsilon, first, foundIndex); double[][] after = SimplifyCurve.SimplifyBetween(points, epsilon, foundIndex, last); // build result. result = new double[2][]; result[0] = new double[before[0].Length + after[0].Length - 1]; result[1] = new double[before[0].Length + after[0].Length - 1]; for (int idx = 0; idx < before[0].Length - 1; idx++) { result[0][idx] = before[0][idx]; result[1][idx] = before[1][idx]; } for (int idx = 0; idx < after[0].Length; idx++) { result[0][idx + before[0].Length - 1] = after[0][idx]; result[1][idx + before[0].Length - 1] = after[1][idx]; } return(result); } } result = new double[2][]; result[0] = new double[] { points[0][first], points[0][last] }; result[1] = new double[] { points[1][first], points[1][last] }; return(result); }