void Update() { List <Site> sites = new List <Site>(siteGenerator.Sites); float newMouseYpos = Camera.main.ScreenToWorldPoint(Input.mousePosition).y; if (Input.GetKeyDown(KeyCode.G)) { renderParabolas = !renderParabolas; foreach (Site site in sites) { site.mParabola.SetParabolaRender(renderParabolas); } } if (sites.Count != 0 && renderParabolas && newMouseYpos != mouseYpos) { root = null; foreach (VoronoiEdge oldEdge in edges) { Destroy(oldEdge.gameObject); } edges.Clear(); mouseYpos = newMouseYpos; foreach (Site site in sites) { site.mParabola.CalculateParabola(site, newMouseYpos); } eventQueue = new SortedSet <VoronoiEvent>(new EventComparer()); foreach (Site site in sites) { if (site.transform.position.y <= mouseYpos) { eventQueue.Add(new SiteEvent(site.transform.position)); } } while (eventQueue.Count != 0) { VoronoiEvent popEvent = eventQueue.Min; eventQueue.Remove(popEvent); sweepY = popEvent.yCoord; if (removed.Contains(popEvent)) { removed.Remove(popEvent); continue; } if (popEvent.GetType() == typeof(SiteEvent)) { AddArc(((SiteEvent)popEvent).mSite); } else { RemoveArc((SqueezeEvent)popEvent); } } if (root != null) { CompleteEdge(root); } } }
private void Generate() { // We'll use a sweeping algorithm to calculate the vertices and edges // Start with a priority queue for our events, initially storing // all our site events (each cell) sorted by y-coord SortedSet <VoronoiEvent> events = new SortedSet <VoronoiEvent>(new VoronoiEventComparer()); foreach (Cell cell in diagram.cells) { events.Add(new SiteEvent { site = cell }); } float sweep = ConfigurationManager.Instance.height; BeachTree beach = new BeachTree(ConfigurationManager.Instance.width, ConfigurationManager.Instance.height, diagram, events); while (events.Count > 0) { VoronoiEvent e = events.Min; events.Remove(e); sweep = e.pos.y; beach.sweep = e.pos.y; if (e.GetType() == typeof(SiteEvent)) { SiteEvent se = (SiteEvent)e; beach.Insert(se.site); } else { VertexEvent ve = (VertexEvent)e; beach.Remove(ve); } } beach.Finish(); List <Edge> halves = diagram.edges.Where(e => e.section != null).ToList(); foreach (Edge e in halves) { e.start.edges.Remove(e); e.start = e.section.end; e.section.left.edges.Remove(e.section); e.section.right.edges.Remove(e.section); e.section.end.edges.Remove(e.section); e.section.start.edges.Remove(e.section); diagram.edges.Remove(e.section); } FixDiagram(); Debug.Log("Done"); ConstructMap(); }
public VoronoiArcNode(Vector2 focus) { mFocus = focus; squeezeEvent = null; }
public List <BeachLineEdge> DoVoronoi(List <VoronoiSite> siteList) { List <BeachLineEdge> outEdges = new List <BeachLineEdge>(); beachLine = new BeachLine(); events = new List <VoronoiEvent>(); // Add site list to event list. foreach (VoronoiSite site in siteList) { events.Add(new SiteEvent(site)); } // Sort site list. events.Sort(); // Test for first two events being very close in y if (events.Count >= 2) { if (events[0].y - events[1].y < 0.01f) { // Add another site events far above them to prevent this from happening events.Insert(0, new SiteEvent(new VoronoiSite(new Vector2(0, -10)))); } } // Start processing events int iterations = 0; while (events.Count != 0) { if (use_max_iterations && iterations == max_iterations) { break; } else { iterations++; } // Pop event off front of list VoronoiEvent thisEvent = events[0]; // Set sweepline sweepLine = thisEvent.y; if (sweepLine >= target_sweepline) { sweepLine = target_sweepline; beachLine.Update(sweepLine); break; } beachLine.Update(sweepLine); if (thisEvent.IsValid()) { // Check event type if (thisEvent is SiteEvent) { SiteEvent siteEvent = (SiteEvent)thisEvent; // Create a new arc for this event. BeachLineArc newArc = new BeachLineArc(siteEvent.Site.Point, sweepLine); // Find arc at this site BeachLineArc arcToSplit = beachLine.SearchX(siteEvent.x); if (arcToSplit == null) { // We could not find an arc, meaning this is the first one. // Lets just add it to the beachline as root. beachLine.SetRoot(newArc); } else { // Split the arc arcToSplit.Split(newArc); // The split will have added newArc to the tree and also created two new edges. // We need to check those for intersections. List <BeachLineArc> arcsToSqueeze = new List <BeachLineArc> { newArc.LeftArc, newArc.RightArc }; foreach (BeachLineArc arc in arcsToSqueeze) { CheckForNewEdgeEvents(arc); } } } else if (thisEvent is EdgeEvent) { EdgeEvent edgeEvent = (EdgeEvent)thisEvent; if (edgeEvent.SqueezedArc != null) { if (edgeEvent.SqueezedArc.LeftEdge != null && edgeEvent.SqueezedArc.RightEdge != null) { BeachLineEdge newEdge; List <BeachLineEdge> outputEdges = edgeEvent.SqueezedArc.Squeeze(out newEdge); // Add edges to output foreach (BeachLineEdge edge in outputEdges) { outEdges.Add(edge); } // Squeeze function will have removed arc and edges from tree and created a new edge. // We need to check that edge for any new intersections. CheckForNewEdgeEvents(newEdge.LeftArc); CheckForNewEdgeEvents(newEdge.RightArc); } } // Otherwise, this must have been pre-empted but not invalidated for some reason } else { Debug.LogError("Wrong event type! Should not happen!"); } } events.RemoveAt(0); } if (iterations != max_iterations) { sweepLine = target_sweepline; beachLine.Update(sweepLine); } if (events.Count == 0) { // We completed the events list. // Add the remaining edges to the output. BeachLineElement node = beachLine.GetRoot(); if (node != null) { // Mode node to start while (node.Prev != null) { node = node.Prev; } // Add all remaining edges while (node.Next != null) { if (node is BeachLineEdge) { outEdges.Add(node as BeachLineEdge); } node = node.Next; } } } return(outEdges); }
// Update is called once per frame void Update() { // Destroy existing gameobjects foreach (Transform t in point_objects) { Destroy(t.gameObject); } point_objects.Clear(); foreach (Transform t in line_objects) { Destroy(t.gameObject); } line_objects.Clear(); if (randomize) { UnityEngine.Random.InitState(seed); points.Clear(); // Generate points for (int i = 0; i < num_points; i++) { Vector2 point = new Vector2( UnityEngine.Random.Range( (-x_range / 2) - edge_size, (x_range / 2) + edge_size ), UnityEngine.Random.Range( (-y_range / 2) - edge_size, (y_range / 2) + edge_size )); points.Add(point); } } // Add points to event list foreach (Vector2 point in points) { events.Add(new VoronoiEvent(point)); } // Sort events by y_value events.Sort(); bool complete_early = false; int iterations = 0; beachLine = new BeachLine(); while (!(events.Count == 0) && !complete_early) { VoronoiEvent e = events[0]; // Get first event // Update directrix for beach line beachLine.SetDirectrix(e.y_value); if (beachLine.root == null) { // This is the first event beachLine.Add(new BeachLineArc(new Arc(e.site, e.y_value))); } // If site event else if (e.IsSiteEvent()) { // Create new arc //Arc newArc = new Arc(e.site, e.y_value); Vector2 intersection = Vector2.zero; Vector2 direction = Vector2.zero; BeachLineArc arcToSplit = beachLine.GetArcAtX(e.site.x, out intersection, out direction); if (arcToSplit != null) { Arc newLeftArc = new Arc(arcToSplit.arc.focus, arcToSplit.arc.directrix); newLeftArc.start_x = arcToSplit.arc.start_x; newLeftArc.end_x = e.site.x; BeachLineArc newLeftBLArc = new BeachLineArc(newLeftArc); Arc newRightArc = new Arc(arcToSplit.arc.focus, arcToSplit.arc.directrix); newRightArc.start_x = e.site.x; newRightArc.end_x = arcToSplit.arc.end_x; BeachLineArc newRightBLArc = new BeachLineArc(newRightArc); Edge newLeftEdge = new Edge(intersection, direction, 0); Edge newRightEdge = new Edge(intersection, -direction, 0); BeachLineEdge newLeftBLEdge = new BeachLineEdge(newLeftEdge); BeachLineEdge newRightBLEdge = new BeachLineEdge(newRightEdge); BeachLineElement parentElement = arcToSplit.parent; bool isLeft = false; if (parentElement != null) { if (parentElement.leftChild == arcToSplit) { isLeft = true; } } arcToSplit.parent = newRightBLEdge; newRightBLEdge.leftChild = arcToSplit; newRightBLArc.parent = newRightBLEdge; newRightBLEdge.rightChild = newRightBLArc; newRightBLEdge.parent = newLeftBLEdge; newLeftBLEdge.rightChild = newRightBLEdge; newLeftBLArc.parent = newLeftBLEdge; newLeftBLEdge.leftChild = newLeftBLArc; if (parentElement == null) { beachLine.root = newLeftBLEdge; newLeftBLEdge.parent = null; } else { newLeftBLEdge.parent = parentElement; if (isLeft) { parentElement.leftChild = newLeftBLEdge; } else { parentElement.rightChild = newLeftBLEdge; } } } //Arc leftArc = arcToSplit.SplitLeft(e.site.x); //Arc rightArc = arcToSplit.SplitRight(e.site.x); //// Direction should always point left //BeachLineEdge leftEdge = new BeachLineEdge(new Edge(intersection, direction, 0)); //BeachLineEdge rightEdge = new BeachLineEdge(new Edge(intersection, -direction, 0)); ////beachLine.Add(new BeachLineArc(newArc)); //arcToSplit.ReplaceWith(leftEdge); //leftEdge.SetLeftChild(new BeachLineArc(leftArc)); //leftEdge.SetRightChild(rightEdge); //rightEdge.SetLeftChild(new BeachLineArc(rightArc)); // This arc is going to split existing arc // We will end of with a left/right arc, plus a left right edge } // Event handled. Remove event from list. events.RemoveAt(0); iterations++; if (iterations == max_iterations) { complete_early = true; } } beachLine.Draw(transform.position); foreach (Vector2 point in points) { Transform point_object = GameObject.CreatePrimitive(PrimitiveType.Sphere).transform; point_object.parent = transform; point_object.localScale = new Vector3(point_size, point_size, point_size); point_object.localPosition = new Vector3(point.x, point.y, 0f); point_objects.Add(point_object); } // TEST Transform newLine = CreateLine(points[0], points[1]); line_objects.Add(newLine); //foreach(Vector2 point in points) //{ // if(point != points[0]) // { // Transform newLine = CreateLine(point, points[0]); // line_objects.Add(newLine); // } //} }
private IEnumerator GenerateVisualized() { // We'll use a sweeping algorithm to calculate the vertices and edges // Start with a priority queue for our events, initially storing // all our site events (each cell) sorted by y-coord SortedSet <VoronoiEvent> events = new SortedSet <VoronoiEvent>(new VoronoiEventComparer()); foreach (Cell cell in diagram.cells) { events.Add(new SiteEvent { site = cell }); } float sweep = ConfigurationManager.Instance.height; BeachTree beach = new BeachTree(ConfigurationManager.Instance.width, ConfigurationManager.Instance.height, diagram, events); GameObject sweepObj = Instantiate(sweepPrefab, lineRenderersContainer); LineRenderer sweepRend = sweepObj.GetComponentInChildren <LineRenderer>(); GameObject eventObj = Instantiate(eventPrefab, verticesContainer); List <GameObject> beachObjs = new List <GameObject>(); List <GameObject> diagramObjs = new List <GameObject>(); foreach (Cell cell in diagram.cells) { GameObject cellGObject = Instantiate(cellPrefab, cellsContainer); cellGObject.transform.localPosition = cell.pos; cellGObject.transform.GetComponentInChildren <TextMeshPro>().text = cell.name; // TODO implement CellController and initialize it } //MakeBeach(beachObjs, beach.GetPoints(sweep)); sweepRend.SetPositions(new Vector3[] { new Vector2(0, sweep), new Vector2(ConfigurationManager.Instance.width, sweep) }); yield return(new WaitForSeconds(0.05f)); while (events.Count > 0) { VoronoiEvent e = events.Min; events.Remove(e); eventObj.transform.localPosition = e.pos; while (sweep - 0.1f > e.pos.y) { sweep = sweep - 0.1f; beach.sweep = sweep; sweepRend.SetPositions(new Vector3[] { new Vector2(0, sweep), new Vector2(ConfigurationManager.Instance.width, sweep) }); MakeVoronoi(diagramObjs); MakeBeach(beachObjs, beach.GetBeachPoints()); yield return(new WaitForSeconds(0.1f)); } sweep = e.pos.y; beach.sweep = e.pos.y; sweepRend.SetPositions(new Vector3[] { new Vector2(0, sweep), new Vector2(ConfigurationManager.Instance.width, sweep) }); MakeVoronoi(diagramObjs); MakeBeach(beachObjs, beach.GetBeachPoints()); yield return(new WaitForSeconds(0.1f)); if (e.GetType() == typeof(SiteEvent)) { SiteEvent se = (SiteEvent)e; beach.Insert(se.site); } else { VertexEvent ve = (VertexEvent)e; beach.Remove(ve); } MakeVoronoi(diagramObjs); MakeBeach(beachObjs, beach.GetBeachPoints()); yield return(new WaitForSeconds(0.1f)); } Debug.Log("Finished Events"); beach.Finish(); List <Edge> halves = diagram.edges.Where(e => e.section != null).ToList(); foreach (Edge e in halves) { e.start.edges.Remove(e); e.start = e.section.end; e.section.left.edges.Remove(e.section); e.section.right.edges.Remove(e.section); e.section.end.edges.Remove(e.section); e.section.start.edges.Remove(e.section); diagram.edges.Remove(e.section); } FixDiagram(); while (beachObjs.Count > 0) { Destroy(beachObjs[0]); beachObjs.RemoveAt(0); } while (diagramObjs.Count > 0) { Destroy(diagramObjs[0]); diagramObjs.RemoveAt(0); } // Construct current map ConstructMap(); }