圆内随机生成坐标
Random generating coordinates within a circle
场景
我正在尝试生成 500 到 1000 个随机坐标(lat,long),它们位于半径为 1 公里的圆内,圆心位于(5.418680,100.327829)。我试图在 php 中对此进行编码,但未能这样做,因为我不知道我应该为 $radius.
提供什么值
$radius = ?;
$origin_x = 5.420525;
$origin_y = 100.319500;
$angle = deg2rad(mt_rand(0, 359));
$pointRadius = mt_rand(0, $radius);
$point[] = array(
'x' => $origin_x + ($pointRadius * cos($angle)),
'y' => $origin_y + ($pointRadius * sin($angle))
);
我想到了另一种方法。我不想在圆内生成点,而是想在正方形边界内生成点,然后应用 Haversine 大圆距离公式来确定随机生成的点是否位于半径为 1KM 的圆内。
注意:生成的点相互重叠就好了。
请指教,我需要大致了解应该采取什么方法。提前致谢。
我会这样做:
- 选择两个独立的x和y坐标,从区间[0,1].
均匀分布
- If x² + y² > 1 你的点在圆圈外。丢弃该样本并重试。不把正方形变成圆形,确保均匀分布。
- 将圆中的坐标转为球体上的lat/lon。如果你想保持均匀分布,你会在这里使用 area-preserving map projection。但由于半径比地球半径小得多,所以这无关紧要,所以你可以使用一些更简单的投影来代替,除非你必须为均匀分布提供强有力的保证。
我想可能有一些方法可以避免第 2 步中的丢弃,但这可能会使事情 方式 变得更加复杂,因此对于实际应用,我会坚持这样做。
在圆的边界内创建随机点:
var bounds = circle.getBounds();
map.fitBounds(bounds);
var sw = bounds.getSouthWest();
var ne = bounds.getNorthEast();
for (var i = 0; i < 100; i++) {
// create a random point inside the bounds
var ptLat = Math.random() * (ne.lat() - sw.lat()) + sw.lat();
var ptLng = Math.random() * (ne.lng() - sw.lng()) + sw.lng();
var point = new google.maps.LatLng(ptLat,ptLng);
如果它们在圆圈内,则保留它们(在这种情况下将它们添加到地图),否则丢弃它们:
if (google.maps.geometry.spherical.computeDistanceBetween(point,circle.getCenter()) < circle.getRadius()) {
createMarker(map, point,"marker "+i);
// break; if only need one point
} // else nothing.
使用 Google 地图的示例 Javascript API v3:
var circle;
var infowindow = new google.maps.InfoWindow({});
function initialize() {
var map = new google.maps.Map(document.getElementById("map"), {
zoom: 4,
center: new google.maps.LatLng(22.7964, 79.8456),
mapTypeId: google.maps.MapTypeId.HYBRID
});
circle = new google.maps.Circle({
center: map.getCenter(),
radius: 1000, // meters
strokeColor: "#0000FF",
strokeOpacity: 0.8,
strokeWeight: 2,
fillColor: "#0000FF",
fillOpacity: 0.26
});
circle.setMap(map);
var bounds = circle.getBounds();
map.fitBounds(bounds);
var sw = bounds.getSouthWest();
var ne = bounds.getNorthEast();
for (var i = 0; i < 100; i++) {
var ptLat = Math.random() * (ne.lat() - sw.lat()) + sw.lat();
var ptLng = Math.random() * (ne.lng() - sw.lng()) + sw.lng();
var point = new google.maps.LatLng(ptLat, ptLng);
if (google.maps.geometry.spherical.computeDistanceBetween(point, circle.getCenter()) < circle.getRadius()) {
createMarker(map, point, "marker " + i);
// break;
}
}
}
function createMarker(map, point, content) {
var marker = new google.maps.Marker({
position: point,
map: map
});
google.maps.event.addListener(marker, "click", function(evt) {
infowindow.setContent(content + "<br>" + marker.getPosition().toUrlValue(6));
infowindow.open(map, marker);
});
return marker;
}
google.maps.event.addDomListener(window, 'load', initialize);
<script src="https://maps.googleapis.com/maps/api/js?libraries=geometry"></script>
<div id="map" style="width: 530px; height: 500px">
</div>
场景
我正在尝试生成 500 到 1000 个随机坐标(lat,long),它们位于半径为 1 公里的圆内,圆心位于(5.418680,100.327829)。我试图在 php 中对此进行编码,但未能这样做,因为我不知道我应该为 $radius.
$radius = ?;
$origin_x = 5.420525;
$origin_y = 100.319500;
$angle = deg2rad(mt_rand(0, 359));
$pointRadius = mt_rand(0, $radius);
$point[] = array(
'x' => $origin_x + ($pointRadius * cos($angle)),
'y' => $origin_y + ($pointRadius * sin($angle))
);
我想到了另一种方法。我不想在圆内生成点,而是想在正方形边界内生成点,然后应用 Haversine 大圆距离公式来确定随机生成的点是否位于半径为 1KM 的圆内。
注意:生成的点相互重叠就好了。
请指教,我需要大致了解应该采取什么方法。提前致谢。
我会这样做:
- 选择两个独立的x和y坐标,从区间[0,1]. 均匀分布
- If x² + y² > 1 你的点在圆圈外。丢弃该样本并重试。不把正方形变成圆形,确保均匀分布。
- 将圆中的坐标转为球体上的lat/lon。如果你想保持均匀分布,你会在这里使用 area-preserving map projection。但由于半径比地球半径小得多,所以这无关紧要,所以你可以使用一些更简单的投影来代替,除非你必须为均匀分布提供强有力的保证。
我想可能有一些方法可以避免第 2 步中的丢弃,但这可能会使事情 方式 变得更加复杂,因此对于实际应用,我会坚持这样做。
在圆的边界内创建随机点:
var bounds = circle.getBounds();
map.fitBounds(bounds);
var sw = bounds.getSouthWest();
var ne = bounds.getNorthEast();
for (var i = 0; i < 100; i++) {
// create a random point inside the bounds
var ptLat = Math.random() * (ne.lat() - sw.lat()) + sw.lat();
var ptLng = Math.random() * (ne.lng() - sw.lng()) + sw.lng();
var point = new google.maps.LatLng(ptLat,ptLng);
如果它们在圆圈内,则保留它们(在这种情况下将它们添加到地图),否则丢弃它们:
if (google.maps.geometry.spherical.computeDistanceBetween(point,circle.getCenter()) < circle.getRadius()) {
createMarker(map, point,"marker "+i);
// break; if only need one point
} // else nothing.
使用 Google 地图的示例 Javascript API v3:
var circle;
var infowindow = new google.maps.InfoWindow({});
function initialize() {
var map = new google.maps.Map(document.getElementById("map"), {
zoom: 4,
center: new google.maps.LatLng(22.7964, 79.8456),
mapTypeId: google.maps.MapTypeId.HYBRID
});
circle = new google.maps.Circle({
center: map.getCenter(),
radius: 1000, // meters
strokeColor: "#0000FF",
strokeOpacity: 0.8,
strokeWeight: 2,
fillColor: "#0000FF",
fillOpacity: 0.26
});
circle.setMap(map);
var bounds = circle.getBounds();
map.fitBounds(bounds);
var sw = bounds.getSouthWest();
var ne = bounds.getNorthEast();
for (var i = 0; i < 100; i++) {
var ptLat = Math.random() * (ne.lat() - sw.lat()) + sw.lat();
var ptLng = Math.random() * (ne.lng() - sw.lng()) + sw.lng();
var point = new google.maps.LatLng(ptLat, ptLng);
if (google.maps.geometry.spherical.computeDistanceBetween(point, circle.getCenter()) < circle.getRadius()) {
createMarker(map, point, "marker " + i);
// break;
}
}
}
function createMarker(map, point, content) {
var marker = new google.maps.Marker({
position: point,
map: map
});
google.maps.event.addListener(marker, "click", function(evt) {
infowindow.setContent(content + "<br>" + marker.getPosition().toUrlValue(6));
infowindow.open(map, marker);
});
return marker;
}
google.maps.event.addDomListener(window, 'load', initialize);
<script src="https://maps.googleapis.com/maps/api/js?libraries=geometry"></script>
<div id="map" style="width: 530px; height: 500px">
</div>