public Configuration(IntAlias <PolygonGrid2D> shape, Vector2Int position, TEnergyData energyData, int node) { ShapeContainer = shape; Position = position; EnergyData = energyData; Node = node; }
public WeightedShape(IntAlias <GridPolygon> shape, double weight) { if (weight <= 0) { throw new ArgumentException("Weight must be greater than zero", nameof(weight)); } Shape = shape; Weight = weight; }
private IntAlias <PolygonGrid2D> GetRoomTemplateInstanceAlias(RoomTemplateInstance roomTemplateInstance) { if (IntAliasMapping.TryGetValue(roomTemplateInstance, out var alias)) { return(alias); } var newAlias = new IntAlias <PolygonGrid2D>(IntAliasMapping.Count, roomTemplateInstance.RoomShape); IntAliasMapping.Add(roomTemplateInstance, newAlias); return(newAlias); }
protected override List <GridRectangle> GetDecomposition(IntAlias <GridPolygon> polygon) { var alias = polygon.Alias; if (alias >= decompositions.Count) { while (alias >= decompositions.Count) { decompositions.Add(null); } } var decomposition = decompositions[alias]; if (decomposition == null) { decomposition = polygonPartitioning.GetPartitions(polygon.Value); decompositions[alias] = decomposition; } return(decomposition); }
private void SetConfiguration(Layout <Configuration <CorridorsData> > layout, int node, IntAlias <PolygonGrid2D> alias) { layout.SetConfiguration(node, new Configuration <CorridorsData>(alias, new Vector2Int(0, 0), new CorridorsData(), node)); }
public static Area Seek(int area) { return((Area)IntAlias.Seek(CacheIndex.Area, area)); }
public static Hall Seek(int hall) { return((Hall)IntAlias.Seek(CacheIndex.Hall, hall)); }
protected override GridRectangle GetBoundingRectangle(IntAlias <GridPolygon> polygon) { return(polygon.Value.BoundingRectangle); }
protected override RectangleGrid2D GetBoundingRectangle(IntAlias <PolygonGrid2D> polygon) { return(polygon.Value.BoundingRectangle); }
protected bool Equals(IntAlias <T> other) { return(Alias == other.Alias); }
/// <summary> /// Computes configuration spaces for a given map description. /// </summary> /// <typeparam name="TNode"></typeparam> /// <typeparam name="TConfiguration"></typeparam> /// <param name="mapDescription"></param> /// <param name="offsets"></param> /// <returns></returns> public IConfigurationSpaces <int, IntAlias <GridPolygon>, TConfiguration, ConfigurationSpace> Generate <TNode, TConfiguration>(MapDescription <TNode> mapDescription, List <int> offsets = null) where TConfiguration : IConfiguration <IntAlias <GridPolygon> > { if (offsets != null && offsets.Count == 0) { throw new ArgumentException("There must be at least one offset if they are set", nameof(offsets)); } if (mapDescription.IsWithCorridors && mapDescription.GetCorridorShapes().Count == 0) { throw new ArgumentException("The map description has corridors enabled but there are no shapes for them.", nameof(mapDescription)); } var graph = mapDescription.GetGraph(); var aliasCounter = 0; var allShapes = new Dictionary <int, Tuple <IntAlias <GridPolygon>, List <IDoorLine> > >(); var shapes = new List <ConfigurationSpaces <TConfiguration> .WeightedShape>(); var shapesForNodes = new Dictionary <int, List <ConfigurationSpaces <TConfiguration> .WeightedShape> >(); var intAliasMapping = new Dictionary <int, RoomInfo>(); var defaultTransformations = new List <Transformation>(mapDescription.GetDefaultTransformations()); // Handle universal shapes foreach (var shape in mapDescription.GetRoomShapes()) { var rotatedShapes = TransformPolygons(shape.RoomDescription, shape.Transformations ?? defaultTransformations).Select(CreateAlias).ToList(); var probability = shape.NormalizeProbabilities ? shape.Probability / rotatedShapes.Count : shape.Probability; shapes.AddRange(rotatedShapes.Select(x => new ConfigurationSpaces <TConfiguration> .WeightedShape(x.Item1, probability))); } // Handle shapes for nodes foreach (var vertex in graph.Vertices.Where(x => !mapDescription.IsCorridorRoom(x))) { var shapesForNode = mapDescription.GetRoomShapesForNodes()[vertex]; if (shapesForNode == null) { shapesForNodes.Add(vertex, null); continue; } var shapesContainer = new List <ConfigurationSpaces <TConfiguration> .WeightedShape>(); foreach (var shape in shapesForNode) { var rotatedShapes = TransformPolygons(shape.RoomDescription, shape.Transformations ?? defaultTransformations).Select(CreateAlias).ToList(); var probability = shape.NormalizeProbabilities ? shape.Probability / rotatedShapes.Count : shape.Probability; shapesContainer.AddRange(rotatedShapes.Select(x => new ConfigurationSpaces <TConfiguration> .WeightedShape(x.Item1, probability))); } shapesForNodes.Add(vertex, shapesContainer); } // Corridor shapes var corridorShapesContainer = new List <ConfigurationSpaces <TConfiguration> .WeightedShape>(); foreach (var shape in mapDescription.GetCorridorShapes()) { var rotatedShapes = TransformPolygons(shape.RoomDescription, shape.Transformations ?? defaultTransformations).Select(CreateAlias).ToList(); var probability = shape.NormalizeProbabilities ? shape.Probability / rotatedShapes.Count : shape.Probability; corridorShapesContainer.AddRange(rotatedShapes.Select(x => new ConfigurationSpaces <TConfiguration> .WeightedShape(x.Item1, probability))); } // Handle shapes for corridores foreach (var vertex in graph.Vertices.Where(mapDescription.IsCorridorRoom)) { shapesForNodes.Add(vertex, corridorShapesContainer); } // Prepare data structures var shapesForNodesArray = new List <ConfigurationSpaces <TConfiguration> .WeightedShape> [shapesForNodes.Count]; foreach (var pair in shapesForNodes) { shapesForNodesArray[pair.Key] = pair.Value; } var configurationSpaces = new ConfigurationSpace[aliasCounter][]; for (var i = 0; i < aliasCounter; i++) { var shape1 = allShapes[i]; configurationSpaces[i] = new ConfigurationSpace[aliasCounter]; for (var j = 0; j < aliasCounter; j++) { var shape2 = allShapes[j]; configurationSpaces[i][j] = GetConfigurationSpace(shape1.Item1.Value, shape1.Item2, shape2.Item1.Value, shape2.Item2, offsets); } } if (shapes.Count == 0 && graph.Vertices.Any(x => !shapesForNodes.ContainsKey(x) || shapesForNodes[x] == null || shapesForNodes[x].Count == 0)) { throw new ArgumentException("There must be at least one shape for each node", nameof(mapDescription)); } LastIntAliasMapping = intAliasMapping; return(new ConfigurationSpaces <TConfiguration>(shapes, shapesForNodesArray, configurationSpaces, lineIntersection)); // Return an already existing alias or create a new one Tuple <IntAlias <GridPolygon>, List <IDoorLine> > CreateAlias(RoomInfo roomInfo) { foreach (var pair in allShapes) { var otherRoomInfo = intAliasMapping[pair.Key]; if (roomInfo.RoomDescription == otherRoomInfo.RoomDescription && roomInfo.Transformations.SequenceEqualWithoutOrder(otherRoomInfo.Transformations)) { return(pair.Value); } } var alias = new IntAlias <GridPolygon>(aliasCounter++, roomInfo.RoomShape); var aliasTuple = Tuple.Create(alias, roomInfo.DoorLines); allShapes.Add(alias.Alias, aliasTuple); intAliasMapping.Add(alias.Alias, roomInfo); return(aliasTuple); } }
/// <inheritdoc /> public override ConfigurationSpace GetConfigurationSpace(IntAlias <GridPolygon> movingPolygon, IntAlias <GridPolygon> fixedPolygon) { return(ConfigurationSpaces_[movingPolygon.Alias][fixedPolygon.Alias]); }
private void SetupGenerator() { var mapping = levelDescriptionMapped.GetMapping(); var chainsGeneric = configuration.Chains; // Create chain decomposition if (chainsGeneric == null) { var chainDecomposition = new Common.TwoStageChainDecomposition <TRoom>(levelDescription, new BreadthFirstChainDecomposition <TRoom>(configuration.ChainDecompositionConfiguration ?? new ChainDecompositionConfiguration())); chainsGeneric = chainDecomposition.GetChains(levelDescription.GetGraph()); } var chains = chainsGeneric .Select(x => new Chain <RoomNode <TRoom> >(x.Nodes.Select(y => mapping[y]).ToList(), x.Number) { IsFromFace = x.IsFromFace }) .ToList(); // Create generator planner var generatorPlanner = new GeneratorPlanner <Layout <TRoom, ConfigurationGrid2D <TRoom, EnergyData> >, RoomNode <TRoom> >(configuration.SimulatedAnnealingMaxBranching); // Create configuration spaces var configurationSpacesGenerator = new ConfigurationSpacesGenerator( new PolygonOverlap(), DoorHandler.DefaultHandler, new OrthogonalLineIntersection(), new GridPolygonUtils()); // var configurationSpaces = configurationSpacesGenerator.GetConfigurationSpaces<ConfigurationNew2<CorridorsDataNew>>(mapDescription); var simpleConfigurationSpaces = new ConfigurationSpacesGrid2D <ConfigurationGrid2D <TRoom, EnergyData>, RoomNode <TRoom> >(levelDescriptionMapped); // Needlessly complex for backwards compatibility #region IntAliasMapping var roomDescriptions = levelDescriptionMapped.GetGraph().Vertices.ToDictionary(x => x, x => (RoomDescriptionGrid2D)levelDescriptionMapped.GetRoomDescription(x)); var roomTemplates = roomDescriptions.Values.SelectMany(x => x.RoomTemplates).Distinct().ToList(); var roomTemplateInstances = roomTemplates.ToDictionary(x => x, configurationSpacesGenerator.GetRoomTemplateInstances); var roomTemplateInstancesMapping = roomTemplateInstances.SelectMany(x => x.Value).CreateIntMapping(); var intAliasMapping = new TwoWayDictionary <RoomTemplateInstanceGrid2D, IntAlias <PolygonGrid2D> >(); foreach (var shape1 in roomTemplateInstancesMapping.Keys) { foreach (var shape2 in roomTemplateInstancesMapping.Keys) { if (!intAliasMapping.ContainsKey(shape1)) { var newAlias = new IntAlias <PolygonGrid2D>(intAliasMapping.Count, shape1.RoomShape); intAliasMapping.Add(shape1, newAlias); shape1.RoomShapeAlias = newAlias; } if (!intAliasMapping.ContainsKey(shape2)) { var newAlias = new IntAlias <PolygonGrid2D>(intAliasMapping.Count, shape2.RoomShape); intAliasMapping.Add(shape2, newAlias); shape2.RoomShapeAlias = newAlias; } } } // TODO: remove when possible foreach (var pair in intAliasMapping) { pair.Key.RoomShapeAlias = pair.Value; } var shapesForNodes = new Dictionary <RoomNode <TRoom>, List <WeightedShape> >(); foreach (var vertex in levelDescriptionMapped.GetGraph().Vertices) { shapesForNodes.Add(vertex, new List <WeightedShape>()); // var roomDescription = levelDescriptionMapped.GetRoomDescription(vertex); var roomDescription = roomDescriptions[vertex]; foreach (var roomTemplate in roomDescription.RoomTemplates) { var instances = roomTemplateInstances[roomTemplate]; foreach (var roomTemplateInstance in instances) { shapesForNodes[vertex].Add(new WeightedShape(intAliasMapping[roomTemplateInstance], 1d / instances.Count)); } } } var usedShapes = new HashSet <int>(); var allShapes = new List <IntAlias <PolygonGrid2D> >(); foreach (var vertex in levelDescriptionMapped.GetGraph().Vertices) { var shapes = shapesForNodes[vertex]; foreach (var shape in shapes) { if (!usedShapes.Contains(shape.Shape.Alias)) { allShapes.Add(shape.Shape); usedShapes.Add(shape.Shape.Alias); } } } var averageSize = (int)allShapes.Select(x => x.Value.BoundingRectangle).Average(x => (x.Width + x.Height) / 2); #endregion // var averageSize = configurationSpaces.GetAverageSize(); var energyUpdater = new BasicEnergyUpdater <RoomNode <TRoom>, ConfigurationGrid2D <TRoom, EnergyData> >(10 * averageSize); var roomShapeGeometry = new FastGridPolygonGeometry <ConfigurationGrid2D <TRoom, EnergyData>, RoomNode <TRoom> >(); // Create generator constraints var stageOneConstraints = new List <INodeConstraint <ILayout <RoomNode <TRoom>, ConfigurationGrid2D <TRoom, EnergyData> >, RoomNode <TRoom>, ConfigurationGrid2D <TRoom, EnergyData>, EnergyData> > { new BasicConstraint <RoomNode <TRoom>, ConfigurationGrid2D <TRoom, EnergyData>, EnergyData>( roomShapeGeometry, simpleConfigurationSpaces, levelDescriptionMapped, configuration.OptimizeCorridorConstraints ), new CorridorConstraint <RoomNode <TRoom>, ConfigurationGrid2D <TRoom, EnergyData>, EnergyData>( levelDescriptionMapped, simpleConfigurationSpaces, roomShapeGeometry ), }; if (levelDescription.MinimumRoomDistance > 0) { stageOneConstraints.Add(new MinimumDistanceConstraint <RoomNode <TRoom>, ConfigurationGrid2D <TRoom, EnergyData>, EnergyData>( levelDescriptionMapped, roomShapeGeometry, levelDescription.MinimumRoomDistance )); } var constraintsEvaluator = new ConstraintsEvaluator <RoomNode <TRoom>, ConfigurationGrid2D <TRoom, EnergyData>, EnergyData>(stageOneConstraints, energyUpdater); var roomShapesHandler = new RoomShapesHandlerGrid2D <RoomNode <TRoom>, ConfigurationGrid2D <TRoom, EnergyData> >( intAliasMapping, levelDescriptionMapped, shapesForNodes, levelDescription.RoomTemplateRepeatModeOverride, levelDescription.RoomTemplateRepeatModeDefault ); // Create layout operations var layoutOperations = new LayoutController <Layout <TRoom, ConfigurationGrid2D <TRoom, EnergyData> >, RoomNode <TRoom>, ConfigurationGrid2D <TRoom, EnergyData>, RoomTemplateInstanceGrid2D, EnergyData>(averageSize, levelDescriptionMapped, constraintsEvaluator, roomShapesHandler, configuration.ThrowIfRepeatModeNotSatisfied, simpleConfigurationSpaces, roomShapeGeometry); var initialLayout = new Layout <TRoom, ConfigurationGrid2D <TRoom, EnergyData> >(levelDescriptionMapped.GetGraph()); var layoutConverter = new BasicLayoutConverterGrid2D <TRoom, ConfigurationGrid2D <TRoom, EnergyData> >(levelDescription, simpleConfigurationSpaces, intAliasMapping); // Create simulated annealing evolver var layoutEvolver = new Common.SimulatedAnnealingEvolver <Layout <TRoom, ConfigurationGrid2D <TRoom, EnergyData> >, RoomNode <TRoom>, ConfigurationGrid2D <TRoom, EnergyData> >(layoutOperations, configuration.SimulatedAnnealingConfiguration, true); // Create the generator itself generator = new ChainBasedGenerator <Layout <TRoom, ConfigurationGrid2D <TRoom, EnergyData> >, LayoutGrid2D <TRoom>, RoomNode <TRoom> >(initialLayout, generatorPlanner, chains, layoutEvolver, layoutConverter); // Register event handlers generator.OnRandomInjected += (random) => { // ((IRandomInjectable)configurationSpaces).InjectRandomGenerator(random); ((IRandomInjectable)layoutOperations).InjectRandomGenerator(random); ((IRandomInjectable)layoutEvolver).InjectRandomGenerator(random); ((IRandomInjectable)layoutConverter).InjectRandomGenerator(random); ((IRandomInjectable)simpleConfigurationSpaces).InjectRandomGenerator(random); ((IRandomInjectable)roomShapesHandler).InjectRandomGenerator(random); }; generator.OnCancellationTokenInjected += (token) => { ((ICancellable)generatorPlanner).SetCancellationToken(token); ((ICancellable)layoutEvolver).SetCancellationToken(token); }; layoutEvolver.OnEvent += (sender, args) => OnSimulatedAnnealingEvent?.Invoke(sender, args); layoutEvolver.OnPerturbed += (sender, layout) => OnPerturbed?.Invoke(layoutConverter.Convert(layout, false)); layoutEvolver.OnPerturbed += (sender, layout) => OnPerturbedInternal?.Invoke(layout); layoutEvolver.OnValid += (sender, layout) => OnPartialValid?.Invoke(layoutConverter.Convert(layout, true)); generatorPlanner.OnLayoutGenerated += layout => OnValid?.Invoke(layoutConverter.Convert(layout, true)); }
public Configuration(IntAlias <GridPolygon> shape, IntVector2 position, TEnergyData energyData) { ShapeContainer = shape; Position = position; EnergyData = energyData; }
/// <inheritdoc /> public override ConfigurationSpace GetConfigurationSpace(IntAlias <PolygonGrid2D> movingPolygon, IntAlias <PolygonGrid2D> fixedPolygon) { throw new InvalidOperationException(); return(ConfigurationSpaces_[movingPolygon.Alias][fixedPolygon.Alias][0]); // TODO: is this ok? }