• GeoHash C#版 找到周围8个区域的GeoHash编码


    相信找到这里的 ,geohash算法原理及实现方式应该也有所了解了。原代码了出自
    邓星林博客
    http://www.cnblogs.com/dengxinglin/archive/2012/12/14/2817761.html
    自已找来,加上8个区的实现,加些注释和例子,测试已经ok。网上只有java版,这里让大家少起弯路

    using System;
    
    namespace sharonjl.utils
    {
        public static class Geohash
        {
            #region Direction enum
    
            public enum Direction
            {
                Top = 0,
                Right = 1,
                Bottom = 2,
                Left = 3 
            }
    
            #endregion
    
            private const string Base32 = "0123456789bcdefghjkmnpqrstuvwxyz";
            private static readonly int[] Bits = new[] {16, 8, 4, 2, 1};
    
            private static readonly string[][] Neighbors = {
                                                               new[]
                                                                   {
                                                                       "p0r21436x8zb9dcf5h7kjnmqesgutwvy", // Top
                                                                       "bc01fg45238967deuvhjyznpkmstqrwx", // Right
                                                                       "14365h7k9dcfesgujnmqp0r2twvyx8zb", // Bottom
                                                                       "238967debc01fg45kmstqrwxuvhjyznp", // Left
                                                                   }, new[]
                                                                          {
                                                                              "bc01fg45238967deuvhjyznpkmstqrwx", // Top
                                                                              "p0r21436x8zb9dcf5h7kjnmqesgutwvy", // Right
                                                                              "238967debc01fg45kmstqrwxuvhjyznp", // Bottom
                                                                              "14365h7k9dcfesgujnmqp0r2twvyx8zb", // Left
                                                                          }
                                                           };
    
            private static readonly string[][] Borders = {
                                                             new[] {"prxz", "bcfguvyz", "028b", "0145hjnp"},
                                                             new[] {"bcfguvyz", "prxz", "0145hjnp", "028b"}
                                                         };
            /// <summary>
            /// 计算相邻
            /// </summary>
            /// <param name="hash"></param>
            /// <param name="direction"></param>
            /// <returns></returns>
            public static String CalculateAdjacent(String hash, Direction direction)
            {
                hash = hash.ToLower();
    
                char lastChr = hash[hash.Length - 1];
                int type = hash.Length%2;
                var dir = (int) direction;
                string nHash = hash.Substring(0, hash.Length - 1);
    
                if (Borders[type][dir].IndexOf(lastChr) != -1)
                {
                    nHash = CalculateAdjacent(nHash, (Direction) dir);
                }
                return nHash + Base32[Neighbors[type][dir].IndexOf(lastChr)];
            }
            /// <summary>
            /// 细化间隔
            /// </summary>
            /// <param name="interval"></param>
            /// <param name="cd"></param>
            /// <param name="mask"></param>
            public static void RefineInterval(ref double[] interval, int cd, int mask)
            {
                if ((cd & mask) != 0)
                {
                    interval[0] = (interval[0] + interval[1])/2;
                }
                else
                {
                    interval[1] = (interval[0] + interval[1])/2;
                }
            }
    
            /// <summary>
            /// 解码
            /// </summary>
            /// <param name="geohash"></param>
            /// <returns></returns>
            public static double[] Decode(String geohash)
            {
                bool even = true;
                double[] lat = {-90.0, 90.0};
                double[] lon = {-180.0, 180.0};
    
                foreach (char c in geohash)
                {
                    int cd = Base32.IndexOf(c);
                    for (int j = 0; j < 5; j++)
                    {
                        int mask = Bits[j];
                        if (even)
                        {
                            RefineInterval(ref lon, cd, mask);
                        }
                        else
                        {
                            RefineInterval(ref lat, cd, mask);
                        }
                        even = !even;
                    }
                }
    
                return new[] {(lat[0] + lat[1])/2, (lon[0] + lon[1])/2};
            }
            /// <summary>
            /// 编码
            /// </summary>
            /// <param name="latitude">纬度</param>
            /// <param name="longitude">经度</param>
            /// <param name="precision">精度</param>
            /// <returns></returns>
            public static String Encode(double latitude, double longitude, int precision = 12)
            {
                bool even = true;
                int bit = 0;
                int ch = 0;
                string geohash = "";
    
                double[] lat = {-90.0, 90.0};
                double[] lon = {-180.0, 180.0};
    
                if (precision < 1 || precision > 20) precision = 12;
    
                while (geohash.Length < precision)
                {
                    double mid;
    
                    if (even)
                    {
                        mid = (lon[0] + lon[1])/2;
                        if (longitude > mid)
                        {
                            ch |= Bits[bit];
                            lon[0] = mid;
                        }
                        else
                            lon[1] = mid;
                    }
                    else
                    {
                        mid = (lat[0] + lat[1])/2;
                        if (latitude > mid)
                        {
                            ch |= Bits[bit];
                            lat[0] = mid;
                        }
                        else
                            lat[1] = mid;
                    }
    
                    even = !even;
                    if (bit < 4)
                        bit++;
                    else
                    {
                        geohash += Base32[ch];
                        bit = 0;
                        ch = 0;
                    }
                }
                return geohash;
            }
    
            /// <summary>
            /// 获取九个格子 顺序 本身 上、下、左、右、 左上、 右上、 左下、右下
            /// </summary>
            /// <param name="geohash"></param>
            /// <returns></returns>
            public static String[] getGeoHashExpand(String geohash)
            { 
            
            try {
                String geohashTop = CalculateAdjacent(geohash, Direction.Top);//
    
                String geohashBottom = CalculateAdjacent(geohash, Direction.Bottom);//
    
                String geohashLeft = CalculateAdjacent(geohash, Direction.Left);//
    
                String geohashRight = CalculateAdjacent(geohash, Direction.Right);//
    
    
                String geohashTopLeft = CalculateAdjacent(geohashLeft, Direction.Top);//左上
    
                String geohashTopRight = CalculateAdjacent(geohashRight, Direction.Top);//右上
    
                String geohashBottomLeft = CalculateAdjacent(geohashLeft, Direction.Bottom);//左下
    
                String geohashBottomRight = CalculateAdjacent(geohashRight, Direction.Bottom);//右下
    
                String[] expand = { geohash, geohashTop, geohashBottom, geohashLeft, geohashRight, geohashTopLeft, geohashTopRight,  geohashBottomLeft, geohashBottomRight};
                return expand;
            } catch (Exception e) {
                return null;
            }
            }
    
    
            ///// <summary>
            ///// test 
            ///// </summary>
            ///// <param name="args"></param>
            //public  void main()
            //{
            //    double lat = 39.90403;
            //    double lon = 116.407526; //需要查询经纬度,目前指向的是BeiJing
            //    string hash = Geohash.Encode(lat, lon);
            //    int geohashLen = 6;
            //    /*获取中心点的geohash*/
            //    String geohash = hash.Substring(0, geohashLen);
            //    /*获取所有的矩形geohash, 一共是九个 ,包含中心点,打印顺序请参考参数*/
            //    String[] result = Geohash.getGeoHashExpand(geohash);
            //}
        }
    }
  • 相关阅读:
    为什么全局变量一定要初始化?
    SecureCRT 使用密钥登录 Ubuntu
    ubuntu samba 服务器搭建
    Linux 软硬链接的区别及目录权限对软硬链接的影响
    【转载】解析 java 按值传递还是按引用传递
    (转)如何学好C语言
    (转)五个方法成为更好的程序员
    (转)SQLite数据库的加密
    鸟哥Linux私房菜(基础篇)——第十一章:认识与学习Bash
    鸟哥Linux私房菜(基础篇)——第五章:首次登入与在线求助 man page笔记
  • 原文地址:https://www.cnblogs.com/lucoo/p/5085986.html
Copyright © 2020-2023  润新知