示例#1
0
 private void Delaunay_Click(object sender, EventArgs e)
 {
     for (int i = 0; i < Array_of_vertexes.Count(); ++i)
         Array_of_vertexes[i].Highlighted = false;
     DrawEvents.Clear();
     DrawEvents.Add(new Painting(Array_of_vertexes, new List<Edge>()));
     List<Vector> Points = new List<Vector>(AlgorithmsVisualiser.Pack_into_ListOfVector(Array_of_vertexes));
     VoronoiGraph graph = new VoronoiGraph();
     graph = AlgorithmsVisualiser.FortuneAlgo(Points);
     List<VoronoiEdge> VE = graph.Edges.ToList<VoronoiEdge>();
     List<Edge> tri = AlgorithmsVisualiser.Delaunay(Array_of_vertexes, graph, DrawEvents);
     foreach(Edge edge in tri)
         edge.color = Color.Red;
     GL.LineWidth(1);
     DrawEvents.Add(new Painting(Array_of_vertexes, tri, VE));
 }
示例#2
0
        /// <summary>
        /// The Voronoi Graph calculation creates the lines that form a voronoi diagram.
        /// </summary>
        /// <param name="points">The points to use for creating the tesselation.</param>
        /// <returns>An IFeatureSet that is the resulting set of lines in the diagram.</returns>
        public static IFeatureSet VoronoiLines(IFeatureSet points)
        {
            double[]     vertices = points.Vertex;
            VoronoiGraph gp       = Fortune.ComputeVoronoiGraph(vertices);

            HandleBoundaries(gp, points.Extent.ToEnvelope());

            FeatureSet result = new FeatureSet();

            foreach (VoronoiEdge edge in gp.Edges)
            {
                Coordinate c1 = edge.VVertexA.ToCoordinate();
                Coordinate c2 = edge.VVertexB.ToCoordinate();
                LineString ls = new LineString(new[] { c1, c2 });
                result.AddFeature(ls);
            }

            return(result);
        }
示例#3
0
        private static List <VoronoiSite> CalculateVoronoiGraph(Dictionary <Vector, VoronoiSite> points, int width, int height)
        {
            VoronoiGraph result = Fortune.ComputeVoronoiGraph(points.Keys.ToList());

            foreach (VoronoiEdge edge in result.Edges)
            {
                VoronoiSite a = points[edge.LeftData];
                VoronoiSite b = points[edge.RightData];
                a.Neighbourgs.Add(b);
                b.Neighbourgs.Add(a);
                a.Edges.Add(edge);
                b.Edges.Add(edge);
            }
            foreach (VoronoiSite site in points.Values)
            {
                site.Reorder(width, height);
            }
            return(points.Values.ToList());
        }
    public bool regenerateVoronoi(bool drawmesh)
    {
        if (GameControl.gameSession == null || (region = GameControl.gameSession.mapGenerator.getRegion()) == null)
        {
            //Debug.Log("Cannot regenerate Voronoi for Water - gameSession is not ready.");
            return(false);
        }

        // prepare noise
        int   noise_seed = (useRandomSeed) ? UnityEngine.Random.Range(int.MinValue, int.MaxValue) : this.seed;
        Noise noise      = new FastPerlinNoise(noiseResolution, noise_seed, noiseAmplitude, noisePersistance);

        noise.setNoiseValues(NoiseMap.adjustNoise(noise.getNoiseValues(), 5));

        // get region parameters
        this.water_elevation = region.getWaterLevelElevation();
        this.size            = region.getViewableSize();
        int halfSize = this.size / 2;

        // generate random coordinates for polygons
        generateXY(out this.X, out this.Y);

        // use voronoi generator
        voronoi = new Voronoi(minDist);
        voronoi.generateVoronoi(X, Y, 0, size, 0, size);

        VoronoiGraph vG = voronoi.getVoronoiGraph();

        foreach (GraphEdge gE in vG.edges)
        {
            gE.x1 -= halfSize;
            gE.x2 -= halfSize;
            gE.y1 -= halfSize;
            gE.y2 -= halfSize;
        }

        if (drawmesh)
        {
            Meshes.WaterMesh.InitializeMesh(region, voronoi.getVoronoiGraph(), mesh, noise, maxWaterLevelDisplacement);
        }
        return(true);
    }
        private List <Line> GenerateLines(VoronoiGraph data)
        {
            var lines      = new List <Line>();
            var linePoints = new List <Point>();

            foreach (var edge in data.Edges)
            {
                if (edge.IsInfinite || edge.IsPartlyInfinite)
                {
                    continue;
                }

                var p1 = new Point(edge.VVertexA[0], edge.VVertexA[1]);
                var p2 = new Point(edge.VVertexB[0], edge.VVertexB[1]);

                var line = new Line(p1, p2);
                lines.Add(line);
            }

            return(lines);
        }
示例#6
0
    public VoronoiGraph RefineGraph(VoronoiGraph g)
    {
        // Removes out of bound edges from a graph
        VoronoiGraph VGErg = new VoronoiGraph();

        foreach (VoronoiEdge e in g.Edges)
        {
            if (EdgeInBounds(e))
            {
                VGErg.Edges.Add(e);
            }
        }

        foreach (VoronoiEdge VE in VGErg.Edges)
        {
            VGErg.Vertizes.Add(VE.VVertexA);
            VGErg.Vertizes.Add(VE.VVertexB);
        }

        return(VGErg);
    }
 public static List<Edge> Delaunay(List<Point> points, VoronoiGraph VG, List<IDrawable> visualSteps)
 {
     List<VoronoiEdge> edges = new List<VoronoiEdge>();
     List<Edge> edges_to_paint = new List<Edge>();
     edges = VG.Edges.ToList<VoronoiEdge>();
     List<Edge> result = new List<Edge>();
     for (int i = 0; i < edges.Count(); ++i)
     {
         Edge e_temp = new Edge(Pack_into_Edge(edges[i]), Color.Yellow);
         edges_to_paint.Add(e_temp);
         visualSteps.Add(new Painting(points,edges_to_paint, edges));
         Point p1 = new Point((int)edges[i].LeftData[0], (int)edges[i].LeftData[1]);
         Point p2 = new Point((int)edges[i].RightData[0], (int)edges[i].RightData[1]);
         Edge e = new Edge(p1, p2, Color.Yellow);
         result.Add(e);
         edges_to_paint.Add(e);
         visualSteps.Add(new Painting(points,edges_to_paint, edges));
         edges_to_paint.RemoveAt(edges_to_paint.Count - 2);
     }
     return result;
 }
示例#8
0
 // Update is called once per frame
 void Update()
 {
     if (Input.GetKeyDown(KeyCode.R))
     {
         Reset();
     }
     if (Input.GetKeyDown(KeyCode.C))
     {
         _result = null;
         CreateSites();
         CalculateVoronoi();
     }
     if (Input.GetKeyDown(KeyCode.F))
     {
         Fracture();
     }
     if (Input.GetKeyDown(KeyCode.E))
     {
         Explode();
     }
 }
示例#9
0
    GenerateRelaxedGraph(List <Vector> cv, int stepsLeft)
    {
        // Implementation of Lloyd's Relaxation algorithm
        // http://en.wikipedia.org/wiki/Lloyd's_algorithm

        VoronoiGraph  vg  = Voronoi(cv);
        List <Vector> ncv = new List <Vector>();

        if (stepsLeft == 0)
        {
            cellVectors = cv;
            return(RefineGraph(vg));
        }

        foreach (Vector v in cv)
        {
            Vector           centroid = new Vector(0, 0);
            HashSet <Vector> corners  = new HashSet <Vector>();

            foreach (VoronoiEdge e in vg.Edges)
            {
                if (e.LeftData != v && e.RightData != v)
                {
                    continue;
                }

                corners.Add(e.VVertexA);
                corners.Add(e.VVertexB);
            }

            foreach (Vector c in corners)
            {
                centroid += c;
            }

            ncv.Add(centroid / corners.Count);
        }

        return(GenerateRelaxedGraph(ncv, stepsLeft - 1));
    }
示例#10
0
        public void LoadMap(LoadMapParams loadMapParams)
        {
            VoronoiGraph voronoiMap = null;

            for (int i = 0; i < 3; i++)
            {
                voronoiMap = Fortune.ComputeVoronoiGraph(loadMapParams.Points);
                foreach (Vector vector in loadMapParams.Points)
                {
                    double v0  = 0.0d;
                    double v1  = 0.0d;
                    int    say = 0;
                    foreach (VoronoiEdge edge in voronoiMap.Edges)
                    {
                        if (edge.LeftData == vector || edge.RightData == vector)
                        {
                            double p0 = (edge.VVertexA[0] + edge.VVertexB[0]) / 2;
                            double p1 = (edge.VVertexA[1] + edge.VVertexB[1]) / 2;
                            v0 += double.IsNaN(p0) ? 0 : p0;
                            v1 += double.IsNaN(p1) ? 0 : p1;
                            say++;
                        }
                    }

                    if (((v0 / say) < 400) && ((v0 / say) > 0))
                    {
                        vector[0] = v0 / say;
                    }

                    if (((v1 / say) < 400) && ((v1 / say) > 0))
                    {
                        vector[1] = v1 / say;
                    }
                }
            }

            voronoiMap = Fortune.ComputeVoronoiGraph(loadMapParams.Points);
            ImproveMapData(voronoiMap, loadMapParams.Fix);
        }
示例#11
0
    // Voronoi methods
    private void makeVoronoiGraph()
    {
        List <Vector> VoronoiVectors = new List <Vector>();

        foreach (TraversableNode node in boarderMap)
        {
            VoronoiVectors.Add(new Vector(node.getCoordinate().x, node.getCoordinate().y));
        }

        VoronoiGraph nonPrunedGraph = Fortune.ComputeVoronoiGraph(VoronoiVectors);

        List <VoronoiEdge> toPrune = new List <VoronoiEdge>();

        VoronoiGraph voronoiGraph = nonPrunedGraph;

        foreach (VoronoiEdge edge in voronoiGraph.Edges)
        {
            VEdgeList.Add(new VEdge(
                              new Vector3((float)edge.VVertexA[0] * gridXSpacing + gridXSpacing / 2, 0, (float)edge.VVertexA[1] * gridYSpacing + gridYSpacing / 2),
                              new Vector3((float)edge.VVertexB[0] * gridXSpacing + gridXSpacing / 2, 0, (float)edge.VVertexB[1] * gridYSpacing + gridYSpacing / 2)));
        }
    }
