private void Subdivide(Point2D a, Point2D b, Point2D c, Point2D d, double minLength, ICollection<Point2D> currentResult) { if (a.Dist(c) < minLength || b.Dist(d) < minLength) { return; } var p = m_RndGen.NextDouble(DividingProportion, 1 - DividingProportion); var q = m_RndGen.NextDouble(DividingProportion, 1 - DividingProportion); var e = Geometry.Interpolate(a, d, p); var f = Geometry.Interpolate(b, c, p); var g = Geometry.Interpolate(a, b, q); var i = Geometry.Interpolate(d, c, q); var h = Geometry.Interpolate(e, f, q); double k2 = DividingProportion / (1 - DividingProportion); var s = 1 + m_RndGen.NextDouble(-0.4, 0.4); var t = 1 + m_RndGen.NextDouble(-0.4, 0.4); var m = 1 + m_RndGen.NextDouble(-0.4, 0.4); var n = 1 + m_RndGen.NextDouble(-0.4, 0.4); Subdivide(a, Geometry.Interpolate(g, a, s), h, Geometry.Interpolate(e, a, t), minLength, currentResult); currentResult.Add(h); Subdivide(h, Geometry.Interpolate(f, c, s), c, Geometry.Interpolate(i, c, t), minLength, currentResult); }
public List<Point2D> Generate(Point2D a, Point2D b, Point2D c, Point2D d, double minLength, bool makeSmooth) { Point2D left, right; if (makeSmooth) { var middle = (a + c) / 2; var smoothMultiplier = Math.Min(1, Geometry.Dist(a, c) / Geometry.Dist(b, middle)) * SmoothnessFactor; left = middle + (b - middle) * smoothMultiplier; smoothMultiplier = Math.Min(1, Geometry.Dist(a, c) / Geometry.Dist(d, middle)) * SmoothnessFactor; right = middle + (d - middle) * smoothMultiplier; } else { left = b; right = d; } var result = new List<Point2D>(); result.Add(a); Subdivide(a, left, c, right, minLength, result); result.Add(c); return result; }
public void Build(IMap map, MapSettings settings) { var noise = this.m_PerlinNoiseGenerator.GenerateNoise((int)map.Width, (int)map.Height, Seed, NoiseFrequency); var mapCenter = new Point2D(map.Width / 2, map.Height / 2); double l = 0; double r = 2; while (r - l > 1e-8) { double m = (l + r) / 2; int count = 0; foreach (var polygon in map.Polygons) { var center = polygon.Center; var dist = Geometry.SpecificDist(mapCenter, center, map.Width, map.Height); if (polygon.IsInside && map.ContainsPointInside(center)) { var noiseValue = noise[(int)center.X, (int)center.Y]; if (noiseValue > (this.BaseK + (dist > m ? (1 - this.BaseK) * (dist / m - 1) : 0))) { count++; } } } if (count > K * map.Polygons.Count) { r = m; } else { l = m; } } foreach (var polygon in map.Polygons) { var center = polygon.Center; var dist = Geometry.SpecificDist(mapCenter, center, map.Width, map.Height); if (polygon.IsInside && map.ContainsPointInside(center)) { var noiseValue = noise[(int)center.X, (int)center.Y]; /*polygon.IsLand = noise[(int) center.X, (int) center.Y] * (map.Width / (4 * dist + map.Width)) > 0.25;*/ polygon.IsLand = noiseValue > (this.BaseK + (dist > l ? (1 - this.BaseK) * (dist / l - 1) : 0)); } else { polygon.IsLand = false; } } }
public void AddTriangle(Point2D point, Triangle triangle) { var c = GetCoordinate(point); if (c != null) { m_Hash[c.X, c.Y] = triangle; TriangleCount++; } }
public bool ContainsPoint(Point2D point) { double[] vects = new double[3]; for (int i = 0; i < 3; i++) { vects[i] = Geometry.Vect(Points[i], Points[(i + 1) % 3], point); } return vects.All(s => s >= 0); }
public Triangle GetTriangle(Point2D point) { var c = GetCoordinate(point); if (c != null) { return m_Hash[c.X, c.Y]; } throw new ApplicationException("Can't find triangle in Hash"); }
private void AddNewPoint(Point2D newPoint) { var point = new StructurePoint(newPoint); _points.Add(point); Triangle triangle = SearchTriangle(point); var newTriangles = new Triangle[3]; for (int i = 0; i < 2; i++) { newTriangles[i] = new Triangle(); } newTriangles[2] = triangle; for (int i = 0; i < 3; i++) { Edge edge = triangle.Edge(i); newTriangles[i].Points = new[] {edge.First, edge.Second, point}; newTriangles[i].Triangles = new[] { newTriangles[(i + 1) % 3], newTriangles[(i + 2) % 3], triangle.Triangles[i] }; if (triangle.Triangles[i] != null) { for (int j = 0; j < 3; j++) { if (triangle.Triangles[i].Triangles[j] == triangle) { triangle.Triangles[i].Triangles[j] = newTriangles[i]; break; } } } } /*newTriangles[2].Id = triangle.Id; Triangles[triangle.Id] = newTriangles[2]; m_TrianglesToCheck.Enqueue(newTriangles[2]);*/ for (int i = 0; i < 2; i++) { AddTriangle(newTriangles[i]); m_TrianglesToCheck.Enqueue(newTriangles[i]); } m_TrianglesToCheck.Enqueue(newTriangles[2]); CheckTriangles(); }
private void ButtonAddRandomPointClick(object sender, EventArgs e) { Point2D point = new Point2D(m_Random.NextDouble() * MaxWidth, m_Random.NextDouble() * MaxHeight); // TODO: centralize try/catch try { m_MapCreatorModel.AddPoint(point); } catch (ApplicationException ex) { MessageBox.Show(ex.Message); } }
public override void Build(IMap map, MapSettings settings) { // TODO: change parameters //var noise = new NormNoiseDecorator(m_NoiseGenerator).GenerateNoise((int)map.Width, (int)map.Height, new Random().Next(), 10); var noise = m_NoiseGenerator.GenerateNoise((int)map.Width, (int)map.Height, new Random().Next(), 10); var queue = new PriorityQueue<Corner>((a, b) => -a.DistanceFromCoast.CompareTo(b.DistanceFromCoast)); foreach (var corner in map.Corners) { if (corner.IsOceanCoast) { corner.DistanceFromCoast = 0; queue.Enqueue(corner); } else { corner.DistanceFromCoast = 1e9; } } while (queue.Count > 0) { var current = queue.Dequeue(); foreach (var corner in current.Corners.Where(c => c != null)) { var dist = current.Dist(corner); if (corner.DistanceFromCoast > current.DistanceFromCoast + dist) { corner.DistanceFromCoast = current.DistanceFromCoast + dist; queue.Enqueue(corner); if (corner.IsLake) { double minNoise = noise[(int)corner.X, (int)corner.Y]; var lakeCorners = new List<Corner> { corner }; double bigStep = 2 * map.Corners.Count * this.SmallStep; var lakeQueue = new Queue<Corner>(); lakeQueue.Enqueue(corner); while (lakeQueue.Count > 0) { var lakeCorner = lakeQueue.Dequeue(); foreach (var c in lakeCorner.Corners) { if (c.IsLake && c.DistanceFromCoast > lakeCorner.DistanceFromCoast + bigStep) { c.DistanceFromCoast = lakeCorner.DistanceFromCoast + this.SmallStep * Geometry.Dist(lakeCorner, c) / map.Diagonal; lakeQueue.Enqueue(c); queue.Enqueue(c); minNoise = Math.Min(minNoise, noise[(int)c.X, (int)c.Y]); lakeCorners.Add(c); } } } foreach (var lakeCorner in lakeCorners) { noise[(int)lakeCorner.X, (int)lakeCorner.Y] = minNoise; } } } } } if (map.Corners.Any(c => c.IsLand)) { var maxDistance = map.Corners.Where(c => c.IsLand).Max(c => c.DistanceFromCoast); foreach (var corner in map.Corners) { double noiseInCorner; if (map.ContainsPointInside(corner)) { noiseInCorner = noise[(int) corner.X, (int) corner.Y]; } else { var point = new Point2D(corner); if (point.X < 0) { point.X = 0; } if (point.X >= map.Width - 1) { point.X = map.Width - 1; } if (point.Y < 0) { point.Y = 0; } if (point.Y >= map.Height - 1) { point.Y = map.Height - 1; } noiseInCorner = noise[(int) point.X, (int) point.Y]; } var distanceConstraint = 2 * corner.DistanceFromCoast/maxDistance; if (corner.IsOcean) { corner.Elevation = -Math.Min(distanceConstraint, noiseInCorner); } else { corner.Elevation = Math.Min(distanceConstraint, noiseInCorner); } } } this.NormalizeCornerElevation(map); }
public static double Cos(Point2D a, Point2D b) { return Scal(a, b) / a.Length / b.Length; }
private void CreateSkeleton(int width, Point2D direction, Polygon current, int totalLength, Queue<Polygon> queue, bool addAtMiddle) { current.InSkeleton = true; current.DistanceFromSkeleton = 0; current.IsLand = true; Polygon middlePolygon = null; Point2D newBaseDirection = null; for (int i = 0; i < totalLength - 1; i++) { Polygon nextPolygon = null; double cos = 0; foreach (var polygon in current.Polygons) { if (polygon.IsInside && !polygon.InSkeleton && polygon.DistanceFromEdge > width) { var newCos = Geometry.Cos(direction, polygon.Center - current.Center); if (nextPolygon == null || cos < newCos) { nextPolygon = polygon; cos = newCos; } } } if (nextPolygon != null) { nextPolygon.InSkeleton = true; nextPolygon.DistanceFromSkeleton = 0; nextPolygon.IsLand = true; queue.Enqueue(nextPolygon); direction = nextPolygon.Center - current.Center; current = nextPolygon; if (i == totalLength / 2) { middlePolygon = current; newBaseDirection = new Point2D(direction.Y, -direction.X); if (m_Random.Next(2) == 0) { newBaseDirection = -newBaseDirection; } } } else { break; } } if (addAtMiddle && middlePolygon != null) { CreateSkeleton(width, newBaseDirection, middlePolygon, totalLength / 2, queue, m_Random.Next(2) == 0); } }
public void AddPoint(Point2D point) { m_Structure.AddPoint(point); UpdateMap(); }
public Polygon(Point2D basePoint) { BasePoint = basePoint; Init(); }
public static double Scal(Point2D a, Point2D b, Point2D c) { return (b.X - a.X)*(c.X - a.X) + (b.Y - a.Y)*(c.Y - a.Y); }
public MapPoint(Point2D point) : base(point) { }
private double Vect(Edge edge, Point2D point) { return Geometry.Vect(edge.First, edge.Second, point); }
public static double Dist(Point2D a, Point2D b) { return Math.Sqrt((a.X - b.X) * (a.X - b.X) + (a.Y - b.Y) * (a.Y - b.Y)); }
private PointInt GetCoordinate(Point2D point) { int x = (int) (m_Size * point.X / Width); int y = (int) (m_Size * point.Y / Height); if (x < 0 || x >= m_Size || y < 0 || y >= m_Size) { return null; } return new PointInt(x, y); }
public double Dist(Point2D point) { return Geometry.Dist(this, point); }
public static double Vect(Point2D a, Point2D b, Point2D c) { return (b.X - a.X) * (c.Y - a.Y) - (b.Y - a.Y) * (c.X - a.X); }
public static double SpecificDist(Point2D center, Point2D p, double width, double height) { double dx = (p.X - center.X) / (width / 2); double dy = (p.Y - center.Y) / (height / 2); return Math.Sqrt(dx*dx + dy*dy); }
// TODO: Finish public static bool SegmentsIntersects(Point2D a, Point2D b, Point2D c, Point2D d) { bool intersect1 = (Vect(a, b, c) * Vect(a, b, d) < 0); bool intersect2 = (Vect(c, d, a) * Vect(c, d, b) < 0); return intersect1 && intersect2; }
public void AddPoint(Point2D point) { AddNewPoint(point); }
public bool ContainsPointInside(Point2D point) { return 0 <= point.X && point.X <= Width && 0 <= point.Y && point.Y <= Height; }
private static double Scal(Point2D a, Point2D b) { return a.X * b.X + a.Y * b.Y; }
public static Point2D Interpolate(Point2D a, Point2D b, double k) { return (1 - k) * a + k * b; }
public Point2D(Point2D point) : this(point.X, point.Y) { }
private void CreateIndent(double[,] noise, double width, double height, double indent) { var mapCenter = new Point2D(width/2, height/2); for (int i = 0; i < width; i++) { for (int j = 0; j < height; j++) { var point = new Point2D(i, j); var dist = Geometry.SpecificDist(mapCenter, point, width, height); if (dist > 1 - indent) { double overhead = (dist - (1 - indent)) / indent; noise[i, j] = Math.Max(0, noise[i, j]*(1 - overhead)); } } } }
public Corner(Point2D point) : base(point.X, point.Y) { Init(); }
public StructurePoint(Point2D point) : base(point.X, point.Y) { }