public async Task <ViewRadiusOutputs> Handler(ViewRadiusInputs 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 <ViewRadiusInputs>(RegionEndpoint.USWest1); } var l = new InvocationWrapper <ViewRadiusInputs, ViewRadiusOutputs>(store, ViewRadius.Execute); var output = await l.InvokeAsync(args); return(output); }
/// <summary> /// The ViewRadius function. /// </summary> /// <param name="model">The input model.</param> /// <param name="input">The arguments to the execution.</param> /// <returns>A ViewRadiusOutputs instance containing computed results and the model with any new elements.</returns> public static ViewRadiusOutputs Execute(Dictionary <string, Model> inputModels, ViewRadiusInputs input) { inputModels.TryGetValue("Envelope", out Model envelopeModel); inputModels.TryGetValue("location", out Model contextBuildingsModel); if (envelopeModel == null) { throw new Exception("Unable to find envelope model."); } if (contextBuildingsModel == null) { throw new Exception("Unable to find Location model."); } var allEnvelopes = envelopeModel.AllElementsOfType <Envelope>(); var allContextBuildings = contextBuildingsModel.AllElementsOfType <Mass>(); if (!allEnvelopes.Any()) { throw new Exception("No envelopes in model."); } if (!allContextBuildings.Any()) { throw new Exception("No context buildings in model."); } var height = input.Height; var envelopesAtHeight = allEnvelopes.Where(env => height > env.Elevation && height < env.Height + env.Elevation); var model = new Model(); int rayCount = 170; var allFaces = allContextBuildings.SelectMany(b => b.Representation.SolidOperations.Select(s => s.Solid.Faces)); var maxTotalScore = 0.0; var totalScore = 0.0; foreach (var envelope in envelopesAtHeight) { var perimeter = envelope.Profile.Perimeter; var vertexAverage = perimeter.Vertices.Average(); var minRadius = perimeter.Vertices.Select(v => v.DistanceTo(vertexAverage)).Max(); var circle = Polygon.Circle(minRadius, rayCount); var rayDirections = circle.Vertices; var totalRadius = input.MaxRadius + minRadius; maxTotalScore += Math.PI * totalRadius * totalRadius; var heightTransform = new Transform(vertexAverage.X, vertexAverage.Y, height); circle = heightTransform.OfPolygon(circle); var maxCircle = new Circle(heightTransform.Origin, totalRadius); var filteredFaces = filterFaces(allFaces.SelectMany(f => f.Values).ToList(), maxCircle); var rays = rayDirections.Select(i => new Ray(maxCircle.Center, i)); List <Vector3> finalIsovistPoints = new List <Vector3>(); foreach (var ray in rays) { List <Vector3> allResults = new List <Vector3>(); foreach (var face in filteredFaces) { if (Intersects(ray, face, out Vector3 result)) { allResults.Add(result); } } if (allResults.Count > 0) { var resultsOrdered = allResults.OrderBy(r => r.DistanceTo(ray.Origin)); finalIsovistPoints.Add(resultsOrdered.First()); } else { finalIsovistPoints.Add(ray.Origin + ray.Direction.Unitized() * totalRadius); } } var isovist = new Polygon(finalIsovistPoints); totalScore += isovist.Area(); Mesh mesh = CreateMeshFromRays(finalIsovistPoints, maxCircle, rayCount); var isovistElement = new Isovist(mesh); model.AddElement(isovistElement); } var outputs = new ViewRadiusOutputs((totalScore / maxTotalScore) * 100); outputs.model = model; return(outputs); }