コード例 #1
0
        public void FortuneThreePoints()
        {
            var points = new List <FortuneSite>
            {
                new FortuneSite(100, 100),
                new FortuneSite(200, 200),
                new FortuneSite(200, 150)
            };
            var edges = FortunesAlgorithm.Run(points, 0, 0, 600, 600);

            var edge = edges.First;

            //edge 1
            Assert.AreEqual(125, edge.Value.Start.X);
            Assert.AreEqual(175, edge.Value.Start.Y);
            Assert.AreEqual(0, edge.Value.End.X);
            Assert.AreEqual(300, edge.Value.End.Y);
            Assert.IsNotNull(edge.Next);
            edge = edge.Next;
            //edge 2
            Assert.AreEqual(600, edge.Value.Start.X);
            Assert.AreEqual(175, edge.Value.Start.Y);
            Assert.AreEqual(125, edge.Value.End.X);
            Assert.AreEqual(175, edge.Value.End.Y);
            Assert.IsNotNull(edge.Next);
            edge = edge.Next;
            //edge 3
            Assert.AreEqual(212.5, edge.Value.Start.X);
            Assert.AreEqual(0, edge.Value.Start.Y);
            Assert.AreEqual(125, edge.Value.End.X);
            Assert.AreEqual(175, edge.Value.End.Y);
            Assert.IsNull(edge.Next);
        }
コード例 #2
0
        public void FortuneColinearPoints()
        {
            var points = new List <FortuneSite>
            {
                new FortuneSite(300, 100),
                new FortuneSite(300, 300),
                new FortuneSite(300, 500)
            };

            var edges = FortunesAlgorithm.Run(points, 0, 0, 600, 600);
            var edge  = edges.First;

            Assert.AreEqual(600, edge.Value.Start.X);
            Assert.AreEqual(400, edge.Value.Start.Y);
            Assert.AreEqual(0, edge.Value.End.X);
            Assert.AreEqual(400, edge.Value.End.Y);
            Assert.IsNotNull(edge.Next);

            edge = edge.Next;
            Assert.AreEqual(600, edge.Value.Start.X);
            Assert.AreEqual(200, edge.Value.Start.Y);
            Assert.AreEqual(0, edge.Value.End.X);
            Assert.AreEqual(200, edge.Value.End.Y);
            Assert.IsNull(edge.Next);
        }
コード例 #3
0
 public SampleGraphImplementation(FortunesAlgorithm <PortableColor> v, int numLloydRelaxations, Random r) : base(v, numLloydRelaxations, r)
 {
     Ocean = SampleColorData.Ocean;
     Lake  = SampleColorData.Lake;
     Beach = SampleColorData.Beach;
     River = SampleColorData.River;
 }
コード例 #4
0
ファイル: VoronoiDemo.cs プロジェクト: EttienneS/VoronoiLib
        private void GeneratePoints()
        {
            points.Clear();

            //generate points
            var w = graphics.GraphicsDevice.Viewport.Width;
            var h = graphics.GraphicsDevice.Viewport.Height;

            for (var i = 0; i < GEN_COUNT; i++)
            {
                points.Add(new FortuneSite(
                               r.Next((int)(w / 20.0), (int)(19 * w / 20.0)),
                               r.Next((int)(h / 20.0), (int)(19 * h / 20.0))));
            }

            //uniq the points
            points.Sort((p1, p2) =>
            {
                if (p1.X.ApproxEqual(p2.X))
                {
                    if (p1.Y.ApproxEqual(p2.Y))
                    {
                        return(0);
                    }
                    if (p1.Y < p2.Y)
                    {
                        return(-1);
                    }
                    return(1);
                }
                if (p1.X < p2.X)
                {
                    return(-1);
                }
                return(1);
            });

            var unique = new List <FortuneSite>(points.Count / 2);
            var last   = points.First();

            unique.Add(last);
            for (var index = 1; index < points.Count; index++)
            {
                var point = points[index];
                if (!last.X.ApproxEqual(point.X) ||
                    !last.Y.ApproxEqual(point.Y))
                {
                    unique.Add(point);
                    last = point;
                }
            }
            points = unique;

            edges = FortunesAlgorithm.Run(points, 0, 0, graphics.GraphicsDevice.Viewport.Width, graphics.GraphicsDevice.Viewport.Height);

            GenerateDelaunay();
            //convert ajd list to edge list... edges get double added
        }
コード例 #5
0
ファイル: Program.cs プロジェクト: twobob/VoronoiLib-GC
        public static void Main(string[] args)
        {
            var r       = new Random();
            var watch   = new Stopwatch();
            var times   = new long[MAX_N, SAMPLES];
            var fortune = new FortunesAlgorithm();

            var output = new PoolLinkedList <VEdge>();

            for (var point = 1; point *INC <= MAX_N; point++)
            {
                var numPoints = point * INC;
                Console.WriteLine($"Running for n = {numPoints}");
                for (var sample = 1; sample <= SAMPLES; sample++)
                {
                    Console.WriteLine($"\tRunning sample {sample}");
                    watch.Reset();
                    var points = GenPoints(numPoints, r);
                    watch.Start();
                    fortune.Run(points, output, 0, 0, WIDTH, HEIGHT);
                    watch.Stop();
                    output.Clear((edge) =>
                    {
                        if (edge.Neighbor != null)
                        {
                            ObjectPool <VEdge> .Recycle(edge.Neighbor);
                        }
                        ObjectPool <VEdge> .Recycle(edge);
                    });
                    times[point - 1, sample - 1] = watch.ElapsedMilliseconds;
                }
            }

            var outFile   = File.CreateText("timings.csv");
            var excelFile = File.CreateText("excelTimings.csv");

            outFile.Write("N, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10" + Environment.NewLine);
            excelFile.Write("N, T (ms)" + Environment.NewLine);
            for (var i = 1; i *INC <= MAX_N; i++)
            {
                var s = i * INC + ", ";
                for (var j = 0; j < SAMPLES - 1; j++)
                {
                    s += times[i - 1, j] + ", ";
                }
                s += times[i - 1, SAMPLES - 1] + Environment.NewLine;
                outFile.Write(s);

                for (var j = 1; j <= SAMPLES; j++)
                {
                    excelFile.Write(i * INC + ", " + times[i - 1, j - 1] + Environment.NewLine);
                }
            }
            outFile.Dispose();
            excelFile.Dispose();
        }