示例#12
0
        private void Delaunay_Click(object sender, EventArgs e)
        {
            for (int i = 0; i < Array_of_vertexes.Count(); ++i)
            {
                Array_of_vertexes[i].Highlighted = false;
            }
            DrawEvents.Clear();
            DrawEvents.Add(new Painting(Array_of_vertexes, new List <Edge>()));
            List <Vector> Points = new List <Vector>(AlgorithmsVisualiser.Pack_into_ListOfVector(Array_of_vertexes));
            VoronoiGraph  graph  = new VoronoiGraph();

            graph = AlgorithmsVisualiser.FortuneAlgo(Points);
            List <VoronoiEdge> VE  = graph.Edges.ToList <VoronoiEdge>();
            List <Edge>        tri = AlgorithmsVisualiser.Delaunay(Array_of_vertexes, graph, DrawEvents);

            foreach (Edge edge in tri)
            {
                edge.color = Color.Red;
            }
            GL.LineWidth(1);
            DrawEvents.Add(new Painting(Array_of_vertexes, tri, VE));
        }
示例#13
0
        public static List <Cellule> Start(DraftSight.Interop.dsAutomation.ReferenceImage img, List <PointF> liste, int nbEquilibrage, out VoronoiGraph graph)
        {
            List <Cellule> listepoincon = null;

            try
            {
                int LgMM = (int)img.Width;
                int HtMM = (int)img.Height;
                int LgPx = LgMM + 1;
                int HtPx = HtMM + 1;
                var bmp  = new Bitmap(img.GetPath());
                Settings.Bmp = bmp.Redimensionner(new Size(LgPx, HtPx));
                bmp.Dispose();
                Settings.Dimensions = new Size(LgMM, HtMM);;
                //Settings.Histogram = BitmapHelper.Histogramme(Settings.Bmp);

                BitmapHelper.Verrouiller(Settings.Bmp);


                Settings.Graph = VoronoiGraph.ComputeVoronoiGraph(liste, LgMM, HtMM, false);

                for (int k = 0; k < nbEquilibrage; k++)
                {
                    liste          = Equilibrer();
                    Settings.Graph = VoronoiGraph.ComputeVoronoiGraph(liste, LgMM, HtMM, false);
                }

                listepoincon = CalculerCellule();

                BitmapHelper.Liberer();

                Settings.Bmp.Dispose();
            }
            catch (Exception ex) { LogDebugging.Log.Message(ex); }

            graph = Settings.Graph;
            return(listepoincon);
        }
示例#14
0
        public static List <Edge> Delaunay(List <Point> points, VoronoiGraph VG, List <IDrawable> visualSteps)
        {
            List <VoronoiEdge> edges          = new List <VoronoiEdge>();
            List <Edge>        edges_to_paint = new List <Edge>();

            edges = VG.Edges.ToList <VoronoiEdge>();
            List <Edge> result = new List <Edge>();

            for (int i = 0; i < edges.Count(); ++i)
            {
                Edge e_temp = new Edge(Pack_into_Edge(edges[i]), Color.Yellow);
                edges_to_paint.Add(e_temp);
                visualSteps.Add(new Painting(points, edges_to_paint, edges));
                Point p1 = new Point((int)edges[i].LeftData[0], (int)edges[i].LeftData[1]);
                Point p2 = new Point((int)edges[i].RightData[0], (int)edges[i].RightData[1]);
                Edge  e  = new Edge(p1, p2, Color.Yellow);
                result.Add(e);
                edges_to_paint.Add(e);
                visualSteps.Add(new Painting(points, edges_to_paint, edges));
                edges_to_paint.RemoveAt(edges_to_paint.Count - 2);
            }
            return(result);
        }
示例#15
0
        private void Relax(VoronoiGraph graph, List <Vector> vectors)
        {
            foreach (var vector in vectors)
            {
                var v0         = 0.0d;
                var v1         = 0.0d;
                var edgesCount = 0;

                foreach (var edge in graph.Edges)
                {
                    if (edge.LeftData == vector || edge.RightData == vector)
                    {
                        var p0 = (edge.VVertexA[0] + edge.VVertexB[0]) / 2;
                        var p1 = (edge.VVertexA[1] + edge.VVertexB[1]) / 2;
                        v0 += double.IsNaN(p0) ? 0 : p0;
                        v1 += double.IsNaN(p1) ? 0 : p1;
                        edgesCount++;
                    }
                }

                vector[0] = v0 / edgesCount;
                vector[1] = v1 / edgesCount;
            }
        }
示例#16
0
 private void Fortune_Click(object sender, EventArgs e)
 {
     for (int i = 0; i < Array_of_vertexes.Count(); ++i)
         Array_of_vertexes[i].Highlighted = false;
     DrawEvents.Clear();
     DrawEvents.Add(new Painting(Array_of_vertexes, new List<Edge>()));
     List<Vector> Points = new List<Vector>(AlgorithmsVisualiser.Pack_into_ListOfVector(Array_of_vertexes));
     VoronoiGraph graph = new VoronoiGraph();
     graph = AlgorithmsVisualiser.FortuneAlgo(Points);
     List<VoronoiEdge> VE = graph.Edges.ToList<VoronoiEdge>();
     DrawEvents.Add(new Painting(Array_of_vertexes, new List<Edge>(), VE));
 }
示例#17
0
        public static VNode ProcessCircleEvent(VCircleEvent e, VNode Root, VoronoiGraph VG, double ys, out VDataNode[] CircleCheckList)
        {
            VDataNode a, b, c;
            VEdgeNode eu, eo;

            b = e.NodeN;
            a = NodeHandler.LeftDataNode(b);
            c = NodeHandler.RightDataNode(b);
            if (a == null || b.Parent == null || c == null || !a.DataPoint.Equals(e.NodeL.DataPoint) || !c.DataPoint.Equals(e.NodeR.DataPoint))
            {
                CircleCheckList = new VDataNode[] { };
                return(Root); // Abbruch da sich der Graph verändert hat
            }
            eu = (VEdgeNode)b.Parent;
            CircleCheckList = new VDataNode[] { a, c };
            //1. Create the new Vertex
            Vector VNew = new Vector(e.Center[0], e.Center[1]);

            //			VNew[0] = Fortune.ParabolicCut(a.DataPoint[0],a.DataPoint[1],c.DataPoint[0],c.DataPoint[1],ys);
            //			VNew[1] = (ys + a.DataPoint[1])/2 - 1/(2*(ys-a.DataPoint[1]))*(VNew[0]-a.DataPoint[0])*(VNew[0]-a.DataPoint[0]);
            VG.Vertizes.Add(VNew);
            //2. Find out if a or c are in a distand part of the tree (the other is then b's sibling) and assign the new vertex
            if (eu.Left == b) // c is sibling
            {
                eo = NodeHandler.EdgeToRightDataNode(a);

                // replace eu by eu's Right
                eu.Parent.Replace(eu, eu.Right);
            }
            else // a is sibling
            {
                eo = NodeHandler.EdgeToRightDataNode(b);

                // replace eu by eu's Left
                eu.Parent.Replace(eu, eu.Left);
            }
            eu.Edge.AddVertex(VNew);
            //			///////////////////// uncertain
            //			if(eo==eu)
            //				return Root;
            //			/////////////////////
            eo.Edge.AddVertex(VNew);
            //2. Replace eo by new Edge
            VoronoiEdge VE = new VoronoiEdge();

            VE.LeftData  = a.DataPoint;
            VE.RightData = c.DataPoint;
            VE.AddVertex(VNew);
            VG.Edges.Add(VE);

            VEdgeNode VEN = new VEdgeNode(VE, false);

            VEN.Left  = eo.Left;
            VEN.Right = eo.Right;
            if (eo.Parent == null)
            {
                return(VEN);
            }
            eo.Parent.Replace(eo, VEN);
            return(Root);
        }
示例#18
0
 void Compute(List <Point> sites)
 {
     this.sites = sites;
     this.graph = this.voronoi.Compute(sites, this.bounds);
 }
示例#19
0
 void CalculateVoronoi()
 {
     _result = _voronoi.Compute(_sites, _bounds);
 }
示例#20
0
        public static VoronoiGraph ComputeVoronoiGraph(IEnumerable <Vector2> datapoints)
        {
            var   pq             = new List <VEvent>();
            var   currentCircles = new Hashtable();
            var   vg             = new VoronoiGraph();
            VNode rootNode       = null;

            foreach (var v in datapoints)
            {
                pq.Add(new VDataEvent(v));
            }
            pq.Sort();
            while (pq.Count > 0)
            {
                var ve = pq.First();
                pq.Remove(ve);
                if (ve == null)
                {
                    return(null);
                }
                VDataNode[] circleCheckList;
                if (ve is VDataEvent)
                {
                    rootNode = VNode.ProcessDataEvent(ve as VDataEvent, rootNode, vg, ve.Y, out circleCheckList);
                }
                else if (ve is VCircleEvent)
                {
                    currentCircles.Remove(((VCircleEvent)ve).NodeN);
                    if (!((VCircleEvent)ve).Valid)
                    {
                        continue;
                    }
                    rootNode = VNode.ProcessCircleEvent(ve as VCircleEvent, rootNode, vg, out circleCheckList);
                }
                else
                {
                    throw new Exception("Got event of type " + ve.GetType() + "!");
                }
                foreach (var vd in circleCheckList)
                {
                    if (currentCircles.ContainsKey(vd))
                    {
                        ((VCircleEvent)currentCircles[vd]).Valid = false;
                        currentCircles.Remove(vd);
                    }
                    var vce = VNode.CircleCheckDataNode(vd, ve.Y);
                    if (vce != null)
                    {
                        pq.Add(vce);
                        pq.Sort();
                        currentCircles[vd] = vce;
                    }
                }
                if (ve is VDataEvent)
                {
                    var dp = ((VDataEvent)ve).DataPoint;
                    foreach (VCircleEvent vce in currentCircles.Values)
                    {
                        if (Dist(dp[0], dp[1], vce.CenterX, vce.CenterY) < vce.Y - vce.CenterY && Math.Abs(Dist(dp[0], dp[1], vce.CenterX, vce.CenterY) - (vce.Y - vce.CenterY)) > 1e-10)
                        {
                            vce.Valid = false;
                        }
                    }
                }
            }
            VNode.CleanUpTree(rootNode);
            foreach (var ve in vg.GetEdges().Select(edge => edge as VoronoiEdge))
            {
                if (Edge.IsUnknownVertex(ve.V2))
                {
                    ve.AddVertex(Edge.GetInfiniteVertex());
                    if (Math.Abs(ve.LeftData[1] - ve.RightData[1]) < 1e-10 && ve.LeftData[0] < ve.RightData[0])
                    {
                        var T = ve.LeftData;
                        ve.LeftData  = ve.RightData;
                        ve.RightData = T;
                    }
                }
            }

            var minuteEdges = new ArrayList();

            foreach (var ve in vg.GetEdges())
            {
                if (!ve.IsPartlyInfinite && ve.V1.Equals(ve.V2))
                {
                    minuteEdges.Add(ve);
                    foreach (var ve2 in vg.GetEdges())
                    {
                        if (ve2.V1.Equals(ve.V1))
                        {
                            ve2.V1 = ve.V1;
                        }
                        if (ve2.V2.Equals(ve.V1))
                        {
                            ve2.V2 = ve.V1;
                        }
                    }
                }
            }
            foreach (VoronoiEdge ve in minuteEdges)
            {
                vg.RemoveEdge(ve, false);
            }

            return(vg);
        }
