Пример #1
0
        /// <summary>
        /// Surface area in radians^2 of spherical triangle on unit sphere.
        ///
        /// For the math, see:
        /// https://en.wikipedia.org/wiki/Spherical_trigonometry#Area_and_spherical_excess
        /// </summary>
        /// <param name="a">length of triangle side A in radians</param>
        /// <param name="b">length of triangle side B in radians</param>
        /// <param name="c">length of triangle side C in radians</param>
        /// <returns>area in radians^2 of triangle on unit sphere</returns>
        /// <!--
        /// geoCoord.c
        /// double triangleEdgeLengthsToArea
        /// -->
        private static decimal TriangleEdgeLengthToArea(decimal a, decimal b, decimal c)
        {
            decimal s = (a + b + c) / 2;

            a  = (s - a) / 2;
            b  = (s - b) / 2;
            c  = (s - c) / 2;
            s /= 2;

            return(4 * DecimalEx.ATan
                       (DecimalEx.Sqrt(DecimalEx.Tan(s) *
                                       DecimalEx.Tan(a) *
                                       DecimalEx.Tan(b) *
                                       DecimalEx.Tan(c))));
        }
Пример #2
0
        /// <summary>
        /// Determines the center point in spherical coordinates of a cell given by 2D
        /// hex coordinates on a particular icosahedral face.
        /// </summary>
        /// <param name="v">The 2D hex coordinates of the cell</param>
        /// <param name="face">The icosahedral face upon which the 2D hex coordinate system is centered</param>
        /// <param name="res">The H3 resolution of the cell</param>
        /// <param name="substrate">
        /// Indicates whether or not this grid is actually a substrate
        /// grid relative to the specified resolution.
        /// </param>
        /// <returns>The spherical coordinates of the cell center point</returns>
        /// <!--
        /// faceIjk.c
        /// void _hex2dToGeo
        /// -->
        public static GeoCoord ToGeoCoord(this Vec2d v, int face, int res, int substrate)
        {
            // calculate (r, theta) in hex2d
            decimal r          = v.Magnitude;
            bool    bSubstrate = substrate != 0;

            if (r < Constants.H3.EPSILON)
            {
                return(Constants.FaceIjk.FaceCenterGeo[face]);
            }

            decimal theta = DecimalEx.ATan2(v.Y, v.X);

            // scale for current resolution length u
            for (var i = 0; i < res; i++)
            {
                r /= Constants.FaceIjk.MSqrt7;
            }

            // scale accordingly if this is a substrate grid
            if (substrate != 0)
            {
                r /= 3.0m;
                if (res.IsResClassIii())
                {
                    r /= Constants.FaceIjk.MSqrt7;
                }
            }

            r *= Constants.H3.RES0_U_GNOMONIC;

            // perform inverse gnomonic scaling of r
            r = DecimalEx.ATan(r);

            // adjust theta for Class III
            // if a substrate grid, then it's already been adjusted for Class III
            if (!bSubstrate && res.IsResClassIii())
            {
                theta = (theta + Constants.H3.M_AP7_ROT_RADS).NormalizeRadians();
            }

            // find theta as an azimuth
            theta = (Constants.FaceIjk.FaceAxesAzRadsCii[face, 0] - theta).NormalizeRadians();

            // now find the point at (r,theta) from the face center
            return(Constants.FaceIjk.FaceCenterGeo[face]
                   .GetAzimuthDistancePoint(theta, r));
        }
Пример #3
0
 public void Test(decimal d, decimal expected, decimal tolerance)
 {
     tolerance = Helper.GetScaledTolerance(expected, (int)tolerance, true);
     Assert.That(DecimalEx.ATan(d), Is.EqualTo(expected).Within(tolerance));
 }