コード例 #6
0
 private void RelaxPoints()
 {
     if (points.Count == 0)
     {
         return;
     }
     points = LloydsRelaxation.Relax(points);
     edges  = FortunesAlgorithm.Run(points, 0, 0, graphics.GraphicsDevice.Viewport.Width, graphics.GraphicsDevice.Viewport.Height);
     GenerateDelaunay();
 }
コード例 #7
0
    private void StartFortunesAlgorithm(MapModel model)
    {
        List <Vector2>    tileCoordinates = PossionDiscSampling.CreateRandomList(model.bounds, model.minDistanceTiles);
        FortunesAlgorithm algorithm       = new FortunesAlgorithm(tileCoordinates);

        algorithm.RemoveShortBoundaries(model.minBoundaryLength);
        algorithm.MakeBoundariesWiggely();
        algorithm.CutCorners(model.bounds);

        (model.borderInits, model.tileInits) = algorithm.GetBordersAndTiles();
    }
コード例 #8
0
        public override void PrepareTest(params string[] args)
        {
            Random rand = new Random();

            fortune             = new FortunesAlgorithm(rand.Next(0, 999999999));
            fortune.UseDelaunay = true;
            if (args.Length > 0)
            {
                fortune.PointCount = int.Parse(args[0]);
            }
        }
コード例 #9
0
ファイル: SampleGenerator.cs プロジェクト: svejdo1/Delaunay
        public static VoronoiGraph CreateVoronoiGraph(int bounds, int numSites, int numLloydRelaxations, int seed)
        {
            var r = new Random(seed);

            //make the intial underlying voronoi structure
            var v = new FortunesAlgorithm <PortableColor>(numSites, bounds, bounds, r, null);

            //assemble the voronoi strucutre into a usable graph object representing a map
            var graph = new SampleGraphImplementation(v, numLloydRelaxations, r);

            return(graph);
        }
コード例 #10
0
        public Task <List <GraphEdge> > Handle(CalculateVoronoiEdges request)
        {
            IVoronoiDiagramAlgorithm algorythm = new FortunesAlgorithm();

            var edges = algorythm.Calculate(
                request.Points,
                0,
                request.Width,
                0,
                request.Height);

            return(Task.FromResult(edges));
        }
コード例 #11
0
ファイル: VoronoiDemo.cs プロジェクト: EttienneS/VoronoiLib
        private void WigglePoints()
        {
            var newPoints = new List <FortuneSite>(points.Count);

            if (points.Count > 0)
            {
                newPoints.AddRange(points.Select(point => new FortuneSite(point.X + 5 * r.NextDouble() - 2.5, point.Y + 5 * r.NextDouble() - 2.5)));
            }
            points = newPoints;

            edges = FortunesAlgorithm.Run(points, 0, 0, graphics.GraphicsDevice.Viewport.Width, graphics.GraphicsDevice.Viewport.Height);

            GenerateDelaunay();
        }
コード例 #12
0
        public VoronoiGraph(FortunesAlgorithm <PortableColor> v, int numLloydRelaxations, Random r)
        {
            this.r     = r;
            bumps      = r.Next(5) + 1;
            startAngle = r.NextDouble() * 2 * Math.PI;
            dipAngle   = r.NextDouble() * 2 * Math.PI;
            dipWidth   = r.NextDouble() * .5 + .2;
            bounds     = v.PlotBounds;
            for (int i = 0; i < numLloydRelaxations; i++)
            {
                var points = v.GetSiteCoordinates();
                for (var j = 0; j < points.Count; j++)
                {
                    var    region = v.GetRegion(points[j]);
                    double x      = 0;
                    double y      = 0;
                    foreach (var c in region)
                    {
                        x += c.X;
                        y += c.Y;
                    }
                    x        /= region.Count;
                    y        /= region.Count;
                    points[j] = new PointDouble(x, y);
                }
                v = new FortunesAlgorithm <PortableColor>(points, null, v.PlotBounds);
            }
            BuildGraph(v);
            ImproveCorners();

            AssignCornerElevations();
            AssignOceanCoastAndLand();
            RedistributeElevations(LandCorners());
            AssignPolygonElevations();

            CalculateDownslopes();
            AssignNormals();
            //calculateWatersheds();
            CreateRivers();
            AssignCornerMoisture();
            RedistributeMoisture(LandCorners());
            AssignPolygonMoisture();
            AssignBiomes();

            if (DrawingHook.ImageFactory != null)
            {
                pixelCenterMap = DrawingHook.ImageFactory.CreateBitmap32bppArgb((int)bounds.width, (int)bounds.width);
            }
        }
