From 4e82fbcdf16258757ed0d57cb3fcc35f0f33a3d1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E9=A9=AC=E4=B8=89=E7=82=AE?= <15856818120@163.com> Date: Tue, 13 May 2025 17:04:47 +0800 Subject: [PATCH] =?UTF-8?q?Bug=E4=BF=AE=E5=A4=8D?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../service/impl/TbTowerServiceImpl.java | 10 +- .../utils/CoordinateTransform.java | 183 ++++++++++++++++++ .../lineManagement/child/towerFormTemp.js | 22 +-- .../lineManagement/child/towerFormTemp.html | 6 +- 4 files changed, 202 insertions(+), 19 deletions(-) create mode 100644 src/main/java/com/bonus/digitalSignage/utils/CoordinateTransform.java diff --git a/src/main/java/com/bonus/digitalSignage/basic/service/impl/TbTowerServiceImpl.java b/src/main/java/com/bonus/digitalSignage/basic/service/impl/TbTowerServiceImpl.java index 18267cd..5fdce1e 100644 --- a/src/main/java/com/bonus/digitalSignage/basic/service/impl/TbTowerServiceImpl.java +++ b/src/main/java/com/bonus/digitalSignage/basic/service/impl/TbTowerServiceImpl.java @@ -77,9 +77,9 @@ public class TbTowerServiceImpl implements TbTowerService { public ServerResponse addTbTower(TbTowerVo data) { try { //判断经纬度是否合法 - if(!StrUtil.isValidLongitude(Double.parseDouble(data.getLon())) || !StrUtil.isValidLatitude(Double.parseDouble(data.getLat()))){ + /* if(!StrUtil.isValidLongitude(Double.parseDouble(data.getLon())) || !StrUtil.isValidLatitude(Double.parseDouble(data.getLat()))){ return ServerResponse.createErroe("请输入正确经纬度"); - } + }*/ TbTowerVo tbTower = tbTowerMapper.getTbTowerBySort(data); if (StringUtils.isNotNull(tbTower)){ return ServerResponse.createErroe("排序已存在"); @@ -90,9 +90,9 @@ public class TbTowerServiceImpl implements TbTowerService { data.setBaiduLat(String.valueOf(bd09[0])); data.setBaiduLon(String.valueOf(bd09[1])); }else { - double[] bd09 =CoordinateConverter.cgcs2000ToBd09(Double.parseDouble(data.getLat()),Double.parseDouble(data.getLon())); - data.setBaiduLat(String.valueOf(bd09[0])); - data.setBaiduLon(String.valueOf(bd09[1])); + double[] bd09 =CoordinateTransform.cgcs2000ToBd09(Double.parseDouble(data.getLat()),Double.parseDouble(data.getLon()),Double.parseDouble(data.getCentralMeridian())); + data.setBaiduLon(String.valueOf(bd09[0])); + data.setBaiduLat(String.valueOf(bd09[1])); } Long userId = UserUtil.getLoginUser().getId(); data.setCreateUserId(userId); diff --git a/src/main/java/com/bonus/digitalSignage/utils/CoordinateTransform.java b/src/main/java/com/bonus/digitalSignage/utils/CoordinateTransform.java new file mode 100644 index 0000000..f8b12e4 --- /dev/null +++ b/src/main/java/com/bonus/digitalSignage/utils/CoordinateTransform.java @@ -0,0 +1,183 @@ +package com.bonus.digitalSignage.utils; + +/** + * @author 马三炮 + * @date 2025/5/13 + */ +public class CoordinateTransform { + + // 定义一些常量 + private static final double x_PI = 3.14159265358979324 * 3000.0 / 180.0; + private static final double PI = 3.1415926535897932384626; + private static final double a = 6378245.0; + private static final double ee = 0.00669342162296594323; + + /** + * CGCS2000转WGS84坐标 + * (实际上CGCS2000和WGS84差异很小,通常可以忽略这步转换) + */ + public static double[] cgcs2000ToWgs84(double lng, double lat) { + // 实际应用中,这里可能需要更精确的转换参数 + // 但通常CGCS2000和WGS84差异在厘米级,可以忽略 + return new double[]{lng, lat}; + } + + /** + * WGS84转GCJ02(火星坐标系) + */ + public static double[] wgs84ToGcj02(double lng, double lat) { + if (outOfChina(lng, lat)) { + return new double[]{lng, lat}; + } + double dlat = transformLat(lng - 105.0, lat - 35.0); + double dlng = transformLng(lng - 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); + dlng = (dlng * 180.0) / (a / sqrtmagic * Math.cos(radlat) * PI); + double mglat = lat + dlat; + double mglng = lng + dlng; + return new double[]{mglng, mglat}; + } + + /** + * GCJ02(火星坐标系)转BD09(百度坐标系) + */ + public static double[] gcj02ToBd09(double lng, double lat) { + double z = Math.sqrt(lng * lng + lat * lat) + 0.00002 * Math.sin(lat * x_PI); + double theta = Math.atan2(lat, lng) + 0.000003 * Math.cos(lng * x_PI); + double bd_lng = z * Math.cos(theta) + 0.0065; + double bd_lat = z * Math.sin(theta) + 0.006; + return new double[]{bd_lng, bd_lat}; + } + + /** + * 判断坐标是否在中国境外 + */ + private static boolean outOfChina(double lng, double lat) { + return lng < 72.004 || lng > 137.8347 || lat < 0.8293 || lat > 55.8271; + } + + /** + * 纬度转换 + */ + private static double transformLat(double lng, double lat) { + double ret = -100.0 + 2.0 * lng + 3.0 * lat + 0.2 * lat * lat + 0.1 * lng * lat + 0.2 * Math.sqrt(Math.abs(lng)); + ret += (20.0 * Math.sin(6.0 * lng * PI) + 20.0 * Math.sin(2.0 * lng * PI)) * 2.0 / 3.0; + ret += (20.0 * Math.sin(lat * PI) + 40.0 * Math.sin(lat / 3.0 * PI)) * 2.0 / 3.0; + ret += (160.0 * Math.sin(lat / 12.0 * PI) + 320 * Math.sin(lat * PI / 30.0)) * 2.0 / 3.0; + return ret; + } + + /** + * 经度转换 + */ + private static double transformLng(double lng, double lat) { + double ret = 300.0 + lng + 2.0 * lat + 0.1 * lng * lng + 0.1 * lng * lat + 0.1 * Math.sqrt(Math.abs(lng)); + ret += (20.0 * Math.sin(6.0 * lng * PI) + 20.0 * Math.sin(2.0 * lng * PI)) * 2.0 / 3.0; + ret += (20.0 * Math.sin(lng * PI) + 40.0 * Math.sin(lng / 3.0 * PI)) * 2.0 / 3.0; + ret += (150.0 * Math.sin(lng / 12.0 * PI) + 300.0 * Math.sin(lng / 30.0 * PI)) * 2.0 / 3.0; + return ret; + } + + /** + * 大地2000转百度坐标系 + */ + public static double[] cgcs2000ToBd09(double x, double y,double lng0) { + // 首先将平面坐标转换为经纬度(这里需要知道大地2000坐标的投影参数) + // 假设x,y是3度带投影坐标,中央经线为120度(需要根据实际情况调整) + //double lng0 = 108; // 中央经线 + double[] latLng = gaussToLatLon(x, y, lng0); + + // CGCS2000转WGS84(通常可以忽略) + double[] wgs84 = cgcs2000ToWgs84(latLng[0], latLng[1]); + + // WGS84转GCJ02 + double[] gcj02 = wgs84ToGcj02(wgs84[0], wgs84[1]); + + // GCJ02转BD09 + double[] bd09 = gcj02ToBd09(gcj02[0], gcj02[1]); + + return bd09; + } + + /** + * 高斯投影反算:由平面坐标(单位:米)反算成经纬度 + * @param x 平面坐标x + * @param y 平面坐标y + * @param lng0 中央经线 + */ + private static double[] gaussToLatLon(double x, double y, double lng0) { + double[] latLon = new double[2]; + + // 投影参数 + double a = 6378137.0; // CGCS2000椭球长半轴 + double f = 1 / 298.257222101; // CGCS2000椭球扁率 + double b = a * (1 - f); // 短半轴 + double e = Math.sqrt(1 - (b * b) / (a * a)); // 第一偏心率 + + // 计算参数 + double e2 = e * e; + double e4 = e2 * e2; + double e6 = e4 * e2; + double e8 = e4 * e4; + + // 计算带号 + int n = (int) (lng0 / 3); + + // 计算经差 + double lngDiff = (y - 500000.0) / (a * (1 - e2 / 4 - 3 * e4 / 64 - 5 * e6 / 256)); + + // 计算底点纬度 + double Bf = x / (a * (1 - e2 / 4 - 3 * e4 / 64 - 5 * e6 / 256)); + + // 迭代计算底点纬度 + double Bf0 = Bf; + double Bf1; + double V; + do { + Bf1 = (x / (a * (1 - e2 / 4 - 3 * e4 / 64 - 5 * e6 / 256))) + + ((3 * e2 / 8 + 3 * e4 / 32 + 45 * e6 / 1024) * Math.sin(2 * Bf0)) - + ((15 * e4 / 256 + 45 * e6 / 1024) * Math.sin(4 * Bf0)) + + (35 * e6 / 3072 * Math.sin(6 * Bf0)); + V = Math.abs(Bf1 - Bf0); + Bf0 = Bf1; + } while (V > 1e-10); + + // 计算纬度 + double Nf = a / Math.sqrt(1 - e2 * Math.sin(Bf1) * Math.sin(Bf1)); + double Tf = Math.tan(Bf1) * Math.tan(Bf1); + double D = lngDiff * lngDiff; + double Cf = e2 * Math.cos(Bf1) * Math.cos(Bf1) / (1 - e2); + + double lat = Bf1 - (Nf * Math.tan(Bf1) / (a * a)) * + (D / 2 - (5 + 3 * Tf + 10 * Cf - 9 * Tf * Cf - 4 * Cf * Cf - 9 * e2) * D * D / 24 + + (61 + 90 * Tf + 298 * Cf + 45 * Tf * Tf - 252 * e2 - 3 * Cf * Cf) * D * D * D / 720); + + double lng = lng0 * Math.PI / 180 + + (lngDiff - (1 + 2 * Tf + Cf) * D * D * D / 6 + + (5 - 2 * Cf + 28 * Tf - 3 * Cf * Cf + 8 * e2 + 24 * Tf * Tf) * D * D * D * D / 120) / Math.cos(Bf1); + + // 转换为度 + lat = lat * 180 / Math.PI; + lng = lng * 180 / Math.PI; + + latLon[0] = lng; + latLon[1] = lat; + + return latLon; + } + + public static void main(String[] args) { + double x = 3730067.601; + double y = 396052.578; + + // 转换为百度坐标系 + double[] bd09 = cgcs2000ToBd09(x, y,108); + + System.out.println("百度坐标系(BD09)经度: " + bd09[0]); + System.out.println("百度坐标系(BD09)纬度: " + bd09[1]); + } +} diff --git a/src/main/resources/static/js/basic/lineManagement/child/towerFormTemp.js b/src/main/resources/static/js/basic/lineManagement/child/towerFormTemp.js index 17e9bef..3c87240 100644 --- a/src/main/resources/static/js/basic/lineManagement/child/towerFormTemp.js +++ b/src/main/resources/static/js/basic/lineManagement/child/towerFormTemp.js @@ -20,10 +20,10 @@ function setParams(params) { $('#wgs84Fields').show(); $('#2000Fields').hide(); // 设置验证规则 - $('input[name^="longitude2000"], input[name^="latitude2000"], input[name="centralMeridian"]').removeAttr('lay-verify'); + /* $('input[name^="longitude2000"], input[name^="latitude2000"], input[name="centralMeridian"]').removeAttr('lay-verify'); $('input[name="longitude"]').attr('lay-verify', 'required|longitude'); $('input[name="latitude"]').attr('lay-verify', 'required|latitude'); - +*/ console.log(idParam + "idParam") if (idParam) { getTowerById(); @@ -73,7 +73,7 @@ function setParams(params) { } }, // 经度验证 - longitude: function (value, item) { + /* longitude: function (value, item) { if (value) { // if (!/^[\-\+]?((180(\.0{1,6})?)|((\d{1,2}|1[0-7]\d)(\.\d{1,6})?))$/.test(value)) { // return '请输入正确的经度(-180.0~+180.0)'; @@ -87,10 +87,10 @@ function setParams(params) { return '经度应精确到最多6位小数且在正确范围内'; } } - }, + },*/ // 纬度验证 - latitude: function (value, item) { + /*latitude: function (value, item) { if (value) { // if (!/^[\-\+]?((90(\.0{1,6})?)|(([0-8]?\d)(\.\d{1,6})?))$/.test(value)) { // return '请输入正确的纬度(-90.0~+90.0)'; @@ -108,7 +108,7 @@ function setParams(params) { return '纬度应精确到最多6位小数'; } } - } + }*/ }); // 表单提交 @@ -151,7 +151,7 @@ function getTowerById() { id: idParam, encryptedData: encryptCBC(JSON.stringify({id: idParam})) }; - + ajaxRequest(url, "POST", params, true, null, function(result) { layer.close(loadingMsg); if (result.code === 200) { @@ -170,7 +170,7 @@ function setFormData(data) { if(data) { // 先设置基本表单数据 form.val("towerForm", data); - + // 根据 uploadType 设置坐标系选择 if(data.uploadType) { $('.coordinate-option').removeClass('active'); @@ -223,7 +223,7 @@ function saveData(data) { params = { encryptedData: encryptCBC(JSON.stringify(params)) } - + // 禁用所有输入框和按钮 function disableForm() { $('input').attr('disabled', true); @@ -237,7 +237,7 @@ function saveData(data) { $('.coordinate-option').css('pointer-events', 'auto'); $('.save, .cancel').removeClass("layui-btn-disabled").attr("disabled", false); } - + ajaxRequest(url, "POST", params, true, function () { disableForm(); // 请求开始时禁用表单 }, function (result) { @@ -268,4 +268,4 @@ function closePage(type) { parent.reloadData() parent.parent.reloadData() } -} \ No newline at end of file +} diff --git a/src/main/resources/static/pages/basic/lineManagement/child/towerFormTemp.html b/src/main/resources/static/pages/basic/lineManagement/child/towerFormTemp.html index c14d8c8..c369bc2 100644 --- a/src/main/resources/static/pages/basic/lineManagement/child/towerFormTemp.html +++ b/src/main/resources/static/pages/basic/lineManagement/child/towerFormTemp.html @@ -116,7 +116,7 @@
+ placeholder="请输入经度(大约73.55°E至135.08°E)---" maxlength="10" class="layui-input">
@@ -124,7 +124,7 @@
+ placeholder="请输入纬度(大约4°N至53°N)---" maxlength="10" class="layui-input">
@@ -140,4 +140,4 @@ - \ No newline at end of file +