示例#21
0
        public VoronoiGraph Compute(List<Point> sites, Bounds bbox)
        {
            this.Reset();

            // Initialize site event queue
            var siteEvents = sites.Take(sites.Count).ToList();
            /*siteEvents.Sort((a, b) =>
                {
                    float r = b.y - a.y;
                    if (r != 0) { return Mathf.CeilToInt(r); }
                    return Mathf.CeilToInt(b.x - a.x);
                });*/
            siteEvents = siteEvents.OrderByDescending(s => s.y).ToList();

            // process queue
            Point site = siteEvents.Last();
            siteEvents.Remove(site);
            int siteid = 0;
            float xsitex = -Mathf.Infinity;
            float xsitey = -Mathf.Infinity;

            // main loop
            for (; ; )
            {
                // we need to figure whether we handle a site or circle event
                // for this we find out if there is a site event and it is
                // 'earlier' than the circle event
                CircleEvent circle = this.firstCircleEvent;

                // add beach section
                if (site && (!circle || site.y < circle.y || (site.y == circle.y && site.x < circle.x)))
                {
                    // only if site is not a duplicate
                    if (site.x != xsitex || site.y != xsitey)
                    {
                        // first create cell for new site
                        //this.cells[siteid] = new Cell(site);
                        this.cells.Insert(siteid, new Cell(site));
                        site.id = siteid++;

                        // then create a beachsection for that site
                        this.AddBeachSection(site);

                        // remember last site coords to detect duplicate
                        xsitey = site.y;
                        xsitex = site.x;
                    }

                    site = siteEvents.Count > 0 ? siteEvents.Last() : null;
                    if (siteEvents.Count > 0) siteEvents.Remove(site);
                }
                // remove beach section
                else if (circle)
                {
                    this.RemoveBeachSection(circle.arc);
                }
                // all done, quit
                else
                {
                    break;
                }
            }

            // wrapping-up
            this.ClipEdges(bbox);

            this.CloseCells(bbox);

            VoronoiGraph graph = new VoronoiGraph();
            graph.sites = sites;
            graph.cells = this.cells;
            graph.edges = this.edges;

            this.Reset();

            return graph;
        }
示例#22
0
        private void ImproveMapData(VoronoiGraph voronoiMap, bool fix = false)
        {
            IFactory fact = new MapItemFactory();

            foreach (VoronoiEdge edge in voronoiMap.Edges)
            {
                if (fix)
                {
                    if (!FixPoints(edge))
                    {
                        continue;
                    }
                }

                Corner c1        = fact.CornerFactory(edge.VVertexA[0], edge.VVertexA[1]);
                Corner c2        = fact.CornerFactory(edge.VVertexB[0], edge.VVertexB[1]);
                Center cntrLeft  = fact.CenterFactory(edge.LeftData[0], edge.LeftData[1]);
                Center cntrRight = fact.CenterFactory(edge.RightData[0], edge.RightData[1]);

                if (c1 == null || c2 == null)
                {
                }

                c1.AddAdjacent(c2);
                c2.AddAdjacent(c1);

                cntrRight.Corners.Add(c1);
                cntrRight.Corners.Add(c2);

                cntrLeft.Corners.Add(c1);
                cntrLeft.Corners.Add(c2);

                Edge e = fact.EdgeFactory(c1, c2, cntrLeft, cntrRight);


                cntrLeft.Borders.Add(e);
                cntrRight.Borders.Add(e);

                cntrLeft.Neighbours.Add(cntrRight);
                cntrRight.Neighbours.Add(cntrLeft);

                c1.AddProtrudes(e);
                c2.AddProtrudes(e);
                c1.AddTouches(cntrLeft);
                c1.AddTouches(cntrRight);
                c2.AddTouches(cntrLeft);
                c2.AddTouches(cntrRight);
            }

            foreach (Corner q in App.AppMap.Corners.Values)
            {
                if (!q.Border)
                {
                    var point = new Point(0, 0);
                    foreach (Center c in q.Touches)
                    {
                        point.X += c.Point.X;
                        point.Y += c.Point.Y;
                    }
                    point.X = point.X / q.Touches.Count;
                    point.Y = point.Y / q.Touches.Count;
                    q.Point = point;
                }
            }

            //foreach (var c in App.AppMap.Centers)
            //{
            //    c.Value.FixBorders();
            //    c.SetEdgeAreas();
            //    c.Value.OrderCorners();
            //}

            IslandHandler.CreateIsland();
        }
示例#23
0
        /// <summary>
        /// Will return the new root (unchanged except in start-up)
        /// </summary>
        public static VNode ProcessDataEvent(VDataEvent e, VNode root, VoronoiGraph vg, double ys, out VDataNode[] circleCheckList)
        {
            if (root == null)
            {
                root            = new VDataNode(e.DataPoint);
                circleCheckList = new[] { (VDataNode)root };
                return(root);
            }
            //1. Find the node to be replaced
            VNode c = FindDataNode(root, ys, e.DataPoint[0]);
            //2. Create the subtree (ONE Edge, but two VEdgeNodes)
            var ve = new VoronoiEdge
            {
                LeftData  = ((VDataNode)c).DataPoint,
                RightData = e.DataPoint,
                V1        = Edge.GetUnknownVertex(),
                V2        = Edge.GetUnknownVertex()
            };

            vg.AddEdge(ve);

            VNode subRoot;

            if (Math.Abs(ve.LeftData[1] - ve.RightData[1]) < 1e-10)
            {
                if (ve.LeftData[0] < ve.RightData[0])
                {
                    subRoot = new VEdgeNode(ve, false)
                    {
                        Left = new VDataNode(ve.LeftData), Right = new VDataNode(ve.RightData)
                    };
                }
                else
                {
                    subRoot = new VEdgeNode(ve, true)
                    {
                        Left = new VDataNode(ve.RightData), Right = new VDataNode(ve.LeftData)
                    };
                }
                circleCheckList = new[] { (VDataNode)subRoot.Left, (VDataNode)subRoot.Right };
            }
            else
            {
                subRoot = new VEdgeNode(ve, false)
                {
                    Left  = new VDataNode(ve.LeftData),
                    Right = new VEdgeNode(ve, true)
                    {
                        Left = new VDataNode(ve.RightData), Right = new VDataNode(ve.LeftData)
                    }
                };
                circleCheckList = new[] { (VDataNode)subRoot.Left, (VDataNode)subRoot.Right.Left, (VDataNode)subRoot.Right.Right };
            }

            //3. Apply subtree
            if (c.Parent == null)
            {
                return(subRoot);
            }
            c.Parent.Replace(c, subRoot);
            return(root);
        }
