//TODO: Unbounded problem could manifest itself here public static VFace closestCell(float x, float y, TriangleNet.Voronoi.BoundedVoronoi voronoi) { int startingIndex = voronoi.Faces.Count / 2; VFace currentCell = voronoi.Faces[startingIndex]; float currentDistance = Mathf.Sqrt((float)(currentCell.generator.X - x) * (float)(currentCell.generator.X - x) + (float)(currentCell.generator.Y - y) * (float)(currentCell.generator.Y - y)); while (true) { TriangleNet.Topology.DCEL.Face nextCell = null; bool foundNeighbour = false; foreach (TriangleNet.Topology.DCEL.HalfEdge edge in currentCell.EnumerateEdges()) { VFace nCell = edge.twin.face; float neighbourX = (float)nCell.generator.X; float neighbourY = (float)nCell.generator.Y; float distanceFromNeighbour = Mathf.Sqrt((neighbourX - x) * (neighbourX - x) + (neighbourY - y) * (neighbourY - y)); if (distanceFromNeighbour < currentDistance) { foundNeighbour = true; currentDistance = distanceFromNeighbour; nextCell = nCell; } } if (!foundNeighbour) { break; } currentCell = nextCell; } return(currentCell); }
public bool CheckCell(VFace cell) { if (cell.Bounded && cell.ID != -1) { return(true); } else { return(false); } }
public bool CheckCell(VFace cell, float minX, float maxX, float minY, float maxY) { if (cell.Bounded && cell.ID != -1 && cell.Generator.X > minX && cell.Generator.X < maxX && cell.Generator.Y > minY && cell.Generator.Y < maxY) { return(true); } else { return(false); } }
//writes into cellMap and endCandidates private bool expandCountries(List <CompilationUnit> cuList, List <VFace> cellMap, Dictionary <int, VFace> endCandidates, VFace startingCell, float b) { Dictionary <int, VFace> candidates = new Dictionary <int, VFace>(); candidates.Add(startingCell.ID, startingCell); for (int i = 1; i < cuList.Count * expansionFactor + 1; i++) { if (candidates.Count == 0) { cellMap.Clear(); endCandidates.Clear(); return(false); } //Select cell from candidates KeyValuePair <int, VFace> selectedCell = selectFromCandidates(candidates, b); //Mark cell in islandVoronoi selectedCell.Value.mark = i; //Add cell to package dictionary cellMap.Add(selectedCell.Value); //Remove cell from future candidates list candidates.Remove(selectedCell.Key); //Add viable candidates around cell foreach (VHEdge edge in selectedCell.Value.EnumerateEdges()) { VFace nCell = edge.twin.face; //If cell is OK, not occupied and not already in candidateList, add to candidate list if (Helperfunctions.checkCell(nCell, -GlobalVar.voronoiCellScalefactor * 0.4f, GlobalVar.voronoiCellScalefactor * 0.4f, -GlobalVar.voronoiCellScalefactor * 0.4f, GlobalVar.voronoiCellScalefactor * 0.4f) && nCell.mark == 0 && !candidates.ContainsKey(nCell.ID)) { candidates.Add(nCell.ID, nCell); } } } //transfer candidates into endCandidates Dict foreach (KeyValuePair <int, VFace> kvp in candidates) { endCandidates.Add(kvp.Key, kvp.Value); } return(true); }
private bool ExpandCountries(List <CompilationUnit> compilationUnits, List <VFace> cellMap, Dictionary <int, VFace> endCells, VFace startCell, float cohesionMultiplier) { Dictionary <int, VFace> cells = new Dictionary <int, VFace>(); cells.Add(startCell.ID, startCell); for (int i = 1; i < compilationUnits.Count * ExpansionFactor + 1; i++) { if (cells.Count == 0) { cellMap.Clear(); endCells.Clear(); return(false); } KeyValuePair <int, VFace> selectedCell = SelectFromCells(cells, cohesionMultiplier); selectedCell.Value.Mark = i; cellMap.Add(selectedCell.Value); cells.Remove(selectedCell.Key); foreach (VHEdge edge in selectedCell.Value.EnumerateEdges()) { VFace nCell = edge.Twin.Face; float scale = CELL_SCALE * 0.4f; bool cellValid = CheckCell(nCell, -scale, scale, -scale, scale); if (cellValid && nCell.Mark == 0 && !cells.ContainsKey(nCell.ID)) { cells.Add(nCell.ID, nCell); } } } //transfer candidates into endCandidates Dict foreach (KeyValuePair <int, VFace> keyValuePair in cells) { endCells.Add(keyValuePair.Key, keyValuePair.Value); } return(true); }
private VFace ClosestCell(float x, float y, BoundedVoronoi voronoi) { int startingIndex = voronoi.Faces.Count / 2; VFace currentCell = voronoi.Faces[startingIndex]; float xDiff = (float)(currentCell.Generator.X - x); float yDiff = (float)(currentCell.Generator.Y - y); float currentDist = Mathf.Sqrt(xDiff * xDiff + yDiff * yDiff); while (true) { VFace nextCell = null; bool foundNeighbour = false; foreach (VHEdge edge in currentCell.EnumerateEdges()) { VFace nCell = edge.Twin.Face; float xDiffNeighbor = (float)(nCell.Generator.X - x); float yDiffNeighbor = (float)(nCell.Generator.Y - y); float distFromNeighbour = Mathf.Sqrt(xDiffNeighbor * xDiffNeighbor + yDiffNeighbor * yDiffNeighbor); if (distFromNeighbour < currentDist) { foundNeighbour = true; currentDist = distFromNeighbour; nextCell = nCell; } } if (!foundNeighbour) { break; } currentCell = nextCell; } return(currentCell); }
//return: the unused candidates //b[1, 10]: cohesion factor. higher b -> more compact "cohesive" islands private Dictionary <int, VFace> constructRegionFromPackage(Package package, CartographicIsland island, Dictionary <int, VFace> startingCandidates, float b) { BoundedVoronoi islandVoronoi = island.getVoronoi(); List <CompilationUnit> cuList = package.getCompilationUnits(); List <VFace> cellMap = new List <VFace>(); Dictionary <int, VFace> newCandidates = new Dictionary <int, VFace>(); VFace startingCell = selectFromCandidates(startingCandidates, b).Value; int maxIterations = 10; int counter = 0; while (expandCountries(cuList, cellMap, newCandidates, startingCell, b) == false && counter < maxIterations) { //Debug.Log("Backtracking"); startingCell = selectFromCandidates(startingCandidates, b).Value; counter++; } island.addPackage(package); island.addPackageCells(cellMap); return(newCandidates); }
private CartographicIsland BuildFromBundle(Bundle bundle) { int seed = bundle.GetHashCode(); TriangleNet.Configuration config = new TriangleNet.Configuration(); BoundedVoronoi voronoi = VoronoiMaker.Instance.CreateRelaxedVoronoi(1, CELL_SCALE, seed); VFace initCell = ClosestCell(0, 0, voronoi); var startCells = new Dictionary <int, VFace>(); startCells.Add(initCell.ID, initCell); var island = new CartographicIsland(bundle, voronoi); int maxCount = bundle.MostCompilationUnits.CompilationUnitCount; foreach (Package package in bundle.Packages) { ConstructRegion(package, island, startCells, maxCount); } ShapeCoastArea(startCells, HEIGHT_PROFILE); SetCoastline(startCells, island); island.Radius = CalculateRadius(startCells, island); foreach (List <VFace> cellMap in island.PackageCells) { List <TNetMesh> packageMeshes = ConstructTNetMeshFromCellmap(cellMap); island.PackageMeshes.Add(packageMeshes); } List <TNetMesh> coastlineMeshes = ConstructTNetMeshFromCellmap(island.CoastlineCells); island.CoastlineMeshes.AddRange(coastlineMeshes); LinkDependencyVertex(bundle, island); return(island); }
private void ShapeCoastArea(Dictionary <int, VFace> coastline, float[] heightProfile) { Dictionary <int, VFace> newCoastline = new Dictionary <int, VFace>(coastline); for (int i = 0; i < heightProfile.Length; i++) { newCoastline.Clear(); foreach (KeyValuePair <int, VFace> kvp in coastline) { foreach (VHEdge edge in kvp.Value.EnumerateEdges()) { VFace nCell = edge.Twin.Face; float scale = CELL_SCALE * 0.4f; bool cellValid = CheckCell(nCell, -scale, scale, -scale, scale); if (cellValid && nCell.Mark == 0 && !coastline.ContainsKey(nCell.ID) && !newCoastline.ContainsKey(nCell.ID)) { newCoastline.Add(nCell.ID, nCell); } } } foreach (KeyValuePair <int, VFace> keyValuePair in newCoastline) { coastline.Add(keyValuePair.Key, keyValuePair.Value); foreach (VHEdge edge in keyValuePair.Value.EnumerateEdges()) { edge.Origin.Z += heightProfile[i]; } } } foreach (KeyValuePair <int, VFace> kvp in newCoastline) { coastline.Remove(kvp.Key); } }
/* * private void populateIslandCoastDistance(CartographicIsland island, int hf) * { * //Init land height to Inf * List<List<VFace>> fragCellList = island.getPackageCells(); * foreach (List<VFace> cellMap in fragCellList) * foreach (VFace face in cellMap) * face.coastDistance = int.MaxValue; * * * //Enqueue the coast region first * Queue<VFace> cellQueue = new Queue<VFace>(); * foreach (VFace face in island.getCoastlineCells()) * { * face.coastDistance = 0; * cellQueue.Enqueue(face); * } * * while (cellQueue.Count > 0) * { * VFace v = cellQueue.Dequeue(); * foreach (VHEdge edge in v.EnumerateEdges()) * { * VFace adjFace = edge.twin.face; * int newDistance = v.coastDistance + hf; * if (newDistance < adjFace.coastDistance) * { * adjFace.coastDistance = newDistance; * cellQueue.Enqueue(adjFace); * } * } * } * } */ /* * private void computeIslandHeight(CartographicIsland island, float hf) * { * //Init land height to Inf * List<List<VFace>> fragCellList = island.getPackageCells(); * foreach(List<VFace> cellMap in fragCellList) * foreach (VFace face in cellMap) * foreach (VHEdge edge in face.EnumerateEdges()) * edge.Origin.Z = Mathf.Infinity; * * //Enqueue the coast region first * Queue<VVertex> vertexQueue = new Queue<VVertex>(); * foreach (VFace face in island.getCoastlineCells()) * { * foreach (VHEdge edge in face.EnumerateEdges()) * vertexQueue.Enqueue(edge.Origin); * } * * while (vertexQueue.Count > 0) * { * VVertex v = vertexQueue.Dequeue(); * foreach (VHEdge edge in v.EnumerateEdges()) * { * VVertex adjVert = edge.Next.Origin; * float newElevation = (float)v.Z + hf; * if (newElevation < adjVert.Z) * { * adjVert.Z = newElevation; * vertexQueue.Enqueue(adjVert); * } * } * } * * } */ //Expands the coastlineCells outwards by hp.length cells and applies the height profile hp during expansion private void shapeCoastArea(Dictionary <int, VFace> coastline, float[] hp) { Dictionary <int, VFace> newestCoastline = new Dictionary <int, VFace>(coastline); for (int i = 0; i < hp.Length; i++) { //Expand cells newestCoastline.Clear(); foreach (KeyValuePair <int, VFace> kvp in coastline) { foreach (VHEdge edge in kvp.Value.EnumerateEdges()) { VFace nCell = edge.twin.face; if (Helperfunctions.checkCell(nCell, -GlobalVar.voronoiCellScalefactor * 0.4f, GlobalVar.voronoiCellScalefactor * 0.4f, -GlobalVar.voronoiCellScalefactor * 0.4f, GlobalVar.voronoiCellScalefactor * 0.4f) && nCell.mark == 0 && !coastline.ContainsKey(nCell.ID) && !newestCoastline.ContainsKey(nCell.ID)) { newestCoastline.Add(nCell.ID, nCell); } } } //Adjust height and Add to coastline foreach (KeyValuePair <int, VFace> kvp in newestCoastline) { coastline.Add(kvp.Key, kvp.Value); foreach (VHEdge edge in kvp.Value.EnumerateEdges()) { edge.Origin.Z += hp[i]; } } } //Remove the last expansion from the coastline, due to artifacts foreach (KeyValuePair <int, VFace> kvp in newestCoastline) { coastline.Remove(kvp.Key); } }
private Dictionary <int, VFace> ConstructRegionFromPackage(Package package, CartographicIsland cartographicIsland, Dictionary <int, VFace> startCells, float cohesionMultiplier) { List <VFace> cellMap = new List <VFace>(); Dictionary <int, VFace> newCells = new Dictionary <int, VFace>(); VFace startCell = SelectFromCells(startCells, cohesionMultiplier).Value; int maxIterations = 20; int counter = 0; bool expand = ExpandCountries(package.CompilationUnits, cellMap, newCells, startCell, cohesionMultiplier); while (!expand && counter < maxIterations) { startCell = SelectFromCells(startCells, cohesionMultiplier).Value; counter++; } cartographicIsland.Packages.Add(package); cartographicIsland.PackageCells.Add(cellMap); return(newCells); }
private CartographicIsland constructIslandFromBundle(Bundle b) { int rngSeed = b.getName().GetHashCode() + 200; RNG = new System.Random(rngSeed); #region VoronoiPlane TriangleNet.Configuration conf = new TriangleNet.Configuration(); List <Vertex> vertices = Helperfunctions.createPointsOnPlane(GlobalVar.voronoiCellScalefactor, GlobalVar.voronoiCellScalefactor, 50, 50, 1.0f, RNG); BoundedVoronoi voronoi = Helperfunctions.createRelaxedVoronoi(vertices, 1); #endregion #region initFirstCell VFace firstCell = Helperfunctions.closestCell(0, 0, voronoi); Dictionary <int, VFace> startingCandidates = new Dictionary <int, VFace>(); startingCandidates.Add(firstCell.ID, firstCell); #endregion List <Package> packages = b.getPackages(); CartographicIsland island = new CartographicIsland(b); island.setVoronoi(voronoi); #region sort package list packages.Sort((x, y) => x.getCompilationUnits().Count.CompareTo(y.getCompilationUnits().Count)); packages.Reverse(); #endregion //Compute maximal compilation unit count in bundle float maxCUCountInIsland = 0; foreach (Package package in packages) { long cuCount = package.getCuCount(); if (cuCount > maxCUCountInIsland) { maxCUCountInIsland = cuCount; } } #region construct regions foreach (Package package in packages) { float cohesionMult = (float)package.getCuCount() / maxCUCountInIsland; cohesionMult *= maxCohesion; cohesionMult = Mathf.Max(minCohesion, cohesionMult); Dictionary <int, VFace> newCandidates = constructRegionFromPackage(package, island, startingCandidates, cohesionMult); updateAndFuseCandidates(startingCandidates, newCandidates); } #endregion #region Shape island coast //Advance startingCandidates X cells outwards and ajdust the height of all vertices shapeCoastArea(startingCandidates, GlobalVar.islandHeightProfile); #endregion #region WeightedCenter & set coast List <VFace> coastlineList = new List <VFace>(); Vector3 weightedCenter = Vector3.zero; foreach (KeyValuePair <int, VFace> kvp in startingCandidates) { coastlineList.Add(kvp.Value); float x = (float)kvp.Value.generator.X; float z = (float)kvp.Value.generator.Y; Vector3 tilePos = new Vector3(x, 0, z); weightedCenter += tilePos; } weightedCenter /= startingCandidates.Count; island.setWeightedCenter(weightedCenter); island.setCoastlineCells(coastlineList); #endregion #region conservative Radius List <float> radii = new List <float>(); foreach (KeyValuePair <int, VFace> kvp in startingCandidates) { float x = (float)kvp.Value.generator.X - island.getWeightedCenter().x; float z = (float)kvp.Value.generator.Y - island.getWeightedCenter().z; float radius = Mathf.Sqrt(x * x + z * z); radii.Add(radius); } float maxRadius = Helperfunctions.computeMax(radii); island.setRadius(maxRadius); #endregion #region TnetMeshesConstruction foreach (List <VFace> cellMap in island.getPackageCells()) { island.addPackageMesh(constructTnetMeshFromCellmap(cellMap)); } island.setCoastlineMesh(constructTnetMeshFromCellmap(coastlineList)); #endregion #region link dependency vertex //Find graph vertex associated with the island BidirectionalGraph <GraphVertex, GraphEdge> depGraph = b.getParentProject().getDependencyGraph(); List <GraphVertex> allVertices = depGraph.Vertices.ToList(); GraphVertex vert = allVertices.Find(v => string.Equals(v.getName(), b.getName())); if (vert != null) { //Link GraphVertex-Island vert.setIsland(island); island.setDependencyVertex(vert); } #endregion return(island); }