Google map EPSG:900913 地图分块算法、切片算法个人解析。一看就明白哈

本文详细解析了Google地图的分块算法原理,包括EPSG:900913投影、不同缩放级别的分辨率计算及如何根据经纬度确定地图切片的位置。
部署运行你感兴趣的模型镜像

Google map 地图分块算法的解析 EPSG:900913

我下面的小伙子总是不明白map api,这块算法原理。我想很多人也一样,所以写一下说明一下哈

projection: "EPSG:900913", //投影为 900913,google 墨卡托投影 units: "m", //屏幕坐标以米为单位
maxResolution: 156543.0339, //最大比例下的每像素屏幕地图单位值 maxExtent: new OpenLayers.Bounds(-20037508, -20037508,20037508, 20037508.34), numZoomLevels: 17。 这是openlayer中的说明,大多人看不懂哈


解释开始:


1、先了解一个常量,世界一张图。一个像素代表多少米

世界范围,一个256*256的图 就是一个世界地图(如下)。 1个像素代表的米数就是 156543.0339。下面这图的面积就是=世界面积=156543.0339*256 * 156543.0339*256




2、其实全世界墨卡托范围是 -20037508, -20037508,20037508, 20037508.34 ,从第四象限到第一象限

其实这个值很简单,就是 -20037508 = -156543.0339*128  ; 为什么称128 呢? 因为 他是256的一半,所以一个像素*128正好代表一个象限的长度,也就是世界的一半长度。


3、切片的级别,比例尺级别

我们一般考虑切片到 18级别 ,maxZoomLevel = 18; 也就是说 世界一张图,被放大到 2的18次方倍哈。宽度、高度同时放大到2的18次方倍

我们用这个函数就可以知道 每个比例尺下,每个像素代表多少米啦。那我们18级别一个像素代表的米为:0.5971642833709717 (一像素不到一米哈)


Map.getZoomUnits = function(zoom)
{
    var zu = [0,0];
    var a = Math.pow(2,(18-zoom));
    zu[0] = 0.5971642833709717 * a;            
    zu[1] = 0.5971642833709717 * a;
    return zu;
};


4、根据墨卡托经纬度定位到x ,y ,z块号。

用点所在的墨卡托 减去 之前的基础墨卡托值,得到相对绝对距离米,再用这个 总米 / 当前比例尺每块代表的米 就知道是在哪一xy块啦

中国一般在第一象限哈

SE.Map.prototype.toMapId = function(point,zoom)
{
    var x=point.MercatorLng-156543.0339*128;
    var y=-156543.0339*128-point.MercatorLat;
    var zu = this.getZoomUnits(zoom,true);
    var spanX = zu[0]*256;//zu[0]为1px代表的纬度,this.imgSize为加载的图片大小(256)
    var spanY = zu[1]*256;//zu[1]为1px代表的经度,this.imgSize为加载的图片大小(256)
    var bx=parseInt(x/spanX);
    var by=parseInt(y/spanY);
    return [bx,by,(x-bx*spanX)/spanX*this.imgSize,(y-by*spanY)/spanY*this.imgSize];
};


附上:经纬度转84、84转经纬度 算法函数:

/**
    w84转为墨卡托坐标(经纬度转墨卡托)
    WGS84是地理坐标的一种,地理坐标本身有很多种,web墨卡托是投影坐标

    lon :    w84经度
    lat :    w84纬度
*/
PG.Tool.forwardMercator = function(lon, lat) {
    lon = parseFloat(lon);
    lat = parseFloat(lat);
    var x = lon * 20037508.34 / 180;
    var y = Math.log(Math.tan((90 + lat) * Math.PI / 360)) / (Math.PI / 180);
    y = y * 20037508.34 / 180;        
    return [x,y];
};

/**
    将墨卡托坐标转为w84(墨卡托转经纬度)

    x :    墨卡托经度
    y :    墨卡托纬度
*/
PG.Tool.inverseMercator = function(x, y) {
    var lon = (x / 20037508.34) * 180;
    var lat = (y / 20037508.34) * 180;
    lat = 180/Math.PI * (2 * Math.atan(Math.exp(lat * Math.PI / 180)) - Math.PI / 2);
    return [lon, lat];
};


