现在的位置: 首页 > 综合 > 正文

墨卡托投影 google 地图

2012年12月22日 ⁄ 综合 ⁄ 共 7915字 ⁄ 字号 评论关闭

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Windows.Forms;

namespace gmap_tool
{
    public partial class gmaptoolMainForm : Form
    {
        public gmaptoolMainForm()
        {
            InitializeComponent();
        }//

    //    /**
    //     * 取GE image url
    //     * @param int intZoom 倍数
    //     * @param double douLongitudeX 经度
    //     * @param double douLatitudeY 纬度
    //     */
    //    public static String getImageURL(int intZoom, double douLongitudeX, double douLatitudeY)
    //{
    //    StringBuffer sbURL = new StringBuffer();
    //    StringBuffer sbT = new StringBuffer("t");

    //    int intX = 0;
    //    int intY = 0;
    //    int intWidthX = 180;
    //    int intHeigthY = 180;

    //    for (int i = 1; i < intZoom; i++)
    //    {
    //        if (douLongitudeX >= intX && douLatitudeY >= intY) //右上位置
    //        {
    //            sbT.append("r");
    //            //设置下一层坐标点位置
    //            intX = intX + intWidthX / 2;
    //            intY = intY + intHeigthY / 2;
    //        }
    //        else if (douLongitudeX >= intX && douLatitudeY < intY) //右下位置
    //        {
    //            sbT.append("s");
    //            intX = intX + intWidthX / 2;
    //            intY = intY - intHeigthY / 2;
    //        }
    //        else if (douLongitudeX < intX && douLatitudeY < intY) //左下位置
    //        {
    //            sbT.append("t");
    //            intX = intX - intWidthX / 2;
    //            intY = intY - intHeigthY / 2;
    //        }
    //        else //左上位置
    //        {
    //            sbT.append("q");
    //            intX = intX - intWidthX / 2;
    //            intY = intY + intHeigthY / 2;
    //        }
           
    //        intWidthX = intWidthX / 2;
    //        intHeigthY = intHeigthY / 2;
    //    }

    //    sbURL.append("http://kh.google.com/kh?v=3&t=";).append(sbT);
    //    return sbURL.toString();
    //}

        /**
         * 取GE image url
         * @param int intZoom 倍数
         * @param double douLongitudeX 经度
         * @param double douLatitudeY 纬度
         */
        public static String getImageURL(int intZoom, double douLongitudeX, double douLatitudeY)
        {
            StringBuilder sbURL = new StringBuilder();
            StringBuilder sbT = new StringBuilder("t");

            int intX = 0;
            int intY = 0;
            int intWidthX = 180;
            int intHeigthY = 180;

            for (int i = 1; i < intZoom; i++)
            {
                if (douLongitudeX >= intX && douLatitudeY >= intY) //右上位置
                {
                    sbT.Append("r");
                    //设置下一层坐标点位置
                    intX = intX + intWidthX / 2;
                    intY = intY + intHeigthY / 2;
                }
                else if (douLongitudeX >= intX && douLatitudeY < intY) //右下位置
                {
                    sbT.Append("s");
                    intX = intX + intWidthX / 2;
                    intY = intY - intHeigthY / 2;
                }
                else if (douLongitudeX < intX && douLatitudeY < intY) //左下位置
                {
                    sbT.Append("t");
                    intX = intX - intWidthX / 2;
                    intY = intY - intHeigthY / 2;
                }
                else //左上位置
                {
                    sbT.Append("q");
                    intX = intX - intWidthX / 2;
                    intY = intY + intHeigthY / 2;
                }
               
                intWidthX = intWidthX / 2;
                intHeigthY = intHeigthY / 2;
            }

            //sbURL.Append("http://kh.google.com/kh?v=3&t=";).Append(sbT);
            sbURL.Append("http://kh.google.com/kh?v=3&t=").Append(sbT);
            //sbURL.Append("http://kh.google.com/kh?v=3&t=";);
            //sbURL.Append(sbT);
            return sbURL.ToString();
        }//

        /**<summary>此函数取得相应纬度对应的瓦片纵轴序号,参数为纬度</summary>*/
        static private int getMercatorLatitude(double lati, int zoom)
        {
            double maxlat = Math.PI;

            double lat = lati;

            if (lat > 90) lat = lat - 180;
            if (lat < -90) lat = lat + 180;

            // conversion degre=>radians
            // 转换度数到弧度
            double phi = Math.PI * lat / 180;

            double res;
            //网上其他帖子这个地方有问题,应该为加号
            //double temp = Math.Tan(Math.PI / 4 phi / 2);
            //res = Math.Log(temp);
            //下面这一句是上面的合并
            res = 0.5 * Math.Log((1 + Math.Sin(phi)) / (1 - Math.Sin(phi)));
            double maxTileY = Math.Pow(2, zoom);
            int result = (int)(((1 - res / maxlat) / 2) * (maxTileY));

            return (result);
        }

        static double get1(double lat, int intZoom)
        {
            //my = math.log(math.tan((90 + lat) * pi_val / 360.0)) / (pi_val / 180.0)
            //my = my * origin_shift / 180.0

            double pi_val = Math.PI;
            double my = Math.Log(Math.Tan((90 + lat) * pi_val / 360.0)) / (pi_val / 180.0);
            //my = my * origin_shift / 180.0

            int count = (int)Math.Pow(2, intZoom);
            my = my * count / 180.0;

            return my;

        }

