/** * 地图工具函数模块 * 提供腾讯地图相关的通用工具函数 * * 主要功能: * - 坐标格式转换 * - 坐标有效性验证 * - 地图实例管理辅助函数 */ /** * 验证坐标是否有效 * @param {number} lng 经度 * @param {number} lat 纬度 * @returns {boolean} 坐标是否有效 */ // export function isValidCoordinate(lng, lat) { // 高德 // return ( // lng !== null && // lng !== undefined && // lat !== null && // lat !== undefined && // lng >= -180 && // lng <= 180 && // lat >= -90 && // lat <= 90 && // !isNaN(lng) && // !isNaN(lat) // ) // } export function isValidCoordinate(lat, lng) { return ( lat !== null && lat !== undefined && lng !== null && lng !== undefined && lat >= -90 && lat <= 90 && lng >= -180 && lng <= 180 && !isNaN(lat) && !isNaN(lng) ) } /** * 将点对象数组转换为 TMap.LatLng 对象数组 * @param {Array<{lng: number, lat: number}>} points 点对象数组 * @returns {Array} TMap.LatLng 对象数组 */ export function convertPointsToLatLng(points) { if (!points || !Array.isArray(points)) { return [] } return points .filter(p => p && isValidCoordinate(p.lng, p.lat)) .map(p => new TMap.LatLng(p.lat, p.lng)) } /** * 将经纬度数组转换为 TMap.LatLng 对象数组 * @param {Array<[number, number]>} lngLatArray 经纬度数组 [[lng, lat], ...] * @returns {Array} TMap.LatLng 对象数组 */ export function convertLngLatArrayToLatLng(lngLatArray) { if (!lngLatArray || !Array.isArray(lngLatArray)) { return [] } return lngLatArray .filter(([lng, lat]) => isValidCoordinate(lng, lat)) .map(([lng, lat]) => new TMap.LatLng(lat, lng)) } /** * 安全地设置地图中心点 * @param {Object} map 地图实例 * @param {number} lng 经度 * @param {number} lat 纬度 * @param {number} zoom 缩放级别(可选) * @returns {boolean} 是否设置成功 */ export function safeSetMapCenter(map, lat, lng, zoom) { if (!map || !isValidCoordinate(lat, lng)) { console.warn('[mapUtils] 无效的地图实例或坐标') return false } try { const center = new TMap.LatLng(lat, lng) map.setCenter(center) if (typeof zoom === 'number' && zoom >= 3 && zoom <= 20) { map.setZoom(zoom) } return true } catch (err) { console.error('[mapUtils] 设置地图中心失败', err) return false } } /** * 安全地获取地图中心点 * @param {Object} map 地图实例 * @returns {Object|null} 包含 lng, lat 的对象,失败返回 null */ export function safeGetMapCenter(map) { if (!map || typeof map.getCenter !== 'function') { return null } try { const center = map.getCenter() return { lat: center.lat, lng: center.lng } } catch (err) { console.error('[mapUtils] 获取地图中心失败', err) return null } } /** * 格式化坐标显示 * @param {Object} point 点对象 {lng, lat} * @param {number} precision 精度(小数位数),默认 5 * @returns {string} 格式化后的坐标字符串 */ export function formatCoordinate(point, precision = 5) { if (!point || !isValidCoordinate(point.lng, point.lat)) { return '--' } return `${point.lng.toFixed(precision)}, ${point.lat.toFixed(precision)}` } /** * 计算两点之间的距离(米) * 使用 Haversine 公式 * @param {Object} point1 点1 {lng, lat} * @param {Object} point2 点2 {lng, lat} * @returns {number} 距离(米) */ export function calculateDistance(point1, point2) { if (!isValidCoordinate(point1.lng, point1.lat) || !isValidCoordinate(point2.lng, point2.lat)) { return 0 } const R = 6371000 // 地球半径(米) const lat1 = point1.lat * Math.PI / 180 const lat2 = point2.lat * Math.PI / 180 const deltaLat = (point2.lat - point1.lat) * Math.PI / 180 const deltaLng = (point2.lng - point1.lng) * Math.PI / 180 const a = Math.sin(deltaLat / 2) * Math.sin(deltaLat / 2) + Math.cos(lat1) * Math.cos(lat2) * Math.sin(deltaLng / 2) * Math.sin(deltaLng / 2) const c = 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1 - a)) return R * c } /** * 判断点是否在多边形内 * 使用射线法 * @param {Object} point 点 {lng, lat} * @param {Array} polygon 多边形顶点数组 [{lng, lat}, ...] * @returns {boolean} 点是否在多边形内 */ export function isPointInPolygon(point, polygon) { if (!isValidCoordinate(point.lng, point.lat) || !polygon || polygon.length < 3) { return false } let inside = false const x = point.lng const y = point.lat for (let i = 0, j = polygon.length - 1; i < polygon.length; j = i++) { const xi = polygon[i].lng const yi = polygon[i].lat const xj = polygon[j].lng const yj = polygon[j].lat const intersect = ((yi > y) !== (yj > y)) && (x < (xj - xi) * (y - yi) / (yj - yi) + xi) if (intersect) { inside = !inside } } return inside }