Example #1
0
        public void Reorder(int width, int height)
        {
            //Checks if the site is fully included in the frame :
            if (Edges.Select(e => e.VVertexA).All(p => IsVectorInRange(p, width, height)) &&
                Edges.Select(e => e.VVertexB).All(p => IsVectorInRange(p, width, height)))
            {
                IsOnBorder = false;
            }
            else
            {
                IsOnBorder = true;
                Vector previousIntersection = null;
                for (int i = Edges.Count - 1; i >= 0; i--)
                {
                    VoronoiEdge edge  = Edges[i];
                    bool        isAIn = IsVectorInRange(edge.VVertexA, width, height);
                    bool        isBIn = IsVectorInRange(edge.VVertexB, width, height);
                    if (isAIn && isBIn) // Edge is fully in, nothing to do
                    {
                        continue;
                    }
                    if (isAIn || isBIn) // One point in in, needs to be clipped
                    {
                        double        slope         = edge.DirectionVector[1] / edge.DirectionVector[0];
                        Vector        pointIn       = isAIn ? new Vector(edge.VVertexA) : new Vector(edge.VVertexB);
                        List <Vector> intersections = new List <Vector>();
                        //Test collision with (0,0) => (width,0) edge :
                        intersections.Add(new Vector(pointIn[0] - pointIn[1] / slope, 0));
                        //Test collision with (0,height) => (width,height) edge :
                        intersections.Add(new Vector(pointIn[0] + (height - pointIn[1]) / slope, height));
                        //Test collision with (0,0) => (0,height) edge :
                        intersections.Add(new Vector(0, pointIn[1] - pointIn[0] * slope));
                        //Test collision with (width,0) => (width,height) edge :
                        intersections.Add(new Vector(width, pointIn[1] + (width - pointIn[0]) * slope));
                        Vector intersection = intersections.MinBy(p => Vector.Dist(p, pointIn));
                        Edges.RemoveAt(i);
                        Edges.Add(new VoronoiEdge {
                            VVertexA = intersection, VVertexB = pointIn
                        });
                        if (previousIntersection == null)
                        {
                            previousIntersection = intersection;
                        }
                        else
                        {
                            if (intersection[0].Equals(previousIntersection[0]) ||
                                intersection[1].Equals(previousIntersection[1]))
                            {
                                Edges.Add(new VoronoiEdge {
                                    VVertexA = intersection, VVertexB = previousIntersection
                                });
                                IsOnBorder           = true;
                                previousIntersection = null;
                            }
                            else
                            {
                                List <Vector> corners = new List <Vector>
                                {
                                    new Vector(0, 0),
                                    new Vector(width, 0),
                                    new Vector(width, height),
                                    new Vector(0, height)
                                };
                                foreach (Vector corner in corners)
                                {
                                    if ((corner[0].Equals(previousIntersection[0]) ||
                                         corner[0].Equals(intersection[0])) &&
                                        (corner[1].Equals(previousIntersection[1]) ||
                                         corner[1].Equals(intersection[1])))
                                    {
                                        Edges.Add(new VoronoiEdge {
                                            VVertexA = corner, VVertexB = previousIntersection
                                        });
                                        Edges.Add(new VoronoiEdge {
                                            VVertexA = corner, VVertexB = intersection
                                        });
                                        IsOnBorder = true;
                                        break;
                                    }
                                }
                                previousIntersection = null;
                            }
                        }
                    }
                    else // Edge fully out, can be safely removed
                    {
                        Edges.RemoveAt(i);
                    }
                }
                if (previousIntersection != null)
                {
                    throw new InvalidOperationException("Error");
                }
            }
            if (Edges.Count == 0)
            {
                throw new InvalidOperationException("No edges");
            }

            VoronoiEdge first = Edges[Edges.Count - 1];

            Edges.RemoveAt(Edges.Count - 1);
            Vector point;

            VoronoiPoints.Add(point = first.VVertexA);
            Edges.RemoveAll((e) => Equals(e.VVertexA, e.VVertexB));
            do
            {
                VoronoiEdge edge = Edges.Single(e => e.VVertexA.Equals(point) || e.VVertexB.Equals(point));
                Edges.Remove(edge);
                if (Equals(edge.VVertexA, point))
                {
                    VoronoiPoints.Add(point = edge.VVertexB);
                }
                else
                {
                    VoronoiPoints.Add(point = edge.VVertexA);
                }
            } while (!Equals(point, first.VVertexB));
            Edges.Clear();
            //Reverse ordering of the points if needed :
            Vector v1 = VoronoiPoints[0] - VoronoiPoints[1];
            Vector v2 = VoronoiCenter - VoronoiPoints[0];

            if (v1[0] * v2[1] - v1[1] * v2[0] > 0)
            {
                VoronoiPoints.Reverse();
            }
        }