gis坐标计算

news/2025/10/5 17:15:34/文章来源:https://www.cnblogs.com/chenTo/p/19126750
package cn.service.hspd.utils;import com.alibaba.fastjson2.JSON;import java.awt.geom.Point2D;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;public class GisUtil {// 两点距离 x,lon 经度  y,lat 纬度private static final double EARTH_RADIUS = 6371000;/*** 计算两点jul** @param p1* @param p2* @return*/public static double jl(Point2D p1, Point2D p2) {double lat1Rad = Math.toRadians(p1.getY());double lon1Rad = Math.toRadians(p1.getX());double lat2Rad = Math.toRadians(p2.getY());double lon2Rad = Math.toRadians(p2.getX());double deltaLat = lat2Rad - lat1Rad;double deltaLon = lon2Rad - lon1Rad;double a = Math.sin(deltaLat / 2) * Math.sin(deltaLat / 2)+ Math.cos(lat1Rad) * Math.cos(lat2Rad)* Math.sin(deltaLon / 2) * Math.sin(deltaLon / 2);double c = 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1 - a));return EARTH_RADIUS * c;}/*** 判断两条线是否相交返回相交点** @param p1* @param p2* @param p3* @param p4* @return*/public static Point2D.Double xj(Point2D p1, Point2D p2, Point2D p3, Point2D p4) {double x1 = p1.getX(), y1 = p1.getY();double x2 = p2.getX(), y2 = p2.getY();double x3 = p3.getX(), y3 = p3.getY();double x4 = p4.getX(), y4 = p4.getY();double d = (x1 - x2) * (y3 - y4) - (y1 - y2) * (x3 - x4);if (d == 0) return null;double xi = ((x3 - x4) * (x1 * y2 - y1 * x2) - (x1 - x2) * (x3 * y4 - y3 * x4)) / d;double yi = ((y3 - y4) * (x1 * y2 - y1 * x2) - (y1 - y2) * (x3 * y4 - y3 * x4)) / d;if (x1 < Math.min(x1, x2) || xi > Math.max(x1, x2) || xi < Math.min(x3, x4) || xi > Math.max(x3, x4))return null;if (yi < Math.min(y1, y2) || yi > Math.max(y1, y2) || yi < Math.min(y3, y4) || yi > Math.max(y3, y4))return null;return new Point2D.Double(xi, yi);}/*** 中心点** @param list* @return*/public static Point2D.Double zxd(List<Point2D.Double> list) {if (list.size() <= 1) return null;Point2D top = list.get(0);Point2D bot = list.get(1);if (list.size() == 2) {return new Point2D.Double((top.getX() + bot.getX()) / 2.0, (top.getY() + bot.getY()) / 2.0);}double maxJl = -1;for (int i = 0; i < list.size(); i++) {for (int j = i + 1; j < list.size(); j++) {if (Math.abs(i - j) == 1 || (i == 0 && j == list.size() - 1)) continue;double jl = jl(list.get(i), list.get(j));if (jl > maxJl) {maxJl = jl;top = list.get(i);bot = list.get(j);}}}return new Point2D.Double((top.getX() + bot.getX()) / 2.0, (top.getY() + bot.getY()) / 2.0);}/*** 最大直径** @param list* @return*/public static double zdzj(List<Point2D.Double> list) {if (list.size() <= 1) return 0;Point2D top = list.get(0);Point2D bot = list.get(1);if (list.size() == 2) {return jl(top, bot);}double maxJl = -1;for (int i = 0; i < list.size(); i++) {for (int j = i + 1; j < list.size(); j++) {if (Math.abs(i - j) == 1 || (i == 0 && j == list.size() - 1)) continue;double jl = jl(list.get(i), list.get(j));if (jl > maxJl) {maxJl = jl;top = list.get(i);bot = list.get(j);}}}return jl(top, bot);}/*** 最x小直径** @param list* @return*/public static double zxzj(List<Point2D.Double> list) {if (list.size() <= 1) return 0;Point2D top = list.get(0);Point2D bot = list.get(1);if (list.size() == 2) {return jl(top, bot);}double min = jl(list.get(0), list.get(3));for (int i = 0; i < list.size(); i++) {for (int j = i + 1; j < list.size(); j++) {if (Math.abs(i - j) == 1 || (i == 0 && j == list.size() - 1)) continue;double jl = jl(list.get(i), list.get(j));if (jl <= min) {min = jl;top = list.get(i);bot = list.get(j);}}}return jl(top, bot);}public static double zc(List<Point2D.Double> list) {double zc = 0;for (int i = 1; i < list.size(); i++) {zc += jl(list.get(i - 1), list.get(i));}return zc;}/*** 计算体积 圆柱 锥形** @param bj* @param height* @param lx     1 圆柱 2 圆锥* @return*/public static double tj(double bj, double height, int lx) {if (lx == 1) {return Math.PI * Math.pow(bj, 2) * height;}return (1.0 / 3) * Math.PI * Math.pow(bj, 2) * height;}public static double format(Double d, int i) {if (d == null) return 0.0;String format = String.format("%." + i + "f", d);return Double.parseDouble(format);}/*** 像素转经纬坐标** @param zs     图片左上位置* @param yx     图片右下位置* @param width  图片宽* @param height 图片高* @param zb     像素信息* @return*/public static Point2D.Double xsTojw(Point2D zs, Point2D yx, double width, double height, Point2D zb) {double lat = zs.getY() - (zb.getY() * (zs.getY() - yx.getY()) / height);double lon = zs.getX() - (zb.getX() * (yx.getX() - zs.getX()) / width);return new Point2D.Double(lon, lat);}// 长半轴private static final double WGS84_A = 6378137.0;// 短半轴private static final double WGS84_B = 6356752.314245;// 扁率private static final double WGS84_F = 1.0 / 298.257223563;// 第一偏心率平方private static final double WGS84_E2 = 6.69437999014e-3;// 收敛经度private static final double WGS84_EPSILON = 1.0e-12;/*** 三维直角坐标转经纬度** @param x* @param y* @param z* @return*/public static Point2D.Double swTojw(double x, double y, double z) {double longitude = Math.atan2(y, x);double p = Math.sqrt(x * x + y * y);double latitude = Math.atan2(z, p * (1 - WGS84_E2));double height = 0.0;int maxIterations = 10;for (int i = 0; i < maxIterations; i++) {double sinLat = Math.sin(latitude);double n = WGS84_A / Math.sqrt(1 - WGS84_E2 * sinLat * sinLat);double newHeight = p / Math.cos(latitude) - n;double newLatitude = Math.atan2(z, p * (1 - WGS84_E2 * n / (n + newHeight)));if (Math.abs(newLatitude - latitude) < WGS84_EPSILON && Math.abs(newHeight - height) < WGS84_EPSILON) {break;}latitude = newLatitude;height = newHeight;}double lon = Math.toDegrees(longitude);double lat = Math.toDegrees(latitude);return new Point2D.Double(lon, lat);}/*** 经纬高转为三维直角坐标** @param lon    经度* @param lat    纬度* @param height 高度* @return*/public static List<Double> jwTosw(double lon, double lat, double height) {double lonRad = Math.toRadians(lon);double latRad = Math.toRadians(lat);double sinLat = Math.sin(latRad);double coslat = Math.cos(latRad);double sinLon = Math.sin(lonRad);double cosLon = Math.cos(lonRad);double n = WGS84_A / Math.sqrt(1 - WGS84_E2 * sinLat * sinLat);double x = (n + height) * coslat * cosLon;double y = (n + height) * coslat * sinLon;double z = (n * (1 - WGS84_E2) + height) * sinLat;return Arrays.asList(x, y, z);}/*** 坐标经纬转像素** @param zs     图片左上位置* @param yx     图片右下位置* @param width  图片宽* @param height 图片高* @param zb     坐标经纬度* @return*/public static Point2D.Double jwToxs(Point2D zs, Point2D yx, double width, double height, Point2D zb) {int x = (int) (zb.getX() - zs.getX() * width / (yx.getX() - zs.getX()));int y = (int) ((zs.getY() - zb.getY()) * height / (zs.getY() - yx.getY()));return new Point2D.Double(x, y);}/*** 判断当前位置是否在多边形区域内** @param orderLocation     当前点* @param partitionLocation 区域顶点* @return*/public static boolean isInPolygon(Map orderLocation, String partitionLocation) {double p_x = Double.parseDouble((String) orderLocation.get("X"));double p_y = Double.parseDouble((String) orderLocation.get("Y"));Point2D.Double point = new Point2D.Double(p_x, p_y);List<Point2D.Double> pointList = new ArrayList<Point2D.Double>();List objects = JSON.parseArray(partitionLocation);for (Object str : objects) {List<Double> doubles = JSON.parseArray(JSON.toJSONString(str), Double.class);double polygonPoint_x = doubles.get(0);double polygonPoint_y = doubles.get(1);Point2D.Double polygonPoint = new Point2D.Double(polygonPoint_x, polygonPoint_y);pointList.add(polygonPoint);}return IsPtInPoly(point, pointList);}/*** 返回一个点是否在一个多边形区域内, 如果点位于多边形的顶点或边上,不算做点在多边形内,返回false** @param point* @param polygon* @return*/public static boolean checkWithJdkGeneralPath(Point2D.Double point, List<Point2D.Double> polygon) {java.awt.geom.GeneralPath p = new java.awt.geom.GeneralPath();Point2D.Double first = polygon.get(0);p.moveTo(first.x, first.y);polygon.remove(0);for (Point2D.Double d : polygon) {p.lineTo(d.x, d.y);}p.lineTo(first.x, first.y);p.closePath();return p.contains(point);}/*** 判断点是否在多边形内,如果点位于多边形的顶点或边上,也算做点在多边形内,直接返回true** @param point 检测点* @param pts   多边形的顶点* @return 点在多边形内返回true, 否则返回false*/public static boolean IsPtInPoly(Point2D.Double point, List<Point2D.Double> pts) {int N = pts.size();boolean boundOrVertex = true; //如果点位于多边形的顶点或边上,也算做点在多边形内,直接返回trueint intersectCount = 0;//cross points count of xdouble precision = 2e-10; //浮点类型计算时候与0比较时候的容差Point2D.Double p1, p2;//neighbour bound verticesPoint2D.Double p = point; //当前点p1 = pts.get(0);//left vertexfor (int i = 1; i <= N; ++i) {//check all raysif (p.equals(p1)) {return boundOrVertex;//p is an vertex}p2 = pts.get(i % N);//right vertexif (p.x < Math.min(p1.x, p2.x) || p.x > Math.max(p1.x, p2.x)) {//ray is outside of our interestsp1 = p2;continue;//next ray left point}if (p.x > Math.min(p1.x, p2.x) && p.x < Math.max(p1.x, p2.x)) {//ray is crossing over by the algorithm (common part of)if (p.y <= Math.max(p1.y, p2.y)) {//x is before of rayif (p1.x == p2.x && p.y >= Math.min(p1.y, p2.y)) {//overlies on a horizontal rayreturn boundOrVertex;}if (p1.y == p2.y) {//ray is verticalif (p1.y == p.y) {//overlies on a vertical rayreturn boundOrVertex;} else {//before ray++intersectCount;}} else {//cross point on the left sidedouble xinters = (p.x - p1.x) * (p2.y - p1.y) / (p2.x - p1.x) + p1.y;//cross point of yif (Math.abs(p.y - xinters) < precision) {//overlies on a rayreturn boundOrVertex;}if (p.y < xinters) {//before ray++intersectCount;}}}} else {//special case when ray is crossing through the vertexif (p.x == p2.x && p.y <= p2.y) {//p crossing over p2Point2D.Double p3 = pts.get((i + 1) % N); //next vertexif (p.x >= Math.min(p1.x, p3.x) && p.x <= Math.max(p1.x, p3.x)) {//p.x lies between p1.x & p3.x++intersectCount;} else {intersectCount += 2;}}}p1 = p2;//next ray left point}if (intersectCount % 2 == 0) {//偶数在多边形外return false;} else { //奇数在多边形内return true;}}
}
package cn.service.hspd.utils;import java.awt.geom.AffineTransform;
import java.awt.geom.Point2D;public class GeoPixelConverter {private final AffineTransform transform;private final double pixelError;public GeoPixelConverter(double topLeftLon, double topLeftLat,double bottomRightLon, double bottomRightLat,int widthPixels, int heightPixels) {// 计算仿射变换参数(保留10位小数)double scaleX = (bottomRightLon - topLeftLon) / widthPixels;double scaleY = (bottomRightLat - topLeftLat) / heightPixels;this.transform = new AffineTransform(scaleX, 0, 0, scaleY, topLeftLon, topLeftLat);// 理论最大误差计算(基于双精度浮点运算)this.pixelError = Math.max(Math.abs(scaleX) * 1e-10,Math.abs(scaleY) * 1e-10);}public Point2D.Double pixelToGeo(int x, int y) {Point2D.Double src = new Point2D.Double(x, y);Point2D.Double dst = new Point2D.Double();transform.transform(src, dst);// 结果四舍五入到小数点后8位dst.x = Math.round(dst.x * 1e8) / 1e8;dst.y = Math.round(dst.y * 1e8) / 1e8;return dst;}public Point2D geoToPixel(double longitude, double latitude) {try {Point2D.Double src = new Point2D.Double(longitude, latitude);Point2D.Double dst = new Point2D.Double();transform.inverseTransform(src, dst);// 像素坐标取整dst.x = Math.round(dst.x);dst.y = Math.round(dst.y);return dst;} catch (Exception e) {throw new IllegalArgumentException("坐标超出转换范围");}}public double getMaxError() {return pixelError;}// 边缘像素补偿算法示例public static Point2D.Double adjustEdgePixel(int x, int y, int width, int height) {// 对边缘像素进行0.5像素偏移补偿double adjX = (x == 0) ? 0.5 : (x == width-1) ? width-1.5 : x;double adjY = (y == 0) ? 0.5 : (y == height-1) ? height-1.5 : y;return new Point2D.Double(adjX, adjY);}public static void main(String[] args) {// 示例:故宫影像图转换(误差<0.00001度)GeoPixelConverter converter = new GeoPixelConverter(116.391111, 39.916667, // 左上角经纬度116.403889, 39.908333, // 右下角经纬度4096, 4096);           // 图像宽高Point2D.Double geo = converter.pixelToGeo(4096, 0);System.out.printf("中心点坐标: %.8f, %.8f%n", geo.x, geo.y);System.out.printf("理论最大误差: %.10f 度", converter.getMaxError());}
}

 

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/928506.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Spring AI Alibaba + Nacos 动态 MCP Server 代理方案 - 详解

Spring AI Alibaba + Nacos 动态 MCP Server 代理方案 - 详解2025-10-05 16:58 tlnshuju 阅读(0) 评论(0) 收藏 举报pre { white-space: pre !important; word-wrap: normal !important; overflow-x: auto !import…

trick 小记

备忘录数据范围可以 \(n^2\) 算法且不考虑顺序的情况下可以连续段 dp要仔细检查数组是否开小,线段树最少 4 倍,建边的数组看条数,一般情况下开 2m,注意看数据范围时 \(k\times 10^x\) 的形式,一数组两用直接开到 …

公司网站维护方案网页设计怎么做网站

Vue3 新项目默认工程文件理解 文章目录 Vue3 新项目默认工程文件理解0、工程文件结构图1、main.ts2、index.html源文件编译后 3、App.vue4、.d.ts 文件作用 0、工程文件结构图 1、main.ts // 引入 createApp 函数 import { createApp } from vue // 引入 style.css 文件&#…

day17 课程()

day17 课程()课程: 17.1 了解异常------------------------------------------------ 执行后17.2 体验异常------------------------------------------------ 执行后17.3 了解异常类型---------------------------…

wordpress移动到回收站时发生错误.wordpress能做app

Charles是在您自己的计算机上运行的Web代理&#xff08;HTTP代理 / HTTP监视器&#xff09;&#xff0c;您的网络浏览器&#xff08;或任何其他Internet应用程序&#xff09;配置为通过Charles访问Internet&#xff0c;Charles可以为您记录并显示发送和接收的所有数据。 Http抓…

NKOJ全TJ计划——NP11744

题目内容 [20241017] Min-max 容斥 小 M 在\(\pi\) 岁时学会了 min-max 容斥。 给定一张 \(n\)个点\(m\)条边的边带权简单连通无向图。现需要将其的每个结点染成黑色或白色。 定义两个结点的距离为这两点间所有路径的边…

ROIR 2025

ROIR 2025 https://www.luogu.com.cn/problem/list?type=luogu&page=1&tag=479|62 二维蚱蜢 先贪心地往右上跳,跳到某维坐标与终点相同,再横着或竖着跳。 不完全质数 意义不明。 显然满足条件的数的形态是,…

网站上线前要做哪些准备如何做营销策划方案

笔记整理 | 谭亦鸣&#xff0c;东南大学博士生来源&#xff1a;EACL’21链接&#xff1a;https://www.aclweb.org/anthology/2021.eacl-main.35.pdf概述与动机本文提出了一种基于递归超图的知识图谱问答方法RecHyperNet&#xff0c;作者认为人回答问题时倾向于在推理过程中递归…

网站建设很简单f2fpay wordpress

1.理论知识&#xff1a;HCIE认证首先要求考生具备扎实的云计算理论基础&#xff0c;包括云计算的基本概念、架构、关键技术、安全管理等方面的知识。考生需要深入理解云计算的核心原理&#xff0c;以及华为云计算产品的特点和优势。 2.实践技能&#xff1a;除了理论知识外&…

贵阳免费网站建设spam free wordpress

思维导图&#xff1a; 不同设备号文件绑定&#xff1a;

网站框架图怎么做我想做微商怎么加入

在编写汉诺塔实验的时候&#xff0c;自己设计了一个全局的计数变量count用来计数移动次数&#xff0c;结果运行的时候报了这样的错误&#xff0c;错误也锁定在全局变量的定义那里。 没想通为什么会有语法错误&#xff0c;去查了一下发下是c的库函数有关键字count&#xff0c;所…

实用指南:万兴PDF手机版

pre { white-space: pre !important; word-wrap: normal !important; overflow-x: auto !important; display: block !important; font-family: "Consolas", "Monaco", "Courier New", …

python编写AI生常用匡架及使用指令集

以下是Python中常用的AI相关框架及其使用指令集,涵盖了机器学习、深度学习、自然语言处理等多个领域: 1. TensorFlow 简介:谷歌开发的开源深度学习框架,支持多种平台和语言。 安装指令: pip install tensorflow …

10月5日在图书馆的3/4天

10月5日在图书馆的3/4天刚过4点,想起来我好像成功开通了博客,正巧做题也累了,那就不摘下带上的耳机了,写写题解吧。 1来看看第一道题吧 https://www.luogu.com.cn/problem/P1990 覆盖墙壁 题目大概 就是给你一面N…

泉州微信网站建设公司百度文库个人登录

Keepass2Android密码管理能帮助我们保存各类网站、应用的密码&#xff0c;大家提前设置好之后每次输入密码的时候只需要输入很少的字符就能快速解锁密码&#xff0c;为大家的日常使用提供方便。软件特色* 几乎可与所有的Android 的浏览器结合使用 (见下文)*快速解锁&#xff1a…

基于原生JavaScript前端和 Flask 后端的Todo 应用 - 详解

基于原生JavaScript前端和 Flask 后端的Todo 应用 - 详解pre { white-space: pre !important; word-wrap: normal !important; overflow-x: auto !important; display: block !important; font-family: "Consolas…

怎么样自学做网站wordpress框架简介

WampServer集成环境安装与配置实习到了第三个礼拜了,原来我们小组是以开发php为主的,我们项目的服务器也是用php做的,因此我觉得很有必要学一下php的相关知识,首先当然是搭建环境了,写篇博客分享下经验. 目录: 一.软件下载 二 ...C&plus;&plus;与Lua交互(三)通过上一篇…

1005模拟赛总结

代码源场。T1是猜结论题没什么好说的,T2需要把摄像头的应用转化一下,不能直接套,并且T2没有对拍导致挂了35分,T4是数据结构题,场上想到了离线,但是线段树维护的值比较巧妙,需要多练。场上还想了一个用平衡树+随…

详细介绍:【AI论文】R2R:通过小型与大型模型之间的令牌路由高效导航发散推理路径

pre { white-space: pre !important; word-wrap: normal !important; overflow-x: auto !important; display: block !important; font-family: "Consolas", "Monaco", "Courier New", …