예제 #1
0
        public async Task <StructureOutputs> Handler(StructureInputs args, ILambdaContext context)
        {
            if (this.store == null)
            {
                // Preload the dependencies (if they exist),
                // so that they are available during model deserialization.
                var asmLocation = this.GetType().Assembly.Location;
                var asmDir      = Path.GetDirectoryName(asmLocation);
                var asmName     = Path.GetFileNameWithoutExtension(asmLocation);
                var depPath     = Path.Combine(asmDir, $"{asmName}.Dependencies.dll");

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

                this.store = new S3ModelStore <StructureInputs>(RegionEndpoint.USWest1);
            }

            var l      = new InvocationWrapper <StructureInputs, StructureOutputs>(store, Structure.Execute);
            var output = await l.InvokeAsync(args);

            return(output);
        }
예제 #2
0
        public async Task <StructureOutputs> Handler(StructureInputs 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 <StructureInputs>(RegionEndpoint.USWest1);
            }

            var l      = new InvocationWrapper <StructureInputs, StructureOutputs>(store, Structure.Execute);
            var output = await l.InvokeAsync(args);

            return(output);
        }
예제 #3
0
        /// <summary>
        /// The Structure function.
        /// </summary>
        /// <param name="model">The model.
        /// Add elements to the model to have them persisted.</param>
        /// <param name="input">The arguments to the execution.</param>
        /// <returns>A StructureOutputs instance containing computed results.</returns>
        public static StructureOutputs Execute(Dictionary <string, Model> models, StructureInputs input)
        {
            List <Level>    levels    = null;
            List <Envelope> envelopes = null;
            var             model     = new Model();

            var envelopeModel = models[ENVELOPE_MODEL_NAME];

            envelopes = envelopeModel.AllElementsOfType <Envelope>().Where(e => e.Direction.IsAlmostEqualTo(Vector3.ZAxis)).ToList();
            if (envelopes.Count() == 0)
            {
                throw new Exception("No element of type 'Envelope' could be found in the supplied model.");
            }
            var levelsModel = models[LEVELS_MODEL_NAME];

            levels = levelsModel.AllElementsOfType <Level>().ToList();

            List <Line> xGrids;
            List <Line> yGrids;

            var gridRotation = CreateGridsFromBoundary(envelopes.First().Profile.Perimeter,
                                                       input.GridXAxisInterval > 0 ? input.GridXAxisInterval : 4,
                                                       input.GridYAxisInterval > 0 ? input.GridYAxisInterval : 4,
                                                       out xGrids,
                                                       out yGrids,
                                                       model);

            levels.Sort(new LevelComparer());

            Level  last             = null;
            var    gridXMaterial    = new Material("GridX", Colors.Red);
            double lumpingTolerance = 2.0;

            foreach (var envelope in envelopes)
            {
                // Inset the footprint just a bit to keep the
                // beams out of the plane of the envelope. Use the biggest
                // beam that we have.
                var footprint = envelope.Profile.Perimeter.Offset(-0.25)[0];

                // Trim all the grid lines by the boundary
                var boundarySegments = footprint.Segments();
                var trimmedXGrids    = TrimGridsToBoundary(xGrids, boundarySegments, model);
                var trimmedYGrids    = TrimGridsToBoundary(yGrids, boundarySegments, model);

                // Trim all the grids against the other grids
                var xGridSegments = TrimGridsWithOtherGrids(trimmedXGrids, trimmedYGrids);
                var yGridSegments = TrimGridsWithOtherGrids(trimmedYGrids, trimmedXGrids);

                var e = envelope.Elevation;
                if (last != null)
                {
                    e = last.Elevation;
                }

                List <Vector3> columnLocations = new List <Vector3>();
                columnLocations.AddRange(CalculateColumnLocations(xGridSegments, e, lumpingTolerance));
                columnLocations.AddRange(CalculateColumnLocations(yGridSegments, e, lumpingTolerance));

                var envLevels = levels.Where(l => l.Elevation >= envelope.Elevation &&
                                             l.Elevation <= envelope.Elevation + envelope.Height).Skip(1).ToList();

                if (envLevels.Count == 0)
                {
                    continue;
                }

                last = envLevels.Last();

                List <Beam> masterFraming = null;
                foreach (var l in envLevels)
                {
                    if (masterFraming == null)
                    {
                        masterFraming = CreateFramingPlan(l.Elevation, xGridSegments, yGridSegments, boundarySegments);
                        model.AddElements(masterFraming);
                    }
                    else
                    {
                        var instances = CreateFramingPlanInstance(masterFraming, l.Elevation);
                        model.AddElements(instances, false);
                    }
                }

                var colProfile = new Profile(Polygon.Rectangle(11 * mToIn, 18 * mToIn));

                GeometricElement masterColumn = null;
                foreach (var lc in columnLocations)
                {
                    if (masterColumn == null)
                    {
                        masterColumn = new Column(Vector3.Origin,
                                                  envLevels.Last().Elevation - lc.Z,
                                                  colProfile,
                                                  BuiltInMaterials.Steel,
                                                  new Transform(lc),
                                                  0,
                                                  0,
                                                  gridRotation);
                        model.AddElement(masterColumn);
                    }
                    else
                    {
                        // var displace = Vector3.Origin - masterColumn.Transform.Origin - lc;
                        var instance = new ElementInstance(masterColumn, new Transform(lc));
                        model.AddElement(instance, false);
                    }
                }
            }

            var output = new StructureOutputs(_longestGridSpan);

            output.model = model;
            return(output);
        }
