Beispiel #1
0
        /// <summary>
        /// Determines the H3 digit corresponding to a unit vector in ijk coordinates.
        /// </summary>
        /// <param name="ijk">The ijk coordinates; must be a unit vector.</param>
        /// <returns>
        /// The H3 digit (0-6) corresponding to the ijk unit vector, or
        /// <see cref="Direction.INVALID_DIGIT"/> INVALID_DIGIT on failure
        /// </returns>
        /// <!--
        /// coordijk.c
        /// Direction _unitIjkToDigit
        /// -->
        internal static Direction ToDirection(this CoordIjk ijk)
        {
            var c    = ijk.Normalized();
            var test = Constants.CoordIjk.UnitVectors.Where(pair => pair.Value == c).ToList();

            return(test.Any()
                       ? test.First().Key
                       : Direction.INVALID_DIGIT);
        }
Beispiel #2
0
        /// <summary>
        /// Determine the containing hex in ijk+ coordinates for a 2D cartesian
        /// coordinate vector (from <a href="http://www.discreteglobalgrids.org/software/">DGGRID</a>).
        /// </summary>
        /// <param name="v">The 2D cartesian coordinate vector.</param>
        /// <!--
        /// coordijk.c
        /// void _hex2dToCoordIJK
        /// -->
        public static CoordIjk ToCoordIjk(this Vec2d v)
        {
            var h = new CoordIjk();

            // quantize into the ij system and then normalize
            decimal a1 = Math.Abs(v.X);
            decimal a2 = Math.Abs(v.Y);

            // first do a reverse conversion
            decimal x2 = a2 / Constants.H3.M_SIN60;
            decimal x1 = a1 + x2 / 2.0m;

            // check if we have the center of a hex
            var m1 = (int)x1;
            var m2 = (int)x2;

            // otherwise round correctly
            decimal r1 = x1 - m1;
            decimal r2 = x2 - m2;

            if (r1 < 0.5m)
            {
                if (r1 < 1.0m / 3.0m)
                {
                    h = r2 < (1.0m + r1) / 2.0m
                            ? h.SetIJ(m1, m2)
                            : h.SetIJ(m1, m2 + 1);
                }
                else
                {
                    h = r2 < (1.0m - r1)
                            ? h.SetJ(m2)
                            : h.SetJ(m2 + 1);

                    h = (1.0m - r1) <= r2 && r2 < (2.0m * r1)
                            ? h.SetI(m1 + 1)
                            : h.SetI(m1);
                }
            }
            else
            {
                if (r1 < 2.0m / 3.0m)
                {
                    h = r2 < (1.0m - r1)
                            ? h.SetJ(m2)
                            : h.SetJ(m2 + 1);

                    h = (2.0m * r1 - 1.0m) < r2 && r2 < (1.0m - r1)
                            ? h.SetI(m1)
                            : h.SetI(m1 + 1);
                }
                else
                {
                    h = r2 < (r1 / 2.0m)
                            ? h.SetIJ(m1 + 1, m2)
                            : h.SetIJ(m1 + 1, m2 + 1);
                }
            }

            // now fold across the axes if necessary
            if (v.X < 0.0m)
            {
                if (h.J % 2 == 0)  // even
                {
                    long axisI = (long)h.J / 2;
                    long diff  = h.I - axisI;
                    h = h.SetI(h.I - (int)(2.0 * diff));
                }
                else
                {
                    long axisI = (long)(h.J + 1) / 2;
                    long diff  = h.I - axisI;
                    h = h.SetI(h.I - (int)(2.0 * diff + 1));
                }
            }

            if (v.Y < 0.0m)
            {
                h = h.SetIJ(h.I - (2 * h.J + 1) / 2, -h.J);
            }

            return(h.Normalized());
        }