Exemple #1
0
        // Improve the random set of points with Lloyd Relaxation.
        private void ImprovePoints()
        {
            // We'd really like to generate "blue noise". Algorithms:
            // 1. Poisson dart throwing: check each new point against all
            //     existing points, and reject it if it's too close.
            // 2. Start with a hexagonal grid and randomly perturb points.
            // 3. Lloyd Relaxation: move each point to the centroid of the
            //     generated Voronoi polygon, then generate Voronoi again.
            // 4. Use force-based layout algorithms to push points away.
            // 5. More at http://www.cs.virginia.edu/~gfx/pubs/antimony/
            // Option 3 is implemented here. If it's run for too many iterations,
            // it will turn into a grid, but convergence is very slow, and we only
            // run it a few times.
            var newPoints = new List <Vector>();

            foreach (var key in _provinces.Keys)
            {
                var provincePoints = _provinces[key];
                var newpoint       = new Vector(2);
                foreach (var point in provincePoints)
                {
                    newpoint.Add(point);
                }
                newpoint[0] /= provincePoints.Count;
                newpoint[1] /= provincePoints.Count;

                newpoint[0] = (newpoint[0] + key[0]) / 2;
                newpoint[1] = (newpoint[1] + key[1]) / 2;

                newPoints.Add(newpoint);
            }


            var height = Convert.ToInt32(txtHeight.Value);
            var width  = Convert.ToInt32(txtWidth.Value);
            var points = Convert.ToInt32(txtPoints.Value);

            OrderedPoints = newPoints
                            .Select(WrapVector)
                            .OrderBy(v => String.Format("{0:000000000}{1:000000000}", height - (int)v[1], (int)v[0]))
                            .ToList();

            for (var x = -1; x <= 1; x++)
            {
                for (var y = -1; y <= 1; y++)
                {
                    if (x == 0 && y == 0)
                    {
                        continue;
                    }
                    for (var i = 0; i < points; i++)
                    {
                        var point = newPoints[i];
                        newPoints.Add(new Vector(point[0] + (x * width), point[1] + (y * height)));
                    }
                }
            }

            _pointList = newPoints;
            //Text = _pointList.Count.ToString();
            _provinces       = null;
            picDiagram.Image = new Bitmap(width, height);
            Map.Neighbours   = new MultiValueDictionary <int, int>();
        }
