예제 #1
0
        public async Task <ClassroomLayoutOutputs> Handler(ClassroomLayoutInputs args, ILambdaContext context)
        {
            // Preload dependencies (if they exist),
            // so that they are available during model deserialization.

            var sw          = System.Diagnostics.Stopwatch.StartNew();
            var asmLocation = this.GetType().Assembly.Location;
            var asmDir      = Path.GetDirectoryName(asmLocation);

            // Explicitly load the dependencies project, it might have types
            // that aren't used in the function but are necessary for correct
            // deserialization.
            var asmName = Path.GetFileNameWithoutExtension(asmLocation);
            var depPath = Path.Combine(asmDir, $"{asmName}.Dependencies.dll");

            if (File.Exists(depPath))
            {
                Console.WriteLine($"Loading dependencies assembly from: {depPath}...");
                Assembly.LoadFrom(depPath);
                Console.WriteLine("Dependencies assembly loaded.");
            }

            // Load all reference assemblies.
            Console.WriteLine($"Loading all referenced assemblies.");
            foreach (var asm in this.GetType().Assembly.GetReferencedAssemblies())
            {
                try
                {
                    Assembly.Load(asm);
                }
                catch (Exception e)
                {
                    Console.WriteLine($"Failed to load {asm.FullName}");
                    Console.WriteLine(e.Message);
                }
            }
            sw.Stop();
            Console.WriteLine($"Time to load assemblies: {sw.Elapsed.TotalSeconds})");

            if (this.store == null)
            {
                this.store = new S3ModelStore <ClassroomLayoutInputs>(RegionEndpoint.USWest1);
            }

            var l      = new InvocationWrapper <ClassroomLayoutInputs, ClassroomLayoutOutputs>(store, ClassroomLayout.Execute);
            var output = await l.InvokeAsync(args);

            return(output);
        }
