Пример #1
0
    void MakeBigPlanAndSave()
    {
        _gridSize = new Vector3Int(150, 1, 150);
        _grid     = new VoxelGrid(_gridSize, _voxelSize, Vector3.zero);

        int    componentCount = _grid.ActiveVoxelsAsList().Count(v => !v.IsOccupied) / 80;
        string prefix         = "bigplan";

        PopulateRandomConfigurableAndSave(componentCount, 10, prefix);
    }
Пример #2
0
    void ReadSaveTrainingData()
    {
        DirectoryInfo folder      = new DirectoryInfo(Application.dataPath + "/Resources/Input Data/TrainingData");
        var           trainingSet = folder.GetDirectories();

        foreach (var set in trainingSet)
        {
            string[] dimensions = set.Name.Split('_');
            int      xSize      = int.Parse(dimensions[0]);
            int      zSize      = int.Parse(dimensions[1]);
            _ammountOfComponents = (xSize * zSize) / 144;

            //iterate through the type of each set
            string[] slabType = { "A", "B", "C", "D" };
            foreach (var type in slabType)
            {
                _gridSize      = new Vector3Int(xSize, 1, zSize);
                _grid          = new VoxelGrid(_gridSize, _voxelSize, Vector3.zero);
                _existingParts = new List <Part>();

                //set the states of the voxel grid
                string statesFile = "Input Data/TrainingData/" + set.Name + "/" + type + "_SlabStates";
                CSVReader.SetGridState(_grid, statesFile);

                //populate structure
                string structureFile = "Input Data/TrainingData/" + set.Name + "/" + type + "_Structure";
                ReadStructure(structureFile);

                //populate knots
                //string knotsFile = "Input Data/TrainingData/" + set.Name + "/" + type + "_Knots";
                //ReadKnots(knotsFile);

                //populate configurables
                string prefix         = set.Name + "_" + type;
                int    componentCount = _grid.ActiveVoxelsAsList().Count(v => !v.IsOccupied) / 120;
                print($"Grid {xSize} x {zSize} with {componentCount}");
                PopulateRandomConfigurableAndSave(componentCount, 10, prefix);
            }
        }
    }
    /// <summary>
    /// Generate spaces on the voxels that are not inside the parts boudaries, or space or part
    /// The method is inspired by a BFS algorithm, continuously checking the neighbours of the
    /// processed voxels until the minimum area is reached. It is designed to be called in a loop
    /// that feeds the numbering / naming of the spaces
    /// </summary>
    /// <param name="number">Current number of the space</param>
    void GenerateSingleSpace(int number)
    {
        int maximumArea     = 1000; //in voxel ammount
        var availableVoxels = _grid.ActiveVoxelsAsList().Where(v => !_boundaries.Contains(v) && !v.IsOccupied && !v.InSpace).ToList();

        if (availableVoxels.Count == 0)
        {
            return;
        }
        Voxel originVoxel = availableVoxels[0];

        //Initiate a new space
        PPSpace space = new PPSpace(_grid);

        originVoxel.InSpace     = true;
        originVoxel.ParentSpace = space;
        space.Voxels.Add(originVoxel);
        space.Indices.Add(originVoxel.Index);
        //Keep running until the space area is under the minimum
        while (space.Voxels.Count < maximumArea)
        {
            List <Voxel> temp = new List <Voxel>();
            foreach (var voxel in space.Voxels)
            {
                //Get the face neighbours which are available
                var newNeighbours = voxel.GetFaceNeighbours().Where(n => availableVoxels.Contains(n));
                foreach (var neighbour in newNeighbours)
                {
                    var nIndex    = neighbour.Index;
                    var gridVoxel = _grid.Voxels[nIndex.x, nIndex.y, nIndex.z];
                    //Only add the nighbour it its not already in the space
                    //or temp list, is active, not occupied(in a part), or another space
                    if (!space.Voxels.Contains(neighbour) && !temp.Contains(neighbour))
                    {
                        if (gridVoxel.IsActive && !gridVoxel.IsOccupied && !gridVoxel.InSpace)
                        {
                            temp.Add(neighbour);
                        }
                    }
                }
            }
            //Break if the temp list returned empty
            if (temp.Count == 0)
            {
                break;
            }
            //Add found neighbours to the space until it reaches maximum capacity
            foreach (var v in temp)
            {
                if (space.Voxels.Count <= maximumArea)
                {
                    v.InSpace     = true;
                    v.ParentSpace = space;
                    space.Voxels.Add(v);
                    space.Indices.Add(v.Index);
                }
            }
        }
        space.Name = $"Space_{number.ToString()}";
        space.CreateArrow();
        _spaces.Add(space);
    }
