< Summary

Information
Class: Morpho25.Utility.EnvimetUtility
Assembly: Morpho25
File(s): D:\a\Morpho\Morpho\project\Morpho\Morpho25\Utility\EnvimetUtility.cs
Line coverage
0%
Covered lines: 0
Uncovered lines: 110
Coverable lines: 110
Total lines: 218
Line coverage: 0%
Branch coverage
0%
Covered branches: 0
Total branches: 22
Branch coverage: 0%
Method coverage

Feature is only available for sponsors

Upgrade to PRO version

Metrics

MethodBranch coverage Cyclomatic complexity Line coverage
Raycasting2D(...)0%40%
Raycasting3D(...)100%10%
GetCentroids(...)0%40%
GetStringRows()0%80%
ToPixel(...)100%10%
GetRayFromFacegroupBbox(...)0%40%
GetASCIImatrix(...)0%40%
GetAtmosphereSpecificHumidity(...)100%10%

File(s)

D:\a\Morpho\Morpho\project\Morpho\Morpho25\Utility\EnvimetUtility.cs

#LineLine coverage
 1using System;
 2using System.Linq;
 3using System.Collections.Generic;
 4using MorphoGeometry;
 5using Morpho25.Geometry;
 6
 7namespace Morpho25.Utility
 8{
 9    /// <summary>
 10    /// Envimet utility class.
 11    /// </summary>
 12    public static class EnvimetUtility
 13    {
 14        /// <summary>
 15        /// Raycasting 2D between facegroup <> rays.
 16        /// </summary>
 17        /// <param name="rays">Rays.</param>
 18        /// <param name="facegroup">Facegroup to hit.</param>
 19        /// <param name="reverse">True to reverse faces of Facegroup.</param>
 20        /// <param name="project">True to project intersections to plane.</param>
 21        /// <returns>Intersection points.</returns>
 22        public static IEnumerable<Vector> Raycasting2D(List<Ray> rays,
 23            FaceGroup facegroup, bool reverse = false,
 24            bool project = false)
 025        {
 026            var intersections = Intersection.RaysFaceGroupIntersect(rays, facegroup,
 027                Intersection.RayFaceIntersect,
 028                reverse, project);
 29            // Clean duplicates
 030            var groups = intersections
 031                .GroupBy(_ => new { x = _.x, y = _.y, })
 032                .ToList();
 33
 034            var pts = new List<Vector>();
 035            foreach (var group in groups)
 036            {
 037                var vectors = group.OrderBy(_ => _.z);
 038                if (reverse)
 039                {
 040                    pts.Add(vectors.Last());
 041                }
 42                else
 043                {
 044                    pts.Add(vectors.First());
 045                }
 046            }
 047            return pts;
 048        }
 49
 50        /// <summary>
 51        /// Raycasting 3D between facegroup <> rays.
 52        /// </summary>
 53        /// <param name="rays">Rays.</param>
 54        /// <param name="facegroup">Facegroup to hit.</param>
 55        /// <param name="reverse">True to reverse faces of Facegroup.</param>
 56        /// <param name="project">True to project intersections to plane.</param>
 57        /// <returns>Intersection points.</returns>
 58        public static IEnumerable<Vector> Raycasting3D(List<Ray> rays,
 59            FaceGroup facegroup, bool reverse = false,
 60            bool project = false)
 061        {
 062            return Intersection.RaysFaceGroupIntersect(rays, facegroup,
 063                Intersection.RayFaceIntersectFrontBack,
 064                reverse, project);
 065        }
 66
 67        /// <summary>
 68        /// Get voxel centroids.
 69        /// </summary>
 70        /// <param name="grid">Grid to use as a guide.</param>
 71        /// <param name="intersections">Intersection points from raycasting.</param>
 72        /// <returns>Voxel centroids.</returns>
 73        public static IEnumerable<Vector> GetCentroids(Grid grid,
 74            IEnumerable<Vector> intersections)
 075        {
 076            var groups = intersections
 077                .GroupBy(_ => new { x = _.x, y = _.y, })
 078                .ToList();
 79
 080            var centroids = new List<Vector>();
 081            foreach (var group in groups)
 082            {
 083                var sortGroup = group.OrderBy(_ => _.z);
 084                var chunks = sortGroup.ToList().ChunkBy(2);
 085                foreach (var pts in chunks)
 086                {
 087                    var heights = pts.Select(_ => _.z);
 088                    var min = heights.Min();
 089                    var max = heights.Max();
 90
 091                    var zCoords = Util.FilterByMinMax(grid.Zaxis, max, min);
 092                    var voxels = zCoords.Select(_ => new Vector(pts[0].x, pts[0].y, Convert.ToSingle(_)));
 93
 094                    centroids.AddRange(voxels);
 095                }
 096            }
 97
 098            return centroids;
 099        }
 100
 101        /// <summary>
 102        /// Get rows for 3D part of envimet.
 103        /// </summary>
 104        /// <param name="matrix">Matrix to wrap.</param>
 105        /// <returns></returns>
 106        public static IEnumerable<string> GetStringRows(Matrix3d<string[]> matrix)
 0107        {
 0108            for (int k = 0; k < matrix.GetLengthZ(); k++)
 0109                for (int j = 0; j < matrix.GetLengthY(); j++)
 0110                    for (int i = 0; i < matrix.GetLengthX(); i++)
 0111                    {
 0112                        if (matrix[i, j, k].Count(_ => _ == null) < 3)
 0113                        {
 0114                            var value = string.Join(",", matrix[i, j, k]);
 0115                            yield return String.Format("{0},{1},{2},{3}", i, j, k, value);
 0116                        }
 0117                    }
 0118        }
 119
 120        /// <summary>
 121        /// Convert vector to pixel.
 122        /// </summary>
 123        /// <param name="vector">Vector.</param>
 124        /// <param name="grid">Grid to use for mapping.</param>
 125        /// <returns>Pixel.</returns>
 126        public static Pixel ToPixel(this Vector vector, Grid grid)
 0127        {
 0128            int i = Util.ClosestValue(grid.Xaxis, vector.x);
 0129            int j = Util.ClosestValue(grid.Yaxis, vector.y);
 0130            int k = Util.ClosestValue(grid.Zaxis, vector.z);
 0131            return new Pixel(i, j, k);
 0132        }
 133
 134        /// <summary>
 135        /// Get minimum rays from Facegroup's boundary box.
 136        /// </summary>
 137        /// <param name="grid">Grid to use for mapping.</param>
 138        /// <param name="facegroup">Facegroup to use for
 139        /// the boundary box.</param>
 140        /// <returns>Rays.</returns>
 141        public static List<Ray> GetRayFromFacegroupBbox(Grid grid,
 142            FaceGroup facegroup)
 0143        {
 0144            BoundaryBox box = new BoundaryBox(facegroup);
 145
 0146            Vector minPt = box.MinPoint;
 0147            Vector maxPt = box.MaxPoint;
 148
 0149            var rayXcomponent = Util.FilterByMinMax(grid.Xaxis,
 0150                maxPt.x, minPt.x);
 0151            var rayYcomponent = Util.FilterByMinMax(grid.Yaxis,
 0152                maxPt.y, minPt.y);
 153
 0154            List<Ray> rays = new List<Ray>();
 0155            foreach (double y in rayYcomponent)
 0156                foreach (double x in rayXcomponent)
 0157                {
 0158                    rays.Add(new Ray(new Vector(
 0159                        (float)x, (float)y, 0),
 0160                        new Vector(0, 0, 1)));
 0161                }
 162
 0163            return rays;
 0164        }
 165
 166        /// <summary>
 167        /// Get ASCII matrix from Matrix 2D.
 168        /// </summary>
 169        /// <param name="matrix">Matrix 2D to use.</param>
 170        /// <returns>ASCII matrix for envimet.</returns>
 171        public static string GetASCIImatrix(Matrix2d matrix)
 0172        {
 0173            string text = string.Empty;
 0174            List<string> rows = new List<string>();
 175
 0176            for (int j = matrix.GetLengthY() - 1; j >= 0; j--)
 0177            {
 0178                string[] line = new string[matrix.GetLengthX()];
 0179                for (int i = 0; i < matrix.GetLengthX(); i++)
 0180                {
 0181                    line[i] = matrix[i, j];
 0182                }
 0183                rows.Add(String.Join(",", line));
 0184            }
 0185            text = String.Join("\n", rows) + "\n";
 186
 0187            return text;
 0188        }
 189
 190        /// <summary>
 191        /// Calculate specific humidity of the atmosphere at 2500m.
 192        /// </summary>
 193        /// <param name="temperature">List of temperature
 194        /// values [°C].</param>
 195        /// <param name="relativeHumidity">List of relative
 196        /// humidity values [%].</param>
 197        /// <returns>Specific humidity at 2500m.</returns>
 198        public static double GetAtmosphereSpecificHumidity(List<double> temperature,
 199            List<double> relativeHumidity)
 0200        {
 201            const double AIR_PRESSURE = 1013.25;
 202
 0203            List<double> kelvinTemperature = temperature
 0204                .Select(_ => _ + Util.TO_KELVIN)
 0205                .ToList();
 206
 0207            double meanTemperature = kelvinTemperature.Average();
 0208            double meanRelativeHumidity = relativeHumidity.Average();
 209
 0210            double eSaturation = 0.6112 * Math.Exp(17.67 * (
 0211                meanTemperature - 273.15) / (meanTemperature - 29.66)) * 10;
 0212            double qSaturation = (0.6112 * (eSaturation / AIR_PRESSURE)) * 1000;
 0213            double specificHumidity = qSaturation * (meanRelativeHumidity / 100);
 214
 0215            return specificHumidity;
 0216        }
 217    }
 218}