コード例 #13
0
ファイル: VoronoiDemo.cs プロジェクト: EttienneS/VoronoiLib
        private void AddPoint(int x, int y)
        {
            var newPoints = new List <FortuneSite>();

            if (points.Count > 0)
            {
                newPoints.AddRange(points.Select(point => new FortuneSite(point.X, point.Y)));
            }

            newPoints.Add(new FortuneSite(x, y));
            points = newPoints;

            edges = FortunesAlgorithm.Run(points, 0, 0, graphics.GraphicsDevice.Viewport.Width, graphics.GraphicsDevice.Viewport.Height);

            GenerateDelaunay();
        }
コード例 #14
0
ファイル: VoronoiDemo.cs プロジェクト: twobob/VoronoiLib-GC
 protected override void Initialize()
 {
     //set full screen
     graphics.PreferredBackBufferHeight = graphics.GraphicsDevice.DisplayMode.Height;
     graphics.PreferredBackBufferWidth  = graphics.GraphicsDevice.DisplayMode.Width;
     graphics.ToggleFullScreen();
     IsMouseVisible = true;
     points         = new List <FortuneSite>();
     edges          = new PoolLinkedList <VEdge>();
     delaunay       = new List <Tuple <Vector2, Vector2> >();
     keyboard       = Keyboard.GetState();
     mouse          = Mouse.GetState();
     fortune        = new FortunesAlgorithm();
     r         = new Random(100);
     help      = new Rectangle(0, 0, 285, 180);
     helpColor = new Color(Color.Black, (float).5);
     base.Initialize();
 }
コード例 #15
0
        private void button1_Click(object sender, EventArgs e)
        {
            var ptCount = (double)nud_ptCount.Value;
            var width = (double)nud_width.Value;
            var height = (double)nud_height.Value;
            var lloyd = (double)nud_Lloyd.Value;
            pictureBox1.Width = (int)(width + __border);
            pictureBox1.Height = (int)(height + __border);

            var dots = PointWorker.GetInstance().GetUniqDots(0, 0, (int)width, (int)height, (int)ptCount);
            //_pts = dots;

            var minX = dots.Min(dot => dot.X);
            var minY = dots.Min(dot => dot.Y);
            var maxX = dots.Max(dot => dot.X);
            var maxY = dots.Max(dot => dot.Y);
            pb1.Value = 0;
            var sw = new Stopwatch();

            var sites = PointWorker.GetInstance().DotsToSites(dots);
            var voronoyPartEdges = FortunesAlgorithm.Run(sites, minX, minY, maxX, maxY);

            _edges = voronoyPartEdges.ToList();
            DrawR(pictureBox1);
            Application.DoEvents();

            for (int i = 0; i < lloyd; i++)
            {
                sw.Restart();
                List<FortuneSite> newC = PointWorker.GetInstance().Relax(voronoyPartEdges, minX, minY, maxX, maxY);
                //_sites = newC;
                DrawR(pictureBox1);
                Application.DoEvents();

                sw.Restart();
                voronoyPartEdges = FortunesAlgorithm.Run(newC, minX, minY, maxX, maxY);
                _edges = voronoyPartEdges.ToList();
                //_pts = PointWorker.GetInstance().SitesToDots(newC);
                DrawR(pictureBox1);
                Application.DoEvents();
            }

            pb1.Value = 1;
        }
コード例 #16
0
        public Graph ExecuteStep(Graph graph)
        {
            var points       = _pointSupplier.Invoke();
            var fortuneSites = points.Select(point => new FortuneSite(point.X, point.Y)).ToList();

            FortunesAlgorithm.Run(fortuneSites, _generationMin.X, _generationMin.Y, _generationMax.X, _generationMax.Y);

            // add entities to graph
            Dictionary <FortuneSite, Entity> siteToEntityMapping = new ();

            foreach (var cell in fortuneSites)
            {
                var             areaEntity    = new Entity(_cellNameSupplier.Invoke(cell.X, cell.Y), graph);
                EntityComponent areaComponent = new ("AreaComponent");
                areaComponent.SetProperty("cell", cell);
                areaEntity.Components.Add(areaComponent);

                ComponentUtility.AddPosition2D(areaEntity, (float)cell.X, (float)cell.Y);

                if (_parent == null)
                {
                    graph.Entities.Add(areaEntity);
                }
                else
                {
                    _parent.AddChild(areaEntity);
                }

                siteToEntityMapping.Add(cell, areaEntity);
            }

            // add relations to graph
            Layer layer = graph.GetOrAddLayer(_layerName);

            foreach (var cell in fortuneSites)
            {
                foreach (var cellNeighbor in cell.Neighbors)
                {
                    layer.AddRelation(siteToEntityMapping[cell], siteToEntityMapping[cellNeighbor]);
                }
            }

            return(graph);
        }
