根据城市坐标范围获取随机10条该范围内的坐标点。

已知某个城市的边界经纬度坐标。格式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;……"

img

下面是一个基于 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

  • 以下回答由chatgpt基于相关博客总结生成:

    我可以使用以下步骤解决该问题:

    1. 将字符串形式的边界坐标转换成合适的数据结构,例如可以使用数组存储经纬度信息,可以采用 JavaScript 中的 split 方法进行拆分和 trim 方法去除空格。
    2. 考虑使用地理信息系统相关的库或者 API,如百度地图 API、高德地图 API、Leaflet.js 等,根据指定城市的名称或地理位置获取该城市的边界信息。
    3. 使用生成坐标点的算法,如 Poisson-Disc Sampling 算法、优化的 Poisson-Disc Sampling 算法等。
    4. 针对不规则形状的边界,可以使用多边形裁剪算法,如 Sutherland-Hodgman 算法。具体实现可以使用 JavaScript 中的 Clipper.js 库。
    5. 最后根据生成的随机坐标点进行实际应用,如标注地图等。

    以下是一个可能的 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;
    }