private static List <SolidAnalysisObject> getEastMidtownEnvelopes(List <Envelope> envelopes, List <RhinoBrep> rhinoBreps, List <RhinoExtrusion> rhinoExtrusions, List <MeshElement> meshEnvelopes, Model model, Boolean showDebugGeometry)
        {
            var analysisObjects = new List <SolidAnalysisObject>();

            var up                      = new Vector3(0, 0, 1);
            var cutHeight               = Units.FeetToMeters(150.0);
            var plane                   = new Plane(new Vector3(0, 0, cutHeight), Vector3.ZAxis);
            var envelopesForBlockage    = new List <Envelope>();
            var meshElementsForBlockage = new List <MeshElement>();

            foreach (var envelope in envelopes)
            {
                var bottom = envelope.Elevation;
                var top    = bottom + envelope.Height;

                if (top < cutHeight)
                {
                    continue;
                }

                if (bottom >= cutHeight)
                {
                    // envelope is above the cutoff, use as-is
                    analysisObjects.AddRange(SolidAnalysisObject.MakeFromEnvelopes(new List <Envelope>()
                    {
                        envelope
                    }));
                }
                else
                {
                    envelopesForBlockage.AddRange(GeoUtilities.SliceAtHeight(envelope, cutHeight, showDebugGeometry));
                }
            }

            foreach (var rhinoBrep in rhinoBreps)
            {
                envelopesForBlockage.AddRange(GeoUtilities.SliceAtHeight(rhinoBrep, cutHeight, showDebugGeometry));
            }

            foreach (var rhinoExtrusion in rhinoExtrusions)
            {
                envelopesForBlockage.AddRange(GeoUtilities.SliceAtHeight(rhinoExtrusion, cutHeight, showDebugGeometry));
            }

            foreach (var meshElement in meshEnvelopes)
            {
                var bbox   = new BBox3(GeoUtilities.TransformedVertices(meshElement.Mesh.Vertices, meshElement.Transform));
                var bottom = bbox.Min.Z;
                var top    = bbox.Max.Z;

                if (top < cutHeight)
                {
                    continue;
                }

                if (bottom >= cutHeight)
                {
                    // envelope is above the cutoff, use as-is
                    meshElementsForBlockage.Add(meshElement);
                }
                else
                {
                    envelopesForBlockage.AddRange(GeoUtilities.SliceAtHeight(meshElement, cutHeight, showDebugGeometry));
                }
            }

            analysisObjects.AddRange(SolidAnalysisObject.MakeFromEnvelopes(envelopesForBlockage));
            analysisObjects.AddRange(SolidAnalysisObject.MakeFromMeshElements(meshElementsForBlockage));

            return(analysisObjects);
        }
        /// <summary>
        /// C# in-progress version of this
        /// </summary>
        /// <param name="model">The input model.</param>
        /// <param name="input">The arguments to the execution.</param>
        /// <returns>A NYCZR8127DaylightEvaluationOutputs instance containing computed results and the model with any new elements.</returns>
        public static NYCZR8127DaylightEvaluationOutputs Execute(Dictionary <string, Model> inputModels, NYCZR8127DaylightEvaluationInputs input)
        {
            var model = new Model();

            inputModels.TryGetValue("Site", out var siteModel);

            if (!inputModels.TryGetValue("Envelope", out var envelopeModel))
            {
                string localFile = "/Users/serenali/Downloads/model 18.json";
                if (File.Exists(localFile))
                {
                    Console.WriteLine("Using local file");
                    string text     = System.IO.File.ReadAllText(localFile);
                    var    envModel = Model.FromJson(text);
                    inputModels["Envelope"] = envModel;
                }
                inputModels.TryGetValue("Envelope", out envelopeModel);
            }

            var siteInput       = getSite(siteModel);
            var envelopes       = getElementsOfType <Envelope>(envelopeModel);
            var rhinoBreps      = getElementsOfType <RhinoBrep>(envelopeModel);
            var rhinoExtrusions = getElementsOfType <RhinoExtrusion>(envelopeModel);
            var meshEnvelopes   = getElementsOfType <MeshElement>(envelopeModel);

            if (siteInput == null)
            {
                throw new ArgumentException("There were no sites found. Please make sure you either meet the dependency of 'Site' or the dependency of 'EnvelopeAndSite."); throw new ArgumentException("BOOO SITE IS NOT FOUND");
            }
            if ((envelopes == null || envelopes.Count < 1) && (meshEnvelopes == null || meshEnvelopes.Count < 1) && (rhinoBreps == null || rhinoBreps.Count < 1) && (rhinoExtrusions == null || rhinoExtrusions.Count < 1))
            {
                throw new ArgumentException("There were no envelopes found. Please make sure you either meet the dependency of 'Envelope' or the dependency of 'EnvelopeAndSite.");
            }

            var site     = siteInput.Perimeter.Bounds();
            var siteRect = Polygon.Rectangle(new Vector3(site.Min.X, site.Min.Y), new Vector3(site.Max.X, site.Max.Y));

            model.AddElement(new ModelCurve(siteRect, name: "Site Bounds Used"));

            GeoUtilities.Model                = model;
            Diagram.Model                     = model;
            SolidAnalysisObject.Model         = model;
            SolidAnalysisObject.SkipSubdivide = input.SkipSubdivide;

            var analysisObjects = SolidAnalysisObject.MakeFromEnvelopes(envelopes);

            foreach (var analysisObject in SolidAnalysisObject.MakeFromMeshElements(meshEnvelopes))
            {
                analysisObjects.Add(analysisObject);
            }

            foreach (var analysisObject in SolidAnalysisObject.MakeFromRhinoBreps(rhinoBreps))
            {
                analysisObjects.Add(analysisObject);
            }

            foreach (var analysisObject in SolidAnalysisObject.MakeFromRhinoExtrusions(rhinoExtrusions))
            {
                analysisObjects.Add(analysisObject);
            }

            // Only applicable for E Midtown
            List <SolidAnalysisObject> analysisObjectsForBlockage = input.QualifyForEastMidtownSubdistrict ? getEastMidtownEnvelopes(envelopes, rhinoBreps, rhinoExtrusions, meshEnvelopes, model, input.DebugVisualization) : null;

            var margin             = 20;
            var vsIndex            = 0;
            var verticalOffsetBase = Settings.ChartHeight + margin;

            var streetScores             = new List <double>();
            var streetLengths            = 0.0;
            var streetScoresTimesLengths = 0.0;

            if (input.VantageStreets.Count < 1)
            {
                throw new Exception("Please provide at least one vantage street");
            }

            foreach (var vantageStreet in input.VantageStreets)
            {
                var matchingOverride = input.Overrides?.VantageStreets.FirstOrDefault(x => x.Identity.Name == vantageStreet.Name);

                var color = DebugUtilities.random.NextColor();
                var vantageStreetMaterial = new Material($"Vantage Street {vantageStreet.Name}", color)
                {
                    EdgeDisplaySettings = new EdgeDisplaySettings {
                        LineWidth = 2
                    }
                };
                var vantagePointMaterial = new Material($"Vantage Point on {vantageStreet.Name}", new Color(color.Red, color.Green, color.Blue, 0.15))
                {
                    EdgeDisplaySettings = new EdgeDisplaySettings {
                        LineWidth = 2
                    }
                };
                var outputVantageStreet = VantageElementUtils.CreateVantageStreet(siteRect, vantageStreet, out var vantagePoints, matchingOverride, model);
                outputVantageStreet.Material = vantageStreetMaterial;

                int vpIndex = 0;

                foreach (var vp in vantagePoints)
                {
                    var transform = new Transform(new Vector3(90.0 + vpIndex * 200.0, site.Max.Y + margin + verticalOffsetBase * vsIndex));

                    var name = $"{vantageStreet.Name}: VP {vpIndex + 1}";

                    vp.Diagram.Draw(name, model, analysisObjects, input, input.DebugVisualization, analysisObjectsForBlockage: analysisObjectsForBlockage);

                    var outputVp = new NYCDaylightEvaluationVantagePoint(
                        vp.Diagram.DaylightBlockage,
                        vp.Diagram.UnblockedDaylightCredit,
                        vp.Diagram.ProfilePenalty,
                        vp.Diagram.AvailableDaylight,
                        vp.Diagram.DaylightRemaining,
                        vp.Diagram.DaylightScore,
                        outputVantageStreet,
                        material: vantagePointMaterial,
                        name: name
                        );
                    outputVp.SetViz(vp.GetViewCone());
                    model.AddElement(outputVp);

                    var vpHelper = vp.GetVisualizationHelpers();
                    vpHelper.Name = $"{outputVp.Name} Helper";
                    // vpHelper.AdditionalProperties["Target"] = outputVp.Id; // makes interface too messy
                    model.AddElement(vpHelper);

                    vpIndex += 1;
                }

                var sumScores           = vantagePoints.Aggregate(0.0, (sum, vp) => sum + vp.Diagram.DaylightScore);
                var vantageStreetScore  = sumScores / vantagePoints.Count;
                var vantageStreetLength = outputVantageStreet.FrontLotLine.Length();

                streetScores.Add(vantageStreetScore);
                streetLengths            += vantageStreetLength;
                streetScoresTimesLengths += vantageStreetScore * vantageStreetLength;

                outputVantageStreet.Score = vantageStreetScore;
                model.AddElement(outputVantageStreet);

                vsIndex += 1;
            }

            var lowestStreetScore = new List <double>(streetScores).OrderBy(score => score).ToList()[0];
            var overallScore      = streetScoresTimesLengths / streetLengths;

            var pass = true;

            if (lowestStreetScore < 66)
            {
                pass = false;
            }
            if (!input.QualifyForEastMidtownSubdistrict && overallScore < 75)
            {
                pass = false;
            }
            if (input.QualifyForEastMidtownSubdistrict && overallScore < 66)
            {
                pass = false;
            }

            Console.WriteLine($"LOWEST SCORE: {lowestStreetScore}");
            Console.WriteLine($"TOTAL SCORE: {overallScore}");

            var output = new NYCZR8127DaylightEvaluationOutputs(lowestStreetScore, overallScore, pass ? "PASS" : "FAIL");

            output.Model = model;

            return(output);
        }