Пример #1
0
 private void LoadPointClass(string file)
 {
     _dataList = DataManager.LoadPointCloudFromCsv(file);
     if (_dataList != null)
     {
         _tips.Clear();
         _nodes.Clear();
         _vVNodes.Clear();
         _edges.Clear();
         _erosionDilatationValue  = 0;
         tbErosionDilatation.Text = $"{_erosionDilatationValue}";
         _openingClosingValue     = 0;
         tbOpeningClosing.Text    = $"{_openingClosingValue}";
         _fileName = System.IO.Path.GetFileName(file);
         Title     = $"Pattern Analyser - Voronoi Diagramm ({_fileName}) - Status: wird berechnet...";
         Stopwatch stopWatch = new Stopwatch();
         stopWatch.Start();
         _voronoiGraph     = Fortune.ComputeVoronoiGraph(_dataList.ToIEnumerableVectorList());
         _voronoiGraphCopy = _voronoiGraph;
         stopWatch.Stop();
         _nodes   = _dataList.ToIEnumerableNodeList(ref _boundingBox).ToList();
         _vVNodes = _nodes;
         _scaled  = true;
         _edges   = _voronoiGraph.Edges.MapEdgeHashSetToEdgeList(ActualHeight, true, _scaled).ToList();
         this.MyDotViewer.LoadPlain(_nodes, _edges, _fileName, _boundingBox);
         _tips.Clear();
         _tips  = _dataList.GetOneKeyValues();
         Title  = $"Pattern Analyser - Voronoi Diagramm ({_fileName}) - Dauer: {stopWatch.ElapsedMilliseconds.ToString()} ms";
         _frame = null;
     }
 }
Пример #2
0
        public void Evaluate(int SpreadMax)
        {
            if (this.FPinInY.PinIsChanged || this.FPinInX.PinIsChanged)
            {
                IList <Vector> vectors = new List <Vector>();

                #region Initialize List
                int ix = 0;
                int iy = 0;
                for (int i = 0; i < SpreadMax; i++)
                {
                    double x, y;
                    this.FPinInX.GetValue(ix, out x);
                    this.FPinInY.GetValue(iy, out y);

                    vectors.Add(new Vector(x, y));

                    ix++;
                    iy++;

                    if (ix >= this.FPinInX.SliceCount)
                    {
                        ix = 0;
                    }

                    if (iy >= this.FPinInY.SliceCount)
                    {
                        iy = 0;
                    }
                }
                #endregion

                VoronoiGraph graph = Fortune.ComputeVoronoiGraph(vectors);

                //Outputs vertices
                this.FPinOutVertX.SliceCount = graph.Vertizes.Count;
                this.FPinOutVertY.SliceCount = graph.Vertizes.Count;

                for (int i = 0; i < graph.Vertizes.Count; i++)
                {
                    this.FPinOutVertX.SetValue(i, graph.Vertizes[i][0]);
                    this.FPinOutVertY.SetValue(i, graph.Vertizes[i][1]);
                }


                //Outputs the edges
                this.FPinOutEdgesX1.SliceCount = graph.Edges.Count;
                this.FPinOutEdgesY1.SliceCount = graph.Edges.Count;
                this.FPinOutEdgesX2.SliceCount = graph.Edges.Count;
                this.FPinOutEdgesY2.SliceCount = graph.Edges.Count;

                for (int i = 0; i < graph.Edges.Count; i++)
                {
                    this.FPinOutEdgesX1.SetValue(i, graph.Edges[i].VVertexA[0]);
                    this.FPinOutEdgesY1.SetValue(i, graph.Edges[i].VVertexA[1]);
                    this.FPinOutEdgesX2.SetValue(i, graph.Edges[i].VVertexB[0]);
                    this.FPinOutEdgesY2.SetValue(i, graph.Edges[i].VVertexB[1]);
                }
            }
        }