コード例 #17
0
    private void Awake()
    {
        List <FortuneSite> sites = new List <FortuneSite>();

        foreach (ForuneSiteMono fsm in fortuneSites)
        {
            sites.Add(fsm.GetSite());
        }

        edges = FortunesAlgorithm.Run(sites, minX, minY, maxX, maxY);

        Debug.Log(edges.Count);

        Dictionary <Vector3, NavigationNode> navNodes = new Dictionary <Vector3, NavigationNode>();

        int i = 1;

        foreach (VEdge edge in edges)
        {
            Vector3 start = TransposeToZ(edge.Start);
            Vector3 end   = TransposeToZ(edge.End);

            if (!navNodes.ContainsKey(start))
            {
                navNodes.Add(start, new GameObject("VoronoiNavNode" + i).AddComponent <NavigationNode>());
                navNodes[start].transform.position = start;
                i++;
            }

            if (!navNodes.ContainsKey(end))
            {
                navNodes.Add(end, new GameObject("VoronoiNavNode" + i).AddComponent <NavigationNode>());
                navNodes[end].transform.position = end;
                i++;
            }

            navNodes[start].AddConnectedNode(navNodes[end]);
            navNodes[end].AddConnectedNode(navNodes[start]);
        }
    }
コード例 #18
0
        public void FortunePointBreak()
        {
            var points = new List <FortuneSite>
            {
                new FortuneSite(100, 100),
                new FortuneSite(500, 100),
                new FortuneSite(300, 200)
            };
            var edges = FortunesAlgorithm.Run(points, 0, 0, 600, 600);
            var edge  = edges.First;

            Assert.AreEqual(325, edge.Value.Start.X);
            Assert.AreEqual(0, edge.Value.Start.Y);
            Assert.AreEqual(600, edge.Value.End.X);
            Assert.AreEqual(550, edge.Value.End.Y);
            Assert.IsNotNull(edge.Next);
            edge = edge.Next;
            Assert.AreEqual(275, edge.Value.Start.X);
            Assert.AreEqual(0, edge.Value.Start.Y);
            Assert.AreEqual(0, edge.Value.End.X);
            Assert.AreEqual(550, edge.Value.End.Y);
            Assert.IsNull(edge.Next);
        }
コード例 #19
0
        public static GameObject LabelPolygon(List <List <GraphNode> > polygonBorders, string label, Color color)
        {
            // 1. Compute voronoi of given points with "VoronoiLib"
            List <FortuneSite> points = new List <FortuneSite>();
            List <GraphNode>   nodes  = new List <GraphNode>();

            foreach (List <GraphNode> polygonBorder in polygonBorders)
            {
                foreach (GraphNode n in polygonBorder)
                {
                    if (!nodes.Contains(n))
                    {
                        nodes.Add(n);
                    }
                }
            }
            foreach (GraphNode n in nodes)
            {
                points.Add(new FortuneSite(n.Vertex.x, n.Vertex.y));
            }

            float margin = 0.2f;
            float minX   = nodes.Min(x => x.Vertex.x) - margin;
            float maxX   = nodes.Max(x => x.Vertex.x) + margin;
            float minY   = nodes.Min(x => x.Vertex.y) - margin;
            float maxY   = nodes.Max(x => x.Vertex.y) + margin;
            LinkedList <VEdge> voronoi = FortunesAlgorithm.Run(points, minX, minY, maxX, maxY);

            // 2. Remove all edges that have either start or end outside of polygon
            List <Vector2> vertices      = nodes.Select(x => x.Vertex).ToList();
            List <VEdge>   edgesToRemove = new List <VEdge>();

            foreach (VEdge edge in voronoi)
            {
                if (!GeometryFunctions.IsPointInPolygon4(vertices, new Vector2((float)edge.Start.X, (float)edge.Start.Y)) || !GeometryFunctions.IsPointInPolygon4(vertices, new Vector2((float)edge.End.X, (float)edge.End.Y)))
                {
                    edgesToRemove.Add(edge);
                }
            }
            foreach (VEdge edge in edgesToRemove)
            {
                voronoi.Remove(edge);
            }

            // DEBUG voronoi
            foreach (VEdge edge in voronoi)
            {
                Debug.DrawLine(new Vector3((float)edge.Start.X, 0f, (float)edge.Start.Y), new Vector3((float)edge.End.X, 0f, (float)edge.End.Y), Color.red, 30);
            }

            // 3. Turn remaining edges into a graph (create a list of for each point representing the points it is connected to)
            Dictionary <VPoint, List <VPoint> > voronoiGraph = new Dictionary <VPoint, List <VPoint> >();

            foreach (VEdge edge in voronoi)
            {
                // handle start point
                if (!voronoiGraph.ContainsKey(edge.Start))
                {
                    voronoiGraph.Add(edge.Start, new List <VPoint>()
                    {
                        edge.End
                    });
                }
                else if (!voronoiGraph[edge.Start].Contains(edge.End))
                {
                    voronoiGraph[edge.Start].Add(edge.End);
                }

                // handle end point
                if (!voronoiGraph.ContainsKey(edge.End))
                {
                    voronoiGraph.Add(edge.End, new List <VPoint>()
                    {
                        edge.Start
                    });
                }
                else if (!voronoiGraph[edge.End].Contains(edge.Start))
                {
                    voronoiGraph[edge.End].Add(edge.Start);
                }
            }

            // 4. Find longest path (with consideration for straightness) between two leaves in graph - this is the centerline
            Dictionary <VPoint, List <VPoint> > voronoiLeaves = voronoiGraph.Where(x => x.Value.Count == 1).ToDictionary(x => x.Key, x => x.Value);

            float         curvePenalty             = 0.00007f;
            float         longestDistance          = float.MinValue;
            List <VPoint> centerLine               = new List <VPoint>();
            float         longestDistanceNoPenalty = float.MinValue;
            List <VPoint> centerLineNoPenalty      = new List <VPoint>();

            foreach (KeyValuePair <VPoint, List <VPoint> > startPoint in voronoiLeaves)
            {
                foreach (KeyValuePair <VPoint, List <VPoint> > endPoint in voronoiLeaves)
                {
                    if (startPoint.Key == endPoint.Key)
                    {
                        continue;
                    }

                    List <VPoint> leavesPath = GetShortestPath(new List <VPoint>()
                    {
                        startPoint.Key
                    }, endPoint.Key, voronoiGraph);
                    if (leavesPath == null)
                    {
                        continue;
                    }
                    float distanceWithPenalty = GetPathDistance(leavesPath, curvePenalty);
                    if (distanceWithPenalty > longestDistance)
                    {
                        longestDistance = distanceWithPenalty;
                        centerLine      = leavesPath;
                    }

                    float distanceNoPenalty = GetPathDistance(leavesPath, 0f);
                    if (distanceNoPenalty > longestDistanceNoPenalty)
                    {
                        longestDistanceNoPenalty = distanceNoPenalty;
                        centerLineNoPenalty      = leavesPath;
                    }
                }
            }

            // If the straight centerline is too short, take the longer curvy one instead
            if (GetPathDistance(centerLine, 0f) < 0.4f * GetPathDistance(centerLineNoPenalty, 0f))
            {
                centerLine = centerLineNoPenalty;
            }

            // 5. Smoothen the centerline
            int           smoothSteps      = 5;
            List <VPoint> smoothCenterLine = new List <VPoint>();

            smoothCenterLine.AddRange(centerLine);
            for (int i = 0; i < smoothSteps; i++)
            {
                smoothCenterLine = SmoothLine(smoothCenterLine);
            }


            // DEBUG centerline
            //Debug.Log("Longest path without curve penalty: " + GetPathDistance(centerLineNoPenalty, 0f));
            //Debug.Log("Longest path with curve penalty: " + GetPathDistance(centerLine, curvePenalty));
            //for (int i = 1; i < centerLineNoPenalty.Count; i++) Debug.DrawLine(new Vector3((float)centerLineNoPenalty[i - 1].X, 0f, (float)centerLineNoPenalty[i - 1].Y), new Vector3((float)centerLineNoPenalty[i].X, 0f, (float)centerLineNoPenalty[i].Y), Color.blue, 30);
            //for (int i = 1; i < centerLine.Count; i++) Debug.DrawLine(new Vector3((float)centerLine[i - 1].X, 0f, (float)centerLine[i - 1].Y), new Vector3((float)centerLine[i].X, 0f, (float)centerLine[i].Y), Color.red, 30);
            for (int i = 1; i < smoothCenterLine.Count; i++)
            {
                Debug.DrawLine(new Vector3((float)smoothCenterLine[i - 1].X, 0f, (float)smoothCenterLine[i - 1].Y), new Vector3((float)smoothCenterLine[i].X, 0f, (float)smoothCenterLine[i].Y), Color.blue, 30);
            }

            // 6. Make sure the path goes from left to right
            double xChange = 0;

            for (int i = 1; i < smoothCenterLine.Count; i++)
            {
                xChange += smoothCenterLine[i].X - smoothCenterLine[i - 1].X;
            }
            if (xChange < 0)
            {
                smoothCenterLine.Reverse();
            }


            // 7. Place text along centerline
            return(DrawTextAlongPath(label, smoothCenterLine, color));
        }