예제 #2
0
        /// <summary>
        /// The ClassroomLayout function.
        /// </summary>
        /// <param name="model">The input model.</param>
        /// <param name="input">The arguments to the execution.</param>
        /// <returns>A ClassroomLayoutOutputs instance containing computed results and the model with any new elements.</returns>
        public static ClassroomLayoutOutputs Execute(Dictionary <string, Model> inputModels, ClassroomLayoutInputs input)
        {
            var spacePlanningZones = inputModels["Space Planning Zones"];
            var levelsModel        = inputModels["Levels"];
            var levels             = spacePlanningZones.AllElementsOfType <LevelElements>();
            var levelVolumes       = levelsModel.AllElementsOfType <LevelVolume>();
            var output             = new ClassroomLayoutOutputs();
            var configJson         = File.ReadAllText("./ClassroomConfigurations.json");
            var configs            = JsonConvert.DeserializeObject <SpaceConfiguration>(configJson);

            var wallMat    = new Material("Drywall", new Color(0.9, 0.9, 0.9, 1.0), 0.01, 0.01);
            var glassMat   = new Material("Glass", new Color(0.7, 0.7, 0.7, 0.3), 0.3, 0.6);
            var mullionMat = new Material("Storefront Mullions", new Color(0.5, 0.5, 0.5, 1.0));

            foreach (var lvl in levels)
            {
                var corridors           = lvl.Elements.OfType <Floor>();
                var corridorSegments    = corridors.SelectMany(p => p.Profile.Segments());
                var meetingRmBoundaries = lvl.Elements.OfType <SpaceBoundary>().Where(z => z.Name == "Classroom");
                var levelVolume         = levelVolumes.First(l => l.Name == lvl.Name);
                var wallCandidateLines  = new List <(Line line, string type)>();
                foreach (var room in meetingRmBoundaries)
                {
                    var  spaceBoundary        = room.Boundary;
                    Line orientationGuideEdge = FindEdgeAdjacentToSegments(spaceBoundary.Perimeter.Segments(), corridorSegments, out var wallCandidates);
                    wallCandidateLines.Add((orientationGuideEdge, "Glass"));
                    var exteriorWalls = FindEdgeAdjacentToSegments(wallCandidates, levelVolume.Profile.Segments(), out var solidWalls, 0.6);
                    wallCandidateLines.AddRange(solidWalls.Select(s => (s, "Solid")));
                    var orientationTransform = new Transform(Vector3.Origin, orientationGuideEdge.Direction(), Vector3.ZAxis);
                    var boundaryCurves       = new List <Polygon>();
                    boundaryCurves.Add(spaceBoundary.Perimeter);
                    boundaryCurves.AddRange(spaceBoundary.Voids ?? new List <Polygon>());

                    var grid       = new Grid2d(boundaryCurves, orientationTransform);
                    var deskConfig = configs["Desk"];
                    foreach (var cell in grid.GetCells())
                    {
                        var rect       = cell.GetCellGeometry() as Polygon;
                        var segs       = rect.Segments();
                        var width      = segs[0].Length();
                        var depth      = segs[1].Length();
                        var trimmedGeo = cell.GetTrimmedCellGeometry();
                        if (!cell.IsTrimmed() && trimmedGeo.Count() > 0)
                        {
                            output.Model.AddElement(InstantiateLayout(configs, width, depth, rect, room.Transform));
                        }
                        else if (trimmedGeo.Count() > 0)
                        {
                            var largestTrimmedShape = trimmedGeo.OfType <Polygon>().OrderBy(s => s.Area()).Last();
                            var cinchedVertices     = rect.Vertices.Select(v => largestTrimmedShape.Vertices.OrderBy(v2 => v2.DistanceTo(v)).First()).ToList();
                            var cinchedPoly         = new Polygon(cinchedVertices);
                            output.Model.AddElement(InstantiateLayout(configs, width, depth, cinchedPoly, room.Transform));
                        }
                        try
                        {
                            if (cell.U.Curve.Length() > 5.6)
                            {
                                cell.U.SplitAtOffset(2.3, false, true);
                                cell.V.SplitAtOffset(0.5, false, true);
                                cell.V.SplitAtOffset(0.5, true, true);
                                var classroomSide = cell[1, 1];
                                classroomSide.U.DivideByFixedLength(deskConfig.Width, FixedDivisionMode.RemainderAtBothEnds);
                                classroomSide.V.DivideByFixedLength(deskConfig.Depth, FixedDivisionMode.RemainderAtBothEnds);
                                foreach (var individualDesk in classroomSide.GetCells())
                                {
                                    var cellRect     = individualDesk.GetCellGeometry() as Polygon;
                                    var trimmedShape = individualDesk.GetTrimmedCellGeometry().FirstOrDefault() as Polygon;
                                    if (trimmedShape == null)
                                    {
                                        continue;
                                    }
                                    if (trimmedShape.Area().ApproximatelyEquals(deskConfig.Width * deskConfig.Depth, 0.1))
                                    {
                                        foreach (var contentItem in deskConfig.ContentItems)
                                        {
                                            var instance = contentItem.ContentElement.CreateInstance(
                                                contentItem.Transform
                                                .Concatenated(orientationTransform)
                                                .Concatenated(new Transform(cellRect.Vertices[0]))
                                                .Concatenated(levelVolume.Transform),
                                                "Desk");
                                            output.Model.AddElement(instance);
                                        }
                                    }
                                }
                            }
                        }
                        catch
                        {
                        }
                    }
                }
                var mullionSize           = 0.07;
                var doorWidth             = 0.9;
                var doorHeight            = 2.1;
                var sideLightWidth        = 0.4;
                var totalStorefrontHeight = Math.Min(2.7, levelVolume.Height);
                var mullion = new StandardWall(new Line(new Vector3(-mullionSize / 2, 0, 0), new Vector3(mullionSize / 2, 0, 0)), mullionSize, totalStorefrontHeight, mullionMat);
                mullion.IsElementDefinition = true;
                if (input.CreateWalls)
                {
                    foreach (var wallCandidate in wallCandidateLines)
                    {
                        if (wallCandidate.type == "Solid")
                        {
                            output.Model.AddElement(new StandardWall(wallCandidate.line, 0.2, levelVolume.Height, wallMat, levelVolume.Transform));
                        }
                        else if (wallCandidate.type == "Glass")
                        {
                            var grid = new Grid1d(wallCandidate.line);
                            grid.SplitAtOffsets(new[] { sideLightWidth, sideLightWidth + doorWidth });
                            grid[2].DivideByApproximateLength(2);
                            var separators = grid.GetCellSeparators(true);
                            var beam       = new Beam(wallCandidate.line, Polygon.Rectangle(mullionSize, mullionSize), mullionMat, 0, 0, 0, isElementDefinition: true);
                            output.Model.AddElement(beam.CreateInstance(levelVolume.Transform, "Base Mullion"));
                            output.Model.AddElement(beam.CreateInstance(levelVolume.Transform.Concatenated(new Transform(0, 0, doorHeight)), "Base Mullion"));
                            output.Model.AddElement(beam.CreateInstance(levelVolume.Transform.Concatenated(new Transform(0, 0, totalStorefrontHeight)), "Base Mullion"));
                            foreach (var separator in separators)
                            {
                                // var line = new Line(separator, separator + new Vector3(0, 0, levelVolume.Height));
                                // output.Model.AddElement(new ModelCurve(line, BuiltInMaterials.XAxis, levelVolume.Transform));
                                var instance = mullion.CreateInstance(new Transform(separator, wallCandidate.line.Direction(), Vector3.ZAxis, 0).Concatenated(levelVolume.Transform), "Mullion");
                                output.Model.AddElement(instance);
                            }
                            output.Model.AddElement(new StandardWall(wallCandidate.line, 0.05, totalStorefrontHeight, glassMat, levelVolume.Transform));
                            var headerHeight = levelVolume.Height - totalStorefrontHeight;
                            if (headerHeight > 0.01)
                            {
                                output.Model.AddElement(new StandardWall(wallCandidate.line, 0.2, headerHeight, wallMat, levelVolume.Transform.Concatenated(new Transform(0, 0, totalStorefrontHeight))));
                            }
                        }
                    }
                }
            }
            InstancePositionOverrides(input.Overrides, output.Model);
            return(output);
        }