示例#24
0
        /// <summary>
        /// Get the position with the largest view cone on a specific target and with respect to an input radius
        /// </summary>
        public static void GetOptimalPosition(float[] target, float radius)
        {
            List <float[]> neighbor_coords         = new List <float[]>();
            ArrayList      neighbor_theta_phi      = new ArrayList();
            ArrayList      neighbor_correspondance = new ArrayList();
            float          min_theta = 1000.0f;
            float          max_theta = 0.0f;
            float          min_phi   = 1000.0f;
            float          max_phi   = 0.0f;

            // Get all the atoms inside the sphere centered on the target and of the input radius, translate them into polar coordinates
            for (int i = 0; i < MoleculeModel.atomsLocationlist.Count; i++)
            {
                double dist = Distance3f(MoleculeModel.atomsLocationlist[i], target);
                if (dist < radius)
                {
                    neighbor_coords.Add(MoleculeModel.atomsLocationlist[i]);
                    float[] atom = new float[3];
                    atom[0] = MoleculeModel.atomsLocationlist[i][0] - target[0];
                    atom[1] = MoleculeModel.atomsLocationlist[i][1] - target[1];
                    atom[2] = MoleculeModel.atomsLocationlist[i][2] - target[2];
                    float  theta     = (float)Math.Acos(atom[2] / dist);
                    float  phi       = (float)Math.Atan2(atom[1], atom[0]);
                    Vector theta_phi = new Vector(2);
                    theta_phi[0] = theta;
                    theta_phi[1] = phi;
                    neighbor_theta_phi.Add(theta_phi);
                    neighbor_correspondance.Add(i);
//							Debug.Log (theta_phi);
                    theta_phi    = new Vector(2);
                    theta_phi[0] = theta + (float)Math.PI / 2;
                    theta_phi[1] = phi + (float)Math.PI;
                    neighbor_theta_phi.Add(theta_phi);
//							Debug.Log (theta_phi);
                    theta_phi    = new Vector(2);
                    theta_phi[0] = theta + (float)Math.PI / 2;
                    theta_phi[1] = phi;
                    neighbor_theta_phi.Add(theta_phi);
//							Debug.Log (theta_phi);
                    theta_phi    = new Vector(2);
                    theta_phi[0] = theta;
                    theta_phi[1] = phi + (float)Math.PI;
                    neighbor_theta_phi.Add(theta_phi);
//							Debug.Log (theta_phi);
                    if (theta + (float)Math.PI / 2 > max_theta)
                    {
                        max_theta = theta + (float)Math.PI / 2;
                    }
                    if (theta < min_theta)
                    {
                        min_theta = theta;
                    }
                    if (phi + (float)Math.PI > max_phi)
                    {
                        max_phi = phi + (float)Math.PI;
                    }
                    if (phi < min_phi)
                    {
                        min_phi = phi;
                    }
                }
            }

//					Debug.Log (neighbor_theta_phi.GetEnumerator().Current[0]+" "+neighbor_theta_phi.GetEnumerator().Current[1]);
//					Debug.Log (neighbor_theta_phi[1][0]+" "+neighbor_theta_phi[1][1]);
//					Debug.Log (neighbor_theta_phi[2][0]+" "+neighbor_theta_phi[2][1]);
//					Debug.Log (neighbor_theta_phi[3][0]+" "+neighbor_theta_phi[3][1]);

            StreamWriter sw = new StreamWriter(@"/Users/trellet/Dev/UnityMol_svn/trunk/Assets/neighbors.txt");


            foreach (Vector neighbor in neighbor_theta_phi)
            {
                sw.WriteLine("" + neighbor[0] + " " + neighbor[1]);
            }
            sw.Close();

//					int length = neighbor_theta_phi.Count;
//					for(int i=0; i<length; i++)
//					{
//						Vector theta_phi = new Vector(2);
//						theta_phi[0] = neighbor_theta_phi[i][0]+ (float) Math.PI;
//						theta_phi[1] = neighbor_theta_phi[i][1]+2*(float) Math.PI;
//						neighbor_theta_phi.Add (theta_phi);
//						theta_phi[0] = neighbor_theta_phi[i][0]+(float) Math.PI;
//						theta_phi[1] = neighbor_theta_phi[i][1];
//						neighbor_theta_phi.Add (theta_phi);
//						theta_phi[0] = neighbor_theta_phi[i][0];
//						theta_phi[1] = neighbor_theta_phi[i][1]+2*(float) Math.PI;
//						neighbor_theta_phi.Add (theta_phi);
//					}
            Debug.Log("Nb of neighbors: " + neighbor_theta_phi.Count);
            Debug.Log("Min/max theta/phi: " + min_theta + " " + max_theta + " " + min_phi + " " + max_phi);

            // Compute the Voronoi graph from the neighbors polar coordinates
            VoronoiGraph result = Fortune.ComputeVoronoiGraph(neighbor_theta_phi);

            MoleculeModel.atomsLocationlist.OrderBy(x => x[0]);
            Debug.Log(result.Vertizes.Count);

            StreamWriter sw2 = new StreamWriter(@"/Users/trellet/Dev/UnityMol_svn/trunk/Assets/vertices.txt");

            BenTools.Data.HashSet temp = new BenTools.Data.HashSet();

            foreach (Vector vert in result.Vertizes)
            {
                if (vert[0] > min_theta && vert[0] < max_theta && vert[1] < max_phi && vert[1] > min_phi)
                {
                    sw2.WriteLine("" + vert[0] + " " + vert[1]);
                    temp.Add(vert);
                }
            }
            sw2.Close();

            result.Vertizes = temp;



            //double min_dist = 1000.0;
            double max_dist = 0.0;

            float[] best_pos = new float[2];
            //float[] best_point = new float[2];
            //float[] vertex = new float[2];
            //float[] point = new float[2];
            //					Vector vert = new Vector();
            //int c = 0;
            double distance = 0.0;
            Dictionary <double, float[]> vertices = new Dictionary <double, float[]>();


            // Find the largest distance between each vertex and the closest point to each of them
            //// 1st METHOD (faster, use the edges that contain point information)
            foreach (VoronoiEdge edge in result.Edges)
            {
                //min_dist = 1000.0;

                if (edge.VVertexA[0] > min_theta && edge.VVertexA[0] < max_theta && edge.VVertexA[1] < max_phi && edge.VVertexA[1] > min_phi)
                {
                    distance = Distance2f(edge.VVertexA, edge.LeftData);
                    float[] t = new float[2];
                    t[0] = (float)edge.VVertexA[0];
                    t[1] = (float)edge.VVertexA[1];
                    vertices[distance] = t;
                    if (distance > max_dist)
                    {
                        max_dist    = distance;
                        best_pos[0] = (float)edge.VVertexA[0];
                        best_pos[1] = (float)edge.VVertexA[1];
                    }
                }
                if (edge.VVertexB[0] > min_theta && edge.VVertexB[0] < max_theta && edge.VVertexB[1] < max_phi && edge.VVertexB[1] > min_phi)
                {
                    distance = Distance2f(edge.VVertexB, edge.LeftData);
                    float[] t = new float[2];
                    t[0] = (float)edge.VVertexA[0];
                    t[1] = (float)edge.VVertexA[1];
                    vertices[distance] = t;
                    if (distance > max_dist)
                    {
                        max_dist    = distance;
                        best_pos[0] = (float)edge.VVertexB[0];
                        best_pos[1] = (float)edge.VVertexB[1];
                    }
                }
            }

            var list = vertices.Keys.ToList();

            list.Sort();
            float[] cartesian = new float[3];
            for (int i = list.Count - 1; i > list.Count - 8; i--)
            {
                //Debug.Log(list[i]+": "+vertices[list[i]][0]+" "+vertices[list[i]][1]);
                cartesian[0] = (radius * (float)Math.Sin(vertices[list[i]][0]) * (float)Math.Cos(vertices[list[i]][1])) + target[0];
                cartesian[1] = (radius * (float)Math.Sin(vertices[list[i]][0]) * (float)Math.Sin(vertices[list[i]][1])) + target[1];
                cartesian[2] = (radius * (float)Math.Cos(vertices[list[i]][0])) + target[2];
                Debug.Log(list[i] + ": " + cartesian[0] + " " + cartesian[1] + " " + cartesian[2]);
            }

            ////// 2nd METHOD (slower, all vertices vs all points)
//					foreach (Vector vert in result.Vertizes)
//					{
//						min_dist = 1000.0;
//
//						foreach (Vector neighbor in neighbor_theta_phi)
//						{
////							vertices[0] = (float) vert[0];
////							vertices[1] = (float) vert[1];
//
//							double dist = Distance2f(vert, neighbor);
//
//							if (dist < min_dist)
//							{
//								min_dist = dist;
//								point[0] = (float) neighbor[0];
//								point[1] = (float) neighbor[1];
//							}
//						}
//						if (min_dist > max_dist)
//						{
//							max_dist = min_dist;
//							best_pos[0] = (float) vert[0];
//							best_pos[1] = (float) vert[1];
//							best_point[0] = point[0];
//							best_point[1] = point[1];
//						}
//
//					}
            Debug.Log("Maximum distance: " + max_dist);
            Debug.Log("Theta and phi: " + best_pos[0] + " " + best_pos[1]);
            float[] best_pos_cart = new float[3];
            //float[] best_pos_cart2 = new float[3];
            //float[] best_pos_cart3 = new float[3];
            //float[] best_pos_cart4 = new float[3];

            // Convert polar coordinates of the best position to cartesian ones + shift to molecule system coordinates
            best_pos_cart[0] = (radius * (float)Math.Sin(best_pos[0]) * (float)Math.Cos(best_pos[1])) + target[0];
            best_pos_cart[1] = (radius * (float)Math.Sin(best_pos[0]) * (float)Math.Sin(best_pos[1])) + target[1];
            best_pos_cart[2] = (radius * (float)Math.Cos(best_pos[0])) + target[2];
            Debug.Log("Best position: " + best_pos_cart[0] + " " + best_pos_cart[1] + " " + best_pos_cart[2]);
//					best_pos_cart2[0] = (radius * (float) Math.Sin(best_pos[0]-Math.PI) * (float) Math.Cos(best_pos[1])) + target[0];
//					best_pos_cart2[1] = (radius * (float) Math.Sin(best_pos[0]-Math.PI) * (float) Math.Sin(best_pos[1])) + target[1];
//					best_pos_cart2[2] = (radius * (float) Math.Cos(best_pos[0]-Math.PI)) + target[2];
//					best_pos_cart3[0] = (radius * (float) Math.Sin(best_pos[0]-Math.PI) * (float) Math.Cos(best_pos[1]-2*Math.PI)) + target[0];
//					best_pos_cart3[1] = (radius * (float) Math.Sin(best_pos[0]-Math.PI) * (float) Math.Sin(best_pos[1]-2*Math.PI)) + target[1];
//					best_pos_cart3[2] = (radius * (float) Math.Cos(best_pos[0]-Math.PI)) + target[2];
//					best_pos_cart4[0] = (radius * (float) Math.Sin(best_pos[0]) * (float) Math.Cos(best_pos[1]-2*Math.PI)) + target[0];
//					best_pos_cart4[1] = (radius * (float) Math.Sin(best_pos[0]) * (float) Math.Sin(best_pos[1]-2*Math.PI)) + target[1];
//					best_pos_cart4[2] = (radius * (float) Math.Cos(best_pos[0])) + target[2];
//					Debug.Log("Best position2: "+best_pos_cart2[0]+" "+best_pos_cart2[1]+" "+best_pos_cart2[2]);
//					Debug.Log("Best position3: "+best_pos_cart3[0]+" "+best_pos_cart3[1]+" "+best_pos_cart3[2]);
//					Debug.Log("Best position4: "+best_pos_cart4[0]+" "+best_pos_cart4[1]+" "+best_pos_cart4[2]);

            // Place the camera at the new best position and make it face the target
            UIData.optim_view            = true;
            maxCamera.optim_target       = new Vector3(target[0], target[1], target[2]);
            maxCamera.optim_cam_position = new Vector3(best_pos_cart[0], best_pos_cart[1], best_pos_cart[2]);
            GameObject camera = GameObject.Find("LoadBox");

            UIData.optim_view_start_point = camera.transform.position;
            UIData.start_time             = Time.time;
            //camera.transform.position = new Vector3(best_pos_cart[0], best_pos_cart[1], best_pos_cart[2]);
//					Wait();
//					camera.transform.position = new Vector3(best_pos_cart2[0], best_pos_cart2[1], best_pos_cart2[2]);
//					Wait();
//					camera.transform.position = new Vector3(best_pos_cart3[0], best_pos_cart3[1], best_pos_cart3[2]);
//					Wait();
//					camera.transform.position = new Vector3(best_pos_cart4[0], best_pos_cart4[1], best_pos_cart4[2]);
            //maxCamera.ghost_target = GameObject.Find("Target");

//					camera.transform.LookAt(ghost_target.transform);
            //result.Vertizes
        }