Exemple #2
0
        private void GenerateProvinces()
        {
            _rightMatrix = new Matrix();
            _rightMatrix.Translate(Width(), 0);
            _leftMatric = new Matrix();
            _leftMatric.Translate(-1 * Width(), 0);
            _downMatrix = new Matrix();
            _downMatrix.Translate(0, Height());
            _upMatrix = new Matrix();
            _upMatrix.Translate(0, -1 * Height());

            Map               = new Dominons3Map();
            Map.MapImage      = picDiagram.Image;
            Map.Title         = "Test Map";
            Map.Filename      = "TestMap";
            Map.IsWrapAround  = true;
            Map.Description   = "Description of Dom 3 Map.";
            Map.ProvinceCount = OrderedPoints.Count;

            var neighbours = new MultiValueDictionary <Vector, Vector>();

            _provinces = new MultiValueDictionary <Vector, Vector>();
            var height = Convert.ToInt32(txtHeight.Value);
            var width  = Convert.ToInt32(txtWidth.Value);

            _indexToPath.Clear();

            MapBounds        = new Rectangle(0, 0, Width(), Height());
            _borderPointX    = new PointF(Width(), 0);
            _borderPointEdge = new PointF(Width(), Height());
            _borderPointY    = new PointF(0, Height());

            var visibleEdges = _graph.Edges
                               .Cast <VoronoiEdge>()
                               .Where(edge => IsVertexValid(edge.VVertexA) && IsVertexValid(edge.VVertexB) && (MapBounds.ContainsEdge(edge) || MapBounds.IntersectsEdge(edge)))
                               .ToArray();

            foreach (var edge in visibleEdges)
            {
                var segmentId = GetSegmentId(edge);

                if (!_indexToPath.ContainsKey(segmentId))
                {
                    _indexToPath[segmentId] = GenerateJaggedSegment(edge);
                }
            }

            foreach (VoronoiEdge edge1 in _graph.Edges)
            {
                if (!IsOutofBounds(height, width, edge1.LeftData) && !IsOutofBounds(height, width, edge1.RightData))
                {
                    neighbours.Add(edge1.LeftData, edge1.RightData);
                    neighbours.Add(edge1.RightData, edge1.LeftData);

                    var leftProvinceId  = OrderedPoints.IndexOf(edge1.LeftData) + 1;
                    var rightProvinceId = OrderedPoints.IndexOf(edge1.RightData) + 1;

                    Map.Neighbours.Add(leftProvinceId, rightProvinceId);
                    Map.Neighbours.Add(rightProvinceId, leftProvinceId);
                }

                if (!IsOutofBounds(height, width, edge1.LeftData) && IsOutofBounds(height, width, edge1.RightData))
                {
                    var leftProvinceId  = OrderedPoints.IndexOf(edge1.LeftData) + 1;
                    var rightProvinceId = OrderedPoints.IndexOf(WrapVector(edge1.RightData)) + 1;

                    Map.Neighbours.Add(leftProvinceId, rightProvinceId);
                    Map.Neighbours.Add(rightProvinceId, leftProvinceId);
                }

                if (IsOutofBounds(height, width, edge1.LeftData) && !IsOutofBounds(height, width, edge1.RightData))
                {
                    var leftProvinceId  = OrderedPoints.IndexOf(WrapVector(edge1.LeftData)) + 1;
                    var rightProvinceId = OrderedPoints.IndexOf(edge1.RightData) + 1;

                    Map.Neighbours.Add(leftProvinceId, rightProvinceId);
                    Map.Neighbours.Add(rightProvinceId, leftProvinceId);
                }

                if (!IsOutofBounds(height, width, edge1.LeftData))
                {
                    _provinces.Add(edge1.LeftData, edge1.VVertexA);
                    _provinces.Add(edge1.LeftData, edge1.VVertexB);
                }
                if (!IsOutofBounds(height, width, edge1.RightData))
                {
                    _provinces.Add(edge1.RightData, edge1.VVertexA);
                    _provinces.Add(edge1.RightData, edge1.VVertexB);
                }
            }

            for (int i = 0; i < OrderedPoints.Count; i++)
            {
                var provinceId = i + 1;
                Map.TerrainTypes[provinceId] = 0;
            }

            using (var g = Graphics.FromImage(picDiagram.Image))
            {
                foreach (var key in _provinces.Keys.ToList())
                {
                    var list = _provinces[key];
                    var f    = list.First();

                    Vector key1   = key;
                    var    points = list
                                    .Select(v => new { angle = GetAngle(f, key1, v), v })
                                    .OrderBy(a => a.angle)
                                    .Select(a => a.v)
                                    .ToList();

                    _provinces[key] = new HashSet <Vector>(points);

                    var randomBrush = GetRandomBrush();
                    g.FillPolygon(randomBrush, points.Select(v => v.ToPointF()).ToArray());
                    g.FillPolygon(randomBrush, points.Select(v => new PointF((float)v[0] + width, (float)v[1])).ToArray());
                    g.FillPolygon(randomBrush, points.Select(v => new PointF((float)v[0] - width, (float)v[1])).ToArray());
                    g.FillPolygon(randomBrush, points.Select(v => new PointF((float)v[0], (float)v[1] + height)).ToArray());
                    g.FillPolygon(randomBrush, points.Select(v => new PointF((float)v[0], (float)v[1] - height)).ToArray());
                    var provId = OrderedPoints.IndexOf(key);
                    g.DrawString(provId.ToString(), _provFont, Brushes.Black, (float)key[0] + 5f, (float)key[1] + 5f);
                }
            }
            picDiagram.Invalidate();
        }