Пример #1
0
        /// <summary>
        /// Adds corridor node greedily.
        /// </summary>
        /// <param name="layout"></param>
        /// <param name="node"></param>
        /// <returns></returns>
        public bool AddCorridorGreedily(TLayout layout, TNode node)
        {
            var configurations = new List <TConfiguration>();
            var neighbors      = layout.Graph.GetNeighbours(node);

            foreach (var neighbor in neighbors)
            {
                if (layout.GetConfiguration(neighbor, out var configuration))
                {
                    configurations.Add(configuration);
                }
            }

            if (configurations.Count == 0)
            {
                throw new InvalidOperationException();
            }

            var foundValid   = false;
            var bestShape    = default(TShapeContainer);
            var bestPosition = new Vector2Int();

            var shapes = ConfigurationSpaces.GetShapesForNode(node).ToList();

            shapes.Shuffle(Random);

            foreach (var shape in shapes)
            {
                var intersection = ConfigurationSpaces.GetMaximumIntersection(CreateConfiguration(shape, new Vector2Int(), node), configurations, out var configurationsSatisfied);

                if (configurationsSatisfied != 2)
                {
                    continue;
                }

                intersection.Shuffle(Random);

                foreach (var intersectionLine in intersection)
                {
                    const int maxPoints = 20;

                    if (intersectionLine.Length > maxPoints)
                    {
                        var mod = intersectionLine.Length / maxPoints - 1;

                        for (var i = 0; i < maxPoints; i++)
                        {
                            var position = intersectionLine.GetNthPoint(i != maxPoints - 1 ? i * mod : intersectionLine.Length + 1);

                            var energyData = stageTwoConstraintsEvaluator.ComputeNodeEnergy(layout, CreateConfiguration(shape, position, node));

                            if (energyData.IsValid)
                            {
                                bestShape    = shape;
                                bestPosition = position;
                                foundValid   = true;
                                break;
                            }

                            if (foundValid)
                            {
                                break;
                            }
                        }
                    }
                    else
                    {
                        var points = intersectionLine.GetPoints();
                        points.Shuffle(Random);

                        foreach (var position in points)
                        {
                            var energyData = stageTwoConstraintsEvaluator.ComputeNodeEnergy(layout, CreateConfiguration(shape, position, node));

                            if (energyData.IsValid)
                            {
                                bestShape    = shape;
                                bestPosition = position;
                                foundValid   = true;
                                break;
                            }

                            if (foundValid)
                            {
                                break;
                            }
                        }
                    }

                    if (foundValid)
                    {
                        break;
                    }
                }
            }

            var newConfiguration = CreateConfiguration(bestShape, bestPosition, node);

            layout.SetConfiguration(node, newConfiguration);

            return(foundValid);
        }
Пример #2
0
        /// <summary>
        /// Greedily adds non corridor node to the layout.
        /// </summary>
        /// <remarks>
        /// Uses special configuration spaces where shapes are not directly connected
        /// but are rather at a specified distance from each other.
        /// </remarks>
        /// <param name="layout"></param>
        /// <param name="node"></param>
        private void AddNonCorridorGreedily(TLayout layout, TNode node)
        {
            var configurations = GetNeighboursOverCorridors(layout, node);

            if (configurations.Count == 0)
            {
                layout.SetConfiguration(node, CreateConfiguration(ConfigurationSpaces.GetRandomShape(node), new IntVector2()));
                return;
            }

            var bestEnergy   = float.MaxValue;
            var bestShape    = default(TShapeContainer);
            var bestPosition = new IntVector2();

            var shapes = ConfigurationSpaces.GetShapesForNode(node).ToList();

            shapes.Shuffle(Random);

            foreach (var shape in shapes)
            {
                var intersection = CorridorConfigurationSpaces.GetMaximumIntersection(CreateConfiguration(shape, new IntVector2()), configurations);

                if (intersection == null)
                {
                    continue;
                }

                intersection.Shuffle(Random);

                foreach (var intersectionLine in intersection)
                {
                    var       tryAll    = true;
                    var       mod       = 1;
                    const int maxPoints = 20;

                    if (intersectionLine.Length > maxPoints)
                    {
                        tryAll = false;
                        mod    = intersectionLine.Length / maxPoints;
                    }

                    var i = 0;

                    foreach (var position in intersectionLine.GetPoints())
                    {
                        if (!tryAll && i % mod != 0 && i != intersectionLine.Length)
                        {
                            continue;
                        }

                        var energy = NodeComputeEnergyData(layout, node, CreateConfiguration(shape, position)).Energy;

                        if (energy < bestEnergy)
                        {
                            bestEnergy   = energy;
                            bestShape    = shape;
                            bestPosition = position;
                        }

                        if (bestEnergy <= 0)
                        {
                            break;
                        }

                        i++;
                    }

                    // There is no point of looking for more solutions when you already reached a valid state
                    // and so no position would be accepted anyway
                    // TODO: What about making it somehow random? If there are more valid positions, choose one at random.
                    if (bestEnergy <= 0)
                    {
                        break;
                    }
                }
            }

            var newConfiguration = CreateConfiguration(bestShape, bestPosition);

            layout.SetConfiguration(node, newConfiguration);
        }
