我试图使用Miller投影将坐标转换为像素。我的方法如下所示:
function millerProjection(lat, lng) {
// Create sec() function //
function sec(value) {
return 1/Math.cos(value);
}
// Create fucntion to change degree to radian //
function toRadian(value) {
return value * Math.PI / 180;
}
lng = toRadian(lng);
lat = toRadian(lat);
// Miller Projection
// var x = lng;
// var y = 1.25 * Math.log(Math.tan(Math.PI / 4 + 0.4 * (lat)));
// Mercator Projection
// var x = lng;
// var y = Math.log(Math.tan(lat) + sec(lat));
var mapSet = {
leftLong: toRadian(-180),
rightLong: toRadian(180),
topLat: toRadian(90),
bottomLat: toRadian(-90),
imageWidth: 2057,
imageHeight: 1512,
}
var x = (lng - mapSet.leftLong) * (mapSet.imageWidth / (mapSet.rightLong - mapSet.leftLong));
var y = (mapSet.topLat - lat) * (mapSet.imageHeight / (mapSet.topLat - mapSet.bottomLat));
console.log(`Miller Projection X: ${x} -- Y: ${y}`);
return { x: x, y: y };
}我用这张图片作为地图:SW.jpg
显然,如果我使用0,0坐标,它标记正确的位置。如果我给它其他坐标,它就不起作用了。地图是问题吗?还是我使用的逻辑有问题?
发布于 2018-04-25 21:54:41
这是:
var x = (lng - mapSet.leftLong) * (mapSet.imageWidth / (mapSet.rightLong - mapSet.leftLong));
var y = (mapSet.topLat - lat) * (mapSet.imageHeight / (mapSet.topLat - mapSet.bottomLat));假设对纬度和经度都进行线性x和y变换,但这只发生在经度上。您可以在所引用的图像中看到纬度之间的不同间距。
让我们回到您注释掉的投影,并使用它是正确的,但需要缩放和翻译:
function millerProjection(lat, lng) {
// Create sec() function
function sec(value) {
return 1/Math.cos(value);
}
// Create fucntion to change degree to radians
function toRadian(value) {
return value * Math.PI / 180;
}
lng = toRadian(lng);
lat = toRadian(lat);
// Miller Projection
var x = lng;
var y = 1.25*Math.log(Math.tan(Math.PI/4+0.4*(lat)));
return [x,y];
}
console.log(millerProjection(90,180));
console.log(millerProjection(-90,-180));
X轴的输出范围是-π到+π,y轴的范围大约是该轴的0.733倍。
现在我们可以缩放和翻译了。我会先缩放,然后再翻译,反之亦然。
要进行缩放,我们需要知道边框的宽度或高度或输出范围。方面是固定的,所以这是最简单的,如果没有指定两者,而是确定一个从另一个。如果我们不均匀地拉伸输出,我们就不再有一个磨坊。
给定一个宽度维度,我们可以使用如下内容进行缩放:
var scale = width / Math.PI / 2; 我们想看看每个弧度需要多少像素。然后,我们可以将投影输出乘以比例,得到缩放值。使用上述方法,我们还可以使用像d3的地理投影模块这样的库来验证我们的投影:
function millerProjection(lat, lng) {
// Create sec() function
function sec(value) {
return 1/Math.cos(value);
}
// Create fucntion to change degree to radians
function toRadian(value) {
return value * Math.PI / 180;
}
lng = toRadian(lng);
lat = toRadian(lat);
// Miller Projection
var x = lng;
var y = -1.25*Math.log(Math.tan(Math.PI/4+0.4*(lat)));
var width = 360;
var scale = width/Math.PI/2;
x *= scale;
y *= scale;
return [x,y];
}
////
// set up reference scale:
var width = 360;
var height = width / Math.PI / 2.303412543376391; // aspect ratio
// set d3 projection for reference:
var d3Miller = d3.geoMiller()
.fitSize([360,180*0.7331989845], {"type": "Polygon","coordinates": [[[180, 90], [-180, 90], [-90, -180], [180, 90]]] })
.translate([0,0]);
// compare the two:
console.log("90N,180W:")
console.log("Miller: ", ...millerProjection(90,-180));
console.log("d3Miller:", ...d3Miller([-180,90]));
console.log("90S,180E:")
console.log("Miller: ",...millerProjection(-90,180));
console.log("d3Miller:", ...d3Miller([180,-90]));
console.log("90S,180E:")
console.log("Miller: ",...millerProjection(-57,162));
console.log("d3Miller:", ...d3Miller([162,-57]));.as-console-wrapper { max-height: 100% !important; top: 0; }<script src="https://d3js.org/d3-array.v1.min.js"></script>
<script src="https://d3js.org/d3-geo.v1.min.js"></script>
<script src="https://d3js.org/d3-geo-projection.v2.min.js"></script>
我取了纬度的负值(根据你的例子),因为当投影的地理坐标在底部有y=0时,y值随着移动而增加。相反,类似的事情(大多数?)图像顶部有y=0,y值随着移动而增加。D3预期后一种约定,所以我没有为引用函数这样做。
看起来不错。我们的数据现在在x轴上有一个从-width/2到width/2的范围,在y上也是这个值的0.733倍。让我们翻译一下数据,这样它就占据了左下角坐标为0,0和宽度*0.733的右上坐标的边框。这很容易,在我们缩放数据之后,我们将width/2添加到x值,width/2*0.733 (或者更准确地说,是width/2/*0.7331989845)添加到y值中:
function millerProjection(lat, lng) {
// Create sec() function
function sec(value) {
return 1/Math.cos(value);
}
// Create fucntion to change degree to radians
function toRadian(value) {
return value * Math.PI / 180;
}
lng = toRadian(lng);
lat = toRadian(lat);
// Miller Projection
var x = lng;
var y = -1.25*Math.log(Math.tan(Math.PI/4+0.4*(lat)));
var width = 2057;
var scale = width/Math.PI/2;
x *= scale;
y *= scale;
x += width/2;
y += width/2*0.7331989845
return [x,y];
}
// compare the two:
console.log("90N,180W:")
console.log("Miller: ", ...millerProjection(90,-180));
console.log("90S,180E:")
console.log("Miller: ",...millerProjection(-90,180));
console.log("45N,45E:")
console.log("Miller: ",...millerProjection(45,45));
console.log("90S,180E:")
console.log("Miller: ",...millerProjection(-57,162));.as-console-wrapper { max-height: 100% !important; top: 0; }<script src="https://d3js.org/d3-array.v1.min.js"></script>
<script src="https://d3js.org/d3-geo.v1.min.js"></script>
<script src="https://d3js.org/d3-geo-projection.v2.min.js"></script>
当然,如果您正在进行图像处理,其中顶部应该是y=0,而y值在向下移动时会增加,那么在进行任何操作之前,请翻转纬度的符号。
https://stackoverflow.com/questions/49945993
复制相似问题