Пример #4
0
    void DefinePartsBoundaries()
    {
        Stopwatch mainStopwatch = new Stopwatch();

        mainStopwatch.Start();

        int partsProcessing = 0;
        int graphProcessing = 0;

        //Algorithm constraints
        int searchRadius      = 15;
        int maximumPathLength = 15;

        //Paralell lists containing the connected parts and the paths lenghts
        //This is later used to make sure that only the shortest connection between 2 parts is maintained
        List <Part[]>           connectedParts  = new List <Part[]>();
        List <HashSet <Voxel> > connectionPaths = new List <HashSet <Voxel> >();
        List <int> connectionLenghts            = new List <int>();

        //Iterate through every existing part that is not structural
        foreach (var part in _existingParts.Where(p => p.Type != PartType.Structure))
        {
            Stopwatch partStopwatch = new Stopwatch();
            partStopwatch.Start();
            var t1 = part.OccupiedVoxels.First();
            var t2 = part.OccupiedVoxels.Last();

            var origins = new Voxel[] { t1, t2 };
            _origins.Add(origins);

            //Finding the neighbouring parts in a given radius from a voxel
            foreach (var origin in origins)
            {
                //List to store the parts that have been found
                List <Part>  foundParts         = new List <Part>();
                List <Voxel> foundBoudaryVoxels = new List <Voxel>();

                //Navigate through the neighbours in a given range
                var neighbours = origin.GetNeighboursInRange(searchRadius);
                foreach (var neighbour in neighbours)
                {
                    if (neighbour.IsOccupied && neighbour.Part != part && !foundParts.Contains(neighbour.Part))
                    {
                        foundParts.Add(neighbour.Part);
                        _foundParts.Add(neighbour.Part.Type);
                    }
                    else if (neighbour.IsBoundary)
                    {
                        foundBoudaryVoxels.Add(neighbour);
                    }
                }

                //var searchRange = neighbours.Where(n => !n.IsOccupied).ToList();
                var searchRange = _grid.ActiveVoxelsAsList().Where(n => !n.IsOccupied).ToList();
                searchRange.Add(origin);

                //Make copy of walkable voxels for this origin voxel
                var localWalkable = new List <Voxel>(searchRange);

                //Find the closest voxel in the neighbouring parts
                //Add it to the localWalkable list
                List <Voxel> targets = new List <Voxel>();
                foreach (var nPart in foundParts)
                {
                    var   nIndices     = nPart.OccupiedIndexes;
                    var   closestIndex = new Vector3Int();
                    float minDistance  = Mathf.Infinity;
                    foreach (var index in nIndices)
                    {
                        var distance = Vector3Int.Distance(origin.Index, index);
                        if (distance < minDistance)
                        {
                            closestIndex = index;
                            minDistance  = distance;
                        }
                    }
                    var closestVoxel = _grid.Voxels[closestIndex.x, closestIndex.y, closestIndex.z];
                    localWalkable.Add(closestVoxel);
                    targets.Add(closestVoxel);
                }

                //Find the closest boundary voxel -> this is broken!
                //var b_closestIndex = new Vector3Int();
                //float b_minDistance = Mathf.Infinity;
                //foreach (var voxel in foundBoudaryVoxels)
                //{
                //    var distance = Vector3Int.Distance(origin.Index, voxel.Index);
                //    if (distance < b_minDistance)
                //    {
                //        b_closestIndex = voxel.Index;
                //        b_minDistance = distance;
                //    }
                //}
                //var b_closestVoxel = _grid.Voxels[b_closestIndex.x, b_closestIndex.y, b_closestIndex.z];
                //localWalkable.Add(b_closestVoxel);
                //targets.Add(b_closestVoxel);

                foreach (var voxel in foundBoudaryVoxels)
                {
                    //this will add all found boudary voxels to the targets
                    //More processing but closer to defining actual boudaries
                    targets.Add(voxel);
                }

                partStopwatch.Stop();
                partsProcessing += (int)partStopwatch.ElapsedMilliseconds;

                foreach (var item in targets)
                {
                    _usedTargets.Add(item);
                }

                //Construct graph with walkable voxels and targets to be processed
                Stopwatch graphStopwatch = new Stopwatch();
                graphStopwatch.Start();
                var faces      = _grid.GetFaces().Where(f => localWalkable.Contains(f.Voxels[0]) && localWalkable.Contains(f.Voxels[1]));
                var graphFaces = faces.Select(f => new TaggedEdge <Voxel, Face>(f.Voxels[0], f.Voxels[1], f));
                var start      = origin;

                //var graph = graphFaces.ToBidirectionalGraph<Voxel, TaggedEdge<Voxel, Face>>();
                //var shortest = graph.ShortestPathsAStar(e => 1.0, v => VoxelDistance(v, start), start);
                var graph    = graphFaces.ToUndirectedGraph <Voxel, TaggedEdge <Voxel, Face> >();
                var shortest = graph.ShortestPathsDijkstra(e => 1.0, start);

                HashSet <Voxel> closest2boudary = new HashSet <Voxel>();
                int             shortestLength  = 1_000_000;
                foreach (var v in targets)
                {
                    var end = v;
                    if (!end.IsBoundary)
                    {
                        //Check if the shortest path is valid
                        if (shortest(end, out var endPath))
                        {
                            Voxel[] pair = new Voxel[] { origin, end };
                            _prospectivePairs.Add(pair);

                            var endPathVoxels = new HashSet <Voxel>(endPath.SelectMany(e => new[] { e.Source, e.Target }));
                            var pathLength    = endPathVoxels.Count;
                            //Check if path length is under minimum
                            if (pathLength <= maximumPathLength &&
                                !endPathVoxels.All(ev => ev.IsOccupied) &&
                                endPathVoxels.Count(ev => ev.GetFaceNeighbours().Any(evn => evn.IsOccupied)) > 2)
                            {
                                //Check if the connection between the parts is unique
                                var isUnique = !connectedParts.Any(cp => cp.Contains(part) && cp.Contains(end.Part));
                                if (!isUnique)
                                {
                                    //If it isn't unique, only replace if the current length is smaller
                                    var existingConnection = connectedParts.First(cp => cp.Contains(part) && cp.Contains(end.Part));
                                    var index          = connectedParts.IndexOf(existingConnection);
                                    var existingLength = connectionLenghts[index];
                                    if (pathLength > existingLength)
                                    {
                                        continue;
                                    }
                                    else
                                    {
                                        //Replace existing conection pair
                                        connectedParts[index]    = new Part[] { part, end.Part };
                                        connectionLenghts[index] = pathLength;
                                        connectionPaths[index]   = endPathVoxels;
                                    }
                                }
                                else
                                {
                                    //Create new connection
                                    connectedParts.Add(new Part[] { part, end.Part });
                                    connectionLenghts.Add(pathLength);
                                    connectionPaths.Add(endPathVoxels);
                                }
                            }
                        }
                    }
                    else
                    {
                        if (shortest(end, out var endPath))
                        {
                            var endPathVoxels = new HashSet <Voxel>(endPath.SelectMany(e => new[] { e.Source, e.Target }));
                            var pathLength    = endPathVoxels.Count;
                            if (pathLength <= maximumPathLength &&
                                endPathVoxels.Count(ev => ev.GetFaceNeighbours().Any(evn => evn.IsOccupied)) > 2)
                            {
                                if (pathLength < shortestLength)
                                {
                                    closest2boudary = endPathVoxels;
                                    shortestLength  = pathLength;
                                }
                                //connectionPaths.Add(endPathVoxels);
                            }
                        }
                    }
                }
                if (closest2boudary.Count > 0)
                {
                    connectionPaths.Add(closest2boudary);
                }
                graphStopwatch.Stop();
                graphProcessing += (int)graphStopwatch.ElapsedMilliseconds;
            }
        }
        //Feed the general boundaries list
        foreach (var path in connectionPaths)
        {
            foreach (var voxel in path)
            {
                if (!voxel.IsOccupied &&
                    !_partsBoundaries.Contains(voxel))
                {
                    _partsBoundaries.Add(voxel);
                }
            }
        }
        mainStopwatch.Stop();
        int mainProcessing = (int)mainStopwatch.ElapsedMilliseconds;

        //print($"Took {mainStopwatch.ElapsedMilliseconds}ms to Process");
        //print($"Took {partsProcessing}ms to Process Parts");
        //print($"Took {graphProcessing}ms to Process Graphs");

        _boundaryPartsTime = partsProcessing;
        _boundaryGraphTime = graphProcessing;
        _boundaryMainTime  = mainProcessing;

        foreach (var t in connectedParts)
        {
            _foundPairs.Add(t);
        }
    }