示例#25
0
        public override List <IActivityData> Process()
        {
            IDatasetElement sElement = base.SourceDatasetElement;
            IFeatureClass   sFc      = base.SourceFeatureClass;

            ActivityBase.TargetDatasetElement tElement = base.TargetDatasetElement;
            IDataset tDs = base.TargetDataset;
            //IFeatureDatabase tDatabase = base.TargetFeatureDatabase;

            GeometryDef geomDef = new GeometryDef(
                geometryType.Polyline,
                null,
                false);

            IFeatureClass    tFc       = base.CreateTargetFeatureclass(geomDef, sFc.Fields);
            IFeatureDatabase tDatabase = FeatureDatabase(tFc);

            Report.featureMax = sFc.CountFeatures;
            Report.featurePos = 0;
            ReportProgess("Query Filter: " + SourceData.FilterClause);

            Nodes nodes = new Nodes();

            using (IFeatureCursor cursor = SourceData.GetFeatures(String.Empty))
            {
                if (cursor == null)
                {
                    return(null);
                }

                IFeature feature;
                while ((feature = cursor.NextFeature) != null)
                {
                    if (Report.featurePos++ % 100 == 0)
                    {
                        ReportProgess();
                    }

                    if (feature.Shape is IPoint)
                    {
                        nodes.Add((IPoint)feature.Shape);
                    }
                }
            }

            VoronoiGraph voronoi = new VoronoiGraph();

            voronoi.ProgressMessage += new VoronoiGraph.ProgressMessageEventHandler(voronoi_ProgressMessage);
            voronoi.Progress        += new VoronoiGraph.ProgressEventHandler(voronoi_Progress);
            voronoi.Calc(nodes);
            List <IPoint> vertices = voronoi.Nodes;
            Edges         edges    = voronoi.Edges;

            ReportProgess("Write Lines");
            Report.featurePos = 0;
            List <IFeature> features = new List <IFeature>();

            foreach (Edge edge in edges)
            {
                Polyline pLine = new Polyline();
                Path     path  = new Path();
                path.AddPoint(vertices[edge.p1]);
                path.AddPoint(vertices[edge.p2]);
                pLine.AddPath(path);

                Feature feature = new Feature();
                feature.Shape = pLine;

                features.Add(feature);
                Report.featurePos++;
                if (features.Count >= 100)
                {
                    if (!tDatabase.Insert(tFc, features))
                    {
                        throw new Exception(tDatabase.lastErrorMsg);
                    }
                    features.Clear();
                    ReportProgess();
                }
            }

            if (features.Count > 0)
            {
                ReportProgess();
                if (!tDatabase.Insert(tFc, features))
                {
                    throw new Exception(tDatabase.lastErrorMsg);
                }
            }

            ReportProgess("Flush Features");
            base.FlushFeatureClass(tFc);

            return(base.ToProcessResult(tFc));
        }
示例#26
0
        protected override int[] GenerateDataImpl(long x, long y, long width, long height)
        {
            int[] data = new int[width * height];

            // Determine output values.
            int noneOutput     = 0;
            int originalOutput = 1;
            int centerOutput   = (this.Result == VoronoiResult.AllValues) ? 2 : 1;
            int edgeOutput     = (this.Result == VoronoiResult.AllValues) ? 3 : (this.Result == VoronoiResult.EdgesAndOriginals) ? 2 : 1;

            // Scan through the size of the array, randomly creating points.
            List <Vector> points = new List <Vector>();

            for (int i = -this.EdgeSampling; i < width + this.EdgeSampling; i++)
            {
                for (int j = -this.EdgeSampling; j < height + this.EdgeSampling; j++)
                {
                    int s = this.GetRandomRange(x + i, y + j, 0, this.PointValue, this.Modifier);
                    //long s = this.GetRandomLong(x + i, y + j) % this.PointValue;
                    //if (s < 0) s = Math.Abs(s);
                    //if (s < 0 || s >= this.PointValue)
                    //    throw new InvalidOperationException();
                    if (s == 0)
                    {
                        points.Add(new Vector(new double[] { i, j }));
                        if (i >= 0 && i < width &&
                            j >= 0 && j < height)
                        {
                            if (this.Result == VoronoiResult.AllValues ||
                                this.Result == VoronoiResult.EdgesAndOriginals ||
                                this.Result == VoronoiResult.OriginalOnly)
                            {
                                data[i + j * width] = originalOutput;
                            }
                        }
                    }
                }
            }

            // Skip computations if we are only outputting original scatter values.
            if (this.Result == VoronoiResult.OriginalOnly)
            {
                return(data);
            }

            // Compute the Voronoi diagram.
            VoronoiGraph graph = Fortune.ComputeVoronoiGraph(points);

            // Output the edges if needed.
            if (this.Result == VoronoiResult.AllValues ||
                this.Result == VoronoiResult.EdgesAndOriginals ||
                this.Result == VoronoiResult.EdgeOnly)
            {
                foreach (VoronoiEdge v in graph.Edges)
                {
                    Vector a = v.VVertexA;
                    Vector b = v.VVertexB;

                    // Normalize vector between two points.
                    double cx = 0, cy = 0;
                    double sx     = b[0] < a[0] ? b[0] : a[0];
                    double sy     = b[0] < a[0] ? b[1] : a[1];
                    double mx     = b[0] > a[0] ? b[0] : a[0];
                    double tx     = b[0] > a[0] ? b[0] - a[0] : a[0] - b[0];
                    double ty     = b[0] > a[0] ? b[1] - a[1] : a[1] - b[1];
                    double length = Math.Sqrt(Math.Pow(tx, 2) + Math.Pow(ty, 2));
                    tx /= length;
                    ty /= length;

                    // Iterate until we reach the target.
                    while (sx + cx < mx)// && sy + cy < my)
                    {
                        if ((int)(sx + cx) >= 0 && (int)(sx + cx) < width &&
                            (int)(sy + cy) >= 0 && (int)(sy + cy) < height &&
                            data[(int)(sx + cx) + (int)(sy + cy) * width] == noneOutput)
                        {
                            data[(int)(sx + cx) + (int)(sy + cy) * width] = edgeOutput;
                        }

                        cx += tx; // b[0] > a[0] ? tx : -tx;
                        cy += ty; // b[1] > a[1] ? ty : -ty;
                    }
                }
            }

            // Output the center points if needed.
            if (this.Result == VoronoiResult.AllValues ||
                this.Result == VoronoiResult.CenterOnly)
            {
                foreach (Vector v in graph.Vertizes)
                {
                    if ((int)v[0] >= 0 && (int)v[0] < width &&
                        (int)v[1] >= 0 && (int)v[1] < height)
                    {
                        data[(int)v[0] + (int)v[1] * width] = centerOutput;
                    }
                }
            }

            // Return the result.
            return(data);
        }
        public static Image CreateImage(VoronoiDiagramContext context, params IEnumerable <Point>[] inputs)
        {
            IEnumerable <IEnumerable <Vector> > dataPoints = inputs.Select(
                input => input.Select(
                    point => new Vector(point.XCoordinate, point.YCoordinate)
                    )
                );
            double factorX = context.Width / (context.MaxX - context.MinX);
            double factorY = context.Height / (context.MaxY - context.MinY);
            double factor  = Math.Min(factorX, factorY);
            double minX    = context.MinX - context.Width * (0.5 / factor - 0.5 / factorX);
            double minY    = context.MinY - context.Height * (0.5 / factor - 0.5 / factorY);

            dataPoints = dataPoints.Select(points => points.Select(vector => new Vector(
                                                                       (vector[0] - minX) * factor,
                                                                       (vector[1] - minY) * factor
                                                                       )));

            PointF toPoint(Vector vector) => new PointF(
                (float)vector[0],
                (float)vector[1]
                );
            RectangleF toRectangle(Vector vector, float radius) => new RectangleF(
                (float)(vector[0]) - radius,
                (float)(vector[1]) - radius,
                radius * 2f,
                radius * 2f
                );

            var image            = new Bitmap(context.Width, context.Height);
            var linePen          = new Pen(context.LineColor);
            var dataPointBrushes = context.DataPointsColors.Select(color => new SolidBrush(color));
            var surface          = Graphics.FromImage(image);

            surface.Clear(context.BackgroundColor);
            surface.SmoothingMode = SmoothingMode.HighQuality;

            try
            {
                VoronoiGraph graph          = Fortune.ComputeVoronoiGraph(dataPoints.First().Distinct());
                double       infiniteLength = context.Width + context.Height;
                foreach (var edge in graph.Edges)
                {
                    Vector left  = edge.VVertexA;
                    Vector right = edge.VVertexB;
                    if (edge.IsPartlyInfinite)
                    {
                        Vector extension = edge.DirectionVector * infiniteLength;
                        if (left == Fortune.VVInfinite)
                        {
                            left = edge.FixedPoint - extension;
                        }
                        if (right == Fortune.VVInfinite)
                        {
                            right = edge.FixedPoint + extension;
                        }
                    }
                    surface.DrawLine(linePen, toPoint(left), toPoint(right));
                }
            }
            catch (Exception) {}

            var target = dataPoints.Zip(
                dataPointBrushes.Zip(
                    context.DataPointsRadii,
                    (brush, radius) => new { brush, radius }),
                (points, style) => new { points, style }
                ).Reverse();

            foreach (var data in target)
            {
                foreach (var point in data.points)
                {
                    surface.FillEllipse(data.style.brush, toRectangle(point, data.style.radius));
                }
            }

            return(image);
        }
示例#28
0
        /// <summary>
        /// The Voronoi Graph calculation creates the lines that form a voronoi diagram.
        /// </summary>
        /// <param name="points">The points to use for creating the tesselation.</param>
        /// <param name="result">The output featureset.</param>
        /// <param name="cropToExtent">The normal polygons have sharp angles that extend like stars.
        /// Cropping will ensure that the original featureset extent plus a small extra buffer amount
        /// is the outer extent of the polygons.  Errors seem to occur if the exact extent is used.</param>
        public static void VoronoiPolygons(IFeatureSet points, IFeatureSet result, bool cropToExtent)
        {
            double[]     vertices = points.Vertex;
            VoronoiGraph gp       = Fortune.ComputeVoronoiGraph(vertices);

            Extent ext = points.Extent;

            ext.ExpandBy(ext.Width / 100, ext.Height / 100);
            IEnvelope env    = ext.ToEnvelope();
            IPolygon  bounds = env.ToPolygon();

            // Convert undefined coordinates to a defined coordinate.
            HandleBoundaries(gp, env);
            for (int i = 0; i < vertices.Length / 2; i++)
            {
                List <VoronoiEdge> myEdges = new List <VoronoiEdge>();
                Vector2            v       = new Vector2(vertices, i * 2);
                foreach (VoronoiEdge edge in gp.Edges)
                {
                    if (!v.Equals(edge.RightData) && !v.Equals(edge.LeftData))
                    {
                        continue;
                    }
                    myEdges.Add(edge);
                }
                List <Coordinate> coords    = new List <Coordinate>();
                VoronoiEdge       firstEdge = myEdges[0];
                coords.Add(firstEdge.VVertexA.ToCoordinate());
                coords.Add(firstEdge.VVertexB.ToCoordinate());
                Vector2 previous = firstEdge.VVertexB;
                myEdges.Remove(myEdges[0]);
                Vector2 start = firstEdge.VVertexA;
                while (myEdges.Count > 0)
                {
                    for (int j = 0; j < myEdges.Count; j++)
                    {
                        VoronoiEdge edge = myEdges[j];
                        if (edge.VVertexA.Equals(previous))
                        {
                            previous = edge.VVertexB;
                            Coordinate c = previous.ToCoordinate();
                            coords.Add(c);
                            myEdges.Remove(edge);
                            break;
                        }

                        // couldn't match by adding to the end, so try adding to the beginning
                        if (edge.VVertexB.Equals(start))
                        {
                            start = edge.VVertexA;
                            coords.Insert(0, start.ToCoordinate());
                            myEdges.Remove(edge);
                            break;
                        }

                        // I don't like the reverse situation, but it seems necessary.
                        if (edge.VVertexB.Equals(previous))
                        {
                            previous = edge.VVertexA;
                            Coordinate c = previous.ToCoordinate();
                            coords.Add(c);
                            myEdges.Remove(edge);
                            break;
                        }

                        if (edge.VVertexA.Equals(start))
                        {
                            start = edge.VVertexB;
                            coords.Insert(0, start.ToCoordinate());
                            myEdges.Remove(edge);
                            break;
                        }
                    }
                }
                for (int j = 0; j < coords.Count; j++)
                {
                    Coordinate cA = coords[j];

                    // Remove NAN values
                    if (double.IsNaN(cA.X) || double.IsNaN(cA.Y))
                    {
                        coords.Remove(cA);
                    }

                    // Remove duplicate coordinates
                    for (int k = j + 1; k < coords.Count; k++)
                    {
                        Coordinate cB = coords[k];
                        if (cA.Equals2D(cB))
                        {
                            coords.Remove(cB);
                        }
                    }
                }
                foreach (Coordinate coord in coords)
                {
                    if (double.IsNaN(coord.X) || double.IsNaN(coord.Y))
                    {
                        coords.Remove(coord);
                    }
                }
                if (coords.Count <= 2)
                {
                    continue;
                }

                Polygon pg = new Polygon(coords);

                if (cropToExtent)
                {
                    try
                    {
                        IGeometry g = pg.Intersection(bounds);
                        IPolygon  p = g as IPolygon;
                        if (p != null)
                        {
                            Feature f = new Feature(p, result);
                            f.CopyAttributes(points.Features[i]);
                        }
                    }
                    catch (Exception)
                    {
                        Feature f = new Feature(pg, result);
                        f.CopyAttributes(points.Features[i]);
                    }
                }
                else
                {
                    Feature f = new Feature(pg, result);
                    f.CopyAttributes(points.Features[i]);
                }
            }
            return;
        }
