Ejemplo n.º 1
0
        private void CreatePrimaryFacades(Footprint footprint, IEnumerable <Section> sections, ICollection <IBuildingFacade> results)
        {
            for (var sideIndex = 0; sideIndex < footprint.Facades.Count; sideIndex++)
            {
                //Get start and end point of this wall
                var sideStart = footprint.Shape[sideIndex];
                var sideEnd   = footprint.Shape[(sideIndex + 1) % footprint.Shape.Count];

                //find which section this side is for
                var sideSegment  = new LineSegment2(sideStart, sideEnd).Line;
                var maybeSection = (from s in sections
                                    let aP = sideSegment.ClosestPointDistanceAlongLine(s.ExternalLineSegment.Start) * sideSegment.Direction + sideSegment.Position
                                             let aD = Vector2.Distance(aP, s.ExternalLineSegment.Start)
                                                      where aD < 0.1f
                                                      let bP = sideSegment.ClosestPointDistanceAlongLine(s.ExternalLineSegment.End) * sideSegment.Direction + sideSegment.Position
                                                               let bD = Vector2.Distance(bP, s.ExternalLineSegment.End)
                                                                        where bD < 0.1f
                                                                        let d = aD + bD
                                                                                orderby d
                                                                                select s).Cast <Section?>().FirstOrDefault();

                //Failed to find a section, this can happen when wall segments are so small the two corner segments either end completely cover the actual wall
                if (!maybeSection.HasValue)
                {
                    continue;
                }
                var section = maybeSection.Value;

                //There are multiple facades for any one wall section, iterate through them and create them
                foreach (var facade in footprint.Facades[sideIndex])
                {
                    //Sanity check that the facade does not underrun the valid range
                    //We can't sanity check overrun (easily) because that's based on the start of the *next* footprint
                    if (facade.Bottom < footprint.BottomIndex)
                    {
                        throw new InvalidOperationException(string.Format("Facade associated with wall at floor {0} attempted to place itself at floor {1}", footprint.BottomIndex, facade.Bottom));
                    }

                    var bot = _floors[facade.Bottom].FloorAltitude;
                    var top = _floors[facade.Top].FloorAltitude + _floors[facade.Top].Bounds.Height;
                    var mid = (bot + top) * 0.5f;

                    var prism = new Prism(top - bot, section.Inner1, section.Inner2, section.Outer1, section.Outer2);

                    //Create a configurable facade in the space
                    var configurableNode = (ConfigurableFacade)CreateChild(prism, Quaternion.Identity, new Vector3(0, mid, 0), new ScriptReference(typeof(ConfigurableFacade)));
                    configurableNode.Section = section;

                    //Create the specified facade in the *same* space
                    //This facade is just a proxy which passes all it's stamps to the configurable facade (created above)
                    var externalFacade = (BaseBuildingFacade)CreateChild(prism, Quaternion.Identity, new Vector3(0, mid, 0), facade.Script);
                    externalFacade.Facade           = configurableNode;
                    externalFacade.Section          = section;
                    externalFacade.BottomFloorIndex = facade.Bottom;
                    externalFacade.TopFloorIndex    = facade.Top;
                    results.Add(externalFacade);

                    //Make sure the building facade subdivides before the configurable facade (this ensures it can configure the facade)
                    configurableNode.AddPrerequisite(externalFacade, true);

                    //Make sure floors subdivide before configurable facade (this ensures it too can configure the facade)
                    for (var i = externalFacade.BottomFloorIndex; i <= externalFacade.TopFloorIndex; i++)
                    {
                        configurableNode.AddPrerequisite(_floors[i], false);
                    }

                    //Make sure the building facade subdivides before the floor (this ensures the floor can see the effects of the facade)
                    for (var i = externalFacade.BottomFloorIndex; i <= externalFacade.TopFloorIndex; i++)
                    {
                        _floors[i].AddPrerequisite(externalFacade, true);
                    }
                }
            }
        }