/// <summary> /// Determine the neighbours of each cell. /// </summary> private void DetermineCellNeighbours(Cell currentCell) { try { // Then run through each of the cell's edges. foreach (HalfEdge currentHalfEdge in currentCell.HalfEdges) { // Now grab the edge. Edge currentEdge = currentHalfEdge.Edge; // Check to see whether the cell is the left or the right side of the edge. if (currentCell.Site == currentEdge.SiteLeft) { // The cell is left, let's grab right. When we do, let's make sure the right side isn't empty, // which is the case when the cell's edge is a border edge. if (currentEdge.SiteRight != null) { currentCell.Neighbours.Add(currentEdge, this.Polygons.Cells[currentEdge.SiteRight.ID]); } } else { // The cell is right, let's grab left. currentCell.Neighbours.Add(currentEdge, this.Polygons.Cells[currentEdge.SiteLeft.ID]); } } } catch (Exception ex) { throw new Exception("Error in DetermineCellNeighbours", ex); } }
/// <summary> /// Calculates perlin noise and uses it to determine the /// elevation of each point in a polygon. /// </summary> private void DetermineCellNoise(Cell currentCell) { try { // While we determine the noise for each of the points that make up the polygon, we also want to use those // points to determine the overall noise for the cell. So let's add all the noise together. double dblTotalNoise = 0; foreach (Point currentPoint in currentCell.Points) { // Calculate noise, but because points are used across different cells, we only have to do it once. if (currentPoint.Noise == 0) { double dblNoise = this.Perlin.Noise(this.NoiseOctaves * currentPoint.x / this.Width, this.NoiseOctaves * currentPoint.y / this.Height, 0); currentPoint.Noise = (dblNoise + 1) / 2; } dblTotalNoise += currentPoint.Noise; } // Now that we've calculated the noise for each of the points, use that to determine the overall noise of the // cell by setting the noise for the site of the cell to the average of the noise of the individual points. currentCell.Site.Noise = (dblTotalNoise / currentCell.Points.Count); } catch (Exception ex) { throw new Exception("Error in DetermineCellNoise", ex); } }
/// <summary> /// Compute the voronoi polygons. /// </summary> /// <created>Dennis Steinmeijer</created> /// <date>2013-07-20</date> public void Compute() { // Set the viewbox. this.Box = new Box() { xl = 0, xr = this.Width, yt = 0, yb = this.Height }; // Check to see whether we have random sites. if (this.SiteList.Count < 1) { throw new Exception("No sites supplied."); } // Initialise some variables. int intSite = 0; double intSiteX = -Polygons.Infinity; double intSiteY = -Polygons.Infinity; // First we'll need to sort the list of sites. this.SiteList.Sort(SortSites); // Then we need to transfer the sites to the stack. foreach (Point objRandomSite in this.SiteList) { this.Sites.Push(objRandomSite); } // Grab the first site. Point objSite = this.Sites.Pop(); // Keep going until we run out of sites or beaches. while (true) { // Grab the first circle event. Circle objCircle = this.FirstCircle; if (objSite != null && (objCircle == null || objSite.y < objCircle.y || (objSite.y == objCircle.y && objSite.x < objCircle.x))) { // Let's make sure we don't happen to have two the exact same points. // If so, just ignore and continue with the next one. if (objSite.x != intSiteX || objSite.y != intSiteY) { // Raise the site counter. intSite++; // Set the site counter as the ID of the site. objSite.ID = intSite; // Create a new cell. Cell objCell = new Cell() { Site = objSite }; // Add the cell to the collection. this.Cells.Add(objSite.ID, objCell); // Add the cell as a beach section. this.AddBeach(objSite); // Let's remember the coordinates of the last handled point. intSiteX = objSite.x; intSiteY = objSite.y; } if (this.Sites.Count < 1) { objSite = null; } else { objSite = this.Sites.Pop(); } } else if (objCircle != null) { // Remove the beach section. this.RemoveBeach(objCircle.Arc); } else { break; } } // wrapping-up: // connect dangling edges to bounding box // cut edges as per bounding box // discard edges completely outside bounding box // discard edges which are point-like this.ClipEdges(); // add missing edges in order to close opened cells this.CloseCells(); }