Пример #3
0
 public IList <TShapeContainer> GetShapesForNode(TNode node)
 {
     return(ConfigurationSpaces.GetShapesForNode(node).ToList());
 }
        /// <summary>
        /// Tries all shapes and positions from the maximum intersection to find a configuration
        /// with the lowest energy.
        /// </summary>
        /// <param name="layout"></param>
        /// <param name="node"></param>
        public override void AddNodeGreedily(TLayout layout, TNode node)
        {
            var configurations = new List <TConfiguration>();
            var neighbours     = layout.Graph.GetNeighbours(node);

            foreach (var neighbour in neighbours)
            {
                if (layout.GetConfiguration(neighbour, out var configuration))
                {
                    configurations.Add(configuration);
                }
            }

            // The first node is set to have a random shape and [0,0] position
            if (configurations.Count == 0)
            {
                layout.SetConfiguration(node, CreateConfiguration(ConfigurationSpaces.GetRandomShape(node), new IntVector2()));
                return;
            }

            var bestEnergy   = float.MaxValue;
            var bestShape    = default(TShapeContainer);
            var bestPosition = new IntVector2();

            var shapes = ConfigurationSpaces.GetShapesForNode(node).ToList();

            // shapes.Shuffle(Random);

            // Try all shapes
            foreach (var shape in shapes)
            {
                var intersection = ConfigurationSpaces.GetMaximumIntersection(CreateConfiguration(shape, new IntVector2()), configurations);

                // Try all lines from the maximum intersection
                foreach (var intersectionLine in intersection)
                {
                    // Limit the number of points to 20.
                    // It is very slow to try all the positions if rooms are big.
                    const int maxPoints = 20;

                    if (intersectionLine.Length > maxPoints)
                    {
                        var mod = intersectionLine.Length / maxPoints - 1;

                        for (var i = 0; i < maxPoints; i++)
                        {
                            var position = intersectionLine.GetNthPoint(i != maxPoints - 1 ? i * mod : intersectionLine.Length);

                            var energy = NodeComputeEnergyData(layout, node, CreateConfiguration(shape, position)).Energy;

                            if (energy < bestEnergy)
                            {
                                bestEnergy   = energy;
                                bestShape    = shape;
                                bestPosition = position;
                            }

                            if (bestEnergy <= 0)
                            {
                                break;
                            }
                        }
                    }
                    else
                    {
                        var points = intersectionLine.GetPoints();
                        points.Shuffle(Random);

                        foreach (var position in points)
                        {
                            var energy = NodeComputeEnergyData(layout, node, CreateConfiguration(shape, position)).Energy;

                            if (energy < bestEnergy)
                            {
                                bestEnergy   = energy;
                                bestShape    = shape;
                                bestPosition = position;
                            }

                            if (bestEnergy <= 0)
                            {
                                break;
                            }
                        }
                    }

                    // There is no point of looking for more solutions when you already reached a valid state
                    // and so no position would be accepted anyway
                    if (bestEnergy <= 0)
                    {
                        break;
                    }
                }
            }

            var newConfiguration = CreateConfiguration(bestShape, bestPosition);

            layout.SetConfiguration(node, newConfiguration);
        }