示例#29
0
        private SRandom _rndGen;                                                               //random generator
        //class constractor
        public Island(int width, int height,
                      int relaxTime, int centerNum,
                      int riverNum, float maxElevation,
                      float mainStreamLengthRatio, //typical: 0.02
                      float subStreamLengthRatio,  //typical: 0.5
                      float riverSplitFreq,        //typical: 0.2
                      int seed = 0)
        {
            this.width          = width;
            this.height         = height;
            this.relaxationTime = relaxTime;
            this.num_of_centers = centerNum;
            this.num_of_rivers  = riverNum;
            this._maxElevation  = maxElevation;

            if (mainStreamLengthRatio < 0f || mainStreamLengthRatio > 0.2f)
            {
                throw new ArgumentOutOfRangeException("ratio must be between 0 and 0.2");
            }
            _mainStreamLength = (int)Math.Floor(Math.Max(width, height) * mainStreamLengthRatio);

            if (subStreamLengthRatio < 0f || subStreamLengthRatio > 1f)
            {
                throw new ArgumentOutOfRangeException("ratio must be between 0 and 1");
            }
            _subStreamLength = (int)Math.Floor(_mainStreamLength * subStreamLengthRatio);

            if (_riverSplitFreq < 0f || _riverSplitFreq > 1f)
            {
                throw new ArgumentOutOfRangeException("frequency must be between 0 and 1");
            }
            _riverSplitFreq = riverSplitFreq;

            _rndGen = new SRandom(seed);
            centers = random_centers(width, height, num_of_centers);
            VoronoiGraph vg = Fortune.ComputeVoronoiGraph(centers); //run voronoi diagram algorithm

            for (int i = 0; i < centers.Count; i++)                 //Initialize and store IslandTiles
            {
                Tiles[centers[i]] = new IslandTile(centers[i], vg, width, height);
            }
            //call improveRandomPoints function "relaxation" times

            for (int re = 0; re < relaxationTime; re++)
            {
                centers = improveRandomPoints(Tiles, centers);
                VoronoiGraph vGraph = Fortune.ComputeVoronoiGraph(centers);
                Tiles = new Dictionary <Vector, IslandTile>();
                for (int j = 0; j < centers.Count; j++)
                {
                    Tiles[centers[j]] = new IslandTile(centers[j], vGraph, width, height);
                }
            }
            NN = new NearestNeighbor(centers);//builded kdtree
            foreach (var item in Tiles.Values)
            {
                if (item.center.data[0] < (width / 10) || item.center.data[0] > (width - width / 10) ||
                    item.center.data[1] < (width / 10) || item.center.data[1] > (width - width / 10))
                {
                    item.iswater   = true;
                    item.elevation = 0;
                    foreach (var c in item.corners)
                    {
                        c.elevation = 0;
                        // totalcorners[c.position] = c;
                        //water.Add(c);
                    }
                    ocean.Add(item);
                }
                else
                {
                    land.Add(item);
                }
            }
            //spreading ocean area
            int waterspreadcount = 0;

            foreach (var item in Tiles.Values)
            {
                if (!item.iswater)
                {
                    foreach (var i in item.neighbors)
                    {
                        if (Tiles[i].iswater)
                        {
                            item.iswater   = true;
                            item.elevation = 0;
                            foreach (var c in item.corners)
                            {
                                c.elevation = 0;
                                //totalcorners[c.position] = c;
                                //water.Add(c);
                            }
                            ocean.Add(item);
                            land.Remove(item);
                            waterspreadcount++;
                        }
                        if (waterspreadcount > (num_of_centers / 3))
                        {
                            break;
                        }
                    }
                }
                if (waterspreadcount > (num_of_centers / 3))
                {
                    break;
                }
            }
            //remove one tile island
            foreach (var item in Tiles.Values)
            {
                float sum_of_elevation = 0;
                foreach (var c in item.corners)
                {
                    sum_of_elevation += c.elevation;
                }
                if (sum_of_elevation == 0)
                {
                    item.iswater   = true;
                    item.elevation = 0;
                    ocean.Add(item);
                    land.Remove(item);
                }
            }
            //-----calculate coastline------------------------
            foreach (var item in land)
            {
                foreach (var c in item.corners)
                {
                    if (c.elevation == 0)
                    {
                        shore.Add(c);
                        item.isshore = true;
                    }
                }
            }
            //calculate elevation for corners
            foreach (var t in Tiles.Values)
            {
                if (!t.iswater)
                {
                    float sum_elevation = 0;
                    foreach (var c in t.corners)
                    {
                        float minDistToShore = float.MaxValue;
                        foreach (var s in shore)
                        {
                            float distToShore = (float)Math.Sqrt((c.position - s.position).data[0] * (c.position - s.position).data[0] +
                                                                 (c.position - s.position).data[1] * (c.position - s.position).data[1]);
                            if (minDistToShore > distToShore)
                            {
                                minDistToShore = distToShore;
                            }
                        }
                        c.elevation    = minDistToShore * minDistToShore / _maxElevation;
                        c.elevation    = Math.Min(c.elevation, _maxElevation);
                        sum_elevation += c.elevation;
                        // totalcorners[c.position] = c;
                    }
                    t.elevation = sum_elevation / t.corners.Count;
                }
            }
            //store total corners

            /*foreach(var item in Tiles.Values)
             * {
             *  foreach (var c in item.corners)
             *      totalcorners.Add(c);
             * }*/
            //landcenters
            foreach (var item in land)
            {
                landcenters.Add(item.center);
            }
            rivers = GenerateRivers();//generate rivers
            foreach (var ri in rivers)
            {
                River.findDischarge(ri);//get discharge for every corner
            }
            //put discharge information in it's tile
            foreach (var kc in River.keeprivercorners)
            {
                foreach (var t in kc.touches)
                {
                    t.hasriver = true;
                    foreach (var c in t.corners)
                    {
                        if (c.position == kc.position)
                        {
                            c.discharge = kc.discharge;
                        }
                        break;
                    }
                }
            }

            StoreBiome();//set biome type for each tile

            //from now on, all data of a tile are generated.
        }
示例#30
0
        private void Canvas1_OnMouseDown(object sender, MouseButtonEventArgs e)
        {
            var rand   = new Random();
            var result = new List <int>();
            var check  = new HashSet <int>();

            for (int i = 0; i < 2000; i++)
            {
                Int32 curValue = rand.Next(0, 4000);
                while (check.Contains(curValue))
                {
                    curValue = rand.Next(0, 4000);
                }
                result.Add(curValue);
                check.Add(curValue);
            }

            //generate points inside our rectangle for our voronoi generator
            var datapointlist = new List <Vector>();

            for (int i = 0; i < 1000; i++)
            {
                datapointlist.Add(new Vector(result[i], result[i + 1000]));
            }

            IEnumerable <Vector> datapoints = datapointlist;



            var vgraph = new VoronoiGraph();

            vgraph = Fortune.ComputeVoronoiGraph(datapoints);

            foreach (var vertex in vgraph.Vertizes)
            {
            }

            var R = 0;
            var G = 0;
            var B = 0;

            foreach (var edge in vgraph.Edges)
            {
                if (R < 255)
                {
                    R++;
                }
                if (R == 255 && G < 255)
                {
                    G++;
                }
                if (R == 255 && G == 255 && B < 255)
                {
                    B++;
                }

                var brush = new SolidColorBrush(Color.FromArgb(255, (byte)R, (byte)G, (byte)B));

                var poly = new Line()
                {
                    X1              = edge.LeftData[0],
                    Y1              = edge.LeftData[1],
                    X2              = edge.RightData[0],
                    Y2              = edge.RightData[1],
                    Stroke          = brush,
                    StrokeThickness = 1
                };

                canvas1.Children.Add(poly);

                canvas1.InvalidateVisual();
                canvas1.UpdateLayout();
            }
        }
        public static VoronoiGraph FortuneAlgo(List<Vector> points)
        {
            BinaryPriorityQueue PQ = new BinaryPriorityQueue();
            Hashtable CurrentCircles = new Hashtable();
            VoronoiGraph VG = new VoronoiGraph();
            VNode RootNode = null;
            for (int i = 0; i < points.Count; ++i)
                PQ.Push(new VDataEvent(points[i]));
            while (PQ.Count > 0)
            {
                VEvent VE = PQ.Pop() as VEvent;
                VDataNode[] CircleCheckList;
                if (VE is VDataEvent)
                    RootNode = ProcessDataEvent(VE as VDataEvent, RootNode, VG, VE.Y, out CircleCheckList);
                else if (VE is VCircleEvent)
                {
                    CurrentCircles.Remove(((VCircleEvent)VE).NodeN);
                    if (!((VCircleEvent)VE).Valid)
                        continue;
                    RootNode = ProcessCircleEvent(VE as VCircleEvent, RootNode, VG, VE.Y, out CircleCheckList);
                }
                else throw new Exception("Got event of type " + VE.GetType().ToString() + "!");
                foreach (VDataNode VD in CircleCheckList)
                {
                    if (CurrentCircles.ContainsKey(VD))
                    {
                        ((VCircleEvent)CurrentCircles[VD]).Valid = false;
                        CurrentCircles.Remove(VD);
                    }
                    VCircleEvent VCE = CircleCheckDataNode(VD, VE.Y);
                    if (VCE != null)
                    {
                        PQ.Push(VCE);
                        CurrentCircles[VD] = VCE;
                    }
                }
                if (VE is VDataEvent)
                {
                    Vector DP = ((VDataEvent)VE).DataPoint;
                    foreach (VCircleEvent VCE in CurrentCircles.Values)
                    {
                        if (MathTools.Dist(DP[0], DP[1], VCE.Center[0], VCE.Center[1]) < VCE.Y - VCE.Center[1] && Math.Abs(MathTools.Dist(DP[0], DP[1], VCE.Center[0], VCE.Center[1]) - (VCE.Y - VCE.Center[1])) > 1e-10)
                            VCE.Valid = false;
                    }
                }
            }
            VNode.CleanUpTree(RootNode);
            foreach (VoronoiEdge VE in VG.Edges)
            {
                if (VE.Done)
                    continue;
                if (VE.VVertexB == Fortune.VVUnkown)
                {
                    VE.AddVertex(Fortune.VVInfinite);
                    if (Math.Abs(VE.LeftData[1] - VE.RightData[1]) < 1e-10 && VE.LeftData[0] < VE.RightData[0])
                    {
                        Vector T = VE.LeftData;
                        VE.LeftData = VE.RightData;
                        VE.RightData = T;
                    }
                }
            }

            ArrayList MinuteEdges = new ArrayList();
            foreach (VoronoiEdge VE in VG.Edges)
            {
                if (!VE.IsPartlyInfinite && VE.VVertexA.Equals(VE.VVertexB))
                {
                    MinuteEdges.Add(VE);
                    foreach (VoronoiEdge VE2 in VG.Edges)
                    {
                        if (VE2.VVertexA.Equals(VE.VVertexA))
                            VE2.VVertexA = VE.VVertexA;
                        if (VE2.VVertexB.Equals(VE.VVertexA))
                            VE2.VVertexB = VE.VVertexA;
                    }
                }
            }
            foreach (VoronoiEdge VE in MinuteEdges)
                VG.Edges.Remove(VE);

            return VG;
        }