OK,明白了吧! 其实就是个世界范围 和 平方的关系。有问题联系我哈。




您可能感兴趣的与本文相关的镜像

LobeChat

LobeChat

AI应用

LobeChat 是一个开源、高性能的聊天机器人框架。支持语音合成、多模态和可扩展插件系统。支持一键式免费部署私人ChatGPT/LLM 网络应用程序。

<think> 我们使用GeoTools进行坐标转换的基本步骤通常包括: 1. 创建坐标参考系统(CRS)工厂,用于查找或定义源CRS和目标CRS。 2. 使用MathTransformFactory创建转换步骤(从源CRS到目标CRS的转换)。 3. 使用转换器对实际的坐标进行转换。 注意:EPSG:900913x2 并不是个标准的EPSG代码。通常,Web墨卡托投影的EPSG代码是3857(或900913,但900913是非官方的,现在已被EPSG:3857取代)。因此,我假设您指的是EPSG:3857(Web墨卡托投影)。如果确实是900913,在GeoTools中也可以使用,因为900913是3857的别名(但注意x2可能是指某种自定义的扩展?)。如果900913x2是自定义的,那么需要自定义CRS定义。 如果900913x2是指EPSG:3857的两倍?这不太符合常规。通常我们转换到EPSG:3857(单位米)即可。所以这里我假设目标CRS是EPSG:3857。 步骤: 1. 设置GeoTools的CRS管理,确保有必要的依赖(例如gt-epsg-hsql)。 2. 获取源CRS(EPSG:4326)和目标CRS(EPSG:3857)。 3. 创建转换并执行。 示例代码: ```java import org.geotools.api.referencing.crs.CoordinateReferenceSystem; import org.geotools.api.referencing.operation.MathTransform; import org.geotools.geometry.jts.JTS; import org.geotools.referencing.CRS; import org.locationtech.jts.geom.Coordinate; import org.locationtech.jts.geom.Geometry; import org.locationtech.jts.geom.GeometryFactory; import org.locationtech.jts.geom.Point; public class CRSTransformExample { public static void main(String[] args) throws Exception { // 源CRS: EPSG:4326 (WGS84) CoordinateReferenceSystem sourceCRS = CRS.decode("EPSG:4326"); // 目标CRS: EPSG:3857 (Web墨卡托) CoordinateReferenceSystem targetCRS = CRS.decode("EPSG:3857"); // 注意:在转换时,需要指定是否进行经度轴交换(通常EPSG:4326是纬度在前,经度在后,但GeoTools默认是经度在前,纬度在后) // 这里我们使用true来强制进行轴交换,以确保正确性(根据实际数据情况) boolean lenient = true; // 允许宽松的转换(例如轴顺序的调整) MathTransform transform = CRS.findMathTransform(sourceCRS, targetCRS, lenient); // 创建个点(以经度、纬度顺序,例如:经度116.39,纬度39.9 代表北京) GeometryFactory geometryFactory = new GeometryFactory(); Point point = geometryFactory.createPoint(new Coordinate(116.39, 39.9)); // 转换几何体 Geometry transformedPoint = JTS.transform(point, transform); // 输出转换后的坐标(单位:米) System.out.println(transformedPoint); } } ``` 注意: - 轴顺序问题:EPSG:4326通常是纬度(y)、经度(x)顺序,但在很多系统中(包括JTS)默认是x(经度),y(纬度)。GeoTools在解码EPSG:4326时,默认会使用标准的轴顺序(纬度、经度),因此我们在转换时设置lenient为true,让GeoTools自动处理轴顺序(通过轴交换)。在创建点时,我们按照经度、纬度的顺序(x, y)创建,这样在转换时,GeoTools会自动调整。 - 如果转换时出现异常,可能需要检查轴顺序。可以通过CRS.decode("EPSG:4326")后打印其轴信息来确认。 引用说明: 在GeoTools中,坐标转换是个核心功能,通过CRS类进行坐标参考系统的查找和转换操作。在转换几何对象时,使用JTS工具类进行转换[^1][^5]。 关于旋转方向的问题(如引用[2]所述),在坐标转换中通常不需要考虑旋转,因为转换参数中已经包含了旋转信息,我们只需要正确使用转换方法即可。 如果目标CRS是自定义的(例如900913x2),那么需要自定义CRS定义。但通常我们使用标准的EPSG:3857。 依赖: 在Maven项目中,需要添加如下依赖(以GeoTools 25.x为例): ```xml <dependency> <groupId>org.geotools</groupId> <artifactId>gt-main</artifactId> <version>25.2</version> </dependency> <dependency> <groupId>org.geotools</groupId> <artifactId>gt-epsg-hsql</artifactId> <version>25.2</version> </dependency> ``` 相关问题: §§相关问题§§ 1. 在GeoTools中如何处理坐标转换时的轴顺序问题? 2. 如何自定义坐标参考系统(CRS)? 3. 转换坐标时出现异常“org.opengis.referencing.NoSuchAuthorityCodeException”该如何解决? 4. 除了点(Point)之外,如何转换线(LineString)或多边形(Polygon)? 5. 在GeoTools中如何将转换后的坐标写回Shapefile? 以上代码和说明提供了基本的转换方法。请根据实际需求调整目标CRS和源CRS。 </think>### Java GeoTools实现EPSG:4326转EPSG:900913坐标转换的方法 在GeoTools中实现EPSG:4326(WGS84经纬度)到EPSG:900913Web墨卡托投影)的坐标转换,需要以下步骤: #### 1. 添加Maven依赖 ```xml <dependency> <groupId>org.geotools</groupId> <artifactId>gt-main</artifactId> <version>25.0</version> <!-- 使用最新版本 --> </dependency> <dependency> <groupId>org.geotools</groupId> <artifactId>gt-epsg-hsql</artifactId> <version>25.0</version> </dependency> ``` #### 2. 核心转换代码 ```java import org.geotools.api.referencing.crs.CoordinateReferenceSystem; import org.geotools.api.referencing.operation.MathTransform; import org.geotools.geometry.jts.JTS; import org.geotools.referencing.CRS; import org.locationtech.jts.geom.Coordinate; import org.locationtech.jts.geom.Geometry; import org.locationtech.jts.geom.GeometryFactory; import org.locationtech.jts.geom.Point; public class CoordinateTransformer { private final MathTransform transform; public CoordinateTransformer() throws Exception { // 定义坐标系(注意900913EPSG:3857的别名) CoordinateReferenceSystem sourceCRS = CRS.decode("EPSG:4326"); CoordinateReferenceSystem targetCRS = CRS.decode("EPSG:900913"); // 创建转换器(处理轴顺序差异) this.transform = CRS.findMathTransform(sourceCRS, targetCRS, true); } public double[] transform(double lon, double lat) throws Exception { GeometryFactory geometryFactory = new GeometryFactory(); // 创建原始点(注意顺序:经度,纬度) Point point = geometryFactory.createPoint(new Coordinate(lon, lat)); // 执行坐标转换 Geometry transformed = JTS.transform(point, this.transform); // 获取结果坐标(Web墨卡托坐标) Coordinate result = transformed.getCoordinate(); return new double[]{result.x, result.y}; } // 使用示例 public static void main(String[] args) throws Exception { CoordinateTransformer transformer = new CoordinateTransformer(); // 转换北京坐标(116.4°E, 39.9°N) double[] result = transformer.transform(116.4, 39.9); System.out.println("转换结果: " + result[0] + ", " + result[1]); } } ``` #### 关键说明: 1. **轴顺序处理** EPSG:4326默认使用`(纬度, 经度)`顺序,但JTS要求`(经度, 纬度)`。设置`CRS.findMathTransform(..., true)`中的`true`参数启用自动轴交换[^2]。 2. **900913与3857** `EPSG:900913`是Google地图使用的非官方代码,等同于标准`EPSG:3857`(Web墨卡托投影)。GeoTools支持两种表示[^1]。 3. **单位转换** 转换后坐标单位为米(Web墨卡托投影),典型值范围:$[-20037508.34, 20037508.34]$ #### 转换示例: | 输入 (EPSG:4326) | 输出 (EPSG:900913) | |------------------|---------------------| | $(0, 0)$ | $(0, 0)$ | | $(116.4, 39.9)$ | $(12957997, 4852834)$ | > **重要提示**:实际使用时应添加异常处理(如FactoryException, TransformException)
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符  | 博主筛选后可见
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值