private double?offsetX; // Not for horizontals private Line(double?slope, ICartesianCoordinate point) { this.slope = slope; offsetX = slope.HasValue ? (slope.Value.Equals(0.0) ? (double?)null : point.X - point.Y / slope.Value) : point.X; offsetY = slope.HasValue ? point.Y - slope.Value * point.X : (double?)null; }
//public static bool IsPointInsideRing_WindingNumber(IEnumerable<ICartesianCoordinate> ring, ICartesianCoordinate point) //{ // //var boundingRectangle = GetBoundingRectangle(ring); // //// obvious cases // //if (point.X < boundingRectangle.LowerLeft.X || point.X > boundingRectangle.UpperRight.X) // // return false; // //if (point.Y < boundingRectangle.LowerLeft.Y || point.Y > boundingRectangle.UpperRight.Y) // // return false; // int windingNumberCount = 0; // the winding number counter // var ringwalker = new RingWalker(ring); // foreach(var pointInRing in ringwalker) // { // if (pointInRing.curr.Equals(point)) // return true; // if (pointInRing.prev.Y <= point.Y) // { // start y <= P.y // if (pointInRing.curr.Y > point.Y && // an upward crossing // !new Triangle(pointInRing.prev, pointInRing.curr, point).RightOrientation()) // P left of edge // ++windingNumberCount; // have a valid up intersect // } // else // { // start y > P.y (no test needed) // if (pointInRing.curr.Y <= point.Y && // a downward crossing // new Triangle(pointInRing.prev, pointInRing.curr, point).RightOrientation()) // P right of edge // --windingNumberCount; // have a valid down intersect // } // } // return windingNumberCount != 0; //} // Winding ring algoritm with few extensions and optimalizations. Very fast. // Bounding rectangle can be used in combination with intelligent polygon but otherwise too time consuming. // Other optimalizations still possible. Same remark. Ex. Monotone polygons etc... public static bool IsPointInsideRing(IList <ICartesianCoordinate> ring, ICartesianCoordinate point /*, bool includeBorder = true*/) { bool flipflop = false; const bool includeBorder = true; // Algoritm could be parameterized to optionally include the border. for (int i = 0, j = ring.Count - 1; i < ring.Count; j = i++) { if (ring[j].Equals(point)) { return(includeBorder); } bool b = ring[i].Y <= point.Y; if (b != (ring[j].Y <= point.Y)) { var triangularOrientation = (ring[j].X - ring[i].X) * (point.Y - ring[i].Y) - (ring[j].Y - ring[i].Y) * (point.X - ring[i].X); //var triangularOrientation = new Triangle(ring[i], ring[j], point).Orientation(); if (triangularOrientation > 0 && b || triangularOrientation < 0 && !b) { flipflop = !flipflop; } else if (triangularOrientation == 0) { return(includeBorder); } } } return(flipflop); }
private double? offsetX; // Not for horizontals private Line(double? slope, ICartesianCoordinate point) { this.slope = slope; offsetX = slope.HasValue ? (slope.Value.Equals(0.0) ? (double?) null : point.X - point.Y / slope.Value) : point.X; offsetY = slope.HasValue ? point.Y - slope.Value * point.X : (double?)null; }
public float StackPoint(ICartesianCoordinate point, int seriesStackPosition) { var start = seriesStackPosition == 0 ? 0 : stack[seriesStackPosition - 1][point.Index].End; var value = direction == SeriesDirection.Horizontal ? point.X : point.Y; var si = stack[seriesStackPosition]; if (si.Count < point.Index + 1) { si.Add(new StackedValue { Start = start, End = start + value }); totals.Add(value); knownMaxLenght++; } else { si[point.Index] = new StackedValue { Start = start, End = start + value }; } var total = totals[point.Index] + value; totals[point.Index] = total; return(total); }
public static double DistanceSquared(ICartesianCoordinate p1, ICartesianCoordinate p2) { var diffX = p2.X - p1.X; var diffY = p2.Y - p1.Y; return(diffX * diffX + diffY * diffY); }
public StackedValue GetStack(int seriesStackPosition, ICartesianCoordinate point) { var p = stack[seriesStackPosition][point.Index]; return(new StackedValue { Start = p.Start, End = p.End }); }
//public static bool IsRectangleInsideRing(ICartesianCoordinate[] ring, IRectangle rectangle) //{ // return (IsPointInsideRing(ring, rectangle.UpperLeft) && // IsPointInsideRing(ring, rectangle.UpperRight) && // IsPointInsideRing(ring, rectangle.LowerLeft) && // IsPointInsideRing(ring, rectangle.LowerRight)); //} public static bool IsPerpendicular(ICartesianCoordinate pointA, ICartesianCoordinate pointB, ICartesianCoordinate pointC, ICartesianCoordinate pointD) { if (pointB.Y.Equals(pointA.Y) && pointD.X.Equals(pointC.X) || pointB.X.Equals(pointA.X) && pointD.Y.Equals(pointC.Y)) { return(true); } var rico1 = (pointB.Y - pointA.Y) / (pointB.X - pointA.X); var rico2 = (pointD.Y - pointC.Y) / (pointD.X - pointC.X); return(rico1 * rico2 == -1); }
// Monotone Chain algoritm by Andrew 1979 public ICartesianCoordinate[] Algorithm(IEnumerable <ICartesianCoordinate> pointcloud) { var pointcloudArray = pointcloud.ToArray(); if (pointcloudArray.Length > 1) { var hull = new ICartesianCoordinate[2 * pointcloudArray.Length]; Array.Sort(pointcloudArray, new PointComparerForMonotoneChainAlgorithm()); int k = 0; // Lower hull for (int i = 0; i < pointcloudArray.Length; i++) { while (k >= 2 && GoniometryAlgorithms.CrossProduct(hull[k - 2], hull[k - 1], pointcloudArray[i]) <= 0) { k--; } hull[k++] = pointcloudArray[i]; } // Upper hull for (int i = pointcloudArray.Length - 2, t = k + 1; i >= 0; i--) { while (k >= t && GoniometryAlgorithms.CrossProduct(hull[k - 2], hull[k - 1], pointcloudArray[i]) <= 0) { k--; } hull[k++] = pointcloudArray[i]; } Array.Resize(ref hull, k - 1); return(hull); } else if (pointcloudArray.Length <= 1) { return(pointcloudArray); } else { return(null); } }
public static Line CreateFromTwoPoints(ICartesianCoordinate pointA, ICartesianCoordinate pointB) { double?slope = pointB.X.Equals(pointA.X) ? (double?)null : (pointB.Y - pointA.Y) / (pointB.X - pointA.X); return(new Line(slope, pointA)); }
public static Line CreateHorizontalThroughPoint(ICartesianCoordinate point) { return new Line(0.0, point); }
public static Line CreateFromSlopeAndPoint(double slope, ICartesianCoordinate point) { return new Line(slope, point); }
public static Line CreateFromTwoPoints(ICartesianCoordinate pointA, ICartesianCoordinate pointB) { double? slope = pointB.X.Equals(pointA.X) ? (double?)null : (pointB.Y - pointA.Y) / (pointB.X - pointA.X); return new Line(slope, pointA); }
public static Line CreateVerticalThroughPoint(ICartesianCoordinate point) { return new Line(null, point); }
public bool Equals(ICartesianCoordinate other) { return X.Equals(other.X) && Y.Equals(other.Y); }
//public static bool Contains(IList<GeoCoordinate> Coordinates, GeoCoordinate coordinate) //{ // bool flipflop = false; // const bool includeBorder = true; // Algoritm could be parameterized to optionally include the border. // for (int i = 0, j = Coordinates.Count - 1; i < Coordinates.Count; j = i++) // { // if (Coordinates[j].Equals(coordinate)) // return includeBorder; // bool b = Coordinates[i].Latitude <= coordinate.Latitude; // if (b != (Coordinates[j].Latitude <= coordinate.Latitude)) // { // var triangularOrientation = (Coordinates[j].Longitude - Coordinates[i].Longitude) * (coordinate.Latitude - Coordinates[i].Latitude) - (Coordinates[j].Latitude - Coordinates[i].Latitude) * (coordinate.Longitude - Coordinates[i].Longitude); // if (triangularOrientation > 0 && b || triangularOrientation < 0 && !b) // flipflop = !flipflop; // else if (triangularOrientation == 0) // return includeBorder; // } // } // return flipflop; //} //public static bool Contains2(IList<PointF2D> Coordinates, GeoCoordinate coordinate) //{ // bool flipflop = false; // const bool includeBorder = true; // Algoritm could be parameterized to optionally include the border. // for (int i = 0, j = Coordinates.Count - 1; i < Coordinates.Count; j = i++) // { // if (Coordinates[j].Equals(coordinate)) // return includeBorder; // bool b = Coordinates[i][1] <= coordinate.Latitude; // if (b != (Coordinates[j][1] <= coordinate.Latitude)) // { // var triangularOrientation = (Coordinates[j][0] - Coordinates[i][0]) * (coordinate.Latitude - Coordinates[i][1]) - (Coordinates[j][1] - Coordinates[i][1]) * (coordinate.Longitude - Coordinates[i][0]); // if (triangularOrientation > 0 && b || triangularOrientation < 0 && !b) // flipflop = !flipflop; // else if (triangularOrientation == 0) // return includeBorder; // } // } // return flipflop; //} public static bool IsLineSegmentInsideRing(IList <ICartesianCoordinate> ring, ICartesianCoordinate pointA, ICartesianCoordinate pointB, bool includeBorder = true) { for (int i = 0; i < ring.Count - 1; i++) { var test1 = new Triangle(ring[i], ring[i + 1], pointA).Orientation() * new Triangle(ring[i], ring[i + 1], pointB).Orientation(); var test2 = new Triangle(pointA, pointB, ring[i]).Orientation() * new Triangle(pointA, pointB, ring[i + 1]).Orientation(); if ((test1 <= 0) && (test2 <= 0)) { return(false); } } return(IsPointInsideRing(ring, pointA /*, includeBorder*/) && IsPointInsideRing(ring, pointB /*, includeBorder*/)); }
public static Line CreateHorizontalThroughPoint(ICartesianCoordinate point) { return(new Line(0.0, point)); }
public static Line CreateFromSlopeAndPoint(double slope, ICartesianCoordinate point) { return(new Line(slope, point)); }
//// TODO check gedoe met includeborder //public static bool IsPointInsideConvexRing(IEnumerable<ICartesianCoordinate> convexRing, ICartesianCoordinate point, bool includeBorder = true) //{ // //var boundingRectangle = GetBoundingRectangle(convexRing); // //// obvious cases // //if (point.X < boundingRectangle.LowerLeft.X || point.X > boundingRectangle.UpperRight.X) // // return false; // //if (point.Y < boundingRectangle.LowerLeft.Y || point.Y > boundingRectangle.UpperRight.Y) // // return false; // foreach (var coordinate in new RingWalker(convexRing)) // .Skip(1).Union(new [] { prev})) // { // var t = new Triangle(coordinate.prevprev, coordinate.prev, point); // var isOnBorder = t.IsFlattened(); // // TODO optimaliseer deze ifs // if ((!point.Equals(coordinate.prevprev) || !includeBorder) && (!point.Equals(coordinate) || !includeBorder) && !t.RightOrientation() && (!isOnBorder || !includeBorder)) // return false; // } // return true; //} //public static bool IsPointInsideRing_Trivial(IEnumerable<ICartesianCoordinate> ring, ICartesianCoordinate point) //{ // var convexring = new RingWalker(ring).Where(t => new Triangle(t.prevprev, t.prev, t.curr).RightOrientation()); // var concavePoints = new RingWalker(ring).Where(t => !new Triangle(t.prevprev, t.prev, t.curr).RightOrientation()); // if (IsPointInsideConvexRing(convexring.Select(t => t.prev), point)) // { // foreach(var concavePoint in concavePoints) // { // if (IsPointInsideConvexRing(new[] {concavePoint.prevprev, concavePoint.curr, concavePoint.prev}, point, false)) // return false; // } // return true; // } // return false; //} public static double CrossProduct(ICartesianCoordinate origin, ICartesianCoordinate P1, ICartesianCoordinate P2) { return((P1.X - origin.X) * (P2.Y - origin.Y) - (P2.X - origin.X) * (P1.Y - origin.Y)); }
public bool Equals(ICartesianCoordinate other) { return(X.Equals(other.X) && Y.Equals(other.Y)); }
public Triangle(ICartesianCoordinate point1, ICartesianCoordinate point2, ICartesianCoordinate point3) { this.point1 = point1; this.point2 = point2; this.point3 = point3; }
public static GDIPoint ToGDI(this ICartesianCoordinate coordinate) { return(new GDIPoint(Convert.ToInt32(coordinate.X), Convert.ToInt32(coordinate.Y))); }
public static Line CreateVerticalThroughPoint(ICartesianCoordinate point) { return(new Line(null, point)); }
public static double DistanceSquared(ICartesianCoordinate p1, ICartesianCoordinate p2) { var diffX = p2.X - p1.X; var diffY = p2.Y - p1.Y; return diffX * diffX + diffY * diffY; }