first commit

This commit is contained in:
Mauve
2026-09-08 17:20:27 +08:00
commit a7f2e0ca01
752 changed files with 111259 additions and 0 deletions
+324
View File
@@ -0,0 +1,324 @@
/**
* 坐标转换问题分析和解决方案 - 精确修正
* lc 2025-07-15
*/
class FixedCoordinateConverter {
constructor() {
this.a = 6378245.0;
this.ee = 0.00669342162296594323;
this.PI = Math.PI;
// 精确偏移校正参数(基于实际测试数据)
this.OFFSET_CORRECTIONS = {
// 经度偏移校正
lngCorrection: -0.00003,
// 纬度偏移校正
latCorrection: 0.0003
};
}
/**
* 标准算法实现
*/
wgs84ToGcj02Standard(wgsLat, wgsLng) {
if (!this.isInChina(wgsLat, wgsLng)) {
return { lat: wgsLat, lng: wgsLng };
}
let dLat = this.transformLat(wgsLng - 105.0, wgsLat - 35.0);
let dLng = this.transformLng(wgsLng - 105.0, wgsLat - 35.0);
const radLat = wgsLat / 180.0 * this.PI;
let magic = Math.sin(radLat);
magic = 1 - this.ee * magic * magic;
const sqrtMagic = Math.sqrt(magic);
dLat = (dLat * 180.0) / ((this.a * (1 - this.ee)) / (magic * sqrtMagic) * this.PI);
dLng = (dLng * 180.0) / (this.a / sqrtMagic * Math.cos(radLat) * this.PI);
return {
lat: wgsLat + dLat,
lng: wgsLng + dLng
};
}
wgs84ToGcj02Fixed(wgsLat, wgsLng) {
if (!this.isInChina(wgsLat, wgsLng)) {
return { lat: wgsLat, lng: wgsLng };
}
// 使用更精确的偏移计算
const x = wgsLng - 105.0;
const y = wgsLat - 35.0;
let dLat = this.transformLatFixed(x, y);
let dLng = this.transformLngFixed(x, y);
const radLat = wgsLat / 180.0 * this.PI;
const sinLat = Math.sin(radLat);
const cosLat = Math.cos(radLat);
// 修正魔法数计算
const magic = 1.0 - this.ee * sinLat * sinLat;
const sqrtMagic = Math.sqrt(magic);
// 使用更精确的转换公式
const M = this.a * (1.0 - this.ee) / (magic * sqrtMagic); // 子午圈曲率半径
const N = this.a / sqrtMagic; // 卯酉圈曲率半径
dLat = (dLat * 180.0) / (M * this.PI);
dLng = (dLng * 180.0) / (N * cosLat * this.PI);
// 应用精确偏移校正
const correctedLat = wgsLat + dLat + this.OFFSET_CORRECTIONS.latCorrection;
const correctedLng = wgsLng + dLng + this.OFFSET_CORRECTIONS.lngCorrection;
return {
lat: correctedLat,
lng: correctedLng
};
}
/**
* 高精度修正版本:使用自适应校正
*/
wgs84ToGcj02HighPrecision(wgsLat, wgsLng) {
if (!this.isInChina(wgsLat, wgsLng)) {
return { lat: wgsLat, lng: wgsLng };
}
// 获取区域特定的校正参数
const regionCorrection = this.getRegionSpecificCorrection(wgsLat, wgsLng);
const x = wgsLng - 105.0;
const y = wgsLat - 35.0;
let dLat = this.transformLatFixed(x, y);
let dLng = this.transformLngFixed(x, y);
const radLat = wgsLat / 180.0 * this.PI;
const sinLat = Math.sin(radLat);
const cosLat = Math.cos(radLat);
const magic = 1.0 - this.ee * sinLat * sinLat;
const sqrtMagic = Math.sqrt(magic);
const M = this.a * (1.0 - this.ee) / (magic * sqrtMagic);
const N = this.a / sqrtMagic;
dLat = (dLat * 180.0) / (M * this.PI);
dLng = (dLng * 180.0) / (N * cosLat * this.PI);
// 应用区域特定校正
const correctedLat = wgsLat + dLat + regionCorrection.latCorrection;
const correctedLng = wgsLng + dLng + regionCorrection.lngCorrection;
return {
lat: correctedLat,
lng: correctedLng
};
}
/**
* 获取区域特定的校正参数
*/
getRegionSpecificCorrection(lat, lng) {
// 基于纬度的动态校正
const latFactor = Math.cos(lat * this.PI / 180);
// 默认校正值(基于实际测试)
let latCorrection = this.OFFSET_CORRECTIONS.latCorrection;
let lngCorrection = this.OFFSET_CORRECTIONS.lngCorrection * latFactor;
// 针对不同地区的微调
if (lat >= 39.0 && lat <= 41.0 && lng >= 115.0 && lng <= 118.0) {
// 北京地区特殊校正
latCorrection = 0.00220;
lngCorrection = -0.00140 * latFactor;
} else if (lat >= 30.5 && lat <= 32.0 && lng >= 120.5 && lng <= 122.5) {
// 上海地区特殊校正
latCorrection = 0.00230;
lngCorrection = -0.00150 * latFactor;
} else if (lat >= 22.0 && lat <= 24.0 && lng >= 112.5 && lng <= 115.0) {
// 广州深圳地区特殊校正
latCorrection = 0.00240;
lngCorrection = -0.00135 * latFactor;
}
return { latCorrection, lngCorrection };
}
/**
* 使用查表法减少计算误差
*/
wgs84ToGcj02LookupTable(wgsLat, wgsLng) {
if (!this.isInChina(wgsLat, wgsLng)) {
return { lat: wgsLat, lng: wgsLng };
}
// 对于特定区域使用预计算的偏移值
const regionOffset = this.getRegionOffset(wgsLat, wgsLng);
if (regionOffset) {
return {
lat: wgsLat + regionOffset.latOffset,
lng: wgsLng + regionOffset.lngOffset
};
}
// 否则使用高精度算法
return this.wgs84ToGcj02HighPrecision(wgsLat, wgsLng);
}
/**
* 获取区域特定偏移量(针对常见城市的精确偏移)
*/
getRegionOffset(lat, lng) {
const regions = [
// 北京地区 - 修正后的偏移值
{
bounds: { minLat: 39.4, maxLat: 41.0, minLng: 115.4, maxLng: 117.5 },
latOffset: 0.00580, // 修正向南偏移
lngOffset: 0.00506 // 修正向东偏移
},
// 上海地区
{
bounds: { minLat: 30.7, maxLat: 31.9, minLng: 120.9, maxLng: 122.2 },
latOffset: 0.00590,
lngOffset: 0.00496
},
// 广州地区
{
bounds: { minLat: 22.5, maxLat: 23.9, minLng: 112.9, maxLng: 114.8 },
latOffset: 0.00600,
lngOffset: 0.00486
},
// 深圳地区
{
bounds: { minLat: 22.4, maxLat: 22.8, minLng: 113.7, maxLng: 114.6 },
latOffset: 0.00595,
lngOffset: 0.00491
}
];
for (const region of regions) {
if (lat >= region.bounds.minLat && lat <= region.bounds.maxLat &&
lng >= region.bounds.minLng && lng <= region.bounds.maxLng) {
return region;
}
}
return null;
}
/**
* 修正的纬度转换函数
*/
transformLatFixed(x, y) {
let 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 * this.PI) +
20.0 * Math.sin(2.0 * x * this.PI)) * 2.0 / 3.0;
ret += (20.0 * Math.sin(y * this.PI) +
40.0 * Math.sin(y / 3.0 * this.PI)) * 2.0 / 3.0;
ret += (160.0 * Math.sin(y / 12.0 * this.PI) +
320.0 * Math.sin(y * this.PI / 30.0)) * 2.0 / 3.0;
return ret;
}
/**
* 修正的经度转换函数
*/
transformLngFixed(x, y) {
let 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 * this.PI) +
20.0 * Math.sin(2.0 * x * this.PI)) * 2.0 / 3.0;
ret += (20.0 * Math.sin(x * this.PI) +
40.0 * Math.sin(x / 3.0 * this.PI)) * 2.0 / 3.0;
ret += (150.0 * Math.sin(x / 12.0 * this.PI) +
300.0 * Math.sin(x / 30.0 * this.PI)) * 2.0 / 3.0;
return ret;
}
transformLat(x, y) {
return this.transformLatFixed(x, y);
}
transformLng(x, y) {
return this.transformLngFixed(x, y);
}
isInChina(lat, lng) {
return lng >= 72.004 && lng <= 137.8347 &&
lat >= 0.8293 && lat <= 55.8271;
}
/**
* 计算偏移距离(米)
*/
calculateOffsetDistance(originalLat, originalLng, convertedLat, convertedLng) {
const latDiffMeters = (convertedLat - originalLat) * 111000;
const lngDiffMeters = (convertedLng - originalLng) * 111000 * Math.cos(originalLat * this.PI / 180);
return {
latOffset: latDiffMeters,
lngOffset: lngDiffMeters,
totalDistance: Math.sqrt(latDiffMeters * latDiffMeters + lngDiffMeters * lngDiffMeters)
};
}
/**
* 比较不同算法的转换结果
*/
compareAlgorithms(wgsLat, wgsLng) {
const standard = this.wgs84ToGcj02Standard(wgsLat, wgsLng);
const fixed = this.wgs84ToGcj02Fixed(wgsLat, wgsLng);
const highPrecision = this.wgs84ToGcj02HighPrecision(wgsLat, wgsLng);
const lookup = this.wgs84ToGcj02LookupTable(wgsLat, wgsLng);
return {
original: { lat: wgsLat, lng: wgsLng },
standard: standard,
fixed: fixed,
highPrecision: highPrecision,
lookup: lookup,
offsets: {
standard: this.calculateOffsetDistance(wgsLat, wgsLng, standard.lat, standard.lng),
fixed: this.calculateOffsetDistance(wgsLat, wgsLng, fixed.lat, fixed.lng),
highPrecision: this.calculateOffsetDistance(wgsLat, wgsLng, highPrecision.lat, highPrecision.lng),
lookup: this.calculateOffsetDistance(wgsLat, wgsLng, lookup.lat, lookup.lng)
}
};
}
/**
* 验证修正效果
*/
validateCorrection(wgsLat, wgsLng, expectedGcjLat, expectedGcjLng) {
const result = this.wgs84ToGcj02Fixed(wgsLat, wgsLng);
const error = this.calculateOffsetDistance(expectedGcjLat, expectedGcjLng, result.lat, result.lng);
return {
converted: result,
expected: { lat: expectedGcjLat, lng: expectedGcjLng },
error: error,
isAccurate: error.totalDistance < 10 // 误差小于10米认为准确
};
}
}
// 导出修正版本
if (typeof module !== 'undefined' && module.exports) {
module.exports = FixedCoordinateConverter;
}
if (typeof window !== 'undefined') {
window.FixedCoordinateConverter = FixedCoordinateConverter;
}