/// <summary> /// Evaluate this building design spec to create a set of building internals (floors and vertical elements) /// </summary> /// <param name="random"></param> /// <param name="metadata"></param> /// <param name="finder"></param> /// <returns></returns> public Internals Internals(Func <double> random, INamedDataCollection metadata, Func <KeyValuePair <string, string>[], Type[], ScriptReference> finder) { Contract.Requires(random != null); Contract.Requires(metadata != null); Contract.Requires(finder != null); Contract.Ensures(Contract.Result <Internals>() != null); var ground = _floorSelectors.OfType <GroundMarker>().Single(); var aboveGround = _floorSelectors.TakeWhile(a => !(a is GroundMarker)).Append(ground).ToArray(); var belowGround = _floorSelectors.SkipWhile(a => !(a is GroundMarker)).Skip(1).ToArray(); List <FootprintSelection> footprints = new List <FootprintSelection>(); //Select above ground floors, then assign indices var above = SelectFloors(random, metadata, finder, aboveGround, ground, aboveGround: true); int index = 0; float compoundHeight = 0; foreach (var run in above.Reverse()) { if (run.Selection.Count > 0) { footprints.Add(new FootprintSelection(run.Marker, index)); foreach (var floor in run.Selection.Reverse()) { floor.Index = index++; floor.CompoundHeight = compoundHeight; compoundHeight += floor.Height; } } } //Select below ground floors, then assign indices var below = SelectFloors(random, metadata, finder, belowGround, ground, aboveGround: false); index = 0; compoundHeight = 0; foreach (var run in below) { foreach (var floor in run.Selection) { floor.Index = --index; floor.CompoundHeight = compoundHeight; compoundHeight -= floor.Height; } footprints.Add(new FootprintSelection(run.Marker, index)); } //Create result object (with floors) var internals = new Internals(this, above.Select(a => a.Selection.ToArray()).ToArray(), below.Select(a => a.Selection.ToArray()).ToArray(), footprints.ToArray()); //Select vertical elements for floors and add to result internals.Verticals = SelectVerticals(random, finder, _verticalSelectors, internals.Floors).ToArray(); //return result return(internals); }
public override void Subdivide(Prism bounds, ISubdivisionGeometry geometry, INamedDataCollection hierarchicalParameters) { _internals = _designer.Internals(Random, HierarchicalParameters, ScriptReference.Find(Random)); HierarchicalParameters.Set(BuildingInternalsName, _internals); base.Subdivide(bounds, geometry, hierarchicalParameters); //Create the node which will create the building form the spec var building = (SpecBuilding)CreateChild(bounds, Quaternion.Identity, Vector3.Zero, new ScriptReference(typeof(SpecBuilding))); //Make sure sibling container subdivide before building foreach (var sibling in Parent.Children.OfType <IBuildingContainer>()) { building.AddPrerequisite(sibling, false); } //Copy neighbour data into building (from container) building.Neighbours = Neighbours; }