コード例 #20
0
        private void BuildGraph(FortunesAlgorithm <PortableColor> v)
        {
            var pointCenterMap = new Dictionary <PointDouble, Center>();
            var points         = v.GetSiteCoordinates();

            points.ForEach((p) =>
            {
                var c   = new Center();
                c.loc   = p;
                c.index = centers.Count;
                centers.Add(c);
                pointCenterMap[p] = c;
            });

            //bug fix
            centers.ForEach((c) =>
            {
                v.GetRegion(c.loc);
            });

            var libedges       = v.Edges;
            var pointCornerMap = new Dictionary <int, Corner>();

            foreach (var libedge in libedges)
            {
                LineSegment vEdge = libedge.VoronoiEdge();
                LineSegment dEdge = libedge.DelaunayLine();

                var edge = new Edge();
                edge.index = edges.Count;
                edges.Add(edge);

                edge.v0 = MakeCorner(pointCornerMap, vEdge.p0);
                edge.v1 = MakeCorner(pointCornerMap, vEdge.p1);
                edge.d0 = pointCenterMap[dEdge.p0];
                edge.d1 = pointCenterMap[dEdge.p1];

                // Centers point to edges. Corners point to edges.
                if (edge.d0 != null)
                {
                    edge.d0.borders.Add(edge);
                }
                if (edge.d1 != null)
                {
                    edge.d1.borders.Add(edge);
                }
                if (edge.v0 != null)
                {
                    edge.v0.protrudes.Add(edge);
                }
                if (edge.v1 != null)
                {
                    edge.v1.protrudes.Add(edge);
                }

                // Centers point to centers.
                if (edge.d0 != null && edge.d1 != null)
                {
                    AddToCenterList(edge.d0.neighbors, edge.d1);
                    AddToCenterList(edge.d1.neighbors, edge.d0);
                }

                // Corners point to corners
                if (edge.v0 != null && edge.v1 != null)
                {
                    AddToCornerList(edge.v0.adjacent, edge.v1);
                    AddToCornerList(edge.v1.adjacent, edge.v0);
                }

                // Centers point to corners
                if (edge.d0 != null)
                {
                    AddToCornerList(edge.d0.corners, edge.v0);
                    AddToCornerList(edge.d0.corners, edge.v1);
                }
                if (edge.d1 != null)
                {
                    AddToCornerList(edge.d1.corners, edge.v0);
                    AddToCornerList(edge.d1.corners, edge.v1);
                }

                // Corners point to centers
                if (edge.v0 != null)
                {
                    AddToCenterList(edge.v0.touches, edge.d0);
                    AddToCenterList(edge.v0.touches, edge.d1);
                }
                if (edge.v1 != null)
                {
                    AddToCenterList(edge.v1.touches, edge.d0);
                    AddToCenterList(edge.v1.touches, edge.d1);
                }
            }
        }
コード例 #21
0
        public World(int widthArea, int heightArea)
        {
regen:

            this.sites    = new List <FortuneSite>();
            this.cities   = new List <Region>();
            this.kingdoms = new List <Kingdom>();
            this.colors   = new List <Color>();
            this.voronoi  = false;
            this.affSite  = true;
            this.croyance = false;
            this.pantheon = new Pantheon();

            this.mapHeight = heightArea;
            this.mapWidth  = widthArea;
            Random rand   = new Random();
            int    nbSite = widthArea * heightArea / 1000; // default: /400

            this.perlinMap = new double[widthArea, heightArea];
            //nbSite = 30;

            this.colors.Add(Color.Red);
            this.colors.Add(Color.Black);
            this.colors.Add(Color.Purple);
            this.colors.Add(Color.Gray);
            this.colors.Add(Color.Cyan);

            this.name = NameGenerator.GenWorldName();

            Perlin p = new Perlin
            {
                Persistence = 0.65,
                Frequency   = .003333,
                OctaveCount = 8,
                Seed        = /*628594615;*/ new Random().Next(999999999)
            };

            for (int i = 0; i < widthArea; i++)
            {
                for (int j = 0; j < heightArea; j++)
                {
                    perlinMap[i, j] = p.GetValue(i, j, 0);
                }
            }

            for (int i = 0; i < nbSite; i++)
            {
                double cadre = 50d;
                var    x     = rand.NextDouble() * widthArea;
                var    y     = rand.NextDouble() * heightArea;
                var    tmp   = new Region(x, y, perlinMap);
                if (!(x < this.mapWidth - cadre && x > cadre &&
                      y < this.mapHeight - cadre && y > cadre))
                {
                    tmp.City = false;
                }
                sites.Add(tmp);
                if (tmp.City)
                {
                    cities.Add(tmp);
                }
            }

            if (this.cities.Count == 0)
            {
                this.Empty();
                goto regen;
            }

            this.vedges = FortunesAlgorithm.Run(ref sites, 0, 0, widthArea, heightArea);

            // Génération Pays
            int nbCapital = 5;

            while (nbCapital > 0)
            {
                var tmp = cities.ElementAt(new Random().Next(cities.Count));
                if (!tmp.Capital)
                {
                    var r = new Random().Next(this.colors.Count);
                    tmp.Capital = true;
                    this.kingdoms.Add(new Kingdom(tmp, this.colors.ElementAt(r), this.pantheon));
                    tmp.GenRegion(this.perlinMap, r + this.colors.ElementAt(r).ToArgb());
                    this.colors.RemoveAt(r);
                    nbCapital--;
                }
            }

            List <string> verifKingdomName = new List <string>();

            foreach (Kingdom k in this.kingdoms)
            {
                if (verifKingdomName.Contains(k.Name))
                {
                    k.Name = NameGenerator.GenKingdomName();
                }

                verifKingdomName.Add(k.Name);
                k.Purge();
            }

            int n = 0;

            foreach (Region c in cities)
            {
                if (!c.Capital)
                {
                    c.GenRegion(this.perlinMap, new Random().Next(999999) + n);
                }

                n++;
            }

            //Génération des religions
            var pTmp = this.pantheon.Gods.Where(g => !g.Forgot).ToList();

            foreach (Kingdom k in this.kingdoms.Where(e => e.Type == KingdomType.Théocratie))
            {
                var id = rand.Next(pTmp.Count);

                var r = pTmp.ElementAt(id);

                k.God      = r;
                r.Capitale = k.Capital;
                r.Followers.Add(k.Capital);
                k.Capital.God          = r;
                k.Capital.GodInfluence = 1;

                pTmp.RemoveAt(id);
            }

            foreach (God g in pTmp)
            {
                var tmp = this.cities.Where(c => c.Kingdom != null ? c.Kingdom.Type != KingdomType.Théocratie : true).ToList();
                var r   = tmp.ElementAt(rand.Next(tmp.Count));
                r.GodInfluence = 1;
                r.God          = g;
                g.Capitale     = r;
                g.Followers.Add(r);
            }

            // foreach region avec 1 de GodInfluence expendre en -0.1 jusqu'a rencontrer une influence equivalente ou atteindre 0.1

            foreach (Region r in this.sites)
            {
                if (r.GodInfluence == 1)
                {
                    var g = this.pantheon.Gods.Where(e => e == r.God).FirstOrDefault();
                    g.GenInfluence(r);
                }
            }

            foreach (FortuneSite site in sites)
            {
                foreach (VEdge vedge in vedges)
                {
                    if (vedge.Left == site || vedge.Right == site)
                    {
                        if (!site.Cell.Contains(vedge))
                        {
                            site.Cell.Add(vedge);
                        }
                    }
                }
            }
        }
コード例 #22
0
        public static void PopulateWithInitialData(TimelineLayer board, NamelessGame game)
        {
            var resolution = WorldGenConstants.Resolution;

            var random = new InternalRandom(game.WorldSettings.GlobalRandom.Next());


            for (int x = 0; x < game.WorldSettings.WorldBoardWidth; x++)
            {
                for (int y = 0; y < game.WorldSettings.WorldBoardHeight; y++)
                {
                    var worldTile = new WorldTile(new Microsoft.Xna.Framework.Point(x, y));
                    var tile      = game.WorldSettings.TerrainGen.GetTileWithoutRiverWater(x, y, (float)game.WorldSettings.WorldBoardWidth / resolution);
                    worldTile.Terrain = tile.Terrain;
                    worldTile.Biome   = tile.Biome;

                    board.WorldTiles[x, y] = worldTile;
                }
            }


            //generate elevation map for river gen
            for (int i = 0; i < resolution; i++)
            {
                for (int j = 0; j < resolution; j++)
                {
                    //fill it with terrain heght with current noises using resolution
                    board.ElevationMap[i][j] = game.WorldSettings.TerrainGen.GetHeightNoise(i, j, 1);
                }
            }

            //copy elevationArray
            var fillArray = new TileForGeneration[resolution][];

            for (int i = 0; i < resolution; i++)
            {
                fillArray[i] = new TileForGeneration[resolution];
                for (int j = 0; j < resolution; j++)
                {
                    fillArray[i][j] = new TileForGeneration()
                    {
                        fillValue = board.ElevationMap[i][j], x = i, y = j, isWater = false
                    };
                }
            }

            List <FortuneSite> points = new List <FortuneSite>();
            LinkedList <VEdge> edges  = new LinkedList <VEdge>();

            for (var i = 0; i < resolution; i++)
            {
                points.Add(new FortuneSite(
                               random.Next(0, resolution - 1),
                               random.Next(0, resolution - 1)));
            }

            //uniq the points
            points.Sort((p1, p2) =>
            {
                if (p1.X.ApproxEqual(p2.X))
                {
                    if (p1.Y.ApproxEqual(p2.Y))
                    {
                        return(0);
                    }
                    if (p1.Y < p2.Y)
                    {
                        return(-1);
                    }
                    return(1);
                }
                if (p1.X < p2.X)
                {
                    return(-1);
                }
                return(1);
            });

            var unique = new List <FortuneSite>(points.Count / 2);
            var last   = points.First();

            unique.Add(last);
            for (var index = 1; index < points.Count; index++)
            {
                var point = points[index];
                if (!last.X.ApproxEqual(point.X) ||
                    !last.Y.ApproxEqual(point.Y))
                {
                    unique.Add(point);
                    last = point;
                }
            }
            points = unique;

            edges = FortunesAlgorithm.Run(points, 0, 0, resolution - 1, resolution - 1);

            //VEdge.Start is a VPoint with location VEdge.Start.X and VEdge.End.Y
            //VEdge.End is the ending point for the edge
            //FortuneSite.Neighbors contains the site's neighbors in the Delaunay Triangulation


            var waterBitmap = new Bitmap(resolution, resolution);

            var graphics = Graphics.FromImage(waterBitmap);

            Pen whitePen = new Pen(System.Drawing.Color.White, 1);

            var edgesByTheSea = edges.Where(
                x =>
                board.ElevationMap[(int)x.Start.X][(int)x.Start.Y] < TileNoiseInterpreter.SeaLevelThreshold &&
                board.ElevationMap[(int)x.End.X][(int)x.End.Y] >= TileNoiseInterpreter.SeaLevelThreshold ||

                board.ElevationMap[(int)x.End.X][(int)x.End.Y] < TileNoiseInterpreter.SeaLevelThreshold &&
                board.ElevationMap[(int)x.Start.X][(int)x.Start.Y] >= TileNoiseInterpreter.SeaLevelThreshold
                );

            var allInlandEdges = edges.Where(
                x =>
                board.ElevationMap[(int)x.End.X][(int)x.End.Y] >= TileNoiseInterpreter.SeaLevelThreshold &&
                board.ElevationMap[(int)x.Start.X][(int)x.Start.Y] >= TileNoiseInterpreter.SeaLevelThreshold
                ).ToList();

            //randommly remove some rivers;
            var cullingChance = 15;
            var culledEdges   = allInlandEdges.Where(edge => random.Next(1, 101) > cullingChance).ToList();

            culledEdges.AddRange(edgesByTheSea.Where(edge => random.Next(1, 101) > cullingChance));

            //remove desert rivers with high probability
            var cullingDesertChance = 90;

            //if not in desert biome ignore, if in desert, cull with high probability
            culledEdges = culledEdges.Where(edge =>
                                            (board.WorldTiles[(int)edge.Start.X, (int)edge.Start.Y].Biome.HasFlag(Biomes.Desert | Biomes.Jungle | Biomes.Savannah) &&
                                             board.WorldTiles[(int)edge.End.X, (int)edge.End.Y].Biome.HasFlag(Biomes.Desert | Biomes.Jungle | Biomes.Savannah)) ||
                                            random.Next(1, 101) < cullingDesertChance).ToList();

            var finalEdges = new List <VEdge>();

            finalEdges.AddRange(culledEdges);

            foreach (var edge in finalEdges)
            {
                var pointCountForLerpAndRandomization = 7;

                var listVectorEdgePoints = new List <Vector2>();
                var startVector          = new Vector2((float)edge.Start.X, (float)edge.Start.Y);
                var endVector            = new Vector2((float)edge.End.X, (float)edge.End.Y);
                var perpendicular        = (endVector - startVector);
                perpendicular.Normalize();
                perpendicular = new Vector2(perpendicular.Y, -perpendicular.X);



                listVectorEdgePoints.Add(startVector);

                var riverWiggle = 3;

                for (int i = 1; i < pointCountForLerpAndRandomization - 1; i++)
                {
                    var newPoint = Vector2.Lerp(startVector, endVector, ((float)i / (pointCountForLerpAndRandomization - 1))) + (perpendicular * (random.Next(-riverWiggle, riverWiggle)));
                    listVectorEdgePoints.Add(newPoint);
                }
                listVectorEdgePoints.Add(endVector);

                graphics.DrawCurve(whitePen, listVectorEdgePoints.Select(x => x.ToPoint().ToPoint()).ToArray());
            }

            for (int x = 3; x < resolution - 3; x++)
            {
                for (int y = 3; y < resolution - 3; y++)
                {
                    if (waterBitmap.GetPixel(x, y).R > 0)
                    {
                        //fillArray[x][y].isWater = true;

                        if (board.ElevationMap[x][y] >= TileNoiseInterpreter.SeaLevelThreshold)
                        {
                            fillArray[x][y].isWater = true;
                        }
                        else
                        {
                            Queue <TileForGeneration> neighbours = new Queue <TileForGeneration>();
                            GenerationUtility.GetNeighbours(fillArray, neighbours, x, y, 2);
                            if (neighbours.Any(n => board.ElevationMap[n.x][n.y] >= TileNoiseInterpreter.SeaLevelThreshold))
                            {
                                fillArray[x][y].isWater = true;
                            }
                        }
                    }
                }
            }


            for (int i = 0; i < resolution; i++)
            {
                for (int j = 0; j < resolution; j++)
                {
                    board.RiverMap[i][j] = fillArray[i][j].isWater;
                }
            }

            var riverBorderMapCopyForCalcultaion = new bool[resolution][];

            for (int i = 0; i < resolution; i++)
            {
                riverBorderMapCopyForCalcultaion[i] = new bool[resolution];
                for (int j = 0; j < resolution; j++)
                {
                    if (board.RiverMap[i][j])
                    {
                        bool borderedByAnythingBesidesWater = false;
                        //not really a radius, more like an side lenght of a square
                        var searchRadius = 3;
                        if (i > searchRadius && i < resolution - searchRadius && j > searchRadius && j < resolution - searchRadius)
                        {
                            for (int k = i - searchRadius; k < i + searchRadius + 1; k++)
                            {
                                for (int l = j - searchRadius; l < j + searchRadius + 1; l++)
                                {
                                    if (!board.RiverMap[k][l])
                                    {
                                        borderedByAnythingBesidesWater = true;
                                    }
                                }
                            }
                        }

                        if (borderedByAnythingBesidesWater)
                        {
                            board.RiverBorderMap[i][j]             = true;
                            riverBorderMapCopyForCalcultaion[i][j] = true;
                        }
                    }
                }
            }


            var pointsNotConnectedToStartingPoints = new List <TileForGeneration>();

            for (int i = 0; i < resolution; i++)
            {
                for (int j = 0; j < resolution; j++)
                {
                    if (board.RiverBorderMap[i][j])
                    {
                        pointsNotConnectedToStartingPoints.Add(fillArray[i][j]);
                    }
                }
            }


            GenerationUtility.AnalyzeAndAddLines(pointsNotConnectedToStartingPoints, riverBorderMapCopyForCalcultaion, out var borderLines);


            for (int i = 0; i < resolution; i++)
            {
                for (int j = 0; j < resolution; j++)
                {
                    board.InlandWaterConnectivity[i][j] = new TileForInlandWaterConnectivity()
                    {
                        x       = i,
                        y       = j,
                        isWater = board.RiverMap[i][j]
                    };
                }
            }

            foreach (var borderLine in borderLines)
            {
                var line = new WaterBorderLine()
                {
                    Points = borderLine.Select(p => new Microsoft.Xna.Framework.Point(p.x, p.y)).ToList()
                };
                board.BorderLines.Add(line);
                foreach (var p in line.Points)
                {
                    board.InlandWaterConnectivity[p.X][p.Y].WaterBorderLines.Add(line);
                }
            }
#if DEBUG
            ImageWriter.WaterWriteImage(board.RiverMap, board.ElevationMap, resolution, "C:\\11\\RiverMap.png", new Color(1, 0, 0, 1f));

            ImageWriter.WaterWriteImage(board.RiverBorderMap, board.ElevationMap, resolution, "C:\\11\\RiverBorderMap.png", new Color(1, 0, 0, 1f));

            ImageWriter.RiverBordersWriteImage(borderLines, board.ElevationMap, resolution, "C:\\11\\riverBordersLines.png");
#endif

            for (int x = 0; x < game.WorldSettings.WorldBoardWidth; x++)
            {
                for (int y = 0; y < game.WorldSettings.WorldBoardHeight; y++)
                {
                    var worldTile = board.WorldTiles[x, y];

                    if (board.RiverMap[x][y] && worldTile.Terrain != TerrainTypes.Water)
                    {
                        worldTile.Terrain = TerrainTypes.Water;
                        worldTile.Biome   = Biomes.River;
                    }
                }
            }
        }