coord-transform.ts 2.4 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980
  1. import proj4 from "proj4";
  2. // 屏幕点和真实点通用对象
  3. type Pos = [number, number, number];
  4. type Conversion = {
  5. scale: number;
  6. rotation: number;
  7. translate: number[];
  8. startAltitude: number[];
  9. altitude: number;
  10. };
  11. // 获取角度
  12. const getAngle = (p1: Pos, p2: Pos) => Math.atan2(p2[0] - p1[0], p2[1] - p1[1]);
  13. // 获取长度
  14. const getLength = (p1: Pos, p2: Pos) =>
  15. Math.sqrt(Math.pow(p2[0] - p1[0], 2) + Math.pow(p2[1] - p1[1], 2));
  16. // 获取本地与魔卡托的映射关系
  17. const getConversion2D = ([p1, p2]: Pos[], [b1, b2]: Pos[]) => {
  18. const rotation = getAngle(p1, p2) - getAngle(b1, b2);
  19. const scale = getLength(b1, b2) / getLength(p1, p2);
  20. const translate = [
  21. b1[0] - scale * (p1[0] * Math.cos(rotation) - p1[1] * Math.sin(rotation)),
  22. b1[1] - scale * (p1[0] * Math.sin(rotation) + p1[1] * Math.cos(rotation)),
  23. ];
  24. const altitude = (b2[2] - b1[2]) / (p2[2] - p1[2]);
  25. const startAltitude = [p1[2], b1[2]];
  26. return {
  27. rotation,
  28. scale,
  29. translate,
  30. startAltitude,
  31. altitude,
  32. };
  33. };
  34. const transform = (point: Pos, cover: Conversion): Pos => {
  35. const ctrla = cover.scale * Math.cos(cover.rotation);
  36. const ctrlb = cover.scale * Math.sin(cover.rotation);
  37. return [
  38. ctrla * point[0] - ctrlb * point[1] + cover.translate[0],
  39. ctrlb * point[0] + ctrla * point[1] + cover.translate[1],
  40. cover.altitude * (point[2] - cover.startAltitude[0]) +
  41. cover.startAltitude[1],
  42. ];
  43. };
  44. const wCoordType = "EPSG:4326";
  45. const tCoordType = "EPSG:3857";
  46. proj4.defs(wCoordType, "+proj=longlat +ellps=GRS80 +no_defs");
  47. proj4.defs(
  48. tCoordType,
  49. "+proj=merc +a=6378137 +b=6378137 +lat_ts=0 +lon_0=0 +x_0=0 +y_0=0 +k=1 +units=m +nadgrids=@null +wktext +no_defs +type=crs"
  50. );
  51. // 传入本地坐标与控制点的关系
  52. export const conversionFactory = (locals: [Pos, Pos], gpss: [Pos, Pos]) => {
  53. const maps = gpss.map((pos) => proj4(wCoordType, tCoordType, pos));
  54. const coverLocalToWeb = getConversion2D(locals, maps);
  55. const coverWebToLocal = getConversion2D(maps, locals);
  56. return {
  57. toLocal(pos: Pos): Pos {
  58. const tPos = transform(
  59. proj4(wCoordType, tCoordType, [...pos]),
  60. coverWebToLocal
  61. );
  62. return tPos;
  63. },
  64. toWGS84(pos: Pos): Pos {
  65. const tPos = transform(pos, coverLocalToWeb);
  66. const wPos = proj4(tCoordType, wCoordType, [...tPos]);
  67. return [wPos[0], wPos[1], tPos[2]];
  68. },
  69. };
  70. };