Пример #3
0
        private void LoadTifImages(string file)
        {
            _fileName = System.IO.Path.GetFileName(file);
            _frame    = BitmapDecoder.Create(new Uri(file), BitmapCreateOptions.PreservePixelFormat, BitmapCacheOption.OnLoad).Frames.First();
            int pixelSize = _frame.Format.BitsPerPixel / 8;
            int stride    = _frame.PixelWidth * pixelSize;
            int size      = _frame.PixelHeight * stride;

            _imagePixels = new byte[size];
            _frame.CopyPixels(_imagePixels, stride, 0);
            _tips.Clear();
            _nodes.Clear();
            _vVNodes.Clear();
            _edges.Clear();
            _erosionDilatationValue  = 0;
            tbErosionDilatation.Text = $"{_erosionDilatationValue}";
            _openingClosingValue     = 0;
            tbOpeningClosing.Text    = $"{_openingClosingValue}";
            int NodeCounter = 0;

            // Take every four pixel of the image
            for (int x = 0; x < _frame.PixelWidth; x = x + 12)
            {
                for (int y = 0; y < _frame.PixelHeight; y = y + 12)
                {
                    int pixelIndex     = y * stride + pixelSize * x;
                    int pixelGrayScale = (int)((_imagePixels[pixelIndex] * .21) + (_imagePixels[pixelIndex + 1] * .71) + (_imagePixels[pixelIndex + 2] * .071));

                    if (pixelGrayScale <= _grayScaleValue)
                    {
                        _nodes.Add(new Node("", x, y, 1));
                        _tips.Add($"Node_{NodeCounter}", NodeCounter);
                        NodeCounter++;
                    }
                    else if (pixelGrayScale > _grayScaleValue && pixelGrayScale < 220)
                    {
                        _nodes.Add(new Node("", x, y, 0));
                        _tips.Add($"Node_{NodeCounter}", NodeCounter);
                        NodeCounter++;
                    }
                }
            }
            _vVNodes     = _nodes;
            _boundingBox = new double[]
            {
                -50, -20, _frame.PixelWidth + 50, _frame.PixelHeight + 20
            };
            Title = $"Pattern Analyser - Voronoi Diagramm ({_fileName}) - Status: wird berechnet...";
            Stopwatch stopWatch = new Stopwatch();

            stopWatch.Start();
            _voronoiGraph     = Fortune.ComputeVoronoiGraph(_nodes.MapNodeToVector());
            _voronoiGraphCopy = _voronoiGraph;
            stopWatch.Stop();
            _edges = _voronoiGraph.Edges.MapEdgeHashSetToEdgeList(ActualHeight, true, _scaled).ToList();
            this.MyDotViewer.LoadPlain(_nodes, _edges, _fileName, _boundingBox, _frame, 1);

            Title = $"Pattern Analyser - Voronoi Diagramm ({_fileName}) - Dauer: {stopWatch.ElapsedMilliseconds.ToString()} ms";
            //this.MyDotViewer.LoadSourceImage(_frame, System.IO.Path.GetFileName(file));
        }
Пример #4
0
    /// <summary>
    /// Creates the voronoi graph.
    /// </summary>
    static void CreateVoronoiGraph()
    {
        //Set map sizes
        WorldGen.MapX = WorldGen.width;
        WorldGen.MapY = WorldGen.height;

        //Create the IslandHandler
        WorldGen.IslandHandler = new IslandService(WorldGen.MapX, WorldGen.MapY);

        //init the points hash
        var points = new HashSet <BenTools.Mathematics.Vector>();

        //for each dot in the complexity setting create random dots that are within the map and add them to the points list
        for (int i = 0; i < WorldGen.DotCount; i++)
        {
            points.Add(new BenTools.Mathematics.Vector(Random.Range(0, WorldGen.MapX), Random.Range(0, WorldGen.MapY)));
        }

        //init the map
        WorldGen.voronoiMap = null;

        //iterate on the graph 3 times (more is square, less is chaotic)
        for (int i = 0; i < 3; i++)
        {
            //set the map to the points by computing the graph
            WorldGen.voronoiMap = Fortune.ComputeVoronoiGraph(points);

            //for each point in the list, do some error checking and reprocessing
            foreach (BenTools.Mathematics.Vector vector in points)
            {
                double v0  = 0.0d;
                double v1  = 0.0d;
                int    say = 0;
                foreach (VoronoiEdge edge in WorldGen.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) < WorldGen.MapX) && ((v0 / say) > 0))
                {
                    vector[0] = v0 / say;
                }

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

        //after 3 runs our grid should be good and we can save the final map
        WorldGen.voronoiMap = Fortune.ComputeVoronoiGraph(points);
    }
