1
0
forked from dyf/dyf-vue-ui
Files
dyf-vue-ui/src/utils/coordinate-transform.ts
2025-09-11 09:49:52 +08:00

212 lines
5.0 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

/**
* 坐标系转换工具
* WGS84地球坐标系与 GCJ02火星坐标系相互转换
*/
// 地标转国测常量
const X_PI = (3.14159265358979324 * 3000.0) / 180.0;
const PI = 3.1415926535897932384626;
const A = 6378245.0; // 卫星椭球坐标投影到平面地图坐标系的投影因子
const EE = 0.00669342162296594323; // 椭球的偏心率
/**
* 坐标点类型定义
*/
export interface CoordinatePoint {
lng: number; // 经度
lat: number; // 纬度
}
/**
* 判断是否在国内,在中国国内的经纬度才需要做偏移
* @param lng 经度
* @param lat 纬度
* @returns 是否在国外
*/
function outOfChina(lng: number, lat: number): boolean {
return (
lng < 72.004 ||
lng > 137.8347 ||
lat < 0.8293 ||
lat > 55.8271
);
}
/**
* 转化经度
* @param lng 经度
* @param lat 纬度
* @returns 转换后的经度偏移量
*/
function transformLng(lng: number, lat: number): number {
let 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;
}
/**
* 转化纬度
* @param lng 经度
* @param lat 纬度
* @returns 转换后的纬度偏移量
*/
function transformLat(lng: number, lat: number): number {
let 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;
}
/**
* WGS84坐标系转GCJ02坐标系地球坐标系转火星坐标系
* @param lng 经度
* @param lat 纬度
* @returns 转换后的坐标 [经度, 纬度]
*/
export function wgs84ToGcj02(lng: number, lat: number): [number, number] {
if (outOfChina(lng, lat)) {
return [lng, lat];
}
const dlat = transformLat(lng - 105.0, lat - 35.0);
const dlng = transformLng(lng - 105.0, lat - 35.0);
const radlat = (lat / 180.0) * PI;
let magic = Math.sin(radlat);
magic = 1 - EE * magic * magic;
const sqrtmagic = Math.sqrt(magic);
const transformedLat =
(dlat * 180.0) /
(((A * (1 - EE)) / (magic * sqrtmagic)) * PI);
const transformedLng =
(dlng * 180.0) / ((A / sqrtmagic) * Math.cos(radlat) * PI);
const mglat = lat + transformedLat;
const mglng = lng + transformedLng;
return [mglng, mglat];
}
/**
* GCJ02坐标系转WGS84坐标系火星坐标系转地球坐标系
* @param lng 经度
* @param lat 纬度
* @returns 转换后的坐标 [经度, 纬度]
*/
export function gcj02ToWgs84(lng: number, lat: number): [number, number] {
if (outOfChina(lng, lat)) {
return [lng, lat];
}
const dlat = transformLat(lng - 105.0, lat - 35.0);
const dlng = transformLng(lng - 105.0, lat - 35.0);
const radlat = (lat / 180.0) * PI;
let magic = Math.sin(radlat);
magic = 1 - EE * magic * magic;
const sqrtmagic = Math.sqrt(magic);
const transformedLat = (dlat * 180.0) / ((A * (1 - EE)) / (magic * sqrtmagic) * PI);
const transformedLng = (dlng * 180.0) / (A / sqrtmagic * Math.cos(radlat) * PI);
const mglat = lat + transformedLat;
const mglng = lng + transformedLng;
return [lng * 2 - mglng, lat * 2 - mglat];
}
/**
* 对象形式的坐标转换 - WGS84转GCJ02
* @param point 坐标点对象 {lng: 经度, lat: 纬度}
* @returns 转换后的坐标点对象
*/
export function wgs84ToGcj02Point(point: CoordinatePoint): CoordinatePoint {
const [lng, lat] = wgs84ToGcj02(point.lng, point.lat);
return { lng, lat };
}
/**
* 对象形式的坐标转换 - GCJ02转WGS84
* @param point 坐标点对象 {lng: 经度, lat: 纬度}
* @returns 转换后的坐标点对象
*/
export function gcj02ToWgs84Point(point: CoordinatePoint): CoordinatePoint {
const [lng, lat] = gcj02ToWgs84(point.lng, point.lat);
return { lng, lat };
}
/**
* 批量转换坐标点 - WGS84转GCJ02
* @param points 坐标点数组
* @returns 转换后的坐标点数组
*/
export function batchWgs84ToGcj02(points: CoordinatePoint[]): CoordinatePoint[] {
return points.map(point => wgs84ToGcj02Point(point));
}
/**
* 批量转换坐标点 - GCJ02转WGS84
* @param points 坐标点数组
* @returns 转换后的坐标点数组
*/
export function batchGcj02ToWgs84(points: CoordinatePoint[]): CoordinatePoint[] {
return points.map(point => gcj02ToWgs84Point(point));
}
// 默认导出
export default {
wgs84ToGcj02,
gcj02ToWgs84,
wgs84ToGcj02Point,
gcj02ToWgs84Point,
batchWgs84ToGcj02,
batchGcj02ToWgs84,
outOfChina
};