private static Ship CreateShip(Point startPoint, Point endPoint) { var list = new List<Point> { startPoint }; if (startPoint != endPoint) { list.Add(endPoint); } list.Sort(); if (list.Count > 1 && startPoint.DistanceTo(endPoint) > 2) { if (list[0].X == list[1].X) { // vertical for (var y = (byte)(list[0].Y + 1); y < list[1].Y; ++y) { list.Add(new Point(list[0].X, y, true, false)); } } else { // Horiz for (var x = (char)(list[0].X + 1); x < list[1].X; ++x) { list.Add(new Point(x, list[0].Y, true, false)); } } } list.Sort(); return new Ship(list.ToArray()); }
public void DistanceTest() { Point p1 = new Point(0, 0); Point p2 = new Point(1, 1); Assert.AreEqual<double>(p1.DistanceTo(p2), 2, "Distance unexpected"); Assert.AreEqual<double>(p1.DistanceTo(p2), p2.DistanceTo(p1), "Distance not equal in both directions"); bool threwException = false; try { p1.DistanceTo(null); } catch (ArgumentNullException) { threwException = true; } Assert.IsTrue(threwException, "Did not throw ArgumentNullException"); }
bool CreateEdgesFromEdges(Point p) { // Point p is near an edge, and we build a perpendicular edge from p to that edge, // or a new edge from p to an end of the edge. bool created = false; int i, N = edges.Count; Edge e; for (i = 0; i < N; i++) { e = edges[i]; double dist = p.DistanceTo(e); // If point p is close to e, but not on e... if (dist < Epsilon && !Util.IsZero(dist)) { Point intersection = e.IntersectWithPerpendicular(p); if (e.Contains(intersection)) { edges.Add(new Edge(p, intersection)); created = true; } else // Or just create with nearest edge end, if possible if (p.DistanceTo(e.P1) < Epsilon) { edges.Add(new Edge(p, e.P1)); created = true; } else if (p.DistanceTo(e.P2) < Epsilon) { edges.Add(new Edge(p, e.P2)); created = true; } } } return created; }
bool MergePointInEdge(Point p) { // Checks if this point belongs to an already existing edge. foreach (Edge e in edges) if (p.DistanceTo(e) < Epsilon && p.Between(e.P1, e.P2)) return true; return false; }
bool ExtendEdges(Point p) { // Point p is on director vector of edge e, and we extend e to include p. List<Edge> extended = new List<Edge>(); foreach (Edge e in edges) if (p.OnLine(e.P1, e.P2) && p != e.P1 && p != e.P2) { int where = p.Where(e.P1, e.P2); if (where == 1 && p.DistanceTo(e.P1) < Epsilon) { e.P1 = p; extended.Add(e); } if (where == 2 && p.DistanceTo(e.P2) < Epsilon) { e.P2 = p; extended.Add(e); } } if (extended.Count == 0) return false; // We try to link 2 extended edges to p to form a single edge. Point P1, P2; for (int i = 0; i < extended.Count; i++) if (extended[i] != null) { if (extended[i].P1 == p) P1 = extended[i].P2; else P1 = extended[i].P1; for (int j = i + 1; j < extended.Count; j++) if (extended[j] != null) { if (extended[j].P1 == p) P2 = extended[j].P2; else P2 = extended[j].P1; if (p.OnLine(P1, P2)) { // This works because extended[i] is a pointer! extended[i].P1 = P1; extended[i].P2 = P2; edges.Remove(extended[j]); extended[j] = null; break; } } } return true; }
bool CreateEdgesFromPoints(Point p) { // Finds >= MinPointsInLine points (including point p) that are ~ colinear and // creates an edge from them. Can build multiple edges. bool created = false; Dictionary<double, List<int>> dex = new Dictionary<double, List<int>>(); for (int i = 0; i < points.Count; i++) if (p.DistanceTo(points[i]) < MinPointsInLine * Epsilon) { double angle; if (Util.IsEqual(p.X, points[i].X)) angle = double.NaN; else { angle = (p.Y - points[i].Y) / (p.X - points[i].X); angle = Math.Truncate(angle / EpsilonAngle) * EpsilonAngle; } if (!dex.ContainsKey(angle)) dex[angle] = new List<int>(2 * MinPointsInLine); dex[angle].Add(i); } foreach (KeyValuePair<double, List<int>> item in dex) if (item.Value.Count >= MinPointsInLine) { // Merge the points from item.Value into a single edge. List<int> indexes = item.Value; Point min, max; min = points[indexes[0]]; max = points[indexes[0]]; for (int i = 1; i < indexes.Count; i++) { min = Point.Min(min, points[indexes[i]]); max = Point.Max(max, points[indexes[i]]); } // Remove the points. indexes.Sort(); for (int i = indexes.Count - 1; i >= 0; i--) points.RemoveAt(indexes[i]); // Add the new edge. Edge newEdge = new Edge(min, max); if (!MergeEdge(newEdge)) edges.Add(newEdge); created = true; } return created; }
/// <summary> /// Calculate Euclidean distance between a point and a finite line segment. /// </summary> /// /// <param name="point">The point to calculate the distance to.</param> /// /// <returns>Returns the Euclidean distance between this line segment and the specified point. Unlike /// <see cref="Line.DistanceToPoint"/>, this returns the distance from the finite segment. (0,0) is 5 units /// from the segment (0,5)-(0,8), but is 0 units from the line through those points.</returns> /// public float DistanceToPoint(Point point) { float segmentDistance; switch (LocateProjection(point)) { case ProjectionLocation.RayA: segmentDistance = point.DistanceTo(start); break; case ProjectionLocation.RayB: segmentDistance = point.DistanceTo(end); break; default: segmentDistance = line.DistanceToPoint(point); break; }; return segmentDistance; }
public Point IntersectCircles(Point c1, double r1, Point c2, double r2, Point c3, double r3) { // To compute the intersection of the 3 circle, we intersect two of them, get 2 // solutions, and see which one is on the third circle. // Step 1: Translate all circle centers so that c1 = (0, 0). c2 = c2 - c1; c3 = c3 - c1; // Step 2: Rotate all around (0, 0) so that c2 is now on Ox axis. double O = Math.Atan2(c2.Y, c2.X); c2 = c2.Rotate(-O); c3 = c3.Rotate(-O); // Step 3: Intersect circles (0, 0, r1) with (c2.X, 0, r2) Point p1 = new Point(), p2 = new Point(), sol; p1.X = p2.X = (r1 * r1 - r2 * r2 + c2.X * c2.X) / (2 * c2.X); // sqrt( negative zero ) = NaN if (r1 > p1.X) p1.Y = Math.Sqrt(r1 * r1 - p1.X * p1.X); else p1.Y = 0; p2.Y = - p1.Y; if (Util.IsEqual(p2.DistanceTo(c3), r3)) sol = p2; else sol = p1; // Unapply step 2 sol = sol.Rotate(O); // Unapply step 1 sol = sol + c1; return sol; }
public override void Query(ref Point point, out Sample.Location sample) { sample.Distance = float.MaxValue; FullLine selectedLine = _Lines[0]; if(_Lines.Length > 1) { foreach(FullLine line in _Lines) { Point point1 = line.Point1; Point point2 = line.Point2; float newDistance = point.SquaredDistanceTo(point1, point2); if(newDistance < sample.Distance) { sample.Distance = newDistance; selectedLine = line; } } } sample.Distance = point.DistanceTo( selectedLine.Point1, selectedLine.Point2, out sample.Intersection); }