        //墨卡托投影
        //百度地图和Google Maps使用的投影方法都是墨卡托投影。
        //经过墨卡托投影后的经线是均匀分布,在此主要介绍纬度的变换方法。
        //墨卡托投影把纬度为Φ (-90°<Φ<90°)的点投影到
        //y = ln(tan(45° + Φ/2))
        //这种投影算法使得赤道附近的纬线较密,极地附近的纬线较稀。极点被投影到无穷远,所以这种投影不适合在高纬度地区使用。Google Maps的选取的范围为 -π<y<π ,这样近似的有 -85°<Φ<85°
        //以上知识即可实现编程转换。

        static double get2(double lat, int intZoom)
        {
            double y = Math.Log(Math.Tan(45 + lat/2));

            return y;
        }

        //原有的方法已经失效了
        public static String getImageURL_new(int intZoom, double douLongitudeX, double douLatitudeY)
        {
            StringBuilder sbURL = new StringBuilder();
            StringBuilder sbT = new StringBuilder("t");

            //double m = Math.Pow(y, x);
            //Console.WriteLine(y + "的" + x + "的次方是" + m);

            int count = (int)Math.Pow(2, 0);

            count = (int)Math.Pow(2, intZoom);

            //count 是按次方将地球的经纬分成了多少块

            double lon_one = (double)(360) / count;//当前 zoom 下一块地图占多少经度
            double lat_one = (double)180 / count;//当前 zoom 下一块地图占多少纬度

            //--------------------------------------------------
            //起始经纬度是不对的,要重新计算
            douLongitudeX = douLongitudeX + 180;
//            douLatitudeY = 90 - douLatitudeY;//不对纬度的百分比不是这样算的,高纬度占的距离要大得多
            //墨卡托投影。由于在显示时使用了墨卡托投影,因此上述的算法需要进行修改。在墨卡托投影中,两条纬线间的距离不一定相等,所以描述tile的角度依据它的垂直位置。

            //--------------------------------------------------

            int x = (int)(douLongitudeX / lon_one);//当前地图分块索引
            int y = (int)(douLatitudeY / lat_one);//当前地图分块索引

            y = (int)Math.Ceiling(get2(douLatitudeY, intZoom));

            y = getMercatorLatitude(douLatitudeY, intZoom);
//            y = (int)Math.Ceiling(get1(douLatitudeY, intZoom));

            //x = (int)(douLongitudeX * count / 360);//当前地图分块索引
            //y = (int)(douLatitudeY / lat_one);//当前地图分块索引

            int intX = 0;
            int intY = 0;
            int intWidthX = 180;
            int intHeigthY = 180;

            for (int i = 1; i < intZoom; i++)
            {
                if (douLongitudeX >= intX && douLatitudeY >= intY) //右上位置
                {
                    sbT.Append("r");
                    //设置下一层坐标点位置
                    intX = intX + intWidthX / 2;
                    intY = intY + intHeigthY / 2;
                }
                else if (douLongitudeX >= intX && douLatitudeY < intY) //右下位置
                {
                    sbT.Append("s");
                    intX = intX + intWidthX / 2;
                    intY = intY - intHeigthY / 2;
                }
                else if (douLongitudeX < intX && douLatitudeY < intY) //左下位置
                {
                    sbT.Append("t");
                    intX = intX - intWidthX / 2;
                    intY = intY - intHeigthY / 2;
                }
                else //左上位置
                {
                    sbT.Append("q");
                    intX = intX - intWidthX / 2;
                    intY = intY + intHeigthY / 2;
                }

                intWidthX = intWidthX / 2;
                intHeigthY = intHeigthY / 2;
            }

            //sbURL.Append("http://kh.google.com/kh?v=3&t=";).Append(sbT);
            //sbURL.Append("http://kh.google.com/kh?v=3&t=").Append(sbT);
            //sbURL.Append("http://kh.google.com/kh?v=3&t=";);
            //sbURL.Append(sbT);

            //http://mt0.google.cn/vt/hl=zh-CN&gl=cn&x=13127&y=7163&z=14&s=

            string s = "http://mt0.google.cn/vt/lyrs=m@121&hl=zh-CN&gl=cn&x="+x+"&y="+y+"&z="+intZoom+"&s=";

            return s;// sbURL.ToString();
        }//

        private void btnGetGMapUrl_Click(object sender, EventArgs e)
        {
            string url = getImageURL(15, Convert.ToDouble(txtLon.Text), Convert.ToDouble(txtLat.Text));
            url = getImageURL_new(Convert.ToInt32(txtZoom.Text), Convert.ToDouble(txtLon.Text), Convert.ToDouble(txtLat.Text));
            txtGMapUrl.Text = url;
            webBrowser_GMapUrl.Navigate(url);
        }

        private void btnGo_Click(object sender, EventArgs e)
        {

            webBrowser_GMapUrl.Navigate(txtGMapUrl.Text);
        }//
    }//
}//

抱歉!评论已关闭.