为什么在北半球画圆会变成椭圆?
why does drawing a circle in the northern hemisphere result in an oval?
我知道可能有一些 geographical/mathematical/Projection 原因,但为什么我的圆会变成椭圆形多边形?我正在尝试从一个点画一个圆。
https://jsfiddle.net/mdecker84/1embLyhj/9/
当我的点坐标为:[0, 0] 或在南半球时,我得到一个完美的圆。不知道怎么回事
var map = new ol.Map({
target: 'map',
layers: [
new ol.layer.Tile({
source: new ol.source.OSM()
})
],
view: new ol.View({
center: ol.proj.fromLonLat([-71.076056, 42.388399], 'EPSG:3857'),
zoom: 9
})
});
var layer = new ol.layer.Vector({
source: new ol.source.Vector({
projection: 'EPSG:4326',
features: []
}),
});
map.addLayer(layer);
var vectorSource = layer.getSource();
function createCircle(circleCenterX, circleCenterY, circleRadius, pointsToEnd) {
let angleToAdd = 360 / pointsToEnd;
let coords = [];
let angle = 0;
for (let i = 0; i < pointsToEnd; i++) {
angle += angleToAdd;
let coordX = circleCenterX + circleRadius * Math.cos(angle * Math.PI / 180);
let coordY = circleCenterY + circleRadius * Math.sin(angle * Math.PI / 180);
coords.push([coordX, coordY]);
}
return coords;
}
function addMarker(coordinates) {
console.log(coordinates);
var marker = new ol.Feature(new ol.geom.Point(coordinates));
marker.setStyle(new ol.style.Style({
image: new ol.style.Circle({
radius: 5,
fill: new ol.style.Fill({
color: 'red'
})
})
}));
vectorSource.addFeature(marker);
}
function addCircle(coords) {
// var lonlat1 = ol.proj.transform([0, 0], 'EPSG:4326','EPSG:3857');
// console.log('var lonlat1',lonlat1)
var circleCoords = createCircle(coords[0], coords[1], 0.2, 180);
console.log(circleCoords);
var polygon = new ol.geom.Polygon([circleCoords]);
polygon.transform('EPSG:4326', 'EPSG:3857');
polygon = new ol.Feature(polygon);
vectorSource.addFeature(polygon);
}
addCircle(ol.proj.toLonLat([-7912507.055205271, 5196764.057392394]));
addMarker([-7912507.055205271, 5196764.057392394]);
html,
body {
height: 100%;
width: 100%;
padding: 0px;
margin: 0px;
}
.map {
height: 100%;
width: 100%;
}
<html>
<head>
<link href="https://cdn.jsdelivr.net/gh/openlayers/openlayers.github.io@master/en/v6.4.3/css/ol.css" rel="stylesheet" />
<script src="https://cdn.jsdelivr.net/gh/openlayers/openlayers.github.io@master/en/v6.4.3/build/ol.js"></script>
</head>
<body>
<div id="map" class="map"></div>
</body>
</html>
这是因为地球是一个球体。就是这样。它仍然是一个圆圈,但在 z-axis
上弯曲了
您的代码在 EPSG:3857 视图中显示的是 EPSG:4326 投影中屏幕上的圆圈,但在地球上,随着您向两极移动,经度会越来越近。对于屏幕上的圆圈,使用 ol.geom.Circle
。但在真实地球上都不会是圆圈,因为你需要 ol.geom.Polygon.circular
如果您想要显示圆形的东西,您可以使用 drawCircle
考虑地球曲率的函数(但它在地面上并不是真正的圆)。
function drawCircle(point, radius, dir) {
var d2r = Math.PI / 180; // degrees to radians
var r2d = 180 / Math.PI; // radians to degrees
var earthsradius = 6378137.0; // 6378137.0 is the radius of the earth in meters
var points = 32;
// find the raidus in lat/lon
var rlat = (radius / earthsradius) * r2d;
var rlng = rlat / Math.cos(point[1] * d2r);
var extp = new Array();
if (dir == 1) {
var start = 0;
var end = points + 1
} // one extra here makes sure we connect the
else {
var start = points + 1;
var end = 0
}
for (var i = start;
(dir == 1 ? i < end : i > end); i = i + dir) {
var theta = Math.PI * (i / (points / 2));
ey = point[0] + (rlng * Math.cos(theta)); // center a + radius x * cos(theta)
ex = point[1] + (rlat * Math.sin(theta)); // center b + radius y * sin(theta)
extp.push([ey, ex]);
}
return extp;
}
var map = new ol.Map({
target: 'map',
layers: [
new ol.layer.Tile({
source: new ol.source.OSM()
})
],
view: new ol.View({
center: ol.proj.fromLonLat([-71.076056, 42.388399], 'EPSG:3857'),
zoom: 9
})
});
var layer = new ol.layer.Vector({
source: new ol.source.Vector({
projection: 'EPSG:4326',
features: []
}),
});
map.addLayer(layer);
var vectorSource = layer.getSource();
function drawCircle(point, radius, dir) {
var d2r = Math.PI / 180; // degrees to radians
var r2d = 180 / Math.PI; // radians to degrees
var earthsradius = 6378137.0; // 6378137.0 is the radius of the earth in meters
var points = 32;
// find the raidus in lat/lon
var rlat = (radius / earthsradius) * r2d;
var rlng = rlat / Math.cos(point[1] * d2r);
var extp = new Array();
if (dir == 1) {
var start = 0;
var end = points + 1
} // one extra here makes sure we connect the
else {
var start = points + 1;
var end = 0
}
for (var i = start;
(dir == 1 ? i < end : i > end); i = i + dir) {
var theta = Math.PI * (i / (points / 2));
ey = point[0] + (rlng * Math.cos(theta)); // center a + radius x * cos(theta)
ex = point[1] + (rlat * Math.sin(theta)); // center b + radius y * sin(theta)
extp.push([ey, ex]);
}
return extp;
}
function addMarker(coordinates) {
console.log(coordinates);
var marker = new ol.Feature(new ol.geom.Point(coordinates));
marker.setStyle(new ol.style.Style({
image: new ol.style.Circle({
radius: 5,
fill: new ol.style.Fill({
color: 'red'
})
})
}));
vectorSource.addFeature(marker);
}
function addCircle(coords) {
// var lonlat1 = ol.proj.transform([0, 0], 'EPSG:4326','EPSG:3857');
// console.log('var lonlat1',lonlat1)
var circleCoords = drawCircle(coords, 20000, 1);
console.log(circleCoords);
var polygon = new ol.geom.Polygon([circleCoords]);
polygon.transform('EPSG:4326', 'EPSG:3857');
polygon = new ol.Feature(polygon);
vectorSource.addFeature(polygon);
}
addCircle(ol.proj.toLonLat([-7912507.055205271, 5196764.057392394]), 20000, 1);
addMarker([-7912507.055205271, 5196764.057392394]);
html,
body {
height: 100%;
width: 100%;
padding: 0px;
margin: 0px;
}
.map {
height: 100%;
width: 100%;
}
<html>
<head>
<link href="https://cdn.jsdelivr.net/gh/openlayers/openlayers.github.io@master/en/v6.4.3/css/ol.css" rel="stylesheet" />
<script src="https://cdn.jsdelivr.net/gh/openlayers/openlayers.github.io@master/en/v6.4.3/build/ol.js"></script>
</head>
<body>
<div id="map" class="map"></div>
</body>
</html>
我知道可能有一些 geographical/mathematical/Projection 原因,但为什么我的圆会变成椭圆形多边形?我正在尝试从一个点画一个圆。
https://jsfiddle.net/mdecker84/1embLyhj/9/
当我的点坐标为:[0, 0] 或在南半球时,我得到一个完美的圆。不知道怎么回事
var map = new ol.Map({
target: 'map',
layers: [
new ol.layer.Tile({
source: new ol.source.OSM()
})
],
view: new ol.View({
center: ol.proj.fromLonLat([-71.076056, 42.388399], 'EPSG:3857'),
zoom: 9
})
});
var layer = new ol.layer.Vector({
source: new ol.source.Vector({
projection: 'EPSG:4326',
features: []
}),
});
map.addLayer(layer);
var vectorSource = layer.getSource();
function createCircle(circleCenterX, circleCenterY, circleRadius, pointsToEnd) {
let angleToAdd = 360 / pointsToEnd;
let coords = [];
let angle = 0;
for (let i = 0; i < pointsToEnd; i++) {
angle += angleToAdd;
let coordX = circleCenterX + circleRadius * Math.cos(angle * Math.PI / 180);
let coordY = circleCenterY + circleRadius * Math.sin(angle * Math.PI / 180);
coords.push([coordX, coordY]);
}
return coords;
}
function addMarker(coordinates) {
console.log(coordinates);
var marker = new ol.Feature(new ol.geom.Point(coordinates));
marker.setStyle(new ol.style.Style({
image: new ol.style.Circle({
radius: 5,
fill: new ol.style.Fill({
color: 'red'
})
})
}));
vectorSource.addFeature(marker);
}
function addCircle(coords) {
// var lonlat1 = ol.proj.transform([0, 0], 'EPSG:4326','EPSG:3857');
// console.log('var lonlat1',lonlat1)
var circleCoords = createCircle(coords[0], coords[1], 0.2, 180);
console.log(circleCoords);
var polygon = new ol.geom.Polygon([circleCoords]);
polygon.transform('EPSG:4326', 'EPSG:3857');
polygon = new ol.Feature(polygon);
vectorSource.addFeature(polygon);
}
addCircle(ol.proj.toLonLat([-7912507.055205271, 5196764.057392394]));
addMarker([-7912507.055205271, 5196764.057392394]);
html,
body {
height: 100%;
width: 100%;
padding: 0px;
margin: 0px;
}
.map {
height: 100%;
width: 100%;
}
<html>
<head>
<link href="https://cdn.jsdelivr.net/gh/openlayers/openlayers.github.io@master/en/v6.4.3/css/ol.css" rel="stylesheet" />
<script src="https://cdn.jsdelivr.net/gh/openlayers/openlayers.github.io@master/en/v6.4.3/build/ol.js"></script>
</head>
<body>
<div id="map" class="map"></div>
</body>
</html>
这是因为地球是一个球体。就是这样。它仍然是一个圆圈,但在 z-axis
上弯曲了您的代码在 EPSG:3857 视图中显示的是 EPSG:4326 投影中屏幕上的圆圈,但在地球上,随着您向两极移动,经度会越来越近。对于屏幕上的圆圈,使用 ol.geom.Circle
。但在真实地球上都不会是圆圈,因为你需要 ol.geom.Polygon.circular
如果您想要显示圆形的东西,您可以使用 drawCircle
考虑地球曲率的函数(但它在地面上并不是真正的圆)。
function drawCircle(point, radius, dir) {
var d2r = Math.PI / 180; // degrees to radians
var r2d = 180 / Math.PI; // radians to degrees
var earthsradius = 6378137.0; // 6378137.0 is the radius of the earth in meters
var points = 32;
// find the raidus in lat/lon
var rlat = (radius / earthsradius) * r2d;
var rlng = rlat / Math.cos(point[1] * d2r);
var extp = new Array();
if (dir == 1) {
var start = 0;
var end = points + 1
} // one extra here makes sure we connect the
else {
var start = points + 1;
var end = 0
}
for (var i = start;
(dir == 1 ? i < end : i > end); i = i + dir) {
var theta = Math.PI * (i / (points / 2));
ey = point[0] + (rlng * Math.cos(theta)); // center a + radius x * cos(theta)
ex = point[1] + (rlat * Math.sin(theta)); // center b + radius y * sin(theta)
extp.push([ey, ex]);
}
return extp;
}
var map = new ol.Map({
target: 'map',
layers: [
new ol.layer.Tile({
source: new ol.source.OSM()
})
],
view: new ol.View({
center: ol.proj.fromLonLat([-71.076056, 42.388399], 'EPSG:3857'),
zoom: 9
})
});
var layer = new ol.layer.Vector({
source: new ol.source.Vector({
projection: 'EPSG:4326',
features: []
}),
});
map.addLayer(layer);
var vectorSource = layer.getSource();
function drawCircle(point, radius, dir) {
var d2r = Math.PI / 180; // degrees to radians
var r2d = 180 / Math.PI; // radians to degrees
var earthsradius = 6378137.0; // 6378137.0 is the radius of the earth in meters
var points = 32;
// find the raidus in lat/lon
var rlat = (radius / earthsradius) * r2d;
var rlng = rlat / Math.cos(point[1] * d2r);
var extp = new Array();
if (dir == 1) {
var start = 0;
var end = points + 1
} // one extra here makes sure we connect the
else {
var start = points + 1;
var end = 0
}
for (var i = start;
(dir == 1 ? i < end : i > end); i = i + dir) {
var theta = Math.PI * (i / (points / 2));
ey = point[0] + (rlng * Math.cos(theta)); // center a + radius x * cos(theta)
ex = point[1] + (rlat * Math.sin(theta)); // center b + radius y * sin(theta)
extp.push([ey, ex]);
}
return extp;
}
function addMarker(coordinates) {
console.log(coordinates);
var marker = new ol.Feature(new ol.geom.Point(coordinates));
marker.setStyle(new ol.style.Style({
image: new ol.style.Circle({
radius: 5,
fill: new ol.style.Fill({
color: 'red'
})
})
}));
vectorSource.addFeature(marker);
}
function addCircle(coords) {
// var lonlat1 = ol.proj.transform([0, 0], 'EPSG:4326','EPSG:3857');
// console.log('var lonlat1',lonlat1)
var circleCoords = drawCircle(coords, 20000, 1);
console.log(circleCoords);
var polygon = new ol.geom.Polygon([circleCoords]);
polygon.transform('EPSG:4326', 'EPSG:3857');
polygon = new ol.Feature(polygon);
vectorSource.addFeature(polygon);
}
addCircle(ol.proj.toLonLat([-7912507.055205271, 5196764.057392394]), 20000, 1);
addMarker([-7912507.055205271, 5196764.057392394]);
html,
body {
height: 100%;
width: 100%;
padding: 0px;
margin: 0px;
}
.map {
height: 100%;
width: 100%;
}
<html>
<head>
<link href="https://cdn.jsdelivr.net/gh/openlayers/openlayers.github.io@master/en/v6.4.3/css/ol.css" rel="stylesheet" />
<script src="https://cdn.jsdelivr.net/gh/openlayers/openlayers.github.io@master/en/v6.4.3/build/ol.js"></script>
</head>
<body>
<div id="map" class="map"></div>
</body>
</html>