예제 #1
0
        //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);
        }
예제 #2
0
 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);
        }