예제 #4
0
        /// <summary>
        /// The Structure function.
        /// </summary>
        /// <param name="model">The model.
        /// Add elements to the model to have them persisted.</param>
        /// <param name="input">The arguments to the execution.</param>
        /// <returns>A StructureOutputs instance containing computed results.</returns>
        public static StructureOutputs Execute(Dictionary <string, Model> models, StructureInputs input)
        {
            var model    = new Model();
            var warnings = new List <string>();

            Elements.Validators.Validator.DisableValidationOnConstruction = true;

            CellComplex cellComplex = null;
            Line        longestEdge = null;

#if DEBUG
            var sw = new Stopwatch();
            sw.Start();
#endif

            if (models.ContainsKey(BAYS_MODEL_NAME))
            {
                var cellsModel = models[BAYS_MODEL_NAME];
                cellComplex = cellsModel.AllElementsOfType <CellComplex>().First();
            }
            else
            {
                warnings.Add("Adding the Bays function to your workflow will give you more configurability. We'll use the default configuration for now.");

                // Create a cell complex with some defaults.
                if (!models.ContainsKey(LEVELS_MODEL_NAME))
                {
                    throw new Exception("If Bays are not supplied Levels are required.");
                }

                var levels       = models[LEVELS_MODEL_NAME];
                var levelVolumes = levels.AllElementsOfType <LevelVolume>().ToList();
                if (levelVolumes.Count == 0)
                {
                    throw new Exception("No LevelVolumes found in your Levels model. Please use a level function that generates LevelVolumes, such as Simple Levels by Envelope");
                }

                // Replicate the old behavior by creating a
                // grid using the envelope's first level base polygon's longest
                // edge as the U axis and its perpendicular as the
                // V axis.

                var firstLevel          = levelVolumes[0];
                var firstLevelPerimeter = firstLevel.Profile.Perimeter;
                longestEdge = firstLevelPerimeter.Segments().OrderBy(s => s.Length()).Last();

                var longestEdgeTransform = longestEdge.TransformAt(0.5);
                var t = new Transform(longestEdge.Start, longestEdgeTransform.XAxis, longestEdge.Direction(), Vector3.ZAxis);

                var toWorld = new Transform(t);
                toWorld.Invert();
                var bbox = new BBox3(firstLevelPerimeter.Vertices.Select(o => toWorld.OfVector(o)).ToList());

                var l = bbox.Max.Y - bbox.Min.Y;
                var w = bbox.Max.X - bbox.Min.X;

                var origin = t.OfVector(bbox.Min);

                var uGrid = new Grid1d(new Line(origin, origin + t.YAxis * l));
                uGrid.DivideByFixedLength(DEFAULT_U);

                var vGrid = new Grid1d(new Line(origin, origin + t.XAxis * w));

                vGrid.DivideByFixedLength(DEFAULT_V);
                var grid = new Grid2d(uGrid, vGrid);

                var u = grid.U;
                var v = grid.V;

                cellComplex = new CellComplex(Guid.NewGuid(), "Temporary Cell Complex");

                // Draw level volumes from each level down.
                for (var i = 1; i < levelVolumes.Count; i++)
                {
                    var levelVolume     = levelVolumes.ElementAt(i);
                    var perimeter       = levelVolume.Profile.Perimeter.Offset(-0.5)[0];
                    var g2d             = new Grid2d(perimeter, grid.U, grid.V);
                    var levelElevation  = levelVolume.Transform.Origin.Z;
                    var lastLevelVolume = levelVolumes.ElementAt(i - 1);
                    foreach (var cell in g2d.GetCells())
                    {
                        foreach (var crv in cell.GetTrimmedCellGeometry())
                        {
                            cellComplex.AddCell((Polygon)crv, lastLevelVolume.Height, levelElevation - lastLevelVolume.Height, g2d.U, g2d.V);
                            if (i == levelVolumes.Count - 1)
                            {
                                cellComplex.AddCell((Polygon)crv, levelVolume.Height, levelElevation, g2d.U, g2d.V);
                            }
                        }
                    }
                }
            }

#if DEBUG
            Console.WriteLine($"{sw.ElapsedMilliseconds} ms for getting or creating a cell complex.");
            sw.Restart();
#endif

            Vector3 primaryDirection;
            Vector3 secondaryDirection;
            IEnumerable <GridLine> gridLines = null;

            if (models.ContainsKey(GRIDS_MODEL_NAME))
            {
                var gridsModel = models[GRIDS_MODEL_NAME];
                gridLines = gridsModel.AllElementsOfType <GridLine>();

                // Group by direction.
                var gridGroups = gridLines.GroupBy(gl => gl.Curve.TransformAt(0).ZAxis).ToList();
                primaryDirection   = gridGroups[0].Key;
                secondaryDirection = gridGroups[1].Key;
            }
            else
            {
                warnings.Add("Adding the Grids function to your workflow will enable you to position and orient the grid. We'll use the default configuration for now with the grid oriented along the longest edge of the structure.");
                // Define the primary direction from the longest edge of the site.
                primaryDirection   = longestEdge.Direction();
                secondaryDirection = longestEdge.TransformAt(0.5).XAxis;
            }

#if DEBUG
            Console.WriteLine($"{sw.ElapsedMilliseconds} ms for getting or creating grids.");
            sw.Restart();
#endif

            var structureMaterial = new Material("Steel", Colors.Gray, 0.5, 0.3);
            model.AddElement(structureMaterial, false);
            model.AddElement(BuiltInMaterials.ZAxis, false);

            var wideFlangeFactory = new WideFlangeProfileFactory();
            var shsProfileFactory = new SHSProfileFactory();
            var rhsProfileFactory = new RHSProfileFactory();

            var columnTypeName   = input.ColumnType.ToString();
            var columnProfile    = GetProfileFromName(columnTypeName, wideFlangeFactory, rhsProfileFactory, shsProfileFactory);
            var colProfileBounds = columnProfile.Perimeter.Bounds();
            var colProfileDepth  = colProfileBounds.Max.Y - colProfileBounds.Min.Y;

            var     girderTypeName     = input.GirderType.ToString();
            Profile girderProfile      = null;
            double  girderProfileDepth = 0;
            if (girderTypeName.StartsWith("LH"))
            {
                girderProfileDepth = Units.InchesToMeters(double.Parse(girderTypeName.Split("LH")[1]));
            }
            else
            {
                girderProfile = GetProfileFromName(girderTypeName, wideFlangeFactory, rhsProfileFactory, shsProfileFactory);
                var girdProfileBounds = girderProfile.Perimeter.Bounds();
                girderProfileDepth = girdProfileBounds.Max.Y - girdProfileBounds.Min.Y;

                // Set the profile down by half its depth so that
                // it sits under the slab.
                girderProfile.Transform(new Transform(new Vector3(0, -girderProfileDepth / 2 - input.SlabThickness)));
            }

            Profile beamProfile      = null;
            double  beamProfileDepth = 0;

            var beamTypeName = input.BeamType.ToString();
            if (beamTypeName.StartsWith("LH"))
            {
                beamProfileDepth = Units.InchesToMeters(double.Parse(beamTypeName.Split("LH")[1]));
            }
            else
            {
                beamProfile = GetProfileFromName(beamTypeName, wideFlangeFactory, rhsProfileFactory, shsProfileFactory);
                var beamProfileBounds = beamProfile.Perimeter.Bounds();
                beamProfileDepth = beamProfileBounds.Max.Y - beamProfileBounds.Min.Y;

                // Set the profile down by half its depth so that
                // it sits under the slab.
                beamProfile.Transform(new Transform(new Vector3(0, -beamProfileDepth / 2 - input.SlabThickness)));
            }

            var edges               = cellComplex.GetEdges();
            var lowestTierSet       = false;
            var lowestTierElevation = double.MaxValue;

            var columnDefintions       = new Dictionary <(double memberLength, Profile memberProfile), Column>();
            var girderDefinitions      = new Dictionary <(double memberLength, Profile memberProfile), GeometricElement>();
            var beamDefinitions        = new Dictionary <(double memberLength, Profile memberProfile), GeometricElement>();
            var girderJoistDefinitions = new Dictionary <(double memberLength, double depth), GeometricElement>();
            var beamJoistDefinitions   = new Dictionary <(double memberLength, double depth), GeometricElement>();

            LProfileFactory lProfileFactory;
            LProfile        L8 = null;
            LProfile        L5 = null;
            LProfile        L2 = null;
            LProfile        L3 = null;

            if (girderProfile == null || beamProfile == null)
            {
                lProfileFactory = new LProfileFactory();
                L8 = Task.Run(async() => await lProfileFactory.GetProfileByTypeAsync(LProfileType.L8X8X1_2)).Result;
                L5 = Task.Run(async() => await lProfileFactory.GetProfileByTypeAsync(LProfileType.L5X5X1_2)).Result;
                L2 = Task.Run(async() => await lProfileFactory.GetProfileByTypeAsync(LProfileType.L2X2X1_8)).Result;
                L3 = Task.Run(async() => await lProfileFactory.GetProfileByTypeAsync(LProfileType.L3X2X3_16)).Result;
            }

#if DEBUG
            Console.WriteLine($"{sw.ElapsedMilliseconds} ms for getting all beam and column profiles.");
            sw.Restart();
#endif

            var xy = new Plane(Vector3.Origin, Vector3.ZAxis);

            // Order edges from lowest to highest.
            foreach (Elements.Spatial.CellComplex.Edge edge in edges.OrderBy(e =>
                                                                             Math.Min(cellComplex.GetVertex(e.StartVertexId).Value.Z, cellComplex.GetVertex(e.EndVertexId).Value.Z)
                                                                             ))
            {
                var memberLength = edge.Length(cellComplex);
                var start        = cellComplex.GetVertex(edge.StartVertexId).Value;
                var end          = cellComplex.GetVertex(edge.EndVertexId).Value;
                var direction    = (end - start).Unitized();

                var warningRepresentation = new Representation(new List <SolidOperation>()
                {
                    new Extrude(Polygon.Rectangle(0.01, 0.01), 0.01, Vector3.ZAxis, false)
                });

                if (edge.IsVertical(cellComplex))
                {
                    // For vertical edges that are not on the grid, we need
                    // a heuristic to determine when we should place a column.
                    // You don't want to place a column all the time because
                    // for non-grid-aligned structures, when you place columns
                    // at every intersection of the envelope and the grid, you
                    // can get columns that are too close together. Instead, we
                    // place a column based on the distance from that column along
                    // a grid line back to a primary grid intersection. If that
                    // distance exceeds the maximum allowable neighbor span,
                    // we place a column.
                    if (!edge.StartsOnGrid(cellComplex))
                    {
                        var maxDistance = double.MinValue;
                        foreach (var e in edge.GetCells().SelectMany(c => c.GetEdges().Where(e =>
                                                                                             e != edge &&
                                                                                             e.StartsOrEndsOnGrid(cellComplex) &&
                                                                                             e.StartsOrEndsAtThisVertex(edge.StartVertexId, cellComplex) &&
                                                                                             e.IsHorizontal(cellComplex))))
                        {
                            var d = e.Length(cellComplex);
                            maxDistance = Math.Max(maxDistance, d);
                        }

                        if (maxDistance < input.MaximumNeighborSpan)
                        {
                            continue;
                        }
                    }

                    var    origin   = start.IsLowerThan(end) ? start : end;
                    var    rotation = Vector3.XAxis.PlaneAngleTo(primaryDirection);
                    Column columnDefinition;
                    if (!columnDefintions.ContainsKey((memberLength, columnProfile)))
                    {
                        columnDefinition = new Column(Vector3.Origin, memberLength, columnProfile, structureMaterial, name: columnProfile.Name)
                        {
                            IsElementDefinition = true
                        };
                        columnDefinition.Representation.SkipCSGUnion = true;
                        columnDefintions.Add((memberLength, columnProfile), columnDefinition);
                        model.AddElement(columnDefinition, false);
                    }
                    else
                    {
                        columnDefinition = columnDefintions[(memberLength, columnProfile)];