示例#32
0
        // Create a basic set of
        public List <TectonicPlate> GeneratePlates()
        {
            // Spawn some random cell centers within a grid.
            // Add one row and column outside of the map so no cells inside the map are border cells.
            List <TectonicPlate> plates = new List <TectonicPlate>();

            for (int left = -PlateSize; left < MapSize.x + PlateSize; left += PlateSize)
            {
                for (int bottom = -PlateSize; bottom < MapSize.y + PlateSize; bottom += PlateSize)
                {
                    int right = left + PlateSize;
                    int top   = bottom + PlateSize;
                    plates.Add(new TectonicPlate
                    {
                        Center          = new ivec2(rand.Next(left, right), rand.Next(bottom, top)),
                        AngularVelocity = (float)rand.NextDouble() * maxPlateAngluarVelocity,
                        LinearVelocity  = new vec2((float)rand.NextDouble() * maxPlateLinearVelocity, (float)rand.NextDouble() * maxPlateLinearVelocity),
                        BaseHeight      = (float)rand.NextDouble() + 1f
                    });
                }
            }

            // Compute voronoi triangulation for plate edges
            var plateVectors = new Dictionary <Vector, TectonicPlate>();

            foreach (var tectonicPlate in plates)
            {
                var center = new Vector(tectonicPlate.Center.x, tectonicPlate.Center.y);
                plateVectors[center] = tectonicPlate;
            }

            VoronoiGraph graph = Fortune.ComputeVoronoiGraph(plateVectors.Keys);

            foreach (var edge in graph.Edges)
            {
                ivec2 a = new ivec2((int)edge.VVertexA[0], (int)edge.VVertexA[1]);
                ivec2 b = new ivec2((int)edge.VVertexB[0], (int)edge.VVertexB[1]);

                // Ignore edges into infinity. We generate cells outside of the map so we have only finite edges in the mep
                if (a.x == Int32.MaxValue || a.x == Int32.MinValue ||
                    a.y == Int32.MaxValue || a.y == Int32.MinValue ||
                    b.x == Int32.MaxValue || b.x == Int32.MinValue ||
                    b.y == Int32.MaxValue || b.y == Int32.MinValue)
                {
                    continue;
                }

                a.x = Math.Min(Math.Max(-200, a.x), MapSize.x + 200);
                a.y = Math.Min(Math.Max(-200, a.y), MapSize.y + 200);
                b.x = Math.Min(Math.Max(-200, b.x), MapSize.x + 200);
                b.y = Math.Min(Math.Max(-200, b.y), MapSize.y + 200);

                // left and right cells of the edges given by the fortune voronoi implementation are incorrect, compute the correct cells again

                ivec2 middle = (a + b) / 2;

                // Find the two plate centers closest to the edge middle point
                List <TectonicPlate> neighborCells = new List <TectonicPlate>();
                neighborCells.AddRange(plates.OrderBy(p => (p.Center - middle).Length).Take(2));

                TectonicPlate left  = neighborCells[0];
                TectonicPlate right = neighborCells[1];

                // left/right correct?
                if (EdgeAngle(neighborCells[0].Center, a, b) > 0)
                {
                    right = neighborCells[0];
                    left  = neighborCells[1];
                }

                float mountainFactor = rand.NextFloat(-1f, 1f);

                var tectonicEdge = new TectonicEdge {
                    A = a, B = b, LeftPlate = left, RightPlate = right, MountainFactor = mountainFactor
                };

                left.Edges.Add(tectonicEdge);
                right.Edges.Add(tectonicEdge);
            }

            SavePlateImage(plates, "plates.svg");

            return(plates);
        }
示例#33
0
        /// <summary>
        /// The original algorithm simply allows edges that have one defined point and
        /// another "NAN" point.  Simply excluding the not a number coordinates fails
        /// to preserve the known direction of the ray.  We only need to extend this
        /// long enough to encounter the bounding box, not infinity.
        /// </summary>
        /// <param name="graph">The VoronoiGraph with the edge list.</param>
        /// <param name="bounds">The polygon bounding the datapoints.</param>
        private static void HandleBoundaries(VoronoiGraph graph, IEnvelope bounds)
        {
            List <ILineString> boundSegments = new List <ILineString>();
            List <VoronoiEdge> unboundEdges  = new List <VoronoiEdge>();

            // Identify bound edges for intersection testing
            foreach (VoronoiEdge edge in graph.Edges)
            {
                if (edge.VVertexA.ContainsNan() || edge.VVertexB.ContainsNan())
                {
                    unboundEdges.Add(edge);
                    continue;
                }

                boundSegments.Add(
                    new LineString(new List <Coordinate> {
                    edge.VVertexA.ToCoordinate(), edge.VVertexB.ToCoordinate()
                }));
            }

            // calculate a length to extend a ray to look for intersections
            IEnvelope env = bounds;
            double    h   = env.Height;
            double    w   = env.Width;
            double    len = Math.Sqrt((w * w) + (h * h));

            // len is now long enough to pass entirely through the dataset no matter where it starts

            foreach (VoronoiEdge edge in unboundEdges)
            {
                // the unbound line passes thorugh start
                Coordinate start = (edge.VVertexB.ContainsNan())
                                       ? edge.VVertexA.ToCoordinate()
                                       : edge.VVertexB.ToCoordinate();

                // the unbound line should have a direction normal to the line joining the left and right source points
                double dx = edge.LeftData.X - edge.RightData.X;
                double dy = edge.LeftData.Y - edge.RightData.Y;
                double l  = Math.Sqrt((dx * dx) + (dy * dy));

                // the slope of the bisector between left and right
                double sx = -dy / l;
                double sy = dx / l;

                Coordinate center = bounds.Center();
                if ((start.X > center.X && start.Y > center.Y) || (start.X < center.X && start.Y < center.Y))
                {
                    sx = dy / l;
                    sy = -dx / l;
                }

                Coordinate end1 = new Coordinate(start.X + (len * sx), start.Y + (len * sy));
                Coordinate end2 = new Coordinate(start.X - (sx * len), start.Y - (sy * len));
                Coordinate end  = (end1.Distance(center) < end2.Distance(center)) ? end2 : end1;
                if (bounds.Contains(end))
                {
                    end = new Coordinate(start.X - (sx * len), start.Y - (sy * len));
                }

                if (edge.VVertexA.ContainsNan())
                {
                    edge.VVertexA = new Vector2(end.ToArray());
                }
                else
                {
                    edge.VVertexB = new Vector2(end.ToArray());
                }
            }
        }
        private static VNode ProcessCircleEvent(VCircleEvent e, VNode Root, VoronoiGraph VG, double ys, out VDataNode[] CircleCheckList)
        {
            VDataNode a, b, c;
            VEdgeNode e1, e2;
            b = e.NodeN;
            a = VNode.LeftDataNode(b);
            c = VNode.RightDataNode(b);
            if (a == null || b.Parent == null || c == null || !a.DataPoint.Equals(e.NodeL.DataPoint) || !c.DataPoint.Equals(e.NodeR.DataPoint))
            {
                CircleCheckList = new VDataNode[] { };
                return Root; // повертаємось, бо графік змінився
            }
            e1 = (VEdgeNode)b.Parent;
            CircleCheckList = new VDataNode[] { a, c };
            //Створюємо нову вершину
            Vector VNew = new Vector(e.Center[0], e.Center[1]);
            VG.Vertizes.Add(VNew);
            //2. виясняємо, чи а або с знаходяться у віддаленій частині дерева (інший - брат b), і призначаємо нову вершину
            if (e1.Left == b) // c - брат
            {
                e2 = VNode.EdgeToRightDataNode(a);
                // замінюємо e1 правим нащадком
                e1.Parent.Replace(e1, e1.Right);
            }
            else // a - брат
            {
                e2 = VNode.EdgeToRightDataNode(b);

                // замінюємо e1 лівим нащадком
                e1.Parent.Replace(e1, e1.Left);
            }
            e1.Edge.AddVertex(VNew);
            e2.Edge.AddVertex(VNew);

            //Замінюємо e2 новим ребром
            VoronoiEdge VE = new VoronoiEdge();
            VE.LeftData = a.DataPoint;
            VE.RightData = c.DataPoint;
            VE.AddVertex(VNew);
            VG.Edges.Add(VE);

            VEdgeNode VEN = new VEdgeNode(VE, false);
            VEN.Left = e2.Left;
            VEN.Right = e2.Right;
            if (e2.Parent == null)
                return VEN;
            e2.Parent.Replace(e2, VEN);
            return Root;
        }
