当前位置: 首页 > news >正文

地图经纬度与地图切片像素坐标换算类

地图经纬度与地图切片像素坐标换算类

具体代码如下

/*** 高德地图栅格切片经纬度转换工具类** @author houxg* @Description 地图栅格切片经纬度工具类,适用于高德,Google Map,OSM* @date 2025/7/20 12:05**/
public class MapTileLnglatTransform {/** Created by CntChen 2016.04.30* 参考资料:http://wiki.openstreetmap.org/wiki/Slippy_map_tilenames* 适用地图:高德,Google Map,OSM*///最大最小地图层级double levelMax;double levelMin;public double Math_sinh(double x) {return (Math.exp(x) - Math.exp(-x)) / 2;}/*** 构造函数** @param levelRange_max 最大地图层级* @param LevelRange_min 最小地图层级*/public MapTileLnglatTransform(double levelRange_max, double LevelRange_min) {this.levelMax = levelRange_max;this.levelMin = LevelRange_min;}/** 某一瓦片等级下瓦片地图X轴(Y轴)上的瓦片数目*/public double getMapSize(double level) {return Math.pow(2, level);}/** 分辨率,表示水平方向上一个像素点代表的真实距离(m)*/public double getResolution(double latitude, double level) {double resolution = 6378137.0 * 2 * Math.PI * Math.cos(latitude) / 256 / this.getMapSize(level);return resolution;}/** 经度转瓦片X坐标* @param longitude 经度* @param level 缩放级别     **/public double lngToTileX(double longitude, double level) {double x = (longitude + 180) / 360;double tileX = Math.floor(x * this.getMapSize(level));/*** 限定边界值, 解决 longitude=180 时边界值错误* latitude 应该没问题, 因为 latitude 不会取到 90/-90*/tileX = Math.min(tileX, Math.pow(2, level) - 1);return tileX;}/*** 纬度转瓦片Y** @param latitude 纬度* @param level    地图级别* @return 瓦片Y*/public double latToTileY(double latitude, double level) {double lat_rad = latitude * Math.PI / 180;double y = (1 - Math.log(Math.tan(lat_rad) + 1 / Math.cos(lat_rad)) / Math.PI) / 2;double tileY = Math.floor(y * this.getMapSize(level));// 代替性算法,使用了一些三角变化,其实完全等价//let sinLatitude = Math.sin(latitude * Math.PI / 180);//let y = 0.5 - Math.log((1 + sinLatitude) / (1 - sinLatitude)) / (4 * Math.PI);//let tileY = Math.floor(y * this._getMapSize(level));return tileY;}/** 从经纬度获取某一级别瓦片坐标编号*/public double[] lnglatToTile(double longitude, double latitude, double level) {double tileX = this.lngToTileX(longitude, level);double tileY = this.latToTileY(latitude, level);return new double[]{tileX, tileY};}/** 从经纬度获取某一级别像素坐标编号* @param {double} longitude 经度* @param {double} latitude 纬度* @param {double} level 级别* @return {double} pixelX 切片X坐标编号*/public double lngToPixelX(double longitude, double level) {double x = (longitude + 180) / 360;double pixelX = Math.floor(x * this.getMapSize(level) * 256 % 256);return pixelX;}/*** 经纬度转切片Y坐标编号** @param latitude 纬度* @param level    地图级别* @return pixelY 切片Y坐标编号*/public double latToPixelY(double latitude, double level) {double sinLatitude = Math.sin(latitude * Math.PI / 180);double y = 0.5 - Math.log((1 + sinLatitude) / (1 - sinLatitude)) / (4 * Math.PI);double pixelY = Math.floor(y * this.getMapSize(level) * 256 % 256);return pixelY;}/** 从经纬度获取点在某一级别瓦片中的像素坐标*/public double[] lnglatToPixel(double longitude, double latitude, double level) {double pixelX = this.lngToPixelX(longitude, level);double pixelY = this.latToPixelY(latitude, level);return new double[]{pixelX, pixelY};}/*** 从像素坐标获取经纬度** @param pixelX 像素坐标X* @param tileX  瓦片坐标X* @param level  瓦片级别* @return 经度*/public double pixelXTolng(double pixelX, double tileX, double level) {double pixelXToTileAddition = pixelX / 256.0;double longitude = (tileX + pixelXToTileAddition) / this.getMapSize(level) * 360 - 180;return longitude;}/*** 瓦片像素坐标Y转纬度** @param pixelY 瓦片像素坐标Y* @param tileY  瓦片坐标Y* @param level  瓦片级别* @return 纬度*/public double pixelYToLat(double pixelY, double tileY, double level) {double pixelYToTileAddition = pixelY / 256.0;double latitude = Math.atan(Math_sinh(Math.PI * (1 - 2 * (tileY + pixelYToTileAddition) / this.getMapSize(level)))) * 180.0 / Math.PI;return latitude;}/** 从某一瓦片的某一像素点到经纬度*//*** 从某一瓦片的某一像素点到经纬度** @param pixelX 瓦片内像素点X坐标* @param pixelY 瓦片内像素点Y坐标* @param tileX  瓦片X坐标* @param tileY  瓦片Y坐标* @param level  瓦片等级* @return [经度, 纬度]*/public double[] pixelToLnglat(double pixelX, double pixelY, double tileX, double tileY, double level) {double lng = this.pixelXTolng(pixelX, tileX, level);double lat = this.pixelYToLat(pixelY, tileY, level);return new double[]{lng, lat};}/*** 测试类** @param args*/public static void main(String[] args) {System.out.println("请输入经纬度,测试开始");if (args.length < 2) {System.out.println("请输入经纬度");return;}double longitude = Double.parseDouble(args[0]);double latitude = Double.parseDouble(args[1]);int zoomIndex = 17;MapTileLnglatTransform mapTransformUtil = new MapTileLnglatTransform(18, 3);double[] tile = mapTransformUtil.lnglatToTile(longitude, latitude, zoomIndex);System.out.printf("longitude:%s,latitude:%s,zoom:%s---", longitude, latitude, zoomIndex);System.out.println("result:");System.out.printf("tileX:%s,tileY:%s---", tile[0], tile[1]);System.out.println("请输入经纬度,测试完成");}}

http://www.dtcms.com/a/289730.html

相关文章:

