feat: fix gps map projection and update map config

This commit is contained in:
2026-03-23 10:05:41 +08:00
parent a4c426df8b
commit 51740761f5
11 changed files with 214 additions and 55 deletions

View File

@@ -3,7 +3,7 @@ import { CompassHeadingController } from '../sensor/compassHeadingController'
import { LocationController } from '../sensor/locationController'
import { WebGLMapRenderer } from '../renderer/webglMapRenderer'
import { type MapRendererStats } from '../renderer/mapRenderer'
import { gcj02ToWgs84, lonLatToWorldTile, worldTileToLonLat, type LonLatPoint } from '../../utils/projection'
import { lonLatToWorldTile, worldTileToLonLat, type LonLatPoint, type MapCalibration } from '../../utils/projection'
import { isTileWithinBounds, type RemoteMapConfig, type TileZoomBounds } from '../../utils/remoteMapConfig'
const RENDER_MODE = 'Single WebGL Pipeline'
@@ -21,6 +21,14 @@ const DEFAULT_TOP_LEFT_TILE_Y = 51199
const DEFAULT_CENTER_TILE_X = DEFAULT_TOP_LEFT_TILE_X + 1
const DEFAULT_CENTER_TILE_Y = DEFAULT_TOP_LEFT_TILE_Y + 1
const TILE_SOURCE = 'https://oss-mbh5.colormaprun.com/wxMap/lcx/{z}/{x}/{y}.png'
const OSM_TILE_SOURCE = 'https://tiles.mymarsgo.xyz/{z}/{x}/{y}.png'
const MAP_OVERLAY_OPACITY = 0.72
const GPS_MAP_CALIBRATION: MapCalibration = {
offsetEastMeters: 0,
offsetNorthMeters: 0,
rotationDeg: 0,
scale: 1,
}
const MIN_PREVIEW_SCALE = 0.55
const MAX_PREVIEW_SCALE = 1.85
const INERTIA_FRAME_MS = 16
@@ -114,6 +122,8 @@ export interface MapEngineViewState {
gpsTracking: boolean
gpsTrackingText: string
gpsCoordText: string
osmReferenceEnabled: boolean
osmReferenceText: string
}
export interface MapEngineCallbacks {
@@ -158,6 +168,8 @@ const VIEW_SYNC_KEYS: Array<keyof MapEngineViewState> = [
'gpsTracking',
'gpsTrackingText',
'gpsCoordText',
'osmReferenceEnabled',
'osmReferenceText',
]
function buildCenterText(zoom: number, x: number, y: number): string {
@@ -524,6 +536,8 @@ export class MapEngine {
gpsTracking: false,
gpsTrackingText: '持续定位待启动',
gpsCoordText: '--',
osmReferenceEnabled: false,
osmReferenceText: 'OSM参考关',
}
this.previewScale = 1
this.previewOriginX = 0
@@ -575,7 +589,7 @@ export class MapEngine {
handleLocationUpdate(longitude: number, latitude: number, accuracyMeters: number | null): void {
const nextPoint: LonLatPoint = gcj02ToWgs84({ lon: longitude, lat: latitude })
const nextPoint: LonLatPoint = { lon: longitude, lat: latitude }
const lastTrackPoint = this.currentGpsTrack.length ? this.currentGpsTrack[this.currentGpsTrack.length - 1] : null
if (!lastTrackPoint || getApproxDistanceMeters(lastTrackPoint, nextPoint) >= GPS_TRACK_MIN_STEP_METERS) {
this.currentGpsTrack = [...this.currentGpsTrack, nextPoint].slice(-GPS_TRACK_MAX_POINTS)
@@ -612,6 +626,16 @@ export class MapEngine {
this.syncRenderer()
}
handleToggleOsmReference(): void {
const nextEnabled = !this.state.osmReferenceEnabled
this.setState({
osmReferenceEnabled: nextEnabled,
osmReferenceText: nextEnabled ? 'OSM参考开' : 'OSM参考关',
statusText: nextEnabled ? `OSM参考底图已开启 (${this.buildVersion})` : `OSM参考底图已关闭 (${this.buildVersion})`,
}, true)
this.syncRenderer()
}
handleToggleGpsTracking(): void {
if (this.locationController.listening) {
this.locationController.stop()
@@ -1364,11 +1388,15 @@ export class MapEngine {
}
buildScene() {
const exactCenter = this.getExactCenterFromTranslate(this.state.tileTranslateX, this.state.tileTranslateY)
return {
tileSource: this.state.tileSource,
osmTileSource: OSM_TILE_SOURCE,
zoom: this.state.zoom,
centerTileX: this.state.centerTileX,
centerTileY: this.state.centerTileY,
exactCenterWorldX: exactCenter.x,
exactCenterWorldY: exactCenter.y,
tileBoundsByZoom: this.tileBoundsByZoom,
viewportWidth: this.state.stageWidth,
viewportHeight: this.state.stageHeight,
@@ -1382,6 +1410,10 @@ export class MapEngine {
previewOriginY: this.previewOriginY || this.state.stageHeight / 2,
track: this.currentGpsTrack.length ? this.currentGpsTrack : SAMPLE_TRACK_WGS84,
gpsPoint: this.currentGpsPoint,
gpsCalibration: GPS_MAP_CALIBRATION,
gpsCalibrationOrigin: worldTileToLonLat({ x: this.defaultCenterTileX, y: this.defaultCenterTileY }, this.defaultZoom),
osmReferenceEnabled: this.state.osmReferenceEnabled,
overlayOpacity: MAP_OVERLAY_OPACITY,
}
}
@@ -1395,8 +1427,8 @@ export class MapEngine {
getCameraState(rotationDeg = this.state.rotationDeg): CameraState {
return {
centerWorldX: this.state.centerTileX,
centerWorldY: this.state.centerTileY,
centerWorldX: this.state.centerTileX + 0.5,
centerWorldY: this.state.centerTileY + 0.5,
viewportWidth: this.state.stageWidth,
viewportHeight: this.state.stageHeight,
visibleColumns: DESIRED_VISIBLE_COLUMNS,
@@ -1410,10 +1442,10 @@ export class MapEngine {
return normalizeRotationDeg(rotationDeg) * Math.PI / 180
}
getBaseCamera(centerWorldX = this.state.centerTileX, centerWorldY = this.state.centerTileY, rotationDeg = this.state.rotationDeg): CameraState {
getBaseCamera(centerTileX = this.state.centerTileX, centerTileY = this.state.centerTileY, rotationDeg = this.state.rotationDeg): CameraState {
return {
centerWorldX,
centerWorldY,
centerWorldX: centerTileX + 0.5,
centerWorldY: centerTileY + 0.5,
viewportWidth: this.state.stageWidth,
viewportHeight: this.state.stageHeight,
visibleColumns: DESIRED_VISIBLE_COLUMNS,
@@ -1437,8 +1469,8 @@ export class MapEngine {
getExactCenterFromTranslate(translateX: number, translateY: number): { x: number; y: number } {
if (!this.state.stageWidth || !this.state.stageHeight) {
return {
x: this.state.centerTileX,
y: this.state.centerTileY,
x: this.state.centerTileX + 0.5,
y: this.state.centerTileY + 0.5,
}
}
@@ -1456,8 +1488,8 @@ export class MapEngine {
tileTranslateX: number
tileTranslateY: number
} {
const nextCenterTileX = Math.round(centerWorldX)
const nextCenterTileY = Math.round(centerWorldY)
const nextCenterTileX = Math.floor(centerWorldX)
const nextCenterTileY = Math.floor(centerWorldY)
if (!this.state.stageWidth || !this.state.stageHeight) {
return {
@@ -1763,6 +1795,13 @@ export class MapEngine {