坐标_坐标转换 - CSDN
精华内容
参与话题
  • 常用坐标系汇总(更新)

    万次阅读 2019-01-11 18:46:39
    前言 ...投影坐标系:墨卡托坐标系 地理坐标系:经纬度坐标系 常用坐标系 (一)WGS84坐标系     WGS-84坐标系(World Geodetic System一1984 Coordinate Sys...

    前言

        随着接触的地图种类越来越多,每种产品对地图服务的坐标系的要求不同,今天遇到了整理的好文,整理记录分享。

    • 投影坐标系:墨卡托坐标系
    • 地理坐标系:经纬度坐标系

    常用坐标系

    (一)WGS84坐标系

        WGS-84坐标系(World Geodetic System一1984 Coordinate System)

        一种国际上采用的地心坐标系。坐标原点为地球质心,其地心空间直角坐标系的Z轴指向BIH (国际时间服务机构)1984.O定义的协议地球极(CTP)方向,X轴指向BIH 1984.0的零子午面和CTP赤道的交点,Y轴与Z轴、X轴垂直构成右手坐标系,称为1984年世界大地坐标系统。
    在这里插入图片描述

    (二)WGS84 Web墨卡托

        Web墨卡托是2005年谷歌在谷歌地图中首次使用的,当时或更早的Web墨卡托使用者还是称其为世界墨卡托 World Mercator - Spherical Mercator (unofficial deprecated ESRI),代号 WKID 54004 (在 EPSG:54004 或 ESRI:54004 中,非官方)。

        在2006年,OSGeo在提出的 Tile Map Service (TMS) 标准中使用代号 OSGEO:41001,WGS84 / Simple Mercator - Spherical Mercator (unofficial deprecated OSGEO / Tile Map Service)。

        2007年8月6日 Christopher Schmidt (OpenLayers的重要贡献者之一)在通过一次GIS讨论中为了在OpenLayers中使用谷歌投影,提出给谷歌投影(Web墨卡托)使用一个统一的代号(已有如54004、41001之类的代号)900913(也形似 Google),并与同年9月11日在OpenLayers的OpenLayers/Layer/SphericalMercator.js中正式使用代号 900913。

        在2008年5月EPSG在6.15版本中正式(可能是谷歌地图取得了巨大成功)给谷歌地图投影赋予 CRS 代号 EPSG:3785(Popular Visualisation CRS / Mercator),这也是Web墨卡托正式被EPSG组织承认(由于Web墨卡托不是标准的地图投影,之前一直没有被EPSG没有收录)。

        很快EPSG于2009年2月9号使用新代号EPSG:3857 代替之前的 EPSG:3785,给谷歌地图投影方法命名为“公共可视化伪墨卡托投影”(PVPM),投影运算方法代号 1024。

        至今,EPSG:3857(WGS 84 / Pseudo-Mercator) 代号是web墨卡托的正式代号。

        在GIS界,离不开 ESRI,Web墨卡托的代号在 ESRI 中也有几个。最早在 ESRI 的软件中给Web墨卡托投影的称号为 102113(WGS 1984 Web Mercator),与 EPSG:3785 对应;后来使用 102100(WGS 1984 Web Mercator Auxiliary Sphere),与 EPSG:3857 对应。

        在 ArcGIS 10.0 版本中,ESRI 正式使用 EPSG:3857 替换之前的 EPSG:102100。

    总之,Web墨卡托现在的正式官方代号 EPSG:3857,同时 900913、3587、54004、41001、102113、102100 和 3785 等也是指Web墨卡托,虽然他们的具体定义会有一些差别,但他们在数学上是相等的。

        Web墨卡托取得了巨大成功,如今主流的Web地图几乎都是使用的Web墨卡托,如国外的 Google Maps,OpenStreetMap,Bing Map,ArcGIS 和 Heremaps 等,国内的百度地图、高德地图、腾讯地图和天地图等也是基于Web墨卡托(由于国内政策的原因,国内地图会有加密要求,一般有两种情况,一种是在 Web墨卡托的基础上经过国家标准加密的国标02坐标系,熟称“火星坐标系”;另一种是在国标的02坐标系下进一步进行加密,如百度地图的BD09坐标系)。

    在这里插入图片描述

    (三)GCJ02经纬度投影

        GCJ-02是由中国国家测绘局(G表示Guojia国家,C表示Cehui测绘,J表示Ju局)制订的地理信息系统的坐标系统。

        它其实就是对真实坐标系统进行人为的加偏处理,按照特殊的算法,将真实的坐标加密成虚假的坐标,而这个加偏并不是线性的加偏,所以各地的偏移情况都会有所不同。而加密后的坐标也常被大家称为“火星坐标系统”。

        该坐标系的坐标值为经纬度格式,单位为度。

        这里的GCJ02经纬度投影,也就是在WGS84经纬度的基础之上,进行GCJ-02加偏。

    (四)GCJ02 Web 墨卡托投影

        GCJ-02是由中国国家测绘局(G表示Guojia国家,C表示Cehui测绘,J表示Ju局)制订的地理信息系统的坐标系统。

        它其实就是对真实坐标系统进行人为的加偏处理,按照特殊的算法,将真实的坐标加密成虚假的坐标,而这个加偏并不是线性的加偏,所以各地的偏移情况都会有所不同。而加密后的坐标也常被大家称为“火星坐标系统”。

        该坐标系的坐标值为Web墨卡托格式,单位为米。

        这里的GCJ02 Web 墨卡托,也就是在标准Web默卡托的基础之上,进行GCJ-02加偏。

    (五)BD09 经纬度投影

        BD09经纬度投影属于百度坐标系,它是在标准经纬度的基础上进行GCJ-02加偏之后,再加上百度自身的加偏算法,也就是在标准经纬度的基础之上进行了两次加偏。

        该坐标系的坐标值为经纬度格式,单位为度。

    (六)BD09 Web 墨卡托影

        BD09 Web 墨卡托属于百度坐标系,它是在标准Web墨卡托的基础上进行GCJ-02加偏之后,再加上百度自身的加偏算法,也就是在Web墨卡托的基础之上进行了两次加偏。

        该坐标系的坐标值为Web墨卡托格式,单位为米。

    (七)北京54坐标系

        中国成立以后,我国大地测量进入了全面发展时期,在全国范围内开展了正规的,全面的大地测量和测图工作,迫切需要建立一个参心大地坐标系。由于当时的"一边倒"政治趋向,故我国采用了前苏联的克拉索夫斯基椭球参数,并与前苏联1942年坐标系进行联测,通过计算建立了我国大地坐标系,定名为1954年北京坐标系。因此,1954年北京坐标系可以认为是前苏联1942年坐标系的延伸。T.A的原点不在北京而是在前苏联的普尔科沃。

        自北京54坐标系统建立以来,在该坐标系内进行了许多地区的局部平差,其成果得到了广泛的应用。但是随着测绘新理论·新技术的不断发展,人们发现该坐标系存在很多缺点,为此,我国在1978年在西安召开了"全国天文大地网整体平差会议",提出了建立属于我国自己的大地坐标系,即后来的1980西安坐标系。

    (八)西安80坐标系

        1978年4月在西安召开全国天文大地网平差会议,确定重新定位,建立我国新的坐标系。为此有了1980年国家大地坐标系。1980年国家大地坐标系采用地球椭球基本参数为1975年国际大地测量与地球物理联合会第十六届大会推荐的数据,即IAG 75地球椭球体。该坐标系的大地原点设在我国中部的陕西省泾阳县永乐镇,位于西安市西北方向约60公里。

    (九)CGCS2000坐标系

        2000中国大地坐标系(China Geodetic Coordinate System 2000,CGCS2000),又称之为2000国家大地坐标系,是中国新一代大地坐标系,21世纪初已在中国正式实施。

        20世纪50年代,为满足测绘工作的迫切需要,中国采用了1954年北京坐标系。1954年之后,随着天文大地网布设任务的完成,通过天文大地网整体平差,于20世纪80年代初中国又建立了1980西安坐标系。1954北京坐标系和1980西安坐标系在中国的经济建设和国防建设中发挥了巨大作用。

        随着情况的变化和时间的推移,上述两个以经典测量技术为基础的局部大地坐标系,已经不能适应科学技术特别是空间技术发展,不能适应中国经济建设和国防建设需要。中国大地坐标系的更新换代,是经济建设、国防建设、社会发展和科技发展的客观需要。

        以地球质量中心为原点的地心大地坐标系,是21世纪空间时代全球通用的基本大地坐标系。以空间技术为基础的地心大地坐标系,是中国新一代大地坐标系的适宜选择。地心大地坐标系可以满足大地测量、地球物理、天文、导航和航天应用以及经济、社会发展的广泛需求。历经多年,中国测绘、地震部门和科学院有关单位为建立中国新一代大地坐标系作了大量基础性工作,20世纪末先后建成全国 GPS一、二级网,国家GPS A、B级网,中国地壳运动观测网络和许多地壳形变网,为地心大地坐标系的实现奠定了较好的基础。中国大地坐标系更新换代的条件也已具备。

    参考:https://blog.csdn.net/mrib/article/details/77944532

    展开全文
  • 三维模型(X,Y,Z)坐标,UV坐标

    万次阅读 2018-12-29 17:12:23
    对于三维模型,有两个最重要的坐标系统,一是顶点的位置(X,Y,Z)坐标,另一个就是UV坐标。什么是UV?简单的说,就是贴图影射到模型表面的依据。 完整的说,其实应该是UVW(因为XYZ已经用过了,所以另选三个字母...

    1.什么是UV?  


    对于三维模型,有两个最重要的坐标系统,一是顶点的位置(X,Y,Z)坐标,另一个就是UV坐标。什么是UV?简单的说,就是贴图影射到模型表面的依据。 完整的说,其实应该是UVW(因为XYZ已经用过了,所以另选三个字母表示)。U和V分别是图片在显示器水平、垂直方向上的坐标,取值一般都是0~1,也 就是(水平方向的第U个像素/图片宽度,垂直方向的第V个像素/图片高度)。那W呢?贴图是二维的,何来三个坐标?嗯嗯,W的方向垂直于显示器表面,一般 用于程序贴图或者某些3D贴图技术(记住,确实有三维贴图这种概念!),对于游戏而言不常用到,所以一般我们就简称UV了。

    所有的图象文件都是二维的一个平面。水平方向是U,垂直方向是V,通过这个平面的,二维的UV坐标系。我们可以定位图象上的任意一个象素。但是一个问题是如何把这个二维的平面贴到三维的NURBS表面和多边形表面呢? 对于NURBS表面。由于他本身具有UV参数,尽管这个UV值是用来定位表面上的点的参数,但由于它也是二维的,所以很容易通过换算把表面上的点和平面图象上的象素对应起来。所以把图象贴带NURBS是很直接的一件事。但是对于多变形模型来讲,贴图就变成一件麻烦的事了。所以多边形为了贴图就额外引进了一个UV坐标,以便把多边形的顶点和图象文件上的象素对应起来,这样才能在多边形表面上定位纹理贴图。所以说多边形的顶点除了具有三维的空间坐标外。还具有二维的UV坐标。  

    UV" 这里是指u,v纹理贴图坐标的简称(它和空间模型的X, Y, Z轴是类似的). 它定义了图片上每个点的位置的信息. 这些点与3D模型是相互联系的, 以决定表面纹理贴图的位置. UV就是将图像上每一个点精确对应到模型物体的表面. 在点与点之间的间隙位置由软件进行图像光滑插值处理. 这就是所谓的UV贴图.  
    那为什么用UV坐标而不是标准的投影坐标呢? 通常给物体纹理贴图最标准的方法就是以planar(平面),cylindrical(圆柱), spherical(球形),cubic(方盒)坐标方式投影贴图.  
    Planar projection(平面投影方式)是将图像沿x,y或z轴直接投影到物体. 这种方法使用于纸张, 布告, 书的封面等 - 也就是表面平整的物体.平面投影的缺点是如果表面不平整, 或者物体边缘弯曲, 就会产生如图A的不理想接缝和变形. 避免这种情况需要创建带有alpha通道的图像, 来掩盖临近的平面投影接缝, 而这会是非常烦琐的工作. 所以不要对有较大厚度的物体和不平整的表面运用平面投影方式. 对于立方体可以在x, y方向分别进行平面投影, 但是要注意边缘接缝的融合. 或者采用无缝连续的纹理, 并使用cubic投影方式. 多数软件有图片自动缩放功能, 使图像与表面吻合. 显然, 如果你的图像与表面形状不同, 自动缩放就会改变图像的比例以吻合表面. 这通常会产生不理想的效果, 所以制作贴图前先测量你的物体尺寸.

    2、uv纹理坐标设定与贴图规则  

    当opengl对一个四方形进行贴图时,会定义纹理贴图坐标,一串数组,相信初学openggl es者看到后会很头疼,不知道写得是什么东西。现在就将我的研究成果与大家分享下!

    当纹理映射启动后绘图时,你必须为OpenGL ES提供其他数据,即顶点数组中各顶点的纹理坐标。纹理坐标定义了图像的哪一部分将被映射到多边形。它的工作方式有点奇怪。 

    下面看下在android平台下Opengl纹理系统坐标,左下角为原点。

    我们现在讨论怎样使用这些纹理坐标。当我们指定顶点数组中的顶点时,我们需要在另一个数组中提供纹理坐标,它称为纹理坐标数组。这里需要注意定义坐标数组顺序,这很关键。

     

     

     

    float texCoords[] = new float[] {
            // FRONT
            0.0f, 0.0f,
            1.0f, 0.0f,
            0.0f, 1.0f,
            1.0f, 1.0f,
      };

    效果如下:

     

    如果我们想截取图片有上角不分做纹理,按照上面方法可获的数组

    float texCoords[] = new float[] {
       // FRONT
               0.5f, 0.5f,
              1f, 0.5f,
              0.5f, 1f,
              1f, 1f
      };

    效果如下:

     

     

    我们看下贴图的原始文件

    你会发现截屏中的图片y轴是颠倒的,其实这是android图像坐标系统与Opengl es 坐标系统不一致导致的。最简单的修正办法将原始图片用工具翻转过来,这样会比用程序翻转节省很多性能,资源是宝贵的。

    三角形纹理映射,只要按照我们的映射规则,便可以顺利完成映射。

    float texCoords[] = new float[] {   
         0.0f, 0.0f,
         1.0f, 0.0f,
         0.5f, 1.0f,
    };

    效果:

     

    看到这里应该知道纹理坐标数组规则定义的意义了吧。

     

    平铺与箔拉

    我们的纹理坐标系统在两个轴上都是从0.0 到 1.0,如果设置超出此范围的值会怎么样?根据视图的设置方式有两种选择。

    平铺(也叫重复)
    一种选择是平铺纹理。按OpenGL的术语,也叫“重复”。如果我们将第一个纹理坐标数组的所有1.0改为2.0:
        static const GLfloat texCoords[] = {
            0.0, 2.0,
            2.0, 2.0,
            0.0, 0.0,
            2.0, 0.0
        };

    我们可以通过glTexParameteri()函数设置。

    glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL10.GL_REPEAT);
    glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL10.GL_REPEAT);

     

    箝位
    另一种可能的选择是让OpenGL ES简单地将超过1.0的值限制为1.0,任何低于0.0的值限制为 0.0。这实际会引起边沿像素重复。

     

    我们可以通过glTexParameteri()函数设置。

    glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
    glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);

     

    展开全文
  • 各种经纬度坐标系转换-百度坐标系、火星坐标系、国际坐标系 WGS84:国际坐标系,为一种大地坐标系,也是目前广泛使用的GPS全球卫星定位系统使用的坐标系。 GCJ02:火星坐标系,是由中国国家测绘局制订的地理信息...

    各种经纬度坐标系转换-百度坐标系、火星坐标系、国际坐标系

     (文章代码参考网上 测试没什么问题, 汇总整理希望对大家有帮助-dou )
     WGS84:国际坐标系,为一种大地坐标系,也是目前广泛使用的GPS全球卫星定位系统使用的坐标系。
     GCJ02:火星坐标系,是由中国国家测绘局制订的地理信息系统的坐标系统。由WGS84坐标系经加密后的坐标系。
     BD09:为百度坐标系,在GCJ02坐标系基础上再次加密。其中bd09ll表示百度经纬度坐标,bd09mc表示百度墨卡托米制坐标
    

    一 : 百度坐标与百度墨卡坐标互转

    import java.util.HashMap;
    import java.util.Map;
    /** 
     * @ClassName: Baidu 
     * @Description: 百度坐标与百度墨卡坐标互转
     * @author: Max dou
     * @date: 2017年4月11日 下午4:49:54 
     */
    public class Baidu {
         public static void main(String[] args) {
                //百度坐标转百度墨卡坐标
                Map<String, Double> location = convertMC2LL(13745329.000000, 5104310.500000);
                System.out.println(location.get("lng")+"==="+location.get("lat"));
                //百度墨卡坐标转百度坐标
                location = convertLL2MC(location.get("lng"),location.get("lat"));
                System.out.println(location.get("x")+"==="+location.get("y"));
    
            }
    
            private static Double EARTHRADIUS = 6370996.81;
            private static Double[] MCBAND = {12890594.86, 8362377.87, 5591021d, 3481989.83, 1678043.12, 0d};
            private static Double[] LLBAND = {75d, 60d, 45d, 30d, 15d, 0d};
            private static Double[][] MC2LL = {{1.410526172116255e-8, 0.00000898305509648872, -1.9939833816331, 200.9824383106796, -187.2403703815547, 91.6087516669843, -23.38765649603339, 2.57121317296198, -0.03801003308653, 17337981.2}, {-7.435856389565537e-9, 0.000008983055097726239, -0.78625201886289, 96.32687599759846, -1.85204757529826, -59.36935905485877, 47.40033549296737, -16.50741931063887, 2.28786674699375, 10260144.86}, {-3.030883460898826e-8, 0.00000898305509983578, 0.30071316287616, 59.74293618442277, 7.357984074871, -25.38371002664745, 13.45380521110908, -3.29883767235584, 0.32710905363475, 6856817.37}, {-1.981981304930552e-8, 0.000008983055099779535, 0.03278182852591, 40.31678527705744, 0.65659298677277, -4.44255534477492, 0.85341911805263, 0.12923347998204, -0.04625736007561, 4482777.06}, {3.09191371068437e-9, 0.000008983055096812155, 0.00006995724062, 23.10934304144901, -0.00023663490511, -0.6321817810242, -0.00663494467273, 0.03430082397953, -0.00466043876332, 2555164.4}, {2.890871144776878e-9, 0.000008983055095805407, -3.068298e-8, 7.47137025468032, -0.00000353937994, -0.02145144861037, -0.00001234426596, 0.00010322952773, -0.00000323890364, 826088.5}};
            private static Double[][] LL2MC = {{-0.0015702102444, 111320.7020616939, 1704480524535203d, -10338987376042340d, 26112667856603880d, -35149669176653700d, 26595700718403920d, -10725012454188240d, 1800819912950474d, 82.5}, {0.0008277824516172526, 111320.7020463578, 647795574.6671607, -4082003173.641316, 10774905663.51142, -15171875531.51559, 12053065338.62167, -5124939663.577472, 913311935.9512032, 67.5}, {0.00337398766765, 111320.7020202162, 4481351.045890365, -23393751.19931662, 79682215.47186455, -115964993.2797253, 97236711.15602145, -43661946.33752821, 8477230.501135234, 52.5}, {0.00220636496208, 111320.7020209128, 51751.86112841131, 3796837.749470245, 992013.7397791013, -1221952.21711287, 1340652.697009075, -620943.6990984312, 144416.9293806241, 37.5}, {-0.0003441963504368392, 111320.7020576856, 278.2353980772752, 2485758.690035394, 6070.750963243378, 54821.18345352118, 9540.606633304236, -2710.55326746645, 1405.483844121726, 22.5}, {-0.0003218135878613132, 111320.7020701615, 0.00369383431289, 823725.6402795718, 0.46104986909093, 2351.343141331292, 1.58060784298199, 8.77738589078284, 0.37238884252424, 7.45}};
    
            /**
             * 墨卡托坐标转经纬度坐标
             * @param x
             * @param y
             * @return
             */
            public static Map<String, Double> convertMC2LL(Double x, Double y) {
                Double[] cF = null;
                x = Math.abs(x);
                y = Math.abs(y);
    
                for (int cE = 0; cE < MCBAND.length; cE++) {
                    if (y >= MCBAND[cE]) {
                        cF = MC2LL[cE];
                        break;
                    }
                }
                Map<String,Double> location = converter(x, y, cF);
                location.put("lng",location.get("x"));
                location.remove("x");
                location.put("lat",location.get("y"));
                location.remove("y");
                return location;
            }
    
    
            /**
             * 经纬度坐标转墨卡托坐标
             * @param lng
             * @param lat
             * @return
             */
            private static Map<String, Double> convertLL2MC(Double lng, Double lat) {
                Double[] cE = null;
                lng = getLoop(lng, -180, 180);
                lat = getRange(lat, -74, 74);
                for (int i = 0; i < LLBAND.length; i++) {
                    if (lat >= LLBAND[i]) {
                        cE = LL2MC[i];
                        break;
                    }
                }
                if (cE!=null) {
                    for (int i = LLBAND.length - 1; i >= 0; i--) {
                        if (lat <= -LLBAND[i]) {
                            cE = LL2MC[i];
                            break;
                        }
                    }
                }
                return converter(lng,lat, cE);
            }
    
    
            private static Map<String, Double> converter(Double x, Double y, Double[] cE) {
                Double xTemp = cE[0] + cE[1] * Math.abs(x);
                Double cC = Math.abs(y) / cE[9];
                Double yTemp = cE[2] + cE[3] * cC + cE[4] * cC * cC + cE[5] * cC * cC * cC + cE[6] * cC * cC * cC * cC + cE[7] * cC * cC * cC * cC * cC + cE[8] * cC * cC * cC * cC * cC * cC;
                xTemp *= (x < 0 ? -1 : 1);
                yTemp *= (y < 0 ? -1 : 1);
                Map<String, Double> location = new HashMap<String, Double>();
                location.put("x", xTemp);
                location.put("y", yTemp);
                return location;
            }
    
            private static Double getLoop(Double lng, Integer min, Integer max) {
                while (lng > max) {
                    lng -= max - min;
                }
                while (lng < min) {
                    lng += max - min;
                }
                return lng;
            }
    
            private static Double getRange(Double lat, Integer min, Integer max) {
                if (min != null) {
                    lat = Math.max(lat, min);
                }
                if (max != null) {
                    lat = Math.min(lat, max);
                }
                return lat;
            }
    }

    二 : 国际坐标即gps坐标、百度坐标、火星坐标转换

    /** 
     * @ClassName: PositionUtil 
     * @Description: 
     * 各地图API坐标系统比较与转换;
     * WGS84坐标系:即地球坐标系,国际上通用的坐标系。设备一般包含GPS芯片或者北斗芯片获取的经纬度为WGS84地理坐标系,
     * 谷歌地图采用的是WGS84地理坐标系(中国范围除外);
     * GCJ02坐标系:即火星坐标系,是由中国国家测绘局制订的地理信息系统的坐标系统。由WGS84坐标系经加密后的坐标系。
     * 谷歌中国地图和搜搜中国地图采用的是GCJ02地理坐标系; BD09坐标系:即百度坐标系,GCJ02坐标系经加密后的坐标系;
     * 搜狗坐标系、图吧坐标系等,估计也是在GCJ02基础上加密而成的。 chenhua
     * @author: Max dou
     * @date: 2017年4月10日 下午4:17:44 
     */
    public class PositionUtil {
        public static final String BAIDU_LBS_TYPE = "bd09ll";
    
        public static double pi = 3.1415926535897932384626;
        public static double a = 6378245.0;
        public static double ee = 0.00669342162296594323;
    
        /**
         * 国际坐标 to 火星坐标系 (GCJ-02) World Geodetic System ==> Mars Geodetic System
         * 
         * @param lat
         * @param lon
         * @return
         */
        public static Gps gps84_To_Gcj02(double lat, double lon) {
            if (outOfChina(lat, lon)) {
                return null;
            }
            double dLat = transformLat(lon - 105.0, lat - 35.0);
            double dLon = transformLon(lon - 105.0, lat - 35.0);
            double radLat = lat / 180.0 * pi;
            double magic = Math.sin(radLat);
            magic = 1 - ee * magic * magic;
            double sqrtMagic = Math.sqrt(magic);
            dLat = (dLat * 180.0) / ((a * (1 - ee)) / (magic * sqrtMagic) * pi);
            dLon = (dLon * 180.0) / (a / sqrtMagic * Math.cos(radLat) * pi);
            double mgLat = lat + dLat;
            double mgLon = lon + dLon;
            return new Gps(mgLat, mgLon);
        }
    
        /**
         * * 火星坐标系 (GCJ-02) to 国际坐标 * * @param lon * @param lat * @return
         * */
        public static Gps gcj_To_Gps84(double lat, double lon) {
            Gps gps = transform(lat, lon);
            double lontitude = lon * 2 - gps.getWgLon();
            double latitude = lat * 2 - gps.getWgLat();
            return new Gps(latitude, lontitude);
        }
    
        /**
         * 火星坐标系 (GCJ-02) to 百度坐标系 (BD-09) 的转换算法 将 GCJ-02 坐标转换成 BD-09 坐标
         * 
         * @param gg_lat
         * @param gg_lon
         */
        public static Gps gcj02_To_Bd09(double gg_lat, double gg_lon) {
            double x = gg_lon, y = gg_lat;
            double z = Math.sqrt(x * x + y * y) + 0.00002 * Math.sin(y * pi);
            double theta = Math.atan2(y, x) + 0.000003 * Math.cos(x * pi);
            double bd_lon = z * Math.cos(theta) + 0.0065;
            double bd_lat = z * Math.sin(theta) + 0.006;
            return new Gps(bd_lat, bd_lon);
        }
    
        /**
         * * 火星坐标系 (GCJ-02) to 百度坐标系 (BD-09) 的转换算法 * * 将 BD-09 坐标转换成GCJ-02 坐标 * * @param
         * bd_lat * @param bd_lon * @return
         */
        public static Gps bd09_To_Gcj02(double bd_lat, double bd_lon) {
            double x = bd_lon - 0.0065, y = bd_lat - 0.006;
            double z = Math.sqrt(x * x + y * y) - 0.00002 * Math.sin(y * pi);
            double theta = Math.atan2(y, x) - 0.000003 * Math.cos(x * pi);
            double gg_lon = z * Math.cos(theta);
            double gg_lat = z * Math.sin(theta);
            return new Gps(gg_lat, gg_lon);
        }
    
        /**
         * 百度坐标系 (BD-09) to 国际坐标
         * @param bd_lat
         * @param bd_lon
         * @return
         */
        public static Gps bd09_To_Gps84(double bd_lat, double bd_lon) {
    
            Gps gcj02 = PositionUtil.bd09_To_Gcj02(bd_lat, bd_lon);
            Gps map84 = PositionUtil.gcj_To_Gps84(gcj02.getWgLat(),
                    gcj02.getWgLon());
            return map84;
    
        }
    
        public static boolean outOfChina(double lat, double lon) {
            if (lon < 72.004 || lon > 137.8347)
                return true;
            if (lat < 0.8293 || lat > 55.8271)
                return true;
            return false;
        }
    
        public static Gps transform(double lat, double lon) {
            if (outOfChina(lat, lon)) {
                return new Gps(lat, lon);
            }
            double dLat = transformLat(lon - 105.0, lat - 35.0);
            double dLon = transformLon(lon - 105.0, lat - 35.0);
            double radLat = lat / 180.0 * pi;
            double magic = Math.sin(radLat);
            magic = 1 - ee * magic * magic;
            double sqrtMagic = Math.sqrt(magic);
            dLat = (dLat * 180.0) / ((a * (1 - ee)) / (magic * sqrtMagic) * pi);
            dLon = (dLon * 180.0) / (a / sqrtMagic * Math.cos(radLat) * pi);
            double mgLat = lat + dLat;
            double mgLon = lon + dLon;
            return new Gps(mgLat, mgLon);
        }
    
        public static double transformLat(double x, double y) {
            double ret = -100.0 + 2.0 * x + 3.0 * y + 0.2 * y * y + 0.1 * x * y
                    + 0.2 * Math.sqrt(Math.abs(x));
            ret += (20.0 * Math.sin(6.0 * x * pi) + 20.0 * Math.sin(2.0 * x * pi)) * 2.0 / 3.0;
            ret += (20.0 * Math.sin(y * pi) + 40.0 * Math.sin(y / 3.0 * pi)) * 2.0 / 3.0;
            ret += (160.0 * Math.sin(y / 12.0 * pi) + 320 * Math.sin(y * pi / 30.0)) * 2.0 / 3.0;
            return ret;
        }
    
        public static double transformLon(double x, double y) {
            double ret = 300.0 + x + 2.0 * y + 0.1 * x * x + 0.1 * x * y + 0.1
                    * Math.sqrt(Math.abs(x));
            ret += (20.0 * Math.sin(6.0 * x * pi) + 20.0 * Math.sin(2.0 * x * pi)) * 2.0 / 3.0;
            ret += (20.0 * Math.sin(x * pi) + 40.0 * Math.sin(x / 3.0 * pi)) * 2.0 / 3.0;
            ret += (150.0 * Math.sin(x / 12.0 * pi) + 300.0 * Math.sin(x / 30.0
                    * pi)) * 2.0 / 3.0;
            return ret;
        }
    
        public static void main(String[] args) {
            Gps gps = new Gps(40.084481,116.395412 );
            System.out.println("gps :" + gps);
            Gps bd = bd09_To_Gcj02(gps.getWgLat(), gps.getWgLon());
            System.out.println("bd  :" + bd);
        }
    }
    
    /** 
     * @ClassName: Gps 
     * @Description: TODO
     * @author: Max dou
     * @date: 2017年4月10日 下午4:19:13 
     */
    public class Gps {
        private double wgLat;
        private double wgLon;
        public Gps(double wgLat, double wgLon) {
        setWgLat(wgLat);
        setWgLon(wgLon);
        }
        public double getWgLat() {
        return wgLat;
        }
        public void setWgLat(double wgLat) {
        this.wgLat = wgLat;
        }
        public double getWgLon() {
        return wgLon;
        }
        public void setWgLon(double wgLon) {
        this.wgLon = wgLon;
        }
        @Override
        public String toString() {
        return wgLat + "," + wgLon;
        }
    }

    三 : 利用百度地图api接口,坐标转换

     参考链接:http://lbsyun.baidu.com/index.php?title=webapi/guide/changeposition
    
    此接口为免费接口,不过每天有限制
    

    四 : 利用百度地图api接口,根据坐标获取地理位置信息
    参考链接:http://lbsyun.baidu.com/index.php?title=webapi/guide/webservice-geocoding
    此接口为免费接口,不过每天有限制:
    限制:

    /**
     * @ClassName: BaiDuUtil
     * @Description: TODO
     * @author: Max dou
     * @date: 2017年4月10日 上午11:58:55
     */
    public class BaiDuUtil {
        public static String getCity(String lat, String lng) {
            JSONObject objSrc = getLocationInfo(lat, lng);
            System.out.println(objSrc.toString());
            JSONObject obj = getLocationInfo(lat, lng).getJSONObject("result")
                    .getJSONObject("addressComponent");
            return obj.getString("city");
        }
    
        public static JSONObject getLocationInfo(String lat, String lng) {
            String url = "http://api.map.baidu.com/geocoder/v2/?location=" + lat
                    + "," + lng + "&output=json&ak=" + "此处填写百度开放平台秘钥"
                    + "&pois=0";
            JSONObject obj = JSONObject.fromObject(HttpUtil.getRequest(url));
            return obj;
        }
        public static void main(String[] args) {
            System.out.println(BaiDuUtil.getCity("40.091637", "116.396764"));
        }
    }

    五 : 阿里云接口 : 根据坐标获取地理位置信息
    (此接口从网上找到的,已现在测试看没有限制条件)

    需要json解析包:
    <dependency>      
        <groupId>net.sf.json-lib</groupId>     
        <artifactId>json-lib</artifactId>      
        <version>2.4</version>      
        <classifier>jdk15</classifier>    
    </dependency>  
    
    import java.net.URL;
    import net.sf.json.JSONArray;
    import net.sf.json.JSONObject;
    
    /** 
     * @ClassName: GetLocation 
     * @Description: TODO
     * @author: Max dou
     * @date: 2017年4月10日 下午1:53:42 
     */
    public class GetLocation {
         public static void main(String[] args) {  
                 String add = getAdd("110.303959", "23.548133");  
                 JSONObject jsonObject = JSONObject.fromObject(add);  
                 JSONArray jsonArray = JSONArray.fromObject(jsonObject.getString("addrList"));  
                 JSONObject j_2 = JSONObject.fromObject(jsonArray.get(1));  
                 JSONObject j_1 = JSONObject.fromObject(jsonArray.get(0));  
                 String allAdd = j_2.getString("admName");  
                 String arr[] = allAdd.split(",");  
                 System.out.println("省:"+arr[0]+"\n市:"+arr[1]+"\n区:"+arr[2]+"\n路:"+j_1.getString("name")+"\n详细地址:"+j_2.getString("name"));  
            }  
    
            public static String getAdd(String log, String lat ){  
                //lat 小  log  大  ,经过测试,数据的经纬度为国家坐标即火星坐标
                //参数解释: 纬度,经度 type 001 (100代表道路,010代表POI,001代表门址,111可以同时显示前三项)  
                String urlString = "http://gc.ditu.aliyun.com/regeocoding?l="+lat+","+log+"&type=111";  
                String res = "";
                try {     
                    URL url = new URL(urlString);    
                    java.net.HttpURLConnection conn = (java.net.HttpURLConnection)url.openConnection();    
                    conn.setDoOutput(true);    
                    conn.setRequestMethod("POST");    
                    java.io.BufferedReader in = new java.io.BufferedReader(new java.io.InputStreamReader(conn.getInputStream(),"UTF-8"));    
                    String line;    
                   while ((line = in.readLine()) != null) {    
                       res += line+"\n";    
                   }    
                    in.close();    
                } catch (Exception e) {    
                    System.out.println("error in wapaction,and e is " + e.getMessage());    
                }   
                System.out.println(res);  
                return res;    
            } 
    }
    

    如有什么问题,请大家指正,谢谢!
    
    展开全文
  • 世界坐标系、相机坐标系、图像平面坐标

    万次阅读 多人点赞 2018-07-12 18:04:09
    一、四个坐标系简介和转换 相机模型为以后一切标定算法的关键,只有这边有相当透彻的理解,对以后的标定算法才能有更好的理解。本人研究了好长时间,几乎每天都重复看几遍,最终才会明白其推导过程。 &nbsp; &...

    一、四个坐标系简介和转换

    相机模型为以后一切标定算法的关键,只有这边有相当透彻的理解,对以后的标定算法才能有更好的理解。本人研究了好长时间,几乎每天都重复看几遍,最终才会明白其推导过程。
         我觉得首先我们要理解相机模型中的四个平面坐标系的关系:像素平面坐标系(u,v)、像平面坐标系(图像物理坐标第(x,y)、相机坐标系(Xc,Yc,Zc)和世界坐标系(Xw,Yw,Zw),在每一篇介绍相机模型的文章中都有介绍。
         我刚开始理解时,看着那一堆的公式十分的头晕,我相信很多初学者和我一样,但仔细想想,只不过是,我们假设了一些参数,使四个坐标系之间的坐标联系起来,这样我们就可以从拍摄的图片上一个点坐标一路反推出世界中的那个点的坐标,这样就达到了我们的目的,三维重建。而那些我们假设的参数,就是我们要标定的内外参数。


    1、像素坐标与像平面坐标系之间的关系 
          确定他们的关系之前,我们可以假设每一个像素在u轴和v轴方向上的物理尺寸为dx和dy。仔细看下他们的模型可以推出以下公式(这个还是比较好理解的):






    解释:1、dx,dy,u0,v0其实都是我们假设出来的参数,dxdy表示感光芯片上像素的实际大小,是连接像素坐标系和真实尺寸坐标系的,u0,v0是图像平面中心,最终是要我们求的内外参数。
    得出这个公式后我们可以运用线性代数的知识把方程用矩阵形式表示:

    当然我们也可以用另一种矩阵形式表示:

    2、相机坐标系与世界坐标系之间的关系 

         这两个坐标系之间的关系我们可以旋转矩阵R和平移矩阵T来得到以下关系:


                                           

                                                                        公式4

       解释:1、 在这个公式中,R为3*3矩阵,T为3*1,0为(0,0,0),简化用Lw表示后为4*4矩阵。

    3、成像投影关系(相机坐标系与像平面坐标系) 


         在相机模型中我们可以得到以下公式:


                                           

                                                                     公式5

               解释:1、

    同样我们用矩阵形式表示:

                                              

                                                                           公式6


    4、得到公式


    而我们可以将以上公式综合一下就可以得到:

      

    因此,内参数矩阵可以表示为:

    =


    外参矩阵可以表示为:,由旋转矩阵R和平移向量T组成


    当然在好多资料上都有这种做法:



    上图中表示的情况是像素坐标系和图像物理坐标系的两个坐标轴不是平行的关系,像素坐标系的两个坐标轴也不是垂直90°的关系,而图像物理坐标系的两个坐标轴是垂直关系。所以,我们在转换两个坐标轴的坐标之间的关系时就必须考虑像素坐标系两个坐标轴之间的夹角了。就有了上面的不同的内参矩阵,理解了就好了。


    二、图像坐标:我想和世界坐标谈谈(B)

             玉米将在这篇博文中,对图像坐标与世界坐标的这场对话中涉及的第二个问题:谈话方式,进行总结。世界坐标是怎样变换进摄像机,投影成图像坐标的呢?

            玉米做了一个简单的图示,在这里做一个提纲。图中显示,世界坐标系通过刚体变换到达摄像机坐标系,然后摄像机坐标系通过透视投影变换到达图像坐标系。可以看出,世界坐标与图像坐标的关系建立在刚体变换和透视投影变换的基础上。为了奖励刚体变和透视投影变换沟通了“世界上最远的距离”,玉米在图上奖励了他们两朵小红花。哈哈


     首先,让我们来看一下刚体变换是如何将世界坐标系与图像坐标系联系起来的吧。这里,先对刚体变换做一个介绍:

            刚体变换(regidbody motion):三维空间中, 当物体不发生形变时,对一个几何物体作旋转, 平移运动,称之为刚体变换

    因为世界坐标系和摄像机坐标都是右手坐标系,所以其不会发生形变。我们想把世界坐标系下的坐标转换到摄像机坐标下的坐标,如下图所示,可以通过刚体变换的方式。空间中一个坐标系,总可以通过刚体变换转换到另外一个个坐标系的。转一转,走一走,就到另外一个坐标系下了。以前可能是面朝大海,经过平移旋转,最终可能只能面朝冰山了,哈哈


    下面让我来看一下,二者之间刚体变化的数学表达。


    其中,XC代表摄像机坐标系,X代表世界坐标系。R代表旋转,T代表平移。R、T与摄像机无关,所以称这两个参数为摄像机的外参数(extrinsic parameter)可以理解为两个坐标原点之间的距离,因其受x,y,z三个方向上的分量共同控制,所以其具有三个自由度。

             R则为分别绕XYZ三轴旋转的效果之和。如下面所示:



     R=r1*r2*r3.其由三个方向的θ控制,故具有三个自由度。

               好了,刚体变换就讲完了。大家应该都了解,世界坐标系到摄像机坐标系之间的转换过程了吧。

              接下来,让我们看看摄像机坐标下的坐标如何投影到图像坐标系下,最终变为照片中的一个像素。这其中包含两个过程:一是从摄像机坐标到“空间图像坐标”(x,y)所发生的透视投影;二是从“连续图像坐标”到“离散图像坐标”(u,v)。后者我们已经在第一篇博文中解释过。所以在这里,主要介绍一下透视投影。

             透视投影(perspective projection): 用中心投影法将形体投射到投影面上,从而获得的一种较为接近视觉效果的单面投影图。有一点像皮影戏。它符合人们心理习惯,即离视点近的物体大,离视点远的物体小,不平行于成像平面的平行线会相交于消隐点(vanish point)。

             啰嗦这么多,其实大家看看示意图,看看公式,秒懂。


      以图中B(XB,YB)点为例,在小孔成像摄像机模型下(几何分析的最常用模型)。这里的f为摄像机的焦距,其属于摄像机的内参数(intrinsic parameter)。其在成像平面上的投影点b(xb,yb)的坐标利用简单的相似三角形比例关系很容易求出:


    上面两式也阐明了摄像机坐标与图像坐标之间的透视投影关系。

                好吧,现在玉米已经把图像坐标与世界坐标之间的这场对话所需经历的三个波折的过程加以了解释。即:刚体变换、透视投影、(x,y)换(u,v)(ps.这个在上一篇博文中讲过)。接下来玉米用一张图把三个过程连接起来。实现从世界坐标(X,Y,Z)到(u,v)之间的转换。让图像坐标与世界坐标直接对话。

             下图中的转换关系,都是用齐次坐标表达的,大家会发现这样的表达非常整洁。

             其实这张图显示的过程还有一个名字:摄像机模型(camera model)。其实也就是摄像机的几何模型了。

             将三者相乘,可以把这三个过程和在一起,写成一个矩阵:


    P就是世界坐标到图像坐标的直接联系人,P就表示了一个投影相机,有下面公式:


    注意在表示齐次坐标时,需要在符号上面加个小帽子。除去齐次坐标控制位P23P具有11个自由度。


           摄像机模型及其中涉及的坐标系等,是弄清3D重建几何框架的基础。可以把它们视为基本运算关系。后面对于三维重建几何框架的推导,都是要用到三个基本坐标系和摄像机模型的。

            </div>
                </div>
    
    展开全文
  • 中国城市中心点坐标

    千次阅读 2019-05-30 16:29:02
    原数据:...以下为经过整理的地区数据,可以直接复制到json中使用 '上海': [121.487899486, 31.24916171], '临沧': [100.092612914, 23.8878061038], '丽江': [100.229628399, 26.8753510895], ...
  • 地图常用坐标

    千次阅读 2018-08-02 10:32:43
    EPSG:4326 大地坐标系,WGS84 EPSG:4490 大地坐标系,cgcs2000 EPSG:3857 投影坐标系,墨卡托投影
  • unity 屏幕坐标&世界坐标相互转换

    万次阅读 2018-02-11 21:04:53
    世界坐标转屏幕坐标:Vector3 screenPos = Camera.main.WorldToScreenPoint(pos); 屏幕坐标转世界坐标:Vector3 worldPos = Camera.main.ScreenToWorldPoint(pos);
  • 转载于:http://www.ab126.com/Geography/3753.html原文博主只让引用链接。
  • 一、各坐标系介绍图像处理、立体视觉经常涉及到世界坐标系、相机坐标系、图像坐标系和像素坐标系。如下图所示:世界坐标系是为了确定相机的位置,在双目视觉中一般将世界坐标系原点定在左相机、右相机或两者X轴方向...
  • 平面坐标转大地坐标(经纬度)

    万次阅读 2016-09-30 16:05:45
    坐标类型选择“平面坐标” 目标坐标类型选择“大地坐标”,椭球基准,根据自己源文件坐标类型来选,我的文件类型是 西安80坐标系,所以选择 国家-80坐标。 3.投影设置(很重要,否则算出来的经纬度偏差很大) 接...
  • Unity有世界坐标、本地坐标(localposition)、UI坐标(这个我好像还没怎么用)、屏幕坐标等等,之前的一个项目需要考虑世界坐标转换为本地坐标,后来经过一番尝试,找到了一种比较取巧的方法。 首先,世界坐标是指...
  • 相机成像原理:世界坐标系、相机坐标系、图像坐标系、像素坐标系之间的转换
  • 本篇微信图文主要介绍Matlab数据可视化方面的内容。polar、pol2cart、cart2pol
  • 像素坐标系与图像坐标

    万次阅读 2018-08-20 15:11:09
    1. 像素坐标系: ...横坐标u和纵坐标v分别是图像所在的行和列, 在视觉处理库OpenCV中,u对应x,v对应y; 2. 图像坐标系: 图像坐标系x-y的原点是O1,为像素坐标系的中点, 如图所示: 假设...
  •  设Oxy,O'x'y'是两个直角坐标系,坐标轴有相同的方向,O'在Oxy中的坐标为(x0,y0).我们用(x,y),(x',y')分别代表点M在坐标系Oxy,O'x'y'中的坐标. 在移轴下,坐标转换公式是   x=x'+x0, y=y'+y0. 2.单纯转轴. 设新旧...
  •   0.前言 最近整理了“相机成像原理”和“视差与深度信息”相关的资料,然后做成了PPT,以备自己用,也提供给相关的...图像处理、立体视觉等等方向常常涉及到四个坐标系:世界坐标系、相机坐标系、图像坐标系、...
  • 经纬度、平面坐标系转换方法

    万次阅读 2016-11-13 16:28:57
    使用工具:经纬度与我国54、80大地坐标转换的小工具 我们经常需要进行坐标系之间、经纬度和XY之间的转换,我们使用这个小工具,做一个介绍。 这里以从XY到经纬度的转换为例:首要要明确 XY使用的坐标系XY点...
  • 三维空间坐标系变换-旋转矩阵

    万次阅读 多人点赞 2018-09-18 14:31:37
    空间中三维坐标变换一般由三种方式实现,第一种是旋转矩阵和旋转向量;第二种是欧拉角;第三种是四元数。这里先介绍旋转矩阵(旋转向量)与欧拉角实现三维空间坐标变换的方法以及两者之间的关系。  这里以常见的世界...
  • 坐标系之间的简单变换

    万次阅读 2019-05-27 16:18:41
    1.坐标系变换 在图形学中,经常需要从一个坐标系变换到另一个坐标系。如下图,两个坐标系xoy和。 在xoy坐标系中的坐标分别为 。 P在xoy坐标系中的坐标分别为 (x, y)。 为了将P点从xoy坐标系转换到中,...
  • 球面坐标系与直角坐标系转换

    千次阅读 2017-07-12 09:54:57
    球面坐标
1 2 3 4 5 ... 20
收藏数 875,208
精华内容 350,083
关键字:

坐标