private void preview_Paint(object sender, PaintEventArgs e) { List<PointF> points = GetRandomPoints(); RectangleF size = new RectangleF(0, 0, preview.Width, preview.Height); Voronoi voronoi = new Voronoi(points, null, size); foreach (PointF point in points) { List<PointF> region = voronoi.Region(point); e.Graphics.DrawRectangle(Pens.Red, point.X, point.Y, 10, 10); e.Graphics.DrawLines(Pens.Black, region.ToArray()); } }
void Start() { List<Vector2> points = GetRandomPoints(); Rect size = new Rect(0, 0, 100, 100); Voronoi voronoi = new Voronoi(points, null, size); foreach (Vector2 point in points) { List<Vector2> region = voronoi.Region(point); for (int i = 0; i < region.Count; i++) { Vector2 next = i < region.Count - 1 ? region[i + 1] : region[0]; Debug.DrawLine(region[i], next, Color.white, 1000); } } }
public static IEnumerable <Vector2> RelaxPoints(IEnumerable <Vector2> startingPoints, float width, float height) { Delaunay.Voronoi v = new Delaunay.Voronoi(startingPoints.ToList(), null, new Rect(0, 0, width, height)); foreach (var point in startingPoints) { var region = v.Region(point); point.Set(0, 0); foreach (var r in region) { point.Set(point.x + r.x, point.y + r.y); } point.Set(point.x / region.Count, point.y / region.Count); yield return(point); } }
private void setUpParkRegions(int objects) { float maxArea = float.MinValue; for (int i = 0; i < roadPoints.Count; i++) { List <Vector2> region = v.Region(roadPoints[i]); float area = Utils.PolygonArea(region); if (area > maxArea) { maxArea = area; thirdParkRegion = secondParkRegion; secondParkRegion = firstParkRegion; firstParkRegion = region; } } parkPoints = new List <Vector2>(); int x, y, iter, j = 0; Vector2 point; while (j < objects) { x = (int)Random.Range(0, Config.WIDTH - 1); y = (int)Random.Range(0, Config.HEIGHT - 1); point = new Vector2(x, y); iter = 0; while (!inParkRegion(point) || Utils.IsPointInSegments(point, normalizedEdges, 5f) && iter < 100) { x = (int)Random.Range(0, Config.WIDTH - 1); y = (int)Random.Range(0, Config.HEIGHT - 1); point = new Vector2(x, y); iter++; } parkPoints.Add(point); j++; } }
public static List <GameObject> GenerateCavePieces(GameObject source, PointsResult pointsResult, int subshatterSteps = 0, Material mat = null) { List <GameObject> pieces = new List <GameObject> (); if (mat == null) { mat = createFragmentMaterial(source); } //get transform information Vector3 origScale = source.transform.localScale; source.transform.localScale = Vector3.one; Quaternion origRotation = source.transform.localRotation; source.transform.localRotation = Quaternion.identity; //get rigidbody information Vector2 origVelocity = source.GetComponent <Rigidbody2D> ().velocity; Rect rect = getRect(source); List <Vector2> points = new List <Vector2> (); foreach (Point point in pointsResult.points) { points.Add(point.point); } List <Vector2> borderPoints = pointsResult.borderPoints; Voronoi voronoi = new Delaunay.Voronoi(points, null, rect); List <List <Vector2> > clippedRegions = new List <List <Vector2> > (); foreach (Point point in pointsResult.points) { bool isWall = pointsResult.isWall(point); float magnitude = point.point.magnitude; bool isCell = magnitude > 100; bool isInStartingArea = Mathf.Abs(Mathf.Abs(point.point.x) - Mathf.Abs(point.point.y)) < 10; if (!isInStartingArea && (isWall || isCell)) { List <Vector2> region = voronoi.Region(point.point); clippedRegions = ClipperHelper.clip(borderPoints, region); foreach (List <Vector2> clippedRegion in clippedRegions) { pieces.Add(generateVoronoiPiece(source, clippedRegion, origVelocity, origScale, origRotation, mat)); } } } List <GameObject> morePieces = new List <GameObject> (); if (subshatterSteps > 0) { subshatterSteps--; foreach (GameObject piece in pieces) { morePieces.AddRange(SpriteExploder.GenerateVoronoiPieces(piece, 3, subshatterSteps)); GameObject.DestroyImmediate(piece); } } else { morePieces = pieces; } //reset transform information source.transform.localScale = origScale; source.transform.localRotation = origRotation; Resources.UnloadUnusedAssets(); return(morePieces); }
public static IEnumerable<Vector2> RelaxPoints(IEnumerable<Vector2> startingPoints, float width, float height) { Delaunay.Voronoi v = new Delaunay.Voronoi(startingPoints.ToList(), null, new Rect(0, 0, width, height)); foreach (var point in startingPoints) { var region = v.Region(point); point.Set(0, 0); foreach (var r in region) point.Set(point.x + r.x, point.y + r.y); point.Set(point.x / region.Count, point.y / region.Count); yield return point; } }
private void BuildGraph(IEnumerable <Vector2> points, Delaunay.Voronoi voronoi) { // Build graph data structure in 'edges', 'centers', 'corners', // based on information in the Voronoi results: point.neighbors // will be a list of neighboring points of the same type (corner // or center); point.edges will be a list of edges that include // that point. Each edge connects to four points: the Voronoi edge // edge.{v0,v1} and its dual Delaunay triangle edge edge.{d0,d1}. // For boundary polygons, the Delaunay edge will have one null // point, and the Voronoi edge may be null. var libedges = voronoi.Edges(); var centerLookup = new Dictionary <Vector2?, Center>(); // Build Center objects for each of the points, and a lookup map // to find those Center objects again as we build the graph foreach (var point in points) { var p = new Center { index = centers.Count, point = point }; centers.Add(p); centerLookup[point] = p; } // Workaround for Voronoi lib bug: we need to call region() // before Edges or neighboringSites are available foreach (var p in centers) { voronoi.Region(p.point); } foreach (var libedge in libedges) { var dedge = libedge.DelaunayLine(); var vedge = libedge.VoronoiEdge(); // Fill the graph data. Make an Edge object corresponding to // the edge from the voronoi library. var edge = new Edge { index = edges.Count, river = 0, // Edges point to corners. Edges point to centers. v0 = MakeCorner(vedge.p0), v1 = MakeCorner(vedge.p1), d0 = centerLookup[dedge.p0], d1 = centerLookup[dedge.p1] }; if (vedge.p0.HasValue && vedge.p1.HasValue) { edge.midpoint = Vector2Extensions.Interpolate(vedge.p0.Value, vedge.p1.Value, 0.5f); } edges.Add(edge); // Centers point to edges. Corners point to edges. if (edge.d0 != null) { edge.d0.borders.Add(edge); } if (edge.d1 != null) { edge.d1.borders.Add(edge); } if (edge.v0 != null) { edge.v0.protrudes.Add(edge); } if (edge.v1 != null) { edge.v1.protrudes.Add(edge); } // Centers point to centers. if (edge.d0 != null && edge.d1 != null) { AddToCenterList(edge.d0.neighbors, edge.d1); AddToCenterList(edge.d1.neighbors, edge.d0); } // Corners point to corners if (edge.v0 != null && edge.v1 != null) { AddToCornerList(edge.v0.adjacent, edge.v1); AddToCornerList(edge.v1.adjacent, edge.v0); } // Centers point to corners if (edge.d0 != null) { AddToCornerList(edge.d0.corners, edge.v0); AddToCornerList(edge.d0.corners, edge.v1); } if (edge.d1 != null) { AddToCornerList(edge.d1.corners, edge.v0); AddToCornerList(edge.d1.corners, edge.v1); } // Corners point to centers if (edge.v0 != null) { AddToCenterList(edge.v0.touches, edge.d0); AddToCenterList(edge.v0.touches, edge.d1); } if (edge.v1 != null) { AddToCenterList(edge.v1.touches, edge.d0); AddToCenterList(edge.v1.touches, edge.d1); } } // TODO: use edges to determine these var topLeft = centers.OrderBy(p => p.point.x + p.point.y).First(); AddCorner(topLeft, 0, 0); var bottomRight = centers.OrderByDescending(p => p.point.x + p.point.y).First(); AddCorner(bottomRight, Width, Height); var topRight = centers.OrderByDescending(p => Width - p.point.x + p.point.y).First(); AddCorner(topRight, 0, Height); var bottomLeft = centers.OrderByDescending(p => p.point.x + Height - p.point.y).First(); AddCorner(bottomLeft, Width, 0); // required for polygon fill foreach (var center in centers) { center.corners.Sort(ClockwiseComparison(center)); } }
private void Demo() { List <uint> colors = new List <uint> (); m_points = new List <Vector2> (); systems = new List <StarSystem> (); TextAsset systemAsset = Resources.Load("systems") as TextAsset; string[] systemList = systemAsset.text.Split('\n'); for (int sys = 0; sys < systemList.Length; sys++) { string[] systemLine = systemList[sys].Split(','); string systemName = systemLine[0]; float systemX = (Convert.ToSingle(systemLine[1])) * 3; float systemY = (Convert.ToSingle(systemLine[2])) * 3; string faction = systemLine[3]; m_pointCount++; colors.Add(0); GameObject sysGO = new GameObject(systemName); StarSystem newSys = sysGO.AddComponent <StarSystem>(); newSys.Setup(systemName, systemX, systemY, faction); systems.Add(newSys); if (systemName.StartsWith("zz")) { newSys.isDummy = true; } m_points.Add(new Vector2(systemX, systemY)); if (systemX < minX) { minX = systemX; } if (systemX > maxX) { maxX = systemX; } if (systemY < minY) { minY = systemY; } if (systemY > maxY) { maxY = systemY; } } m_mapWidth = maxX - minX; m_mapHeight = maxY - minY; Delaunay.Voronoi v = new Delaunay.Voronoi(m_points, colors, new Rect(minX, minY, m_mapWidth, m_mapHeight)); foreach (StarSystem sys in systems) { sys.border = v.Region(new Vector2(sys.x, sys.y)); for (int i = 0; i < sys.border.Count; i++) { int nextCounter = i + 1; if (nextCounter == sys.border.Count) { nextCounter = 0; } _mapManager.ClaimBoundary(sys, sys.border[i], sys.border[nextCounter]); } } _mapManager.Draw(); // m_edges = v.VoronoiDiagram (); //m_spanningTree = v.SpanningTree (KruskalType.MINIMUM); //m_delaunayTriangulation = v.DelaunayTriangulation (); }
public void BuildSystems(bool buildOnServer) { TextAsset systemAsset = Resources.Load("stivessystems") as TextAsset; string[] systemList = systemAsset.text.Split('\n'); _mapPoints = new List <Vector2>(); _mapSystems = new List <StarSystem>(); float minX = 0, maxX = 0, minY = 0, maxY = 0; for (int sys = 0; sys < systemList.Length; sys++) { string[] systemLine = systemList[sys].Split(','); string systemName = systemLine[0]; float systemX; float systemY; string faction; // Skip badly formatted systems until we clean it all up try { systemX = (Convert.ToSingle(systemLine[1])) * _settings.CoordinateMultiplier; systemY = (Convert.ToSingle(systemLine[2])) * _settings.CoordinateMultiplier; faction = systemLine[3]; } catch (FormatException ex) { Debug.LogError("Could not load " + systemName + " (" + ex.Message + ")"); continue; } catch (IndexOutOfRangeException ex) { Debug.Log("WARNING: Found an incomplete line. Not necessarily a problem." + " (" + ex.Message + ")"); continue; } // Voronoi Build _colors.Add(0); _mapPoints.Add(new Vector2(systemX, systemY)); if (systemX < minX) { minX = systemX; } if (systemX > maxX) { maxX = systemX; } if (systemY < minY) { minY = systemY; } if (systemY > maxY) { maxY = systemY; } // Save info to use after the Voronoi StarSystem newSS = new StarSystem(); newSS.Name = systemName; newSS.Faction = faction; newSS.X = systemX; newSS.Y = systemY; newSS.OrigX = (Convert.ToSingle(systemLine[1])); newSS.OrigY = (Convert.ToSingle(systemLine[2])); if (systemName.StartsWith("zz")) { newSS.IsDummy = true; } else if (systemLine[4] != "") { try { newSS.StarClass = systemLine[4]; if (systemLine[5].StartsWith("x")) { if (systemLine[5] == "x") { newSS.PlanetsKnown = 0; } else { newSS.PlanetsKnown = Convert.ToInt32(systemLine[5].Substring(1)); } newSS.PlanetsUnknown = true; } else { newSS.PlanetsKnown = Convert.ToInt32(systemLine[5]); } if (systemLine[6] != "x") { newSS.Gravity = Convert.ToSingle(systemLine[6]); } newSS.Atmosphere = systemLine[7]; if (systemLine[8] != "x") { newSS.Water = Convert.ToInt32(systemLine[8].TrimEnd(new char[] { '%' })); } newSS.Climate = systemLine[9]; newSS.Terrain = systemLine[10]; if (systemLine[11] != "x") { newSS.Development = Convert.ToInt32(systemLine[11]); } newSS.HasFlag = (systemLine[12] == "flag"); // Survived the import - mark the data usable newSS.DataAvailable = true; } catch (FormatException ex) { Debug.Log("WARNING: Failed to add extra data for " + systemName + " (" + ex.Message + ")"); } } if (newSS.IsDummy) { newSS.StarClass = "dummy"; } else if (newSS.StarClass == "" || newSS.StarClass == "hx" || newSS.StarClass == "cluster") { // If StarClass wasn't set, let's generate one // TODO: Read values from settings somewhere // HM 10%, HK 35%, HG 35%, HF 10%, HA 10% int roll = UnityEngine.Random.Range(1, 101); if (roll <= 10) { newSS.StarClass = "hm"; } if (roll > 10 && roll <= 45) { newSS.StarClass = "hk"; } if (roll > 45 && roll <= 80) { newSS.StarClass = "hg"; } if (roll > 80 && roll <= 90) { newSS.StarClass = "hf"; } if (roll > 90 && roll <= 100) { newSS.StarClass = "hf"; } } _mapSystems.Add(newSS); } // Generate the map regions using Voronoi algorithm _mapWidth = maxX - minX; _mapHeight = maxY - minY; _voro = new Delaunay.Voronoi(_mapPoints, _colors, new Rect(minX, minY, _mapWidth, _mapHeight)); for (int t = 0; t < _mapPoints.Count; t++) { if (!_settings.ShowDummySystems && _mapSystems[t].IsDummy) { continue; // Skip dummy systems } List <Vector2> li = _voro.Region(_mapPoints[t]); createRegion(li, _mapSystems[t], buildOnServer); } }
public void buildGraph(List<Vector2> points, Voronoi voronoi) { Center p; Corner q; Vector2 point; Vector2 other; List<Delaunay.Edge> libedges= voronoi.Edges(); Dictionary<System.Nullable<Vector2>,Center> centerLookup = new Dictionary<System.Nullable<Vector2>,Center>(); // Build Center objects for each of the points, and a lookup map // to find those Center objects again as we build the graph foreach ( Vector2 ppp in points) { System.Nullable<Vector2> pp = (System.Nullable<Vector2>) ppp; p = new Center(); p.index = centers.Count; p.point = (Vector2) pp; p.neighbors = new List<Center>(); p.borders = new List<Edge>(); p.corners = new List<Corner>(); centers.Add(p); centerLookup[pp] = p; } foreach ( Center po in centers) { voronoi.Region(po.point); } foreach (Delaunay.Edge libedge in libedges) { LineSegment dedge = libedge.DelaunayLine(); LineSegment vedge = libedge.VoronoiEdge(); // Fill the graph data. Make an Edge object corresponding to // the edge from the voronoi library. Edge edge = new Edge(); edge.index = edges.Count; edge.river = 0; edges.Add(edge); edge.midpoint = null; if (vedge.p0!= null && vedge.p1 != null) edge.midpoint = Vector2.Lerp( (Vector2) vedge.p0, (Vector2) vedge.p1, 0.5f); // Edges point to corners. Edges point to centers. edge.v0 = makeCorner(vedge.p0); edge.v1 = makeCorner(vedge.p1); edge.d0 = centerLookup[dedge.p0]; edge.d1 = centerLookup[dedge.p1]; // Centers point to edges. Corners point to edges. if (edge.d0 != null) { edge.d0.borders.Add(edge); } if (edge.d1 != null) { edge.d1.borders.Add(edge); } if (edge.v0 != null) { edge.v0.protrudes.Add(edge); } if (edge.v1 != null) { edge.v1.protrudes.Add(edge); } // Centers point to centers. if (edge.d0 != null && edge.d1 != null) { addToCenterList(edge.d0.neighbors, edge.d1); addToCenterList(edge.d1.neighbors, edge.d0); } // Corners point to corners if (edge.v0 != null && edge.v1 != null) { addToCornerList(edge.v0.adjacent, edge.v1); addToCornerList(edge.v1.adjacent, edge.v0); } // Centers point to corners if (edge.d0 != null) { addToCornerList(edge.d0.corners, edge.v0); addToCornerList(edge.d0.corners, edge.v1); } if (edge.d1 != null) { addToCornerList(edge.d1.corners, edge.v0); addToCornerList(edge.d1.corners, edge.v1); } // Corners point to centers if (edge.v0 != null) { addToCenterList(edge.v0.touches, edge.d0); addToCenterList(edge.v0.touches, edge.d1); } if (edge.v1 != null) { addToCenterList(edge.v1.touches, edge.d0); addToCenterList(edge.v1.touches, edge.d1); } } }