已知某个城市的边界经纬度坐标。格式var zhengzhou = "117.071417,32.489032;117.073517,32.490105;117.074674,32.491732;117.074889,32.495026;117.074503,32.498105;”,现在要获取该坐标范围内的随机十条经纬坐标;
注意事项:
1,该列表表示的是该城市的区域 是个不规则形状;
2,知道该城市边界的坐标串;
问题:如何生成该区域内随机的坐标点?
已合肥为例。下面是合肥的范围坐标;
"117.071417,32.489032;117.073517,32.490105;117.074674,32.491732;117.074889,32.495026;117.074503,32.498105;117.075318,32.499817;117.076646,32.501102;117.078468,32.502066;117.078982,32.506344;117.079583,32.511564;117.078811,32.513402;117.076541,32.515581;117.073541,32.516561;117.074505,32.520947;117.075491,32.523173;117.076356,32.523745;117.078405,32.525101;117.082947,32.527408;117.083443,32.527689;117.083426,32.528085;117.083583,32.528308;117.083749,32.52844;117.084335,32.528672;117.084575,32.528729;117.084682,32.52887;117.08475,32.52917;117.084613,32.529717;117.084672,32.530109;117.084868,32.530481;117.08569,32.530638;117.08665,32.530619;117.08757,32.530444;117.088255,32.530327;117.088804,32.530425;117.089391,32.530758;117.090096,32.530974;117.091156,32.530979;117.091888,32.531188;117.093384,32.532155;117.094066,32.532284;117.094362,32.532185;117.094584,32.531997;117.095219,32.530727;117.09558,32.530324;117.095923,32.530101;117.098228,32.529672;117.098873,32.529629;117.099289,32.529763;117.100003,32.530451;117.100436,32.530466;117.100859,32.530329;117.101096,32.530149;117.101441,32.529375;117.101729,32.529084;117.102067,32.529014;117.102805,32.529151;……"
下面是一个基于 Python 的示例代码,可以用来根据城市坐标范围获取随机10条该范围内的坐标点:
import random
# 定义城市坐标范围
xmin, ymin = (110.13522, 19.763128)
xmax, ymax = (110.401639, 20.024933)
# 生成随机坐标点
points = []
for i in range(10):
point = (random.uniform(xmin, xmax), random.uniform(ymin, ymax))
points.append(point)
# 打印坐标点
for point in points:
print(point)
在上述代码中,我们首先定义了城市的坐标范围,然后使用 random.uniform() 函数生成随机坐标点。最后,我们循环遍历所有坐标点并打印出来。
你可以根据自己的需要修改范围和生成的坐标点数量。
字数限制,完整的合肥边界获取地址,f12中查看https://lbs.amap.com/demo/javascript-api/example/district-search/draw-district-boundaries
我可以使用以下步骤解决该问题:
以下是一个可能的 JavaScript 代码实现(使用 Leaflet.js 库生成地图和标记):
// 将字符串形式的边界坐标转换为数组形式
const borderStr = "117.071417,32.489032;117.073517,32.490105;117.074674,32.491732;117.074889,32.495026;117.074503,32.498105;"
const borderCoords = borderStr.trim().split(";").map(coord => coord.split(",").map(parseFloat));
// 向 Leaflet.js 库添加多边形裁剪算法
L.Polygon.include({
clipPolygon: function (border) {
var pointsCount = this._latlngs.length;
var clippedPolygons = [];
var borderBounds = L.bounds(border);
var isOutside = L.point([-180, -90]).distanceTo(L.point([180, 90])) * 2;
var polygonPoints = [];
var maskPoly = L.polygon([borderBounds.getNorthWest(), borderBounds.getNorthEast(), borderBounds.getSouthEast(), borderBounds.getSouthWest()], {
fillOpacity: 0.0,
color: '#000'
});
for (var i = 0; i < pointsCount; i++) {
var p = this._map.latLngToLayerPoint(this._latlngs[i]);
if (!borderBounds.contains(p)) {
continue; // 快速排除离边界较远的点
}
var rad = isOutside;
for (var j = 0; j < border.length; j++) {
var p1 = border[j];
var p2 = border[(j + 1) % border.length];
if (p1[0] == p2[0] && p1[1] == p2[1]) {
continue;
}
var d = L.LineUtil.pointToSegmentDistance(p, L.point(p1), L.point(p2));
if (d < rad) {
rad = d;
}
}
polygonPoints.push([p.x, p.y]);
}
var clipperPoints = ClipperLib.JS.Lighten(polygonPoints, 0.1);
var subjectPolygon = new ClipperLib.Path(clipperPoints.length, 2);
for (var i = 0; i < clipperPoints.length; i++) {
subjectPolygon[i] = new ClipperLib.IntPoint(clipperPoints[i][0], clipperPoints[i][1]);
}
var clipperBorder = new ClipperLib.Path(border.length, 2);
for (var i = 0; i < border.length; i++) {
clipperBorder[i] = new ClipperLib.IntPoint(border[i][0] * isOutside, border[i][1] * isOutside);
}
var clipperSolution = new ClipperLib.Paths();
ClipperLib.Clipper.SimplifyPolygon(subjectPolygon, clipperSolution);
ClipperLib.Clipper.Area(clipperSolution, clipperSolution);
ClipperLib.Clipper.PolyTreeToPaths(clipperSolution, clipperSolution);
for (var i = 0; i < clipperSolution.length; i++) {
var clippedPoints = [];
for (var j = 0; j < clipperSolution[i].length; j++) {
var point = clipperSolution[i][j];
clippedPoints.push(L.point(point.X, point.Y));
}
var poly = L.polygon(clippedPoints);
if (maskPoly.intersects(poly)) {
clippedPolygons.push(poly);
}
}
return clippedPolygons;
}
});
// 在地图上显示边界
const map = L.map('map').setView([32.489032, 117.071417], 13);
const border = L.polygon(borderCoords, {
opacity: 0.5,
fillOpacity: 0.0,
}).addTo(map);
// 在指定的城市边界范围内生成随机的10个坐标点,并用标记在地图上显示
const points = PoissonDiscSampler(borderCoords, 50, 10, 30); // 假设使用 Poisson-Disc Sampling 算法
points.forEach(point => {
L.marker(L.latLng(point[1], point[0])).addTo(map)
});
其中 PoissonDiscSampler 函数可能的实现如下:
function PoissonDiscSampler(border, radius, maxTries, maxPoints) {
const sqrtRadius = radius * Math.SQRT1_2;
const width = border.map(coord => coord[0]).reduce((a, b) => Math.max(a, b)) - border.map(coord => coord[0]).reduce((a, b) => Math.min(a, b));
const height = border.map(coord => coord[1]).reduce((a, b) => Math.max(a, b)) - border.map(coord => coord[1]).reduce((a, b) => Math.min(a, b));
const cellSize = sqrtRadius / Math.sqrt(2);
const cols = Math.floor(width / cellSize) + 1;
const rows = Math.floor(height / cellSize) + 1;
const grid = Array.from(new Array(cols * rows), () => []);
const points = [];
const activePoints = [];
function addPoint(p) {
const col = Math.floor((p[0] - border.map(coord => coord[0]).reduce((a, b) => Math.min(a, b))) / cellSize);
const row = Math.floor((p[1] - border.map(coord => coord[1]).reduce((a, b) => Math.min(a, b))) / cellSize);
grid[col * rows + row].push(p);
points.push(p);
activePoints.push(p);
}
const firstPoint = [
border.map(coord => coord[0]).reduce((a, b) => a + b) / border.length,
border.map(coord => coord[1]).reduce((a, b) => a + b) / border.length,
];
addPoint(firstPoint);
while (activePoints.length > 0 && points.length < maxPoints) {
const randomIndex = Math.floor(Math.random() * activePoints.length);
const center = activePoints[randomIndex];
let found = false;
for (let i = 0; i < maxTries; i++) {
const angle = Math.random() * 2 * Math.PI;
const distance = (Math.random() + 1) * sqrtRadius;
const p = [
center[0] + distance * Math.cos(angle),
center[1] + distance * Math.sin(angle),
];
if (p[0] < border.map(coord => coord[0]).reduce((a, b) => Math.min(a, b)) || p[0] > border.map(coord => coord[0]).reduce((a, b) => Math.max(a, b)) || p[1] < border.map(coord => coord[1]).reduce((a, b) => Math.min(a, b)) || p[1] > border.map(coord => coord[1]).reduce((a, b) => Math.max(a, b))) {
continue; // 新点不在边界内
}
const col = Math.floor((p[0] - border.map(coord => coord[0]).reduce((a, b) => Math.min(a, b))) / cellSize);
const row = Math.floor((p[1] - border.map(coord => coord[1]).reduce((a, b) => Math.min(a, b))) / cellSize);
let isValid = true;
for (let k = Math.max(col - 2, 0); k <= Math.min(col + 2, cols - 1); k++) {
for (let l = Math.max(row - 2, 0); l <= Math.min(row + 2, rows - 1); l++) {
for (let m = 0; m < grid[k * rows + l].length; m++) {
const point = grid[k * rows + l][m];
if (point) {
const dx = p[0] - point[0];
const dy = p[1] - point[1];
if (dx * dx + dy * dy < radius * radius) {
isValid = false;
break;
}
}
}
if (!isValid) {
break;
}
}
if (!isValid) {
break;
}
}
if (isValid) {
addPoint(p);
found = true;
}
}
if (!found) {
activePoints.splice(randomIndex, 1);
}
}
return points;
}