private void CreateHighlightEffect(double x, double y)
        {
            Point?point = _voronoi.NearestSitePoint(x, y);

            if (point.HasValue)
            {
                List <LineSegment> boundaries = _voronoi.VoronoiBoundaryForSite(point.Value);
                IEnumerable <Line> lines      = ShapeSegments.Where(segment => segment is Line).Cast <Line>();
            }
        }
예제 #2
0
    private void CreateFromVoronoi(Voronoi voronoi)
    {
        vertices = new Dictionary <Vector3, Vertex>();

        nodesByCenterPosition = new Dictionary <Vector3, Node>();
        var edgesByStartPosition = new Dictionary <Vector3, List <Edge> >();

        edges = new List <Edge>();

        plotBounds = voronoi.plotBounds;

        var bottomLeftSite  = voronoi.NearestSitePoint(plotBounds.xMin, plotBounds.yMin);
        var bottomRightSite = voronoi.NearestSitePoint(plotBounds.xMax, plotBounds.yMin);
        var topLeftSite     = voronoi.NearestSitePoint(plotBounds.xMin, plotBounds.yMax);
        var topRightSite    = voronoi.NearestSitePoint(plotBounds.xMax, plotBounds.yMax);

        var topLeft     = new Vector3(plotBounds.xMin, 0, plotBounds.yMax);
        var topRight    = new Vector3(plotBounds.xMax, 0, plotBounds.yMax);
        var bottomLeft  = new Vector3(plotBounds.xMin, 0, plotBounds.yMin);
        var bottomRight = new Vector3(plotBounds.xMax, 0, plotBounds.yMin);

        var siteEdges = new Dictionary <Vector2, List <LineSegment> >();

        var edgePointsRemoved = 0;

        foreach (var edge in voronoi.Edges())
        {
            if (!edge.visible)
            {
                continue;
            }

            var p1 = edge.clippedEnds[Delaunay.LR.Side.LEFT];
            var p2 = edge.clippedEnds[Delaunay.LR.Side.RIGHT];

            var segment = new LineSegment(p1, p2);

            if (Vector2.Distance(p1.Value, p2.Value) < 0.001f)
            {
                edgePointsRemoved++;
                continue;
            }

            if (edge.leftSite != null)
            {
                if (!siteEdges.ContainsKey(edge.leftSite.Coord))
                {
                    siteEdges.Add(edge.leftSite.Coord, new List <LineSegment>());
                }
                siteEdges[edge.leftSite.Coord].Add(segment);
            }

            if (edge.rightSite != null)
            {
                if (!siteEdges.ContainsKey(edge.rightSite.Coord))
                {
                    siteEdges.Add(edge.rightSite.Coord, new List <LineSegment>());
                }
                siteEdges[edge.rightSite.Coord].Add(segment);
            }
        }

        Debug.Assert(edgePointsRemoved == 0, string.Format("{0} edge points too close and have been removed", edgePointsRemoved));

        foreach (var site in voronoi.SiteCoords())
        {
            var boundries   = GetBoundriesForSite(siteEdges, site);
            var center      = ToVector3(site);
            var currentNode = new Node {
                centerPoint = center
            };

            nodesByCenterPosition.Add(center, currentNode);

            Edge firstEdge    = null;
            Edge previousEdge = null;

            for (var i = 0; i < boundries.Count; i++)
            {
                var edge = boundries[i];

                var start = ToVector3(edge.p0.Value);
                var end   = ToVector3(edge.p1.Value);
                if (start == end)
                {
                    continue;
                }

                previousEdge = AddEdge(edgesByStartPosition, previousEdge, start, end, currentNode);
                if (firstEdge == null)
                {
                    firstEdge = previousEdge;
                }
                if (currentNode.startEdge == null)
                {
                    currentNode.startEdge = previousEdge;
                }

                // We need to figure out if the two edges meet, and if not then
                // insert some more edges to close the polygon
                var insertEdges = false;
                if (i < boundries.Count - 1)
                {
                    start       = ToVector3(boundries[i + 0].p1.Value);
                    end         = ToVector3(boundries[i + 1].p0.Value);
                    insertEdges = start != end;
                }
                else if (i == boundries.Count - 1)
                {
                    start       = ToVector3(boundries[i].p1.Value);
                    end         = ToVector3(boundries[0].p0.Value);
                    insertEdges = start != end;
                }

                if (insertEdges)
                {
                    // Check which corners are within this node
                    var startIsTop    = start.z == voronoi.plotBounds.yMax;
                    var startIsBottom = start.z == voronoi.plotBounds.yMin;
                    var startIsLeft   = start.x == voronoi.plotBounds.xMin;
                    var startIsRight  = start.x == voronoi.plotBounds.xMax;

                    var hasTopLeft     = site == topLeftSite && !(startIsTop && startIsLeft);
                    var hasTopRight    = site == topRightSite && !(startIsTop && startIsRight);
                    var hasBottomLeft  = site == bottomLeftSite && !(startIsBottom && startIsLeft);
                    var hasBottomRight = site == bottomRightSite && !(startIsBottom && startIsRight);

                    if (startIsTop)
                    {
                        if (hasTopRight)
                        {
                            previousEdge = AddEdge(edgesByStartPosition, previousEdge, start, topRight, currentNode);
                        }
                        if (hasBottomRight)
                        {
                            previousEdge = AddEdge(edgesByStartPosition, previousEdge, previousEdge.destination.position, bottomRight, currentNode);
                        }
                        if (hasBottomLeft)
                        {
                            previousEdge = AddEdge(edgesByStartPosition, previousEdge, previousEdge.destination.position, bottomLeft, currentNode);
                        }
                        if (hasTopLeft)
                        {
                            previousEdge = AddEdge(edgesByStartPosition, previousEdge, previousEdge.destination.position, topLeft, currentNode);
                        }
                    }
                    else if (startIsRight)
                    {
                        if (hasBottomRight)
                        {
                            previousEdge = AddEdge(edgesByStartPosition, previousEdge, start, bottomRight, currentNode);
                        }
                        if (hasBottomLeft)
                        {
                            previousEdge = AddEdge(edgesByStartPosition, previousEdge, previousEdge.destination.position, bottomLeft, currentNode);
                        }
                        if (hasTopLeft)
                        {
                            previousEdge = AddEdge(edgesByStartPosition, previousEdge, previousEdge.destination.position, topLeft, currentNode);
                        }
                        if (hasTopRight)
                        {
                            previousEdge = AddEdge(edgesByStartPosition, previousEdge, previousEdge.destination.position, topRight, currentNode);
                        }
                    }
                    else if (startIsBottom)
                    {
                        if (hasBottomLeft)
                        {
                            previousEdge = AddEdge(edgesByStartPosition, previousEdge, start, bottomLeft, currentNode);
                        }
                        if (hasTopLeft)
                        {
                            previousEdge = AddEdge(edgesByStartPosition, previousEdge, previousEdge.destination.position, topLeft, currentNode);
                        }
                        if (hasTopRight)
                        {
                            previousEdge = AddEdge(edgesByStartPosition, previousEdge, previousEdge.destination.position, topRight, currentNode);
                        }
                        if (hasBottomRight)
                        {
                            previousEdge = AddEdge(edgesByStartPosition, previousEdge, previousEdge.destination.position, bottomRight, currentNode);
                        }
                    }
                    else if (startIsLeft)
                    {
                        if (hasTopLeft)
                        {
                            previousEdge = AddEdge(edgesByStartPosition, previousEdge, start, topLeft, currentNode);
                        }
                        if (hasTopRight)
                        {
                            previousEdge = AddEdge(edgesByStartPosition, previousEdge, previousEdge.destination.position, topRight, currentNode);
                        }
                        if (hasBottomRight)
                        {
                            previousEdge = AddEdge(edgesByStartPosition, previousEdge, previousEdge.destination.position, bottomRight, currentNode);
                        }
                        if (hasBottomLeft)
                        {
                            previousEdge = AddEdge(edgesByStartPosition, previousEdge, previousEdge.destination.position, bottomLeft, currentNode);
                        }
                    }

                    previousEdge = AddEdge(edgesByStartPosition, previousEdge, previousEdge.destination.position, end, currentNode);
                }
            }

            // Connect up the end of the loop
            previousEdge.next  = firstEdge;
            firstEdge.previous = previousEdge;

            AddLeavingEdge(firstEdge);
        }

        ConnectOpposites(edgesByStartPosition);
    }