示例#35
0
 void Compute(List<Point> sites)
 {
     this.sites = sites;
     this.graph = this.voronoi.Compute(sites, this.bounds);
 }
        private static VNode ProcessDataEvent(VDataEvent e, VNode Root, VoronoiGraph VG, double ys, out VDataNode[] CircleCheckList)
        {
            if (Root == null)
            {
                Root = new VDataNode(e.DataPoint);
                CircleCheckList = new VDataNode[] { (VDataNode)Root };
                return Root;
            }
            //Знаходимо вузол для заміщення
            VNode C = VNode.FindDataNode(Root, ys, e.DataPoint[0]);
            //Створюємо піддерево з одним ребром, але двома VEdgeNodes
            VoronoiEdge VE = new VoronoiEdge();
            VE.LeftData = ((VDataNode)C).DataPoint;
            VE.RightData = e.DataPoint;
            VE.VVertexA = Fortune.VVUnkown;
            VE.VVertexB = Fortune.VVUnkown;
            VG.Edges.Add(VE);

            VNode SubRoot;
            if (Math.Abs(VE.LeftData[1] - VE.RightData[1]) < 1e-10)
            {
                if (VE.LeftData[0] < VE.RightData[0])
                {
                    SubRoot = new VEdgeNode(VE, false);
                    SubRoot.Left = new VDataNode(VE.LeftData);
                    SubRoot.Right = new VDataNode(VE.RightData);
                }
                else
                {
                    SubRoot = new VEdgeNode(VE, true);
                    SubRoot.Left = new VDataNode(VE.RightData);
                    SubRoot.Right = new VDataNode(VE.LeftData);
                }
                CircleCheckList = new VDataNode[] { (VDataNode)SubRoot.Left, (VDataNode)SubRoot.Right };
            }
            else
            {
                SubRoot = new VEdgeNode(VE, false);
                SubRoot.Left = new VDataNode(VE.LeftData);
                SubRoot.Right = new VEdgeNode(VE, true);
                SubRoot.Right.Left = new VDataNode(VE.RightData);
                SubRoot.Right.Right = new VDataNode(VE.LeftData);
                CircleCheckList = new VDataNode[] { (VDataNode)SubRoot.Left, (VDataNode)SubRoot.Right.Left, (VDataNode)SubRoot.Right.Right };
            }

            //"Застосовуємо" піддерево
            if (C.Parent == null)
                return SubRoot;
            C.Parent.Replace(C, SubRoot);
            return Root;
        }
示例#37
0
        public void Reset()
        {
            GL.Enable(EnableCap.LineSmooth);
            GL.Enable(EnableCap.PolygonSmooth);
            //		GL.Enable(EnableCap.DepthTest);
            Matrix4 modelview = Matrix4.LookAt(Vector3.Zero, Vector3.UnitZ, Vector3.UnitY);

            GL.MatrixMode(MatrixMode.Modelview);
            GL.LoadMatrix(ref modelview);

            int seeds      = 1280;
            int extraSeeds = 512;

            Vector[] points = new Vector[seeds + extraSeeds];

            double thetaOffset = Tau / 4;

            for (int i = 0; i < seeds + extraSeeds; i++)
            {
                double theta = (double)(i + 1) * Tau / Phi;
                double r     = Math.Sqrt(i + 1);
                double x     = (r) * Math.Cos(theta + thetaOffset);
                double y     = (r) * Math.Sin(theta + thetaOffset);

                points[i] = new Vector(new double[] { x, y });
            }

            VoronoiGraph graph = Fortune.ComputeVoronoiGraph(points);

            cells = new SortedDictionary <Vector, List <VoronoiEdge> >();
            foreach (VoronoiEdge edge in graph.Edges)
            {
                if (double.IsNaN(edge.VVertexA.X) ||
                    double.IsNaN(edge.VVertexA.Y) ||
                    double.IsNaN(edge.VVertexB.X) ||
                    double.IsNaN(edge.VVertexB.Y)
                    )
                {
                    continue;
                }

                if (!cells.ContainsKey(edge.LeftData))
                {
                    cells[edge.LeftData] = new List <VoronoiEdge>();
                }

                cells[edge.LeftData].Add(edge);

                if (!cells.ContainsKey(edge.RightData))
                {
                    cells[edge.RightData] = new List <VoronoiEdge>();
                }

                cells[edge.RightData].Add(edge);

                Complex pA = new Complex(edge.VVertexA.X, edge.VVertexA.Y);
                Complex pB = new Complex(edge.VVertexB.X, edge.VVertexB.Y);

                int       sampleCount = 2;
                Complex[] samples     = new Complex[sampleCount];
                samples[0] = pA;
                samples[sampleCount - 1] = pB;
                for (int i = 1; i < sampleCount - 1; i++)
                {
                    double ratio = (double)i / sampleCount;
                    samples[i] = pA * (1 - ratio) + pB * ratio;
                }
            }

            for (int i = 0; i < seeds; i++)
            {
                Queue <VoronoiEdge> edges    = new Queue <VoronoiEdge>(cells.Values.ElementAt(i));
                var            firstEdge     = edges.Dequeue();
                List <Complex> polygonPoints = new List <Complex>();
                polygonPoints.Add(new Complex(firstEdge.VVertexA.X * scale, firstEdge.VVertexA.Y * scale));
                polygonPoints.Add(new Complex(firstEdge.VVertexB.X * scale, firstEdge.VVertexB.Y * scale));
                while (edges.Count > 0)
                {
                    var     edge = edges.Dequeue();
                    Complex pA   = new Complex(edge.VVertexA.X * scale, edge.VVertexA.Y * scale);
                    Complex pB   = new Complex(edge.VVertexB.X * scale, edge.VVertexB.Y * scale);

                    if (polygonPoints[0] == pA)
                    {
                        polygonPoints.Insert(0, pB);
                        continue;
                    }
                    if (polygonPoints[0] == pB)
                    {
                        polygonPoints.Insert(0, pA);
                        continue;
                    }

                    if (polygonPoints[polygonPoints.Count - 1] == pA)
                    {
                        polygonPoints.Add(pB);
                        continue;
                    }
                    if (polygonPoints[polygonPoints.Count - 1] == pB)
                    {
                        polygonPoints.Add(pA);
                        continue;
                    }

                    edges.Enqueue(edge);
                }

                polygons.Add(polygonPoints);
            }

            for (int i = 0; i <= ModuloActor.MaxMod; i++)
            {
                ModuloActor.Maps[i] = CreateIndexMap(i, cells);
            }

            actors[0] = new ModuloActor(21, 0 / 3, new Color4(1f, 0.5f, 0.5f, 1f));
            actors[1] = new ModuloActor(13, 1 / 3, new Color4(0.5f, 1f, 0.5f, 1f));
            actors[2] = new ModuloActor(0, 2 / 3, new Color4(0.5f, 0.5f, 1f, 1f));

            ModuloActor.AnnounceFibonaccis();
        }
示例#38
0
        public static VoronoiGraph FortuneAlgo(List <Vector> points)
        {
            BinaryPriorityQueue PQ             = new BinaryPriorityQueue();
            Hashtable           CurrentCircles = new Hashtable();
            VoronoiGraph        VG             = new VoronoiGraph();
            VNode RootNode = null;

            for (int i = 0; i < points.Count; ++i)
            {
                PQ.Push(new VDataEvent(points[i]));
            }
            while (PQ.Count > 0)
            {
                VEvent      VE = PQ.Pop() as VEvent;
                VDataNode[] CircleCheckList;
                if (VE is VDataEvent)
                {
                    RootNode = ProcessDataEvent(VE as VDataEvent, RootNode, VG, VE.Y, out CircleCheckList);
                }
                else if (VE is VCircleEvent)
                {
                    CurrentCircles.Remove(((VCircleEvent)VE).NodeN);
                    if (!((VCircleEvent)VE).Valid)
                    {
                        continue;
                    }
                    RootNode = ProcessCircleEvent(VE as VCircleEvent, RootNode, VG, VE.Y, out CircleCheckList);
                }
                else
                {
                    throw new Exception("Got event of type " + VE.GetType().ToString() + "!");
                }
                foreach (VDataNode VD in CircleCheckList)
                {
                    if (CurrentCircles.ContainsKey(VD))
                    {
                        ((VCircleEvent)CurrentCircles[VD]).Valid = false;
                        CurrentCircles.Remove(VD);
                    }
                    VCircleEvent VCE = CircleCheckDataNode(VD, VE.Y);
                    if (VCE != null)
                    {
                        PQ.Push(VCE);
                        CurrentCircles[VD] = VCE;
                    }
                }
                if (VE is VDataEvent)
                {
                    Vector DP = ((VDataEvent)VE).DataPoint;
                    foreach (VCircleEvent VCE in CurrentCircles.Values)
                    {
                        if (MathTools.Dist(DP[0], DP[1], VCE.Center[0], VCE.Center[1]) < VCE.Y - VCE.Center[1] && Math.Abs(MathTools.Dist(DP[0], DP[1], VCE.Center[0], VCE.Center[1]) - (VCE.Y - VCE.Center[1])) > 1e-10)
                        {
                            VCE.Valid = false;
                        }
                    }
                }
            }
            VNode.CleanUpTree(RootNode);
            foreach (VoronoiEdge VE in VG.Edges)
            {
                if (VE.Done)
                {
                    continue;
                }
                if (VE.VVertexB == Fortune.VVUnkown)
                {
                    VE.AddVertex(Fortune.VVInfinite);
                    if (Math.Abs(VE.LeftData[1] - VE.RightData[1]) < 1e-10 && VE.LeftData[0] < VE.RightData[0])
                    {
                        Vector T = VE.LeftData;
                        VE.LeftData  = VE.RightData;
                        VE.RightData = T;
                    }
                }
            }

            ArrayList MinuteEdges = new ArrayList();

            foreach (VoronoiEdge VE in VG.Edges)
            {
                if (!VE.IsPartlyInfinite && VE.VVertexA.Equals(VE.VVertexB))
                {
                    MinuteEdges.Add(VE);
                    foreach (VoronoiEdge VE2 in VG.Edges)
                    {
                        if (VE2.VVertexA.Equals(VE.VVertexA))
                        {
                            VE2.VVertexA = VE.VVertexA;
                        }
                        if (VE2.VVertexB.Equals(VE.VVertexA))
                        {
                            VE2.VVertexB = VE.VVertexA;
                        }
                    }
                }
            }
            foreach (VoronoiEdge VE in MinuteEdges)
            {
                VG.Edges.Remove(VE);
            }

            return(VG);
        }