/// <summary> /// Returns all the intersections the line has with this polygon. /// </summary> /// <param name="line"></param> /// <returns></returns> public PointF2D[] Intersections(LineF2D line) { List <PointF2D> points = new List <PointF2D>(); foreach (LineF2D polygon_line in this.LineEnumerator) { // calculate the intersection. PrimitiveF2D primitive = line.Intersection(polygon_line); // the primitive not null. if (primitive != null) { if (primitive is LineF2D) { // primitive is a line; convert. LineF2D intersect_line = (primitive as LineF2D); // we are sure the line is a segment. // if the line is not a segment this means that the polygon contains an line with infinite length; impossible. // TODO: how to determine the order? points.Add(intersect_line.Point1); points.Add(intersect_line.Point2); } else if (primitive is PointF2D) { // primitive is a point; convert. PointF2D point = (primitive as PointF2D); points.Add(point); } } } return(points.ToArray()); }
public static PointF2D PositionAtPosition(double[] x, double[] y, double position) { if (x.Length < 2) { throw new ArgumentOutOfRangeException("Given coordinates do not represent a polyline."); } double num1 = 0.0; for (int index = 1; index < x.Length; ++index) { double num2 = x[index - 1] - x[index]; double num3 = y[index - 1] - y[index]; double num4 = System.Math.Sqrt(num2 * num2 + num3 * num3); if (num1 + num4 > position) { LineF2D lineF2D = new LineF2D(new PointF2D(x[index - 1], y[index - 1]), new PointF2D(x[index], y[index])); double num5 = position - num1; VectorF2D vectorF2D = lineF2D.Direction.Normalize() * num5; return(lineF2D.Point1 + vectorF2D); } num1 += num4; } LineF2D lineF2D1 = new LineF2D(new PointF2D(x[x.Length - 2], y[x.Length - 2]), new PointF2D(x[x.Length - 1], y[x.Length - 1])); return(lineF2D1.Point1 + lineF2D1.Direction.Normalize() * (position - num1)); }
/// <summary> /// Returns a position on the given polyline corresponding with the given position. (0 smaller than position smaller than polyline.lenght). /// </summary> /// <param name="x"></param> /// <param name="y"></param> /// <param name="position"></param> /// <returns></returns> public static PointF2D PositionAtPosition(double[] x, double[] y, double position) { if (x.Length < 2) { throw new ArgumentOutOfRangeException("Given coordinates do not represent a polyline."); } double lenght = 0; LineF2D localLine = null; for (int idx = 1; idx < x.Length; idx++) { localLine = new LineF2D(new PointF2D(x[idx - 1], y[idx - 1]), new PointF2D(x[idx], y[idx])); double localLength = localLine.Length; if (lenght + localLength > position) { // position is between point at idx and idx + 1. double localPosition = position - lenght; VectorF2D vector = localLine.Direction.Normalize() * localPosition; return(localLine.Point1 + vector); } lenght = lenght + localLength; } return(localLine.Point1 + (localLine.Direction.Normalize() * (position - lenght))); }
/// <summary> /// Returns a position on the given polyline corresponding with the given position. (0 smaller than position smaller than polyline.lenght). /// </summary> /// <param name="x"></param> /// <param name="y"></param> /// <param name="position"></param> /// <returns></returns> public static PointF2D PositionAtPosition(double[] x, double[] y, double position) { if (x.Length < 2) throw new ArgumentOutOfRangeException("Given coordinates do not represent a polyline."); double lenght = 0; LineF2D localLine; for (int idx = 1; idx < x.Length; idx++) { double xDiff = (x [idx - 1] - x [idx]); double yDiff = (y [idx - 1] - y [idx]); double localLength = System.Math.Sqrt ((xDiff * xDiff) + (yDiff * yDiff)); if(lenght + localLength > position) { // position is between point at idx and idx + 1. localLine = new LineF2D(new PointF2D(x[idx - 1], y[idx - 1]), new PointF2D(x[idx], y[idx])); double localPosition = position - lenght; VectorF2D vector = localLine.Direction.Normalize() * localPosition; return localLine.Point1 + vector; } lenght = lenght + localLength; } localLine = new LineF2D(new PointF2D(x[x.Length - 2], y[x.Length - 2]), new PointF2D(x[x.Length - 1], y[x.Length - 1])); return localLine.Point1 + (localLine.Direction.Normalize() * (position - lenght)); }
/// <summary> /// Fits this rectangle to the given points. /// </summary> /// <param name="points">The points to wrap the rectangle around.</param> /// <param name="percentage">The margin in percentage.</param> /// <returns></returns> public RectangleF2D Fit(PointF2D[] points, double percentage) { if (points == null) { throw new ArgumentNullException("points"); } if (points.Length < 2) { throw new ArgumentOutOfRangeException("Rectangle fit needs at least two points."); } // calculate the center. double[] center = new double[] { points[0][0], points[0][1] }; for (int idx = 1; idx < points.Length; idx++) { center[0] = center[0] + points[idx][0]; center[1] = center[1] + points[idx][1]; } center[0] = center[0] / points.Length; center[1] = center[1] / points.Length; PointF2D centerPoint = new PointF2D(center); LineF2D line = null; // calculate the width. double width = 0; for (int idx = 0; idx < points.Length; idx++) { line = new LineF2D(points[idx], points[idx] + this._vectorY); double distance = line.Distance(centerPoint); if (distance > width) { // the distance is larger. width = distance; } } width = width * 2; // calculate the height. double height = 0; for (int idx = 0; idx < points.Length; idx++) { line = new LineF2D(points[idx], points[idx] + this._vectorX); double distance = line.Distance(centerPoint); if (distance > height) { // this distance is larger. height = distance; } } height = height * 2; // expand with the given percentage. width = width + (width / 100.0 * percentage); height = height + (height / 100.0 * percentage); return(RectangleF2D.FromBoundsAndCenter(width, height, centerPoint[0], centerPoint[1], this.DirectionY)); }
/// <summary> /// Transforms the given the coordinates to a coordinate system defined inside this rectangle. /// </summary> /// <param name="width">Width.</param> /// <param name="height">Height.</param> /// <param name="reverseX">If set to <c>true</c> reverse x.</param> /// <param name="reverseY">If set to <c>true</c> reverse y.</param> /// <param name="point">Point.</param> /// <param name="transformed">Transformed.</param> public void TransformTo(double width, double height, bool reverseX, bool reverseY, PointF2D point, double[] transformed) { if (transformed == null) { throw new ArgumentNullException(); } if (transformed.Length != 2) { throw new ArgumentException("Tranformed array needs to be of length 2."); } PointF2D reference = _bottomLeft; VectorF2D vectorX = _vectorX; VectorF2D vectorY = _vectorY; if (reverseX && !reverseY) { reference = this.BottomRight; vectorX = _vectorX * -1; } else if (!reverseX && reverseY) { reference = this.TopLeft; vectorY = _vectorY * -1; } else if (reverseX && reverseY) { reference = this.TopRight; vectorX = _vectorX * -1; vectorY = _vectorY * -1; } LineF2D xLine = new LineF2D(point, point + vectorX, false); PointF2D yIntersection = xLine.Intersection(new LineF2D(reference, reference + vectorY)) as PointF2D; VectorF2D yIntersectionVector = (yIntersection - reference); double yFactor = yIntersectionVector.Size / vectorY.Size; if (!yIntersectionVector.CompareNormalized(vectorY, 0.0001)) { yFactor = -yFactor; } LineF2D yLine = new LineF2D(point, point + vectorY); PointF2D xIntersection = yLine.Intersection(new LineF2D(reference, reference + vectorX)) as PointF2D; VectorF2D xIntersectionVector = (xIntersection - reference); double xFactor = xIntersectionVector.Size / vectorX.Size; if (!xIntersectionVector.CompareNormalized(vectorX, 0.0001)) { xFactor = -xFactor; } transformed [0] = xFactor * width; transformed [1] = yFactor * height; }
public bool Intersects(LineF2D line) { PointF2D[] corners = this.Corners; LinePointPosition linePointPosition = line.PositionOfPoint(corners[0]); for (int index = 1; index <= corners.Length; ++index) { if (line.PositionOfPoint(corners[index]) != linePointPosition) { return(true); } } return(false); }
/// <summary> /// Transforms the given the coordinates to a coordinate system defined inside this rectangle. /// </summary> /// <param name="width">The width of the rectangle in the coordinate system of the given coordinates.</param> /// <param name="height">The height of the rectangle in the coordinate system of the given coordinates.</param> /// <param name="reverseX">Assumes that the origin of the x-axis is on the top of this rectangle if false.</param> /// <param name="reverseY">Assumes that the origin of the y-axis is on the right of this rectangle if false.</param> /// <param name="x">The x-coordinate to transform.</param> /// <param name="y">The y-coordinate to transform.</param> public double[][] TransformTo(double width, double height, bool reverseX, bool reverseY, double[] x, double[] y) { PointF2D reference = _bottomLeft; VectorF2D vectorX = _vectorX; VectorF2D vectorY = _vectorY; if (reverseX && !reverseY) { reference = this.BottomRight; vectorX = _vectorX * -1; } else if (!reverseX && reverseY) { reference = this.TopLeft; vectorY = _vectorY * -1; } else if (reverseX && reverseY) { reference = this.TopRight; vectorX = _vectorX * -1; vectorY = _vectorY * -1; } double[][] transformed = new double[x.Length][]; for (int idx = 0; idx < x.Length; idx++) { PointF2D point = new PointF2D(x [idx], y [idx]); LineF2D xLine = new LineF2D(point, point + vectorX, false); PointF2D yIntersection = xLine.Intersection(new LineF2D(reference, reference + vectorY)) as PointF2D; VectorF2D yIntersectionVector = (yIntersection - reference); double yFactor = yIntersectionVector.Size / vectorY.Size; if (!yIntersectionVector.CompareNormalized(vectorY, 0.0001)) { yFactor = -yFactor; } LineF2D yLine = new LineF2D(point, point + vectorY); PointF2D xIntersection = yLine.Intersection(new LineF2D(reference, reference + vectorX)) as PointF2D; VectorF2D xIntersectionVector = (xIntersection - reference); double xFactor = xIntersectionVector.Size / vectorX.Size; if (!xIntersectionVector.CompareNormalized(vectorX, 0.0001)) { xFactor = -xFactor; } transformed[idx] = new double[] { xFactor *width, yFactor *height }; } return(transformed); }
public bool Intersects(PointF2D point1, PointF2D point2) { PointF2D[] corners = this.Corners; LineF2D lineF2D = new LineF2D(point1, point2, true); LinePointPosition linePointPosition = lineF2D.PositionOfPoint(corners[0]); for (int index = 1; index < corners.Length; ++index) { if (lineF2D.PositionOfPoint(corners[index]) != linePointPosition) { return(true); } } return(false); }
public RectangleF2D Fit(PointF2D[] points, double percentage) { if (points == null) { throw new ArgumentNullException("points"); } if (points.Length < 2) { throw new ArgumentOutOfRangeException("Rectangle fit needs at least two points."); } double[] values = new double[2] { points[0][0], points[0][1] }; for (int index = 1; index < points.Length; ++index) { values[0] = values[0] + points[index][0]; values[1] = values[1] + points[index][1]; } values[0] = values[0] / (double)points.Length; values[1] = values[1] / (double)points.Length; PointF2D p = new PointF2D(values); double num1 = 0.0; for (int index = 0; index < points.Length; ++index) { double num2 = new LineF2D(points[index], points[index] + this._vectorY).Distance(p); if (num2 > num1) { num1 = num2; } } double num3 = num1 * 2.0; double num4 = 0.0; for (int index = 0; index < points.Length; ++index) { double num2 = new LineF2D(points[index], points[index] + this._vectorX).Distance(p); if (num2 > num4) { num4 = num2; } } double num5 = num4 * 2.0; return(RectangleF2D.FromBoundsAndCenter(num3 + num3 / 100.0 * percentage, num5 + num5 / 100.0 * percentage, p[0], p[1], this.DirectionY)); }
/// <summary> /// Projects a point onto the given line. /// /// (= intersection of the line with an angle 90° different from this line through the given point) /// </summary> /// <param name="point"></param> /// <returns>The projection point if it occurs inside the segmented line.</returns> public PointF2D ProjectOn(PointF2D point) { if (this.Length == 0 && this.IsSegment) { // cannot project on a line of length zero. return(null); } // get the direction. VectorF2D direction = this.Direction; // rotate. VectorF2D rotated = direction.Rotate90(true); // create second point PointF2D point2 = new PointF2D((point + rotated).ToArray()); if (point[0] != point2[0] || point[1] != point2[1]) { // create line. LineF2D line = new LineF2D( point, point2, false, false); // intersect. PrimitiveF2D primitive = this.Intersection(line, true); if (primitive == null) { return(null); } else if (primitive is PointF2D) { return(primitive as PointF2D); } else { throw new InvalidOperationException(); } } else { return(point2); } }
/// <summary> /// Transforms the given the coordinates to a coordinate system defined inside this rectangle. /// </summary> /// <param name="width">The width of the rectangle in the coordinate system of the given coordinates.</param> /// <param name="height">The height of the rectangle in the coordinate system of the given coordinates.</param> /// <param name="reverseX">Assumes that the origin of the x-axis is on the top of this rectangle if false.</param> /// <param name="reverseY">Assumes that the origin of the y-axis is on the right of this rectangle if false.</param> /// <param name="point">The coordinate to transform.</param> public double[] TransformTo(double width, double height, bool reverseX, bool reverseY, PointF2D point) { PointF2D reference = _bottomLeft; VectorF2D vectorX = _vectorX; VectorF2D vectorY = _vectorY; if (reverseX && !reverseY) { reference = this.BottomRight; vectorX = _vectorX * -1; } else if (!reverseX && reverseY) { reference = this.TopLeft; vectorY = _vectorY * -1; } else if (reverseX && reverseY) { reference = this.TopRight; vectorX = _vectorX * -1; vectorY = _vectorY * -1; } LineF2D xLine = new LineF2D(point, point + vectorX, false); PointF2D yIntersection = xLine.Intersection(new LineF2D(reference, reference + vectorY)) as PointF2D; VectorF2D yIntersectionVector = (yIntersection - reference); double yFactor = yIntersectionVector.Size / vectorY.Size; if (!yIntersectionVector.CompareNormalized(vectorY, 0.0001)) { yFactor = -yFactor; } LineF2D yLine = new LineF2D(point, point + vectorY); PointF2D xIntersection = yLine.Intersection(new LineF2D(reference, reference + vectorX)) as PointF2D; VectorF2D xIntersectionVector = (xIntersection - reference); double xFactor = xIntersectionVector.Size / vectorX.Size; if (!xIntersectionVector.CompareNormalized(vectorX, 0.0001)) { xFactor = -xFactor; } return(new double[] { xFactor *width, yFactor *height }); }
/// <summary> /// Returns true if the line intersects with this bounding box. /// </summary> /// <param name="line"></param> /// <returns></returns> public bool Intersects(LineF2D line) { // if all points have the same relative position with respect to the line // there is no intersection. In the other case there is. PointF2D[] corners = this.Corners; LinePointPosition first_position = line.PositionOfPoint(corners[0]); for (int idx = 1; idx <= corners.Length; idx++) { if (line.PositionOfPoint(corners[idx]) != first_position) { return(true); } } return(false); }
/// <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 override double Distance(PointF2D p) { double num1 = new LineF2D(this.BottomLeft, this.BottomRight, true).Distance(p); double num2 = new LineF2D(this.BottomRight, this.TopRight, true).Distance(p); if (num2 < num1) { num1 = num2; } double num3 = new LineF2D(this.TopRight, this.TopLeft, true).Distance(p); if (num3 < num1) { num1 = num3; } double num4 = new LineF2D(this.TopLeft, this.BottomLeft, true).Distance(p); if (num4 < num1) { num1 = num4; } return(num1); }
public PointF2D[] Intersections(LineF2D line) { List<PointF2D> pointF2DList = new List<PointF2D>(); foreach (LineF2D line1 in this.LineEnumerator) { PrimitiveF2D primitiveF2D = line.Intersection(line1); if (primitiveF2D != null) { if (primitiveF2D is LineF2D) { LineF2D lineF2D = primitiveF2D as LineF2D; pointF2DList.Add(lineF2D.Point1); pointF2DList.Add(lineF2D.Point2); } else if ((object) (primitiveF2D as PointF2D) != null) { PointF2D pointF2D = primitiveF2D as PointF2D; pointF2DList.Add(pointF2D); } } } return pointF2DList.ToArray(); }
/// <summary> /// Calculates and returns the line intersection. /// </summary> /// <param name="line"></param> /// <param name="doSegment"></param> /// <returns></returns> public PrimitiveF2D Intersection(LineF2D line, bool doSegment) { if (line == this) { // if the lines equal, the full lines intersect. return line; } else if (line.A == this.A && line.B == this.B && line.C == this.C) { // if the lines equal in direction and position; return the smallest segment. KeyValuePair<double, PointF2D> point1 = new KeyValuePair<double, PointF2D>( 0, this.Point1); KeyValuePair<double, PointF2D> point2 = new KeyValuePair<double, PointF2D>( this.Point1.Distance(this.Point2), this.Point2); // sort. KeyValuePair<double, PointF2D> temp; if (point2.Key < point1.Key) { // point2 smaller than point1. temp = point2; point2 = point1; point1 = temp; } KeyValuePair<double, PointF2D> point = new KeyValuePair<double, PointF2D>( this.Point1.Distance(line.Point1), line.Point1); if (point.Key < point2.Key) // sort. { // point smaller than point2. temp = point; point = point2; point2 = temp; } if (point2.Key < point1.Key) { // point2 smaller than point1. temp = point2; point2 = point1; point1 = temp; } point = new KeyValuePair<double, PointF2D>( this.Point1.Distance(line.Point2), line.Point2); if (point.Key < point2.Key) // sort. { // point smaller than point2. temp = point; point = point2; point2 = temp; } if (point2.Key < point1.Key) { // point2 smaller than point1. temp = point2; point2 = point1; point1 = temp; } // this line is a segment. if (doSegment && (this.IsSegment1 || this.IsSegment2)) { // test where the intersection lies. double this_distance = this.Point1.Distance(this.Point2); if (this.IsSegment) { // if in any directions one of the points are further away from the point. double this_distance_1 = System.Math.Min(this.Point1.Distance(point1.Value), this.Point1.Distance(point2.Value)); if (this_distance_1 > this_distance) { // the point is further away. return null; } } else if (this.IsSegment1) { // if in any directions one of the points are further away from the point. double this_distance_1 = this.Point1.Distance(point1.Value); if (this_distance_1 > this_distance) { // the point is further away. return null; } } else if (this.IsSegment2) { // if in any directions one of the points are further away from the point. double this_distance_2 = this.Point2.Distance(point1.Value); if (this_distance_2 > this_distance) { // the point is further away. return null; } } } // other line is a segment. if (doSegment && (line.IsSegment1 || line.IsSegment2)) { // test where the intersection lies. double this_distance = line.Point1.Distance(line.Point2); if (line.IsSegment) {// if in any directions one of the points are further away from the point. double this_distance_1 = System.Math.Min(line.Point1.Distance(point1.Value), line.Point1.Distance(point2.Value)); if (this_distance_1 > this_distance) { // the point is further away. return null; } } else if (line.IsSegment1) { // if in any directions one of the points are further away from the point. double this_distance_1 = line.Point1.Distance(point1.Value); if (this_distance_1 > this_distance) { // the point is further away. return null; } } else if (line.IsSegment2) { // if in any directions one of the points are further away from the point. double this_distance_2 = line.Point2.Distance(point2.Value); if (this_distance_2 > this_distance) { // the point is further away. return null; } } } return new LineF2D( point1.Value, point2.Value, true); } else { // line.A = A1, line.B = B1, line.C = C1, this.A = A2, this.B = B2, this.C = C2 double det = (line.A * this.B - this.A * line.B); if (det == 0) // TODO: implement an accuracy threshold epsilon. { // lines are parallel; no intersections. return null; } else { // lines are not the same and not parallel so they will intersect. double x = (this.B * line.C - line.B * this.C) / det; double y = (line.A * this.C - this.A * line.C) / det; // create the point. PointF2D point = new PointF2D(new double[]{x, y}); // this line is a segment. if (doSegment && (this.IsSegment1 || this.IsSegment2)) { // test where the intersection lies. double this_distance = this.Point1.Distance(this.Point2); if (this.IsSegment) {// if in any directions one of the points are further away from the point. double this_distance_1 = this.Point1.Distance(point); if (this_distance_1 > this_distance) { // the point is further away. return null; } double this_distance_2 = this.Point2.Distance(point); if (this_distance_2 > this_distance) { // the point is further away. return null; } } else if (this.IsSegment1 && this.Point2.Distance(point) > this_distance) { // only check this direction and only if the points lies far enough away from point2. VectorF2D pointDirection = point - this.Point2; VectorF2D point2ToPoint1 = this.Direction.Inverse; if (pointDirection.CompareNormalized(point2ToPoint1, 0.001)) { // point lies in the direction of the segmented point1 and far away from point2 return null; } } else if (this.IsSegment1 && this.Point1.Distance(point) > this_distance) { // only check this direction and only if the points lies far enough away from point1. VectorF2D pointDirection = point - this.Point1; VectorF2D point1ToPoint2 = this.Direction; if (pointDirection.CompareNormalized(point1ToPoint2, 0.001)) { // point lies in the direction of the segmented point1 and far away from point2 return null; } } } // line this is a segment. if (doSegment && (line.IsSegment1 || line.IsSegment2)) { // test where the intersection lies. double line_distance = line.Point1.Distance(line.Point2); if (line.IsSegment) {// if in any directions one of the points are further away from the point. double line_distance_1 = line.Point1.Distance(point); if (line_distance_1 > line_distance) { // the point is further away. return null; } double line_distance_2 = line.Point2.Distance(point); if (line_distance_2 > line_distance) { // the point is further away. return null; } } else if (line.IsSegment1 && line.Point2.Distance(point) > line_distance) { // only check line direction and only if the points lies far enough away from point2. VectorF2D pointDirection = point - line.Point2; VectorF2D point2ToPoint1 = line.Direction.Inverse; if (pointDirection.CompareNormalized(point2ToPoint1, 0.001)) { // point lies in the direction of the segmented point1 and far away from point2 return null; } } else if (line.IsSegment1 && line.Point1.Distance(point) > line_distance) { // only check line direction and only if the points lies far enough away from point1. VectorF2D pointDirection = point - line.Point1; VectorF2D point1ToPoint2 = line.Direction; if (pointDirection.CompareNormalized(point1ToPoint2, 0.001)) { // point lies in the direction of the segmented point1 and far away from point2 return null; } } } // the intersection is valid. return point; } } }
/// <summary> /// Return true if the given line intersects with this line. /// </summary> /// <param name="line">Line.</param> public bool Intersects(LineF2D line) { return this.Intersection (line) != null; }
/// <summary> /// Return true if the given line intersects with this line. /// </summary> /// <param name="line">Line.</param> /// <param name="doSegment"></param> public bool Intersects(LineF2D line, bool doSegment) { return this.Intersection (line, doSegment) != null; }
/// <summary> /// Transforms the given the coordinates to a coordinate system defined inside this rectangle. /// </summary> public double[] TransformTo(double width, double height, bool reverseX, bool reverseY, PointF2D point) { PointF2D reference = _bottomLeft; VectorF2D vectorX = _vectorX; VectorF2D vectorY = _vectorY; if (reverseX && !reverseY) { reference = this.BottomRight; vectorX = _vectorX * -1; } else if (!reverseX && reverseY) { reference = this.TopLeft; vectorY = _vectorY * -1; } else if (reverseX && reverseY) { reference = this.TopRight; vectorX = _vectorX * -1; vectorY = _vectorY * -1; } LineF2D xLine = new LineF2D (point, point + vectorX, false); PointF2D yIntersection = xLine.Intersection (new LineF2D (reference, reference + vectorY)) as PointF2D; VectorF2D yIntersectionVector = (yIntersection - reference); double yFactor = yIntersectionVector.Size / vectorY.Size; if (!yIntersectionVector.CompareNormalized (vectorY, 0.0001)) { yFactor = -yFactor; } LineF2D yLine = new LineF2D (point, point + vectorY); PointF2D xIntersection = yLine.Intersection (new LineF2D (reference, reference + vectorX)) as PointF2D; VectorF2D xIntersectionVector = (xIntersection - reference); double xFactor = xIntersectionVector.Size / vectorX.Size; if (!xIntersectionVector.CompareNormalized (vectorX, 0.0001)) { xFactor = -xFactor; } return new double[] { xFactor * width, yFactor * height }; }
/// <summary> /// Transforms the given the coordinates to a coordinate system defined inside this rectangle. /// </summary> /// <param name="width">Width.</param> /// <param name="height">Height.</param> /// <param name="reverseX">If set to <c>true</c> reverse x.</param> /// <param name="reverseY">If set to <c>true</c> reverse y.</param> /// <param name="point">Point.</param> /// <param name="transformed">Transformed.</param> public void TransformTo(double width, double height, bool reverseX, bool reverseY, PointF2D point, double[] transformed) { if (transformed == null) { throw new ArgumentNullException (); } if (transformed.Length != 2) { throw new ArgumentException ("Tranformed array needs to be of length 2."); } PointF2D reference = _bottomLeft; VectorF2D vectorX = _vectorX; VectorF2D vectorY = _vectorY; if (reverseX && !reverseY) { reference = this.BottomRight; vectorX = _vectorX * -1; } else if (!reverseX && reverseY) { reference = this.TopLeft; vectorY = _vectorY * -1; } else if (reverseX && reverseY) { reference = this.TopRight; vectorX = _vectorX * -1; vectorY = _vectorY * -1; } LineF2D xLine = new LineF2D (point, point + vectorX, false); PointF2D yIntersection = xLine.Intersection (new LineF2D (reference, reference + vectorY)) as PointF2D; VectorF2D yIntersectionVector = (yIntersection - reference); double yFactor = yIntersectionVector.Size / vectorY.Size; if (!yIntersectionVector.CompareNormalized (vectorY, 0.0001)) { yFactor = -yFactor; } LineF2D yLine = new LineF2D (point, point + vectorY); PointF2D xIntersection = yLine.Intersection (new LineF2D (reference, reference + vectorX)) as PointF2D; VectorF2D xIntersectionVector = (xIntersection - reference); double xFactor = xIntersectionVector.Size / vectorX.Size; if (!xIntersectionVector.CompareNormalized (vectorX, 0.0001)) { xFactor = -xFactor; } transformed [0] = xFactor * width; transformed [1] = yFactor * height; }
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!"); }
/// <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 (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; }
/// <summary> /// Return true if the given line intersects with this line. /// </summary> /// <param name="line">Line.</param> public bool Intersects(LineF2D line) { return(this.Intersection(line) != null); }
/// <summary> /// Calculates and returns the line intersection. /// </summary> /// <param name="line"></param> /// <returns></returns> public PrimitiveF2D Intersection(LineF2D line) { return this.Intersection(line, true); }
/// <summary> /// Return true if the given line intersects with this line. /// </summary> /// <param name="line">Line.</param> /// <param name="doSegment"></param> public bool Intersects(LineF2D line, bool doSegment) { return(this.Intersection(line, doSegment) != null); }
/// <summary> /// Calculates and returns the line intersection. /// </summary> /// <param name="line"></param> /// <returns></returns> public PrimitiveF2D Intersection(LineF2D line) { return(this.Intersection(line, true)); }
/// <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; }
/// <summary> /// Projects a point onto the given line. /// /// (= intersection of the line with an angle 90° different from this line through the given point) /// </summary> /// <param name="point"></param> /// <returns>The projection point if it occurs inside the segmented line.</returns> public PointF2D ProjectOn(PointF2D point) { // get the direction. VectorF2D direction = this.Direction; // rotate. VectorF2D rotated = direction.Rotate90(true); // create second point PointF2D point2 = new PointF2D((point + rotated).ToArray()); if (point[0] != point2[0] || point[1] != point2[1]) { // create line. LineF2D line = new LineF2D( point, point2, false, false); // intersect. PrimitiveF2D primitive = this.Intersection(line, true); if (primitive == null) { return null; } else if (primitive is PointF2D) { return primitive as PointF2D; } else { throw new InvalidOperationException(); } } else { return point2; } }
/// <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(double[] coordinate) { int number = 0; if (this.X[0] == coordinate[0] && this.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 < this.X.Length - 1; idx++) { if (this.X[idx + 1] == coordinate[0] && this.Y[idx + 1] == coordinate[1]) { // the given point is one of the corners. return true; } bool idxRight = this.X[idx] > coordinate[0]; bool idx1Right = this.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 ((this.Y[idx] <= coordinate[1] && this.Y[idx + 1] >= coordinate[1]) && !(this.Y[idx] == coordinate[1] && this.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(this.X[idx], this.Y[idx]), new PointF2D(this.X[idx + 1], this.Y[idx + 1])); if (localLine.PositionOfPoint(new PointF2D(coordinate)) == LinePointPosition.Left) { number++; } } } else if ((this.Y[idx] >= coordinate[1] && this.Y[idx + 1] <= coordinate[1]) && !(this.Y[idx] == coordinate[1] && this.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(this.X[idx], this.Y[idx]), new PointF2D(this.X[idx + 1], this.Y[idx + 1])); if (localLine.PositionOfPoint(new PointF2D(coordinate)) == LinePointPosition.Right) { number--; } } } } } return number != 0; }
/// <summary> /// Fits this rectangle to the given points. /// </summary> /// <param name="points">The points to wrap the rectangle around.</param> /// <param name="percentage">The margin in percentage.</param> /// <returns></returns> public RectangleF2D Fit(PointF2D[] points, double percentage) { if (points == null) { throw new ArgumentNullException("points"); } if (points.Length < 2) { throw new ArgumentOutOfRangeException("Rectangle fit needs at least two points."); } // calculate the center. double[] center = new double[] { points[0][0], points[0][1] }; for (int idx = 1; idx < points.Length; idx++) { center[0] = center[0] + points[idx][0]; center[1] = center[1] + points[idx][1]; } center[0] = center[0] / points.Length; center[1] = center[1] / points.Length; PointF2D centerPoint = new PointF2D(center); LineF2D line = null; // calculate the width. double width = 0; for (int idx = 0; idx < points.Length; idx++) { line = new LineF2D(points[idx], points[idx] + this._vectorY); double distance = line.Distance(centerPoint); if (distance > width) { // the distance is larger. width = distance; } } width = width * 2; // calculate the height. double height = 0; for (int idx = 0; idx < points.Length; idx++) { line = new LineF2D(points[idx], points[idx] + this._vectorX); double distance = line.Distance(centerPoint); if (distance > height) { // this distance is larger. height = distance; } } height = height * 2; // expand with the given percentage. width = width + (width / 100.0 * percentage); height = height + (height / 100.0 * percentage); return RectangleF2D.FromBoundsAndCenter(width, height, centerPoint[0], centerPoint[1], this.DirectionY); }
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> /// Calculates and returns the line intersection. /// </summary> /// <param name="line"></param> /// <param name="doSegment"></param> /// <returns></returns> public PrimitiveF2D Intersection(LineF2D line, bool doSegment) { if (line == this) { // if the lines equal, the full lines intersect. return(line); } else if (line.A == this.A && line.B == this.B && line.C == this.C) { // if the lines equal in direction and position; return the smallest segment. KeyValuePair <double, PointF2D> point1 = new KeyValuePair <double, PointF2D>( 0, this.Point1); KeyValuePair <double, PointF2D> point2 = new KeyValuePair <double, PointF2D>( this.Point1.Distance(this.Point2), this.Point2); // sort. KeyValuePair <double, PointF2D> temp; if (point2.Key < point1.Key) { // point2 smaller than point1. temp = point2; point2 = point1; point1 = temp; } KeyValuePair <double, PointF2D> point = new KeyValuePair <double, PointF2D>( this.Point1.Distance(line.Point1), line.Point1); if (point.Key < point2.Key) // sort. { // point smaller than point2. temp = point; point = point2; point2 = temp; } if (point2.Key < point1.Key) { // point2 smaller than point1. temp = point2; point2 = point1; point1 = temp; } point = new KeyValuePair <double, PointF2D>( this.Point1.Distance(line.Point2), line.Point2); if (point.Key < point2.Key) // sort. { // point smaller than point2. temp = point; point = point2; point2 = temp; } if (point2.Key < point1.Key) { // point2 smaller than point1. temp = point2; point2 = point1; point1 = temp; } // this line is a segment. if (doSegment && (this.IsSegment1 || this.IsSegment2)) { // test where the intersection lies. double this_distance = this.Point1.Distance(this.Point2); if (this.IsSegment) { // if in any directions one of the points are further away from the point. double this_distance_1 = System.Math.Min(this.Point1.Distance(point1.Value), this.Point1.Distance(point2.Value)); if (this_distance_1 > this_distance) { // the point is further away. return(null); } } else if (this.IsSegment1) { // if in any directions one of the points are further away from the point. double this_distance_1 = this.Point1.Distance(point1.Value); if (this_distance_1 > this_distance) { // the point is further away. return(null); } } else if (this.IsSegment2) { // if in any directions one of the points are further away from the point. double this_distance_2 = this.Point2.Distance(point1.Value); if (this_distance_2 > this_distance) { // the point is further away. return(null); } } } // other line is a segment. if (doSegment && (line.IsSegment1 || line.IsSegment2)) { // test where the intersection lies. double this_distance = line.Point1.Distance(line.Point2); if (line.IsSegment) {// if in any directions one of the points are further away from the point. double this_distance_1 = System.Math.Min(line.Point1.Distance(point1.Value), line.Point1.Distance(point2.Value)); if (this_distance_1 > this_distance) { // the point is further away. return(null); } } else if (line.IsSegment1) { // if in any directions one of the points are further away from the point. double this_distance_1 = line.Point1.Distance(point1.Value); if (this_distance_1 > this_distance) { // the point is further away. return(null); } } else if (line.IsSegment2) { // if in any directions one of the points are further away from the point. double this_distance_2 = line.Point2.Distance(point2.Value); if (this_distance_2 > this_distance) { // the point is further away. return(null); } } } return(new LineF2D( point1.Value, point2.Value, true)); } else { // line.A = A1, line.B = B1, line.C = C1, this.A = A2, this.B = B2, this.C = C2 double det = (line.A * this.B - this.A * line.B); if (det == 0) // TODO: implement an accuracy threshold epsilon. { // lines are parallel; no intersections. return(null); } else { // lines are not the same and not parallel so they will intersect. double x = (this.B * line.C - line.B * this.C) / det; double y = (line.A * this.C - this.A * line.C) / det; // create the point. PointF2D point = new PointF2D(new double[] { x, y }); // this line is a segment. if (doSegment && (this.IsSegment1 || this.IsSegment2)) { // test where the intersection lies. double this_distance = this.Point1.Distance(this.Point2); if (this.IsSegment) {// if in any directions one of the points are further away from the point. double this_distance_1 = this.Point1.Distance(point); if (this_distance_1 > this_distance) { // the point is further away. return(null); } double this_distance_2 = this.Point2.Distance(point); if (this_distance_2 > this_distance) { // the point is further away. return(null); } } else if (this.IsSegment1 && this.Point2.Distance(point) > this_distance) { // only check this direction and only if the points lies far enough away from point2. VectorF2D pointDirection = point - this.Point2; VectorF2D point2ToPoint1 = this.Direction.Inverse; if (pointDirection.CompareNormalized(point2ToPoint1, 0.001)) { // point lies in the direction of the segmented point1 and far away from point2 return(null); } } else if (this.IsSegment1 && this.Point1.Distance(point) > this_distance) { // only check this direction and only if the points lies far enough away from point1. VectorF2D pointDirection = point - this.Point1; VectorF2D point1ToPoint2 = this.Direction; if (pointDirection.CompareNormalized(point1ToPoint2, 0.001)) { // point lies in the direction of the segmented point1 and far away from point2 return(null); } } } // line this is a segment. if (doSegment && (line.IsSegment1 || line.IsSegment2)) { // test where the intersection lies. double line_distance = line.Point1.Distance(line.Point2); if (line.IsSegment) {// if in any directions one of the points are further away from the point. double line_distance_1 = line.Point1.Distance(point); if (line_distance_1 > line_distance) { // the point is further away. return(null); } double line_distance_2 = line.Point2.Distance(point); if (line_distance_2 > line_distance) { // the point is further away. return(null); } } else if (line.IsSegment1 && line.Point2.Distance(point) > line_distance) { // only check line direction and only if the points lies far enough away from point2. VectorF2D pointDirection = point - line.Point2; VectorF2D point2ToPoint1 = line.Direction.Inverse; if (pointDirection.CompareNormalized(point2ToPoint1, 0.001)) { // point lies in the direction of the segmented point1 and far away from point2 return(null); } } else if (line.IsSegment1 && line.Point1.Distance(point) > line_distance) { // only check line direction and only if the points lies far enough away from point1. VectorF2D pointDirection = point - line.Point1; VectorF2D point1ToPoint2 = line.Direction; if (pointDirection.CompareNormalized(point1ToPoint2, 0.001)) { // point lies in the direction of the segmented point1 and far away from point2 return(null); } } } // the intersection is valid. return(point); } } }
/// <summary> /// Returns true if the two points could potentially intersect this bounding box. /// /// This is a rudemantairy quick test to rule out intersection. /// - If false is returned there can be no intersection. /// - If true is returned there might be intersection but it is not certain. /// </summary> /// <param name="line"></param> /// <returns></returns> public bool IntersectsPotentially(LineF2D line) { return(this.IntersectsPotentially(line.Point1, line.Point2)); }
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)); }
/// <summary> /// Returns all the intersections the line has with this polygon. /// </summary> /// <param name="line"></param> /// <returns></returns> public PointF2D[] Intersections(LineF2D line) { List<PointF2D> points = new List<PointF2D>(); foreach (LineF2D polygon_line in this.LineEnumerator) { // calculate the intersection. PrimitiveF2D primitive = line.Intersection(polygon_line); // the primitive not null. if (primitive != null) { if (primitive is LineF2D) { // primitive is a line; convert. LineF2D intersect_line = (primitive as LineF2D); // we are sure the line is a segment. // if the line is not a segment this means that the polygon contains an line with infinite length; impossible. // TODO: how to determine the order? points.Add(intersect_line.Point1); points.Add(intersect_line.Point2); } else if (primitive is PointF2D) { // primitive is a point; convert. PointF2D point = (primitive as PointF2D); points.Add(point); } } } return points.ToArray(); }
public PrimitiveF2D Intersection(LineF2D line, bool doSegment) { if (line == this) { return((PrimitiveF2D)line); } if (line.A == this.A && line.B == this.B && line.C == this.C) { KeyValuePair <double, PointF2D> keyValuePair1 = new KeyValuePair <double, PointF2D>(0.0, this.Point1); KeyValuePair <double, PointF2D> keyValuePair2 = new KeyValuePair <double, PointF2D>(this.Point1.Distance(this.Point2), this.Point2); if (keyValuePair2.Key < keyValuePair1.Key) { KeyValuePair <double, PointF2D> keyValuePair3 = keyValuePair2; keyValuePair2 = keyValuePair1; keyValuePair1 = keyValuePair3; } KeyValuePair <double, PointF2D> keyValuePair4 = new KeyValuePair <double, PointF2D>(this.Point1.Distance(line.Point1), line.Point1); if (keyValuePair4.Key < keyValuePair2.Key) { KeyValuePair <double, PointF2D> keyValuePair3 = keyValuePair4; keyValuePair4 = keyValuePair2; keyValuePair2 = keyValuePair3; } if (keyValuePair2.Key < keyValuePair1.Key) { KeyValuePair <double, PointF2D> keyValuePair3 = keyValuePair2; keyValuePair2 = keyValuePair1; keyValuePair1 = keyValuePair3; } keyValuePair4 = new KeyValuePair <double, PointF2D>(this.Point1.Distance(line.Point2), line.Point2); if (keyValuePair4.Key < keyValuePair2.Key) { KeyValuePair <double, PointF2D> keyValuePair3 = keyValuePair4; keyValuePair4 = keyValuePair2; keyValuePair2 = keyValuePair3; } if (keyValuePair2.Key < keyValuePair1.Key) { KeyValuePair <double, PointF2D> keyValuePair3 = keyValuePair2; keyValuePair2 = keyValuePair1; keyValuePair1 = keyValuePair3; } if (doSegment && (this.IsSegment1 || this.IsSegment2)) { double num = this.Point1.Distance(this.Point2); if (this.IsSegment) { if (System.Math.Min(this.Point1.Distance(keyValuePair1.Value), this.Point1.Distance(keyValuePair2.Value)) > num) { return((PrimitiveF2D)null); } } else if (this.IsSegment1) { if (this.Point1.Distance(keyValuePair1.Value) > num) { return((PrimitiveF2D)null); } } else if (this.IsSegment2 && this.Point2.Distance(keyValuePair1.Value) > num) { return((PrimitiveF2D)null); } } if (doSegment && (line.IsSegment1 || line.IsSegment2)) { double num = line.Point1.Distance(line.Point2); if (line.IsSegment) { if (System.Math.Min(line.Point1.Distance(keyValuePair1.Value), line.Point1.Distance(keyValuePair2.Value)) > num) { return((PrimitiveF2D)null); } } else if (line.IsSegment1) { if (line.Point1.Distance(keyValuePair1.Value) > num) { return((PrimitiveF2D)null); } } else if (line.IsSegment2 && line.Point2.Distance(keyValuePair2.Value) > num) { return((PrimitiveF2D)null); } } return((PrimitiveF2D) new LineF2D(keyValuePair1.Value, keyValuePair2.Value, true)); } double num1 = line.A * this.B - this.A * line.B; if (num1 == 0.0) { return((PrimitiveF2D)null); } PointF2D p = new PointF2D(new double[2] { (this.B * line.C - line.B * this.C) / num1, (line.A * this.C - this.A * line.C) / num1 }); if (doSegment && (this.IsSegment1 || this.IsSegment2)) { double num2 = this.Point1.Distance(this.Point2); if (this.IsSegment) { if (this.Point1.Distance(p) > num2) { return((PrimitiveF2D)null); } if (this.Point2.Distance(p) > num2) { return((PrimitiveF2D)null); } } else if (this.IsSegment1 && this.Point2.Distance(p) > num2) { if ((p - this.Point2).CompareNormalized(this.Direction.Inverse, 0.001)) { return((PrimitiveF2D)null); } } else if (this.IsSegment1 && this.Point1.Distance(p) > num2 && (p - this.Point1).CompareNormalized(this.Direction, 0.001)) { return((PrimitiveF2D)null); } } if (doSegment && (line.IsSegment1 || line.IsSegment2)) { double num2 = line.Point1.Distance(line.Point2); if (line.IsSegment) { if (line.Point1.Distance(p) > num2) { return((PrimitiveF2D)null); } if (line.Point2.Distance(p) > num2) { return((PrimitiveF2D)null); } } else if (line.IsSegment1 && line.Point2.Distance(p) > num2) { if ((p - line.Point2).CompareNormalized(line.Direction.Inverse, 0.001)) { return((PrimitiveF2D)null); } } else if (line.IsSegment1 && line.Point1.Distance(p) > num2 && (p - line.Point1).CompareNormalized(line.Direction, 0.001)) { return((PrimitiveF2D)null); } } return((PrimitiveF2D)p); }