  • 2.组合式API知识点(1)
  • imx6ull-系统移植篇11——U-Boot 移植(下)
  • 不只是“能用”:从语义化到 ARIA,打造“信息无障碍”Web 应用的实战清单
  • Python关于numpy的基础知识数组的升维
  • leetcode丑数II计算第n个丑数
  • 操作系统总结
  • dify创建OCR工作流
  • springboot-profile
  • [学习] 双边带调制 (DSB) 与单边带调制 (SSB) 深度对比
  • 【Java学习|黑马笔记|Day18】Stream流|获取、中间方法、终结方法、收集方法及其练习
  • Redis面试精讲 Day 4:Redis事务与原子性保证
  • Node.js:常用工具、GET/POST请求的写法、工具模块
  • 基于单片机无线防丢/儿童防丢报警器
  • xavier nx上编译fast-livo过程中出现的问题记录
  • 分享一款免费好用的电视远程推送传输助手TV版软件
  • week4
  • 游戏剧情抄袭侵权比对报告:防止“爆款”变“爆雷”
  • 【分布式 ID】详解百度 uid-generator(源码篇)
  • 【每日算法】专题十_哈希表
  • 代码随想录-250720-划分字母区间
  • 什么是 Linux 发行版?什么是 Linxu 操作系统?
  • python字符串的讲解和应用
  • kotlin Flow快速学习2025
  • Function Callingの进化路:源起篇
  • (5)从零开发 Chrome 插件:Vue3 Chrome 插件待办事项应用
  • 7.20 树hash |字典树模板❗
  • LangChain4j多模型共存+整合SpringBoot
  • springboot websocket 自动重启方案
  • SpringBoot3集成MapstructPlus
  • 抓包工具使用教程