Example #1
0
        /// <summary>
        /// Encodes a coordinate on the sphere to the corresponding icosahedral face and
        /// containing 2D hex coordinates relative to that face center.
        /// </summary>
        /// <param name="g">The spherical coordinates to encode.</param>
        /// <param name="res">The desired H3 resolution for the encoding.</param>
        /// <param name="face">The icosahedral face containing the spherical coordinates.</param>
        /// <param name="v">The 2D hex coordinates of the cell containing the point.</param>
        /// <!-- Based off 3.1.1 -->
        public static void _geoToHex2d(GeoCoord g, int res, ref int face, ref Vec2d v)
        {
            Vec3d v3d = new Vec3d();

            Vec3d._geoToVec3d(g, ref v3d);

            // determine the icosahedron face
            face = 0;
            double sqd = Vec3d._pointSquareDist(faceCenterPoint[0], v3d);

            for (int f = 1; f < Constants.NUM_ICOSA_FACES; f++)
            {
                double sqdT = Vec3d._pointSquareDist(faceCenterPoint[f], v3d);
                if (sqdT < sqd)
                {
                    face = f;
                    sqd  = sqdT;
                }
            }

            // cos(r) = 1 - 2 * sin^2(r/2) = 1 - 2 * (sqd / 4) = 1 - sqd/2
            double r = Math.Acos(1 - sqd / 2);

            if (r < Constants.EPSILON)
            {
                v.x = 0.0;
                v.y = 0.0;
                return;
            }

            // now have face and r, now find CCW theta from CII i-axis
            double theta =
                GeoCoord._posAngleRads(faceAxesAzRadsCII[face, 0] -
                                       GeoCoord._posAngleRads(GeoCoord._geoAzimuthRads(faceCenterGeo[face], g)));

            // adjust theta for Class III (odd resolutions)
            if (H3Index.isResClassIII(res))
            {
                theta = GeoCoord._posAngleRads(theta - Constants.M_AP7_ROT_RADS);
            }

            // perform gnomonic scaling of r
            r = Math.Tan(r);

            // scale for current resolution length u
            r /= Constants.RES0_U_GNOMONIC;
            for (int i = 0; i < res; i++)
            {
                r *= M_SQRT7;
            }

            // we now have (r, theta) in hex2d with theta ccw from x-axes

            // convert to local x,y
            v.x = r * Math.Cos(theta);
            v.y = r * Math.Sin(theta);
        }
Example #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>
        /// <param name="g">The spherical coordinates of the cell center point.</param>
        /// <!-- Based off 3.1.1 -->
        public static void _hex2dToGeo(ref Vec2d v, int face, int res, int substrate, ref GeoCoord g)
        {
            // calculate (r, theta) in hex2d
            double r = Vec2d._v2dMag(v);

            if (r < Constants.EPSILON)
            {
                g = faceCenterGeo[face];
                return;
            }

            double theta = Math.Atan2(v.y, v.x);

            // scale for current resolution length u
            for (int i = 0; i < res; i++)
            {
                r /= M_SQRT7;
            }

            // scale accordingly if this is a substrate grid
            if (substrate > 0)
            {
                r /= 3.0;
                if (H3Index.isResClassIII(res))
                {
                    r /= M_SQRT7;
                }
            }

            r *= Constants.RES0_U_GNOMONIC;

            // perform inverse gnomonic scaling of r
            r = Math.Atan(r);

            // adjust theta for Class III
            // if a substrate grid, then it's already been adjusted for Class III
            if (substrate == 0 && H3Index.isResClassIII(res))
            {
                theta = GeoCoord._posAngleRads(theta + Constants.M_AP7_ROT_RADS);
            }

            // find theta as an azimuth
            theta = GeoCoord._posAngleRads(faceAxesAzRadsCII[face, 0] - theta);

            // now find the point at (r,theta) from the face center
            GeoCoord._geoAzDistanceRads(ref faceCenterGeo[face], theta, r, ref g);
        }