如何使地图可视区域内的阿尔卑斯山峰查询结果均匀分布?
解决地图缩小后山峰查询结果分布不均的方案
方案1:网格划分采样
将当前可视区域均匀划分为多个网格,每个网格内选取最高海拔的若干山峰,最后合并结果并补全数量,确保每个区域都有山峰入选,避免结果集中在单一高海拔地带。
比如划分为4×4网格,每个网格取1个最高海拔山峰,若总数不足20,再从剩余山峰中补选高海拔的:
// 计算网格步长 const latStep = (lat_max - lat_min) / 4; const lngStep = (lng_max - lng_min) / 4; const mountains = []; // 遍历所有网格 for (let i = 0; i < 4; i++) { for (let j = 0; j < 4; j++) { const gridLatMin = lat_min + i * latStep; const gridLatMax = lat_min + (i + 1) * latStep; const gridLngMin = lng_min + j * lngStep; const gridLngMax = lng_min + (j + 1) * lngStep; const gridPeaks = await prisma.mountain.findMany({ where: { lat: { gt: gridLatMin, lt: gridLatMax }, lng: { gt: gridLngMin, lt: gridLngMax }, }, orderBy: { elevation: "desc" }, take: 1, }); mountains.push(...gridPeaks); } } // 补选剩余数量的高海拔山峰 if (mountains.length < 20) { const existingIds = mountains.map(m => m.id); const additionalPeaks = await prisma.mountain.findMany({ where: { lat: { gt: lat_min, lt: lat_max }, lng: { gt: lng_min, lt: lng_max }, id: { notIn: existingIds }, }, orderBy: { elevation: "desc" }, take: 20 - mountains.length, }); mountains.push(...additionalPeaks); }
方案2:空间加权排序
结合山峰的海拔高度与到可视区域中心的距离,计算加权得分并排序,让既高海拔又空间分散的山峰优先入选。需要数据库支持基础的数学计算(或空间函数):
用平面距离近似计算(无需空间扩展)
const centerLat = (lat_min + lat_max) / 2; const centerLng = (lng_min + lng_max) / 2; const mountains = await prisma.$queryRaw` SELECT *, (elevation * 1000) / ( SQRT(POW(lat - ${centerLat}, 2) + POW(lng - ${centerLng}, 2)) + 1 ) AS weighted_score FROM mountain WHERE lat > ${lat_min} AND lat < ${lat_max} AND lng > ${lng_min} AND lng < ${lng_max} ORDER BY weighted_score DESC LIMIT 20; `;
用空间函数精确计算(需PostGIS等扩展)
const centerLat = (lat_min + lat_max) / 2; const centerLng = (lng_min + lng_max) / 2; const mountains = await prisma.$queryRaw` SELECT *, (elevation * 1000) / (ST_Distance( ST_Point(lng, lat), ST_Point(${centerLng}, ${centerLat}) ) + 1) AS weighted_score FROM mountain WHERE lat > ${lat_min} AND lat < ${lat_max} AND lng > ${lng_min} AND lng < ${lng_max} ORDER BY weighted_score DESC LIMIT 20; `;
可通过调整1000这个系数,平衡海拔和空间分布的优先级。
方案3:分层空间抽样
先将可视区域内的山峰按海拔分为高、中、低三层,再在每层内按空间维度排序抽样,确保不同海拔段的山峰都有展示:
// 1. 获取可视区域内的海拔范围 const elevationRange = await prisma.mountain.aggregate({ where: { lat: { gt: lat_min, lt: lat_max }, lng: { gt: lng_min, lt: lng_max }, }, _min: { elevation: true }, _max: { elevation: true }, }); const minElev = elevationRange._min.elevation; const maxElev = elevationRange._max.elevation; const mid1 = minElev + (maxElev - minElev) / 3; const mid2 = minElev + 2 * (maxElev - minElev) / 3; // 2. 分层抽样:按海拔段分配数量 const highPeaks = await prisma.mountain.findMany({ where: { lat: { gt: lat_min, lt: lat_max }, lng: { gt: lng_min, lt: lng_max }, elevation: { gte: mid2 }, }, orderBy: { lng: "asc" }, // 按经度排序实现空间分散 take: 7, }); const midPeaks = await prisma.mountain.findMany({ where: { lat: { gt: lat_min, lt: lat_max }, lng: { gt: lng_min, lt: lng_max }, elevation: { gte: mid1, lt: mid2 }, }, orderBy: { lng: "asc" }, take: 7, }); const lowPeaks = await prisma.mountain.findMany({ where: { lat: { gt: lat_min, lt: lat_max }, lng: { gt: lng_min, lt: lng_max }, elevation: { lt: mid1 }, }, orderBy: { lng: "asc" }, take: 6, }); // 合并结果 const mountains = [...highPeaks, ...midPeaks, ...lowPeaks];
内容的提问来源于stack exchange,提问作者flexwie
相关产品推荐
相关产品推荐