Пример #5
0
 public Generator(int size)
 {
     _size = size;
     GenerateSquareGrid(size);
     _voronoiGraph = Fortune.ComputeVoronoiGraph(_points);
     BuildGraph();
     ImproveCorners();
 }
Пример #6
0
        private void Button_Click(object sender, RoutedEventArgs e)
        {
            MainCanvas.Children.Clear();

            var cells = new Dictionary <FortuneVoronoi.Common.Point, VoronoiCell>();

            const int    internalSitesCnt   = 1600;
            const int    horBorderSitesCnt  = 50;
            const int    vertBorderSitesCnt = 50;
            const int    resolution         = 16;
            const double realWidth          = 1000.0;
            const double realHeight         = 700.0;
            var          dx = realWidth / horBorderSitesCnt / resolution;
            var          dy = realHeight / vertBorderSitesCnt / resolution;

            var borderSites = SitesGridGenerator.GenerateTileBorder(horBorderSitesCnt, vertBorderSitesCnt, resolution);

            var internalSites = SitesGridGenerator.GenerateInternalSites(horBorderSitesCnt, vertBorderSitesCnt, resolution, internalSitesCnt);

            foreach (var site in borderSites.Concat(internalSites))
            {
                var x = site.X * dx;
                var y = site.Y * dy;
                var v = new FortuneVoronoi.Common.Point(x, y);

                if (cells.ContainsKey(v))
                {
                    continue;
                }

                cells.Add(v, new VoronoiCell {
                    IsVisible = !site.IsBorder, Site = new FortuneVoronoi.Common.Point(x, y)
                });
            }

            var graph = Fortune.ComputeVoronoiGraph(cells);

            foreach (var cell in cells.Values.Where(c => c.IsVisible && c.IsClosed))
            {
                var rgbFill = new byte[3];
                _rnd.NextBytes(rgbFill);
                var fill = new SolidColorBrush(System.Windows.Media.Color.FromRgb(rgbFill[0], rgbFill[1], rgbFill[2]));

                var triangles = cell.CreateTriangles();
                foreach (var triangle in triangles)
                {
                    triangle.Fill = fill;

                    Canvas.SetLeft(triangle, MainCanvas.ActualWidth * 0.5);
                    Canvas.SetTop(triangle, MainCanvas.ActualHeight * 0.5);
                    MainCanvas.Children.Add(triangle);
                }
            }
        }
Пример #7
0
        public VoronoiTemparature(List <TemperatureLocation> temp)
        {
            temperature = temp;
            List <Vector> vectors = new List <Vector>();

            foreach (TemperatureLocation t in temperature)
            {
                vectors.Add(new Vector(t.X, t.Y));
            }
            maxTemperature = GetMaxTemperature();
            minTemperature = GetMinTemperature();
            graph          = Fortune.ComputeVoronoiGraph(vectors);
        }
Пример #8
0
        public Image ComputeVoronoiMap(Image image, bool drawEdges)
        {
            if (image == null || this.points.Count <= 0)
            {
                return(null);
            }

            this.progress = 5;

            VoronoiGraph graph = Fortune.ComputeVoronoiGraph(this.points);

            Color[,] colors = Sampler.BitmapToColorArray((Bitmap)image);

            int width  = colors.GetLength(0) - 1;
            int height = colors.GetLength(1) - 1;

            image = (Image) new Bitmap(width + 1, height + 1);
            Graphics g = Graphics.FromImage(image);

            this.progress = 30;

            polygons = GetRegions(graph);

            this.progress = 92;

            foreach (scg.KeyValuePair <Vector, scg.List <PointF> > region in polygons)
            {
                Vector v  = region.Key;
                int    ix = Math.Min(Math.Max((int)Math.Round(v[0]), 0), width);
                int    iy = Math.Min(Math.Max((int)Math.Round(v[1]), 0), height);

                PointF[] ps = region.Value.ToArray();

                g.FillPolygon(new SolidBrush(colors[ix, iy]), ps, FillMode.Alternate);
            }

            g.Flush();

            this.image = image;

            this.progress = 95;

            if (drawEdges)
            {
                DrawEdges(image);
            }

            this.progress = 100;

            return(image);
        }
Пример #9
0
        public void TestMethod1()
        {
            var shape = new Vector2[] {
                new Vector2(200, 100),
                new Vector2(200, -200),
                new Vector2(100, -200),
                new Vector2(100, -100),
                new Vector2(-100, -100),
                new Vector2(-100, 100),
            };

            var result = Fortune.ComputeVoronoiGraph(shape);

            //Display result
            StringBuilder pathVoronoiEdges = new StringBuilder();

            var min = new Vector2(float.MaxValue);

            foreach (var voronoiEdge in result.Edges)
            {
                min = Vector2.Min(voronoiEdge.LeftData, min);
                min = Vector2.Min(voronoiEdge.RightData, min);

                float length = voronoiEdge.Length;
                if (float.IsPositiveInfinity(length))
                {
                    length = 1000;
                }

                var b = voronoiEdge.FixedPoint + voronoiEdge.DirectionVector * length;
                pathVoronoiEdges.Append($"<path d=\"M {voronoiEdge.FixedPoint.X} {voronoiEdge.FixedPoint.Y} L {b.X} {b.Y} \" stroke=\"black\"></path>");
            }

            StringBuilder shapeData = new StringBuilder();

            shapeData.Append($"M {shape.First().X} {shape.First().Y}");
            foreach (var point in shape.Skip(1))
            {
                shapeData.Append($"L {point.X} {point.Y} ");
            }
            shapeData.Append("Z");

            Console.WriteLine(
                "<svg width=\"500px\" height=\"500px\"><g transform=\"translate({2} {3})\">{0}<path d=\"{1}\" fill=\"none\" stroke=\"green\"></path></g></svg>",
                pathVoronoiEdges,
                shapeData,
                -min.X + 1,
                -min.Y + 1
                );
        }
Пример #10
0
        /// <summary>
        /// The Voronoi Graph calculation creates a delaunay tesselation where
        /// each point is effectively converted into triangles.
        /// </summary>
        /// <param name="points">The points to use for creating the tesselation.</param>
        /// <returns>The generated line featureset.</returns>
        public static IFeatureSet DelaunayLines(IFeatureSet points)
        {
            double[]     vertices = points.Vertex;
            VoronoiGraph gp       = Fortune.ComputeVoronoiGraph(vertices);
            FeatureSet   result   = new FeatureSet();

            foreach (VoronoiEdge edge in gp.Edges)
            {
                Coordinate c1 = edge.RightData.ToCoordinate();
                Coordinate c2 = edge.LeftData.ToCoordinate();
                LineString ls = new LineString(new [] { c1, c2 });
                result.AddFeature(ls);
            }
            return(result);
        }
Пример #11
0
        public void LoadMap(LoadMapParams loadMapParams)
        {
            MapX          = loadMapParams.MapX;
            MapY          = loadMapParams.MapY;
            IslandHandler = new IslandService(MapX, MapY);

            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) < MapX) && ((v0 / say) > 0))
                    {
                        vector[0] = v0 / say;
                    }

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



            voronoiMap = Fortune.ComputeVoronoiGraph(loadMapParams.Points);
            ImproveMapData(voronoiMap, loadMapParams.Fix);
        }
Пример #12
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);
        }
Пример #13
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());
        }
        //Generate the voronoi diagram using an external library
        public VoronoiDiagram GetVoronoi(List <Point> points)
        {
            _siteCells = new Dictionary <Point, Cell>();

            var nrPoints = points.Count;

            var dataPoints = new Vector[nrPoints];

            for (int i = 0; i < nrPoints; i++)
            {
                var point = points[i];
                if (_siteCells.ContainsKey(point))
                {
                    continue;
                }

                dataPoints[i] = new Vector(point.X, point.Y);

                var cell = new Cell {
                    SitePoint = point
                };
                _siteCells.Add(point, cell);
            }

            //Create Voronoi Data using library
            var data = Fortune.ComputeVoronoiGraph(dataPoints);

            //data = BenTools.Mathematics.Fortune.FilterVG(data, 15);

            //Create Diagram
            _voronoi = new VoronoiDiagram();


            _voronoi.HalfEdges = GenerateLines(data);

            _voronoi.VoronoiCells = GenerateCells(data);
            _voronoi.Sites        = points;

            return(_voronoi);
        }
Пример #15
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)));
        }
    }
Пример #16
0
        public VoronoiCell[] GenerateTileCells(int internalCellsCount)
        {
            var mapWidth  = TilesSize.x;
            var mapHeight = TilesSize.y;

            var cells = new Dictionary <FortuneVoronoi.Common.Point, VoronoiCell>();

            var dx = mapWidth / HorBorderSitesCnt / Resolution;
            var dy = mapHeight / VertBorderSitesCnt / Resolution;


            var internalSites = SitesGridGenerator.GenerateInternalSites(HorBorderSitesCnt, VertBorderSitesCnt, Resolution, internalCellsCount,
                                                                         (min, max) => new IntPoint(Random.Range(min, max), Random.Range(min, max)));

            if (!CachedBorders.ContainsKey(TilesSize))
            {
                var borderSites = SitesGridGenerator.GenerateTileBorder(HorBorderSitesCnt, VertBorderSitesCnt, Resolution,
                                                                        (min, max) => new IntPoint(Random.Range(min, max), Random.Range(min, max))); // (int)((min + max) * 0.5f)
                CachedBorders.Add(TilesSize, borderSites);
            }

            foreach (var site in internalSites.Concat(CachedBorders[TilesSize]).Distinct())
            {
                var x = site.X * dx;
                var y = site.Y * dy;
                var v = new FortuneVoronoi.Common.Point(x, y);

                cells.Add(v, new VoronoiCell {
                    IsVisible = !site.IsBorder, Site = v
                });
            }

            var graph = Fortune.ComputeVoronoiGraph(cells);

            return(cells.Values.Where(c => c.IsVisible && c.IsClosed).ToArray());
        }
Пример #17
0
        public World(string countriesFile, string citiesFolder)
        {
            var bordersTemp = new Dictionary <string, string[]>();
            var missing     = new List <string>();

            using (var s = File.OpenText(countriesFile)) {
                while (!s.EndOfStream)
                {
                    var l = s.ReadLine();

                    var sections = l?.Split('\t');

                    var c = new Country();
                    if (sections == null)
                    {
                        continue;
                    }
                    c.Name = sections[0];

                    var stats = sections[1].Split(',');
                    c.Population   = int.Parse(stats[0]);
                    c.Density      = double.Parse(stats[1]);
                    c.GdpPerCapita = double.Parse(stats[2]);

                    stats = sections[2].Split(new[] { ',' }, StringSplitOptions.RemoveEmptyEntries);

                    if (bordersTemp.ContainsKey(c.Name))
                    {
                        Console.WriteLine($"Possible Duplicate: {c.Name}.");
                    }
                    else if (stats.Any())
                    {
                        bordersTemp.Add(c.Name, stats);
                    }

                    c.Ocean = bool.Parse(sections[3]);

                    _countries.Add(c);
                }
            }
            foreach (var country in _countries)
            {
                var highwaysTemp = new Dictionary <City, string[]>();
                //Load cities
                if (File.Exists($".\\{citiesFolder}\\{country.Name}.dat"))
                {
                    using (var s = File.OpenText($".\\{citiesFolder}\\{country.Name}.dat")) {
                        while (!s.EndOfStream)
                        {
                            var str = s.ReadLine()?.Split('\t');
                            if (country.Cities.Any(o => o.Name == str?[0]))
                            {
                                continue;
                            }
                            var coor = str?[1].Split(',').Select(double.Parse).ToArray() ?? new[] { 0.0, 0.0 };
                            var c    = new City(str?[0], country, coor[0], coor[1]);
                            highwaysTemp.Add(c, str?[2].Split(','));
                            country.Cities.Add(c);
                        }
                    }

                    foreach (var city in country.Cities)
                    {
                        if (!highwaysTemp.ContainsKey(city))
                        {
                            continue;
                        }
                        foreach (var s in highwaysTemp[city].Where(s => s != city.Name))
                        {
                            if (country.Cities.Count(o => o.Name == s) == 0)
                            {
                                Console.WriteLine($"Missing city: '{s}'.");
                            }
                            else
                            {
                                city.BorderCities.Add(country.Cities.First(o => o.Name == s));
                            }
                        }
                    }
                }
                else
                {
                    Console.WriteLine($"Missing city file {country.Name}.dat");
                }

                _countries.AsParallel().Where(o => o.Cities.Count > 0).SelectMany(o => ConvexHull.Create(o.Cities).Points).ForEach(o => o.IsHull = true);

                //Load borders
                if (!bordersTemp.ContainsKey(country.Name))
                {
                    continue;
                }
                foreach (var s in bordersTemp[country.Name])
                {
                    if (_countries.Count(o => o.Name == s) == 0)
                    {
                        if (!missing.Contains(s))
                        {
                            missing.Add(s);
                        }
                        country.BorderCountries.Add(new Country {
                            Name = s
                        });
                    }
                    else
                    {
                        country.BorderCountries.AddRange(_countries.Where(o => o.Name == s));
                    }
                }
            }

            // Outbound
            foreach (var source in _countries.Where(o => o.Cities.Count != 0 && o.BorderCountries.Count != 0))
            {
                foreach (var source1 in source.BorderCountries.Where(o => o.Cities.Count != 0 && !source.Outbound.ContainsKey(o)))
                {
                    var graph = Fortune.ComputeVoronoiGraph(source.Cities.Union(source1.Cities).Where(o => o.IsHull).Select(o => new Vector(o.Position)
                    {
                        Tag = o
                    }));
                    var voronoiEdge = graph.Edges.Where(o => ((City)o.LeftData.Tag).Country != ((City)o.RightData.Tag).Country)
                                      .MinBy(o => Connection <City> .Distance((City)o.LeftData.Tag, (City)o.RightData.Tag));
                    var rightCity = (City)voronoiEdge.RightData.Tag;
                    var leftCity  = (City)voronoiEdge.LeftData.Tag;
                    source.Outbound[source1] = leftCity.Country != source ? rightCity : leftCity;
                    source1.Outbound[source] = rightCity.Country != source1 ? leftCity : rightCity;
                }
            }
        }
Пример #18
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);
        }
Пример #19
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();
            }
        }
Пример #20
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
        }
Пример #21
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();
        }
Пример #22
0
 public static VoronoiGraph Voronoi(List <Vector> vectors)
 {
     return(Fortune.ComputeVoronoiGraph(vectors));
 }
Пример #23
0
        /// <summary>
        /// Starts plan generation process
        /// </summary>
        public void Generate()
        {
            var datapoints = new List <Vector>(Parameters.PolygonsCount);

            var r = new Random(Parameters.GridSeed);

            for (int i = 0; i < Parameters.PolygonsCount; i++)
            {
                datapoints.Add(new Vector(r.Next(0, Parameters.MapSize.X), r.Next(0, Parameters.MapSize.Y)));
            }

            var graph = Fortune.ComputeVoronoiGraph(datapoints);

            for (int i = 0; i < Parameters.RelaxCount; i++)
            {
                Relax(graph, datapoints);
                graph = Fortune.ComputeVoronoiGraph(datapoints);
            }

            FillMap(graph);

            {
                // adding elevation data

                var elevationNoise = new SimplexNoise(new Random(Parameters.ElevationSeed));
                elevationNoise.SetParameters(0.0008, SimplexNoise.InflectionMode.NoInflections, SimplexNoise.ResultScale.ZeroToOne);

                foreach (var poly in this)
                {
                    var noiseVal = elevationNoise.GetNoise2DValue(poly.Center.X, poly.Center.Y, 4, 0.8);
                    var col      = 255 / noiseVal.MaxValue * noiseVal.Value;
                    poly.Elevation = (int)col;
                }

                //// elevate each corner
                //if (!Parameters.CenterElevation)
                //    ElevateCorners();
            }

            if (Parameters.CenterElevation)
            {
                var poly = GetAtPoint(new Point(Parameters.MapSize.X / 2, Parameters.MapSize.Y / 2));
                poly.Elevation = 200;
                StartPropagation(poly, 15);
            }

            // making island
            {
                //r = new Random((int)voronoiSeedNumeric.Value);
                var borderElevation = 80;
                var step            = 20;
                for (int x = 0; x < Parameters.MapSize.X; x += 5)
                {
                    var poly = GetAtPoint(new Point(x, 0));

                    poly.Elevation = borderElevation;// r.Next(0, 100);
                    StartPropagation(poly, step);


                    poly           = GetAtPoint(new Point(x, Parameters.MapSize.Y));
                    poly.Elevation = borderElevation;// r.Next(0, 100);
                    StartPropagation(poly, step);
                }

                for (int y = 0; y < Parameters.MapSize.Y; y += 5)
                {
                    var poly = GetAtPoint(new Point(0, y));

                    poly.Elevation = borderElevation;// r.Next(0, 100);
                    StartPropagation(poly, step);


                    poly = GetAtPoint(new Point(Parameters.MapSize.X, y));

                    poly.Elevation = borderElevation;// r.Next(0, 100);
                    StartPropagation(poly, step);
                }
            }

            ElevateCorners();

            #region Moisturizing
            {
                var noise = new SimplexNoise(new Random(Parameters.ElevationSeed));
                noise.SetParameters(0.0008d, SimplexNoise.InflectionMode.NoInflections, SimplexNoise.ResultScale.ZeroToOne);

                foreach (var poly in this)
                {
                    var noiseVal = noise.GetNoise2DValue(poly.Center.X, poly.Center.Y, 2, 0.8);
                    var col      = 100 / noiseVal.MaxValue * noiseVal.Value;
                    poly.Moisture = (int)col;

                    foreach (var corner in poly.Corners)
                    {
                        noiseVal         = noise.GetNoise2DValue(corner.Point.X, corner.Point.Y, 2, 0.8);
                        col              = 2 / noiseVal.MaxValue * noiseVal.Value;
                        corner.WaterFlow = (int)col;
                    }
                }

                // fix heights

                foreach (var poly in this)
                {
                    foreach (var neighbor in poly.Neighbors)
                    {
                        if (poly.Elevation == neighbor.Elevation)
                        {
                            neighbor.Elevation = (int)neighbor.Neighbors.Average(n => n.Elevation);
                        }
                    }
                }

                // calculate rivers
                _corners1 = new HashSet <Corner>();

                // get unique corners
                foreach (var poly in this)
                {
                    foreach (var corner in poly.Corners)
                    {
                        if (!_corners1.Contains(corner) && corner.Polygons.Find(p => p.Elevation <= 127) == null)
                        {
                            _corners1.Add(corner);
                        }
                    }
                }

                var list = new List <Corner>(_corners1);
                list.Sort(new CornerHeightComparer());

                // propagate flow
                foreach (var corner in list)
                {
                    // find lowest edge
                    Edge lowestEdge = corner.Edges[0];
                    int  height     = lowestEdge.GetOpposite(corner).Elevation;
                    for (int i = 0; i < corner.Edges.Count; i++)
                    {
                        var tmp = corner.Edges[i].GetOpposite(corner).Elevation;
                        if (tmp < height)
                        {
                            height     = tmp;
                            lowestEdge = corner.Edges[i];
                        }
                    }

                    lowestEdge.WaterFlow += corner.WaterFlow;
                    lowestEdge.GetOpposite(corner).WaterFlow += corner.WaterFlow;
                }

                // remove rivers that not going to oceans

                _waterCorners = new List <Corner>();

                foreach (var poly in this)
                {
                    foreach (var corner in poly.Corners)
                    {
                        int solid = corner.Polygons.Count(p => p.Elevation > 127);

                        if (solid == 2)
                        {
                            _waterCorners.Add(corner);
                        }
                    }
                }

                // collect all correct edges
                _rivers.Clear();

                foreach (var waterCorner in _waterCorners)
                {
                    var root = new RiverBranch();
                    CollectRiver(waterCorner, root);
                    if (!root.Final)
                    {
                        _riverRoots.Add(root);
                    }
                }

                // fix river flows
                // stage 1: remove all flows
                foreach (var riverBranch in _riverRoots)
                {
                    EnumerateTree(riverBranch, b => { if (b.Edge != null)
                                                      {
                                                          b.Edge.WaterFlow = 0;
                                                      }
                                  });
                }
                // stage 2: reflow it
                foreach (var riverBranch in _riverRoots)
                {
                    FillRiver(riverBranch);
                }

                // remove all non-river
                foreach (var poly in this)
                {
                    foreach (var edge in poly.Edges)
                    {
                        if (edge.WaterFlow > 0 && !_rivers.Contains(edge))
                        {
                            edge.WaterFlow = 0;
                        }
                    }
                }

                // update moisture for polygons
                foreach (var poly in this)
                {
                    if (poly.Elevation > 127)
                    {
                        poly.Moisture = poly.Neighbors.Sum(p =>
                        {
                            var v = p.Neighbors.Sum(n => n.Edges.Sum(ed => ed.WaterFlow > 0 ? 1 : 0));
                            v     = v + p.Neighbors.Sum(n => n.Elevation < 127 && !n.Ocean ? 3 : 0);
                            return(p.Edges.Sum(ed => ed.WaterFlow > 0 ? 1 : 0) + v);
                        });
                    }
                }
            }
            #endregion

            // detect ocean
            {
                SetOcean(GetAtPoint(new Point(0, 0)));
                SetOcean(GetAtPoint(new Point(Parameters.MapSize.X, 0)));
                SetOcean(GetAtPoint(new Point(0, Parameters.MapSize.Y)));
                SetOcean(GetAtPoint(new Point(Parameters.MapSize.X, Parameters.MapSize.Y)));
            }

            // set biomes
            {
                foreach (var poly in this)
                {
                    if (poly.Elevation > 127)
                    {
                        poly.Biome = _biome.GetBiomeWith(poly.Elevation, poly.Moisture > _biome.Moisture.Maximum ? _biome.Moisture.Maximum : poly.Moisture);
                    }
                }
            }

            //find coastline
            foreach (var polygon in this)
            {
                foreach (var edge in polygon.Edges)
                {
                    Polygon poly;
                    Polygon poly2;
                    if (((poly = edge.Polygons.Find(p => p.Elevation > 127)) != null) && ((poly2 = edge.Polygons.Find((p => p.Elevation <= 127))) != null))
                    {
                        poly.Coast  = true;
                        poly2.Coast = true;
                        edge.Coast  = true;
                    }
                }
            }
        }
Пример #24
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);
        }
Пример #25
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;
        }
        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);
        }
Пример #27
0
 private void ComputeVoronoi()
 {
     _graph = Fortune.ComputeVoronoiGraph(_pointList);
 }
Пример #28
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.
        }