从种子点生成特定半径内的随机地理坐标

2024-01-08

我使用以下函数从种子点生成指定半径内的随机地理坐标:

function randomGeo(center, radius) {
    var y0 = center.latitude;
    var x0 = center.longitude;
    var rd = radius / 111300;

    var u = Math.random();
    var v = Math.random();

    var w = rd * Math.sqrt(u);
    var t = 2 * Math.PI * v;
    var x = w * Math.cos(t);
    var y = w * Math.sin(t);

    var xp = x / Math.cos(y0);

    return {
        'latitude': y + y0,
        'longitude': xp + x0
    };
}

我使用 2000m 半径和以下种子点循环多次执行此操作:

location: { // Oxford
    latitude: 51.73213,
    longitude: -1.20631
}

我预计所有这些结果都在 2000m 以内;相反,我看到的值超过 10000m:

[ { latitude: 51.73256540025445, longitude: -1.3358092771716716 },   // 3838.75070783092
  { latitude: 51.7214165686511, longitude: -1.1644147572878725 },    // 3652.1890457730474
  { latitude: 51.71721400063117, longitude: -1.2082082568884593 },   // 8196.861603477768
  { latitude: 51.73583824510363, longitude: -1.0940424351649711 },   // 5104.820455873758
  { latitude: 51.74017571473442, longitude: -1.3150742602532257 },   // 4112.3279147866215
  { latitude: 51.73496163915278, longitude: -1.0379454413532996 },   // 9920.01459343298
  { latitude: 51.73582333121239, longitude: -1.0939302282840453 },   // 11652.160906253064
  { latitude: 51.72145745285658, longitude: -1.2491630482776055 },   // 7599.550622138115
  { latitude: 51.73036335927129, longitude: -1.3516902043395063 },   // 8348.276271205428
  { latitude: 51.748104753808924, longitude: -1.2669212014250266 },  // 8880.760669882042
  { latitude: 51.72010719621805, longitude: -1.327161328951446 },    // 8182.466715589904
  { latitude: 51.725727610071125, longitude: -1.0691503599266818 } ] // 2026.3687763449955

鉴于我(无耻!)从其他地方抄袭了这个解决方案(尽管我已经看到了几个类似的实现),我似乎无法弄清楚数学出了问题。

(另外,如果您需要的话,这就是我计算距离的方式。很确定这是正确的。)

function distance(lat1, lon1, lat2, lon2) {
    var R = 6371000;
    var a = 0.5 - Math.cos((lat2 - lat1) * Math.PI / 180) / 2 + Math.cos(lat1 * Math.PI / 180) * Math.cos(lat2 * Math.PI / 180) * (1 - Math.cos((lon2 - lon1) * Math.PI / 180)) / 2;
    return R * 2 * Math.asin(Math.sqrt(a));
}

问题似乎源于这样一个事实:这只是一个不准确的计算,具体取决于您使用的中心点。特别是这一行:

var xp = x / Math.cos(y0);

删除这条线并将经度更改为

'longitude': x + x0

似乎将所有点保持在指定的半径内,尽管如果没有这条线,在某些情况下这些点似乎不会完全填充从东到西。

无论如何,我发现有人遇到类似的问题here https://gis.stackexchange.com/questions/69328/generate-random-location-within-specified-distance-of-a-given-point使用其他人的 Matlab 代码作为可能的解决方案。如果您想使用不同的公式,取决于您需要随机点的均匀分布程度。

这是您提供的公式的谷歌地图可视化:

<!doctype html>
<html>
<head>
    <script type="text/javascript" src="//maps.google.com/maps/api/js?sensor=false"></script>
    <script type="text/javascript" src="//ajax.googleapis.com/ajax/libs/jquery/2.1.4/jquery.min.js"></script>

    <script>
    var distanceLimit = 2000; //in meters
    var numberRandomPoints = 200;
    var mapZoomLevel = 11;
    var locationindex = 0;
    var locations = [
        {'name': 'Oxford, England', 'latitude': 51.73213, 'longitude': -1.20631},
        {'name': 'Quito, Ecuador', 'latitude': -0.2333, 'longitude': -78.5167},
        {'name': 'Ushuaia, Argentina', 'latitude': -54.8000, 'longitude': -68.3000},
        {'name': 'McMurdo Station, Antartica', 'latitude': -77.847281, 'longitude': 166.667942},
        {'name': 'Norilsk, Siberia', 'latitude': 69.3333, 'longitude': 88.2167},
        {'name': 'Greenwich, England', 'latitude': 51.4800, 'longitude': 0.0000},
        {'name': 'Suva, Fiji', 'latitude': -18.1416, 'longitude': 178.4419},
        {'name': 'Tokyo, Japan', 'latitude': 35.6833, 'longitude': 139.6833},
        {'name': 'Mumbai, India', 'latitude': 18.9750, 'longitude': 72.8258},
        {'name': 'New York, USA', 'latitude': 40.7127, 'longitude': -74.0059},
        {'name': 'Moscow, Russia', 'latitude': 55.7500, 'longitude': 37.6167},
        {'name': 'Cape Town, South Africa', 'latitude': -33.9253, 'longitude': 18.4239},
        {'name': 'Cairo, Egypt', 'latitude': 30.0500, 'longitude': 31.2333},
        {'name': 'Sydney, Australia', 'latitude': -33.8650, 'longitude': 151.2094},
    ];
    </script>
</head>
<body>
<div id="topbar">
    <select id="location_switch">
    <script>
        for (i=0; i<locations.length; i++) {
            document.write('<option value="' + i + '">' + locations[i].name + '</option>');
        }
    </script>
    </select>
    <img src="http://google.com/mapfiles/ms/micons/ylw-pushpin.png" style="height:15px;"> = Center
    <img src="https://maps.gstatic.com/mapfiles/ms2/micons/red.png" style="height:15px;"> = No Longitude Adjustment
    <img src="https://maps.gstatic.com/mapfiles/ms2/micons/pink.png" style="height:15px;"> = With Longitude Adjustment (var xp = x / Math.cos(y0);)
</div>

<div id="map_canvas" style="position:absolute; top:30px; left:0px; height:100%; height:calc(100% - 30px); width:100%;overflow:hidden;"></div>

<script>
var markers = [];
var currentcircle;

//Create the default map
var mapcenter = new google.maps.LatLng(locations[locationindex].latitude, locations[locationindex].longitude);
var myOptions = {
    zoom: mapZoomLevel,
    scaleControl: true,
    center: mapcenter
};
var map = new google.maps.Map(document.getElementById('map_canvas'), myOptions);

//Draw default items
var centermarker = addCenterMarker(mapcenter, locations[locationindex].name + '<br>' + locations[locationindex].latitude + ', ' + locations[locationindex].longitude);
var mappoints = generateMapPoints(locations[locationindex], distanceLimit, numberRandomPoints);
drawRadiusCircle(map, centermarker, distanceLimit);
createRandomMapMarkers(map, mappoints);

//Create random lat/long coordinates in a specified radius around a center point
function randomGeo(center, radius) {
    var y0 = center.latitude;
    var x0 = center.longitude;
    var rd = radius / 111300; //about 111300 meters in one degree

    var u = Math.random();
    var v = Math.random();

    var w = rd * Math.sqrt(u);
    var t = 2 * Math.PI * v;
    var x = w * Math.cos(t);
    var y = w * Math.sin(t);

    //Adjust the x-coordinate for the shrinking of the east-west distances
    var xp = x / Math.cos(y0);

    var newlat = y + y0;
    var newlon = x + x0;
    var newlon2 = xp + x0;

    return {
        'latitude': newlat.toFixed(5),
        'longitude': newlon.toFixed(5),
        'longitude2': newlon2.toFixed(5),
        'distance': distance(center.latitude, center.longitude, newlat, newlon).toFixed(2),
        'distance2': distance(center.latitude, center.longitude, newlat, newlon2).toFixed(2),
    };
}

//Calc the distance between 2 coordinates as the crow flies
function distance(lat1, lon1, lat2, lon2) {
    var R = 6371000;
    var a = 0.5 - Math.cos((lat2 - lat1) * Math.PI / 180) / 2 + Math.cos(lat1 * Math.PI / 180) * Math.cos(lat2 * Math.PI / 180) * (1 - Math.cos((lon2 - lon1) * Math.PI / 180)) / 2;
    return R * 2 * Math.asin(Math.sqrt(a));
}

//Generate a number of mappoints
function generateMapPoints(centerpoint, distance, amount) {
    var mappoints = [];
    for (var i=0; i<amount; i++) {
        mappoints.push(randomGeo(centerpoint, distance));
    }
    return mappoints;
}

//Add a unique center marker
function addCenterMarker(centerposition, title) {
    
    var infowindow = new google.maps.InfoWindow({
        content: title
    });
    
    var newmarker = new google.maps.Marker({
        icon: 'http://google.com/mapfiles/ms/micons/ylw-pushpin.png',
        position: mapcenter,
        map: map,
        title: title,
        zIndex: 3
    });
    
    google.maps.event.addListenerOnce(map, 'tilesloaded', function() {
        infowindow.open(map,newmarker);
    });
    
    markers.push(newmarker);
    return newmarker;
}

//Draw a circle on the map
function drawRadiusCircle (map, marker, distance) {
    currentcircle = new google.maps.Circle({
        map: map,
        radius: distance
    });
    currentcircle.bindTo('center', marker, 'position');
}

//Create markers for the randomly generated points
function createRandomMapMarkers(map, mappoints) {
    for (var i = 0; i < mappoints.length; i++) {
        //Map points without the east/west adjustment
        var newmappoint = new google.maps.LatLng(mappoints[i].latitude, mappoints[i].longitude);
        var marker = new google.maps.Marker({
            position:newmappoint,
            map: map,
            title: mappoints[i].latitude + ', ' + mappoints[i].longitude + ' | ' + mappoints[i].distance + 'm',
            zIndex: 2
        });
        markers.push(marker);

        //Map points with the east/west adjustment
        var newmappoint = new google.maps.LatLng(mappoints[i].latitude, mappoints[i].longitude2);
        var marker = new google.maps.Marker({
            icon: 'https://maps.gstatic.com/mapfiles/ms2/micons/pink.png',
            position:newmappoint,
            map: map,
            title: mappoints[i].latitude + ', ' + mappoints[i].longitude2 + ' | ' + mappoints[i].distance2 + 'm',
            zIndex: 1
        });
        markers.push(marker);
    }
}

//Destroy all markers
function clearMarkers() {
    for (var i = 0; i < markers.length; i++) {
        markers[i].setMap(null);
    }
    markers = [];
}

$('#location_switch').change(function() {
    var newlocation = $(this).val();
    
    clearMarkers();

    mapcenter = new google.maps.LatLng(locations[newlocation].latitude, locations[newlocation].longitude);
    map.panTo(mapcenter);
    centermarker = addCenterMarker(mapcenter, locations[newlocation].name + '<br>' + locations[newlocation].latitude + ', ' + locations[newlocation].longitude);
    mappoints = generateMapPoints(locations[newlocation], distanceLimit, numberRandomPoints);

    //Draw default items
    currentcircle.setMap(null);
    drawRadiusCircle(map, centermarker, distanceLimit);
    createRandomMapMarkers(map, mappoints);
});
</script>
</body>
</html>
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

从种子点生成特定半径内的随机地理坐标 的相关文章

  • 在 javascript/jquery 中将光标更改为等待

    当调用函数时 如何让光标更改为此加载图标以及如何将其更改回 javascript jquery 中的普通光标 在你的 jQuery 中使用 body css cursor progress 然后又恢复正常 body css cursor d
  • 如何在同一页面上使用AJAX处理多个表单

    我有一个表单 当我单击 提交 时 它就被提交了 然后该表单隐藏 操作页面的结果显示在 div 中 classname dig 它工作正常 但是当我添加另一个表单时 它停止正常工作并且所有表单同时提交 我如何更改我的代码 done click
  • 使用 vscode 调试器调试 next.js

    我已经使用安装了一个项目创建下一个应用程序 https github com segmentio create next app 我需要使用我的编辑器 vscode 调试服务器端渲染 所以我访问过vscode recipes 如何调试 ne
  • 关闭选项卡时要求确认[关闭]

    Closed 这个问题不符合堆栈溢出指南 help closed questions 目前不接受答案 当我在某些浏览器上关闭页面时 我希望出现一个消息框 并询问我是否真的要关闭页面 有两个按钮 如果我单击No那么这个标签就不会被关闭 我怎样
  • 为什么 JavaScript base-36 转换看起来不明确

    我目前正在编写一段使用 Base 36 编码的 JavaScript 我遇到了这个问题 parseInt welcomeback 36 toString 36 看来要回归了 welcomebacg 我在 Chrome 开发者控制台和 Nod
  • 解析“流”JSON

    我在浏览器中有一个网格 我想通过 JSON 将数据行发送到网格 但浏览器应该在接收到 JSON 时不断解析它 并在解析时将行添加到网格中 换句话说 在接收到整个 JSON 对象后 不应将行全部添加到网格中 应该在接收到行时将其添加到网格中
  • 使用 useReducers 调度函数发送多个操作?

    使用时是否可以通过调度函数发送多个动作useReducer挂钩反应 我尝试向它传递一组操作 但这会引发未处理的运行时异常 明确地说 通常会有一个初始状态对象和一个减速器 如下所示 const initialState message1 nu
  • 使用模数按字母顺序对列表进行排序

    我在获取元素列表并按字母顺序对它们进行排序方面没有任何问题 但我很难理解如何使用模数来做到这一点 更新 这是按我的方式工作的代码 但是 我更喜欢下面提供的答案的可重用性 因此接受了该答案
  • Meteor:应用程序无法在 0.9.1.1 版本上运行

    出现类似错误 Error TypeError undefined is not a function evaluating Template create anonymous function iron dynamic template j
  • Google App Engine:修改云运行环境

    我正在尝试部署一个使用自定义 Node js 服务器的 Next js 应用程序 我想将自定义构建变量注入应用程序 next config js const NODE ENV process env NODE ENV const envTy
  • JavaScript 重定向到新窗口

    我有以下代码 它根据下拉列表的值重定向到页面 我如何使其在新窗口中打开 function goto form var index form select selectedIndex if form select options index
  • 使用 KnockoutJs 映射插件进行递归模板化

    我正在尝试使用以下方法在树上进行递归模板化ko映射 插入 http knockoutjs com documentation plugins mapping html 但我无法渲染它 除非我定义separate每个级别的模板 在以下情况下
  • 将div设置为隐藏,延时后可见

    我试图在 X 时间后 也许甚至在随机时间之后 但现在我们只做固定时间 在黑色背景上出现一个黄色方块 function initialSetup if document getElementById yellow null document
  • Electron - 为什么在关闭事件时将 BrowserWindow 实例设置为 null

    The 电子文档 https electronjs org docs api browser window 提供以下代码示例来创建新窗口 const BrowserWindow require electron let win new Br
  • Javascript 数组到 VBScript

    我有一个使用 Javascript 构建的对象数组 我需要使用 VBScript 读取它 如下例所示 我找不到在 VbScript 代码中循环遍历数组的方法myArray object 这个例子是我的问题的简化 我无法更改页面的默认语言 这
  • FireFox 中的自动滚动

    我的应用程序是实时聊天 我有一个 Div 来包装消息 每条消息都是一个 div 所以 在几条消息之后 我的 DOM 看起来像这样 div div Message number two div div div div
  • Safari 支持 JavaScript window.onerror 吗?

    我有一个附加到 window onerror 的函数 window onerror function errorMsg url line window alert asdf 这在 firefox chrome 和 IE 中工作正常 但在 s
  • JQuery 图像上传不适用于未来的活动

    我希望我的用户可以通过帖子上传图像 因此 每个回复表单都有一个上传表单 用户可以通过单击上传按钮上传图像 然后单击提交来提交帖子 现在我的上传表单可以上传第一个回复的图像 但第二个回复的上传不起作用 我的提交过程 Ajax 在 php 提交
  • 如何在 pg-promise 中设置模式

    我正在搜索的文档pg 承诺 https github com vitaly t pg promise特别是在创建客户端时 但我无法找到设置连接中使用的默认架构的选项 它始终使用public架构 我该如何设置 通常 为数据库或角色设置默认架构
  • 如何获取浏览器视口中当前显示的内容

    如何获取当前正在显示长文档的哪一部分的指示 例如 如果我的 html 包含 1 000 行 1 2 3 9991000 并且用户位于显示第 500 行的中间附近 那么我想得到 500 n501 n502 或类似的内容 显然 大多数场景都会比

随机推荐

  • 如何使用机器人框架和 selenium 读取 Web 控制台输出?

    我正在尝试读取网页的控制台输出 特别是我需要使用 RF 和 Selenium 进行 POST GET PUT ajax 调用 我在网上找到了一些帮助 但似乎无法使其发挥作用 我的Python脚本是 from selenium webdriv
  • 如何动态设置 EditText 高度

    我想简单地将 EditText 组件的高度设置为用户屏幕高度的 50 我正在从 xml 文件 main xml 创建初始布局 该文件加载到 Activity 的 onCreate Bundle 中 从 xml 配置中 我了解如何将 Edit
  • IronPython Web 框架

    Python 似乎有很多优秀的 Web 框架 有人在 IronPython 中使用过这些 Pylons Web2Py Django 吗 Django 已在 IronPython 上运行 http unbracketed org 2008 m
  • 依赖类型:依赖对类型与不相交联合有何相似之处?

    我一直在研究依赖类型 我了解以下内容 Why 通用量化 https en wikipedia org wiki Universal quantification被表示为依赖函数类型 x A B x means 对全部x类型的A有一个类型的值
  • C# Windows 窗体用户控件控件设计器支持

    我正在寻找的是对用户控件内的控件的相同类型的设计器支持 即 调整用户控件内的文本框大小 移动标签将用户控件放置到表单上之后 我能做的事 创建一个用户控件 使用设计器向其添加控件 创建一个新的窗口窗体应用程序 将用户控件添加到工具箱 将控件拖
  • JQuery 在该位置插入表格行

    我一直在研究一种能够向 html 表插入行的解决方案 这非常棘手 我发现了一些有用的东西 但仅适用于第一个 插入 我不知道我做错了什么 我有一个包含 3 列的基本表格 每个表格都有一个按钮 允许在两行之间插入一行 我在这个网站上搜索了一个解
  • 如何让 .env 预提交 + mypy + django-stubs

    我尝试在提交之前配置启动 mypy django stubs 检查 我使用预提交 当我尝试提交时 出现错误django core exceptions ImproperlyConfigured 设置 POSTGRES DB 环境变量 该变量
  • java.sql 中的日期时间等效项? (有 java.sql.datetime 吗?)

    到目前为止 我还没有找到明确的答案 我想知道使用PreparedStatement 的SQL 类型DATETIME 和java 类型的等价物是什么 我已经发现 http www java2s com Code Java Database S
  • Shell 脚本中的 exec ${PERL-perl} -Sx $0 ${1+"$@"} 是什么意思?

    我的任务是将包含 Shell 脚本 Perl 代码的 shell 脚本转换为 Python 我设法将 Perl 代码转换为 Python 但是有这个shell脚本语句我不明白 usr bin sh exec PERL perl Sx 0 1
  • 没有元素时流的特殊行为

    我如何用 java 8 Streams API 表达这一点 我想表演itemConsumer对于流的每个项目 如果有 没有我想要执行的项目emptyAction 当然我可以写这样的东西 Consumer itemConsumer Syste
  • 没有画布的 HTML5 getImageData [重复]

    这个问题在这里已经有答案了 有没有办法在没有画布的情况下使用图像的 getImageData 我想要获取图像鼠标位置处的像素颜色 不 你不能 但是获取 imageData 可以使用内存中的画布来完成 这既快速又简单 var canvas d
  • Powershell ISE 在使用 GitLab Runner 时抛出 RemoteException

    I am trying to stop GitlabRunner windows service using powershell When I execute the command in elevated powershell prom
  • 如何使用可视化代码编辑器在 chrome 上运行 flutter

    如何在 Chrome 上运行 flutter 应用程序 我已经安装了颤振套件并运行 颤振通道测试版 颤振升级 并在 Visual Studio Code 上安装扩展 就像与flutter mobile create flutter laun
  • Python内存模型和指针

    我正在学习 Python 并对 Python 的内存模型感到困惑 变量包含它所引用的对象的内存地址 这听起来就像 Python 变量实际上是指针 因为它们只直接包含实际对象实例的内存地址 那么当我调用变量名时Python会做什么呢 Pyth
  • 在 Python 中将频谱图存储为图像

    我想将音频的 STFT 频谱图存储为图像 下面的代码向我显示了一个频谱图作为输出 但是当保存为图像时 我得到了不同的图像 import numpy as np import matplotlib pyplot as plt import p
  • UICollectionViewCell 中的标签文本未更新

    我正在尝试更改 a 的文本UILabel in a UICollectionViewCell之后UICollectionViewCell已加载 当点击button 但屏幕上的标签不会更新 控制台显示标签的文本属性已更新 但标签似乎并未使用新
  • 对于没有正文的 4xx 错误,Content-Type 应该是什么?

    考虑一个获得以下响应的 HTTP 请求 405 Method Not Allowed Content Length 0 像这样的内容类型应该是什么 设置为无 Not set Set to text plain or text html 您没
  • Lucene.net 2.9.2 排序(排序不起作用)

    我在 NET 中对 lucene net 索引进行排序时遇到问题 我尝试了 stackoverflow 上的几乎所有解决方案并寻找谷歌答案 我正在使用 Lucene NET 2 9 2 和 ASP NET 2 0 我想像在 sql 中一样对
  • 如何在适用于 iOS 的谷歌地图 sdk 中设置带有位置的中心地图视图

    如何在 iOS 版谷歌地图 sdk 中设置中心地图视图和位置 使用mapkit 我们可以执行setCenter Location 如何使用适用于 iOS 的 google 地图 sdk 执行此操作 使用 GMSCameraPosition
  • 从种子点生成特定半径内的随机地理坐标

    我使用以下函数从种子点生成指定半径内的随机地理坐标 function randomGeo center radius var y0 center latitude var x0 center longitude var rd radius