public static List <LineSegmentFr> Voronoi(List <PointFr> points) { var triangulation = TriangulateIterative(points); var ch = new PolygonFr(ConvexHullJarvis(points)); var dictTriEdges = new Dictionary <LineSegmentFr, PointFr>(); var voronoiDiagram = new List <LineSegmentFr>(); foreach (var triangle in triangulation) { var circumCenter = triangle.CircumCircle().Center; foreach (var edge in triangle.Edges(true)) { if (dictTriEdges.ContainsKey(edge)) { voronoiDiagram.Add(new LineSegmentFr(circumCenter, dictTriEdges[edge], true)); dictTriEdges.Remove(edge); } else { dictTriEdges.Add(edge, circumCenter); } } } voronoiDiagram.AddRange( dictTriEdges.Where(kvp => ch.Contains2(kvp.Value) && kvp.Key.Center() != kvp.Value) .Select(kvp => new LineSegmentFr(kvp.Key.Center(), kvp.Value))); for (var i = voronoiDiagram.Count - 1; i >= 0; i--) { var edge = voronoiDiagram[i]; var chIntersections = ch.Intersections(edge); if (chIntersections.Count > 2) { throw new Exception("Błędne obliczenia"); } if (!ch.Contains2(edge.StartPoint) && !ch.Contains2(edge.EndPoint)) // chIntersections.Count > 1 || { voronoiDiagram.Remove(edge); continue; } if (!ch.Contains2(edge.StartPoint)) { edge.StartPoint = chIntersections.Except(edge.EndPoints()).Single(); } else if (!ch.Contains2(edge.EndPoint)) { edge.EndPoint = chIntersections.Except(edge.EndPoints()).Single(); } voronoiDiagram[i] = edge; } return(voronoiDiagram); }
public static bool IsInsideConvexPolygon(PointFr point, PolygonFr polygon) { var vertices = polygon.Vertices.ToList(); // wierzchołki posortowane przeciwnie do wskazówek zegara względem wnętrza wielokąta var edges = polygon.Edges().ToList(); if (vertices.Count < 3) { throw new ArgumentException("Polygon can't have less than 3 vertices"); } if (ConvexHullJarvis(vertices).Count != vertices.Count) // Powinno wystarczyć Count { throw new ArgumentException("Polygon must be convex"); } if (vertices.Count == 3) { return(!edges.Any(point.IsRightOf)); } var polyCenter = polygon.Center; if (polyCenter == null) { throw new Exception("Can't calculate center of the Polygon"); } var mid = (PointFr)polyCenter; while (edges.Count > 1) { var testSegment = new LineSegmentFr(mid, edges[edges.Count / 2].StartPoint); if (point.IsRightOf(testSegment)) { edges = edges.Take(edges.Count / 2).ToList(); } else if (point.IsLeftOf(testSegment)) { edges = edges.Skip(edges.Count / 2).ToList(); } else if (testSegment.Contains(point)) { return(true); } else { throw new Exception("Invalid calculations performed, it should never happen"); } } return(!point.IsRightOf(edges.Single())); // czyli IsLeftOf + Contains, jeżeli jest we wierzchołku to będzie spełniony ostatni warunek z while'a }
public static bool IsInsidePolygon(PointFr point, PolygonFr polygon) { if (polygon.Edges(true).Any(edge => edge.Contains(point))) { return(true); } var vertices = polygon.Vertices.ToList(); int i, j = vertices.Count - 1; var contains = false; for (i = 0; i < vertices.Count; i++) { if ((vertices[i].Y < point.Y && vertices[j].Y >= point.Y || vertices[j].Y < point.Y && vertices[i].Y >= point.Y) && (vertices[i].X <= point.X || vertices[j].X <= point.X)) { contains ^= (vertices[i].X + (point.Y - vertices[i].Y) / (vertices[j].Y - vertices[i].Y) * (vertices[j].X - vertices[i].X) < point.X); } j = i; } return(contains); }
public bool Contains(PolygonFr polygon) { var ps = polygon.Vertices.ToList(); return(ps.Count != 0 && ps.All(Contains)); }