我有一个在球体边缘生成点的应用程序。它们被记录为Lat/Lon坐标,单位为度或弧度(例如度(。
我不知道如何在笛卡尔平面上显示它们,从球体外部的点观看(想象一颗卫星拍摄地球(。
在下面的例子中,我有8个点(两组四个点,位于包含球体的不同纬度(。我已经手动绘制了它们,就像你从两个角度看到的那样——一个在"北极"上方,另一个在‘赤道’上的一点上方。
在本例中,自上而下的视图将清晰地看到所有8个点,但假设球体是透明的,则侧视图将具有重叠点。
我不能100%确定,但我怀疑观察剂在球体上方的"高度"是相关的,因此将其作为变量似乎是有效的。
我想功能应该是这样的:
function translateSpherePoint(sphereRadius, pointLat, pointLon, viewX, viewY, viewZ){
//magic code
return {newPointX, newPointY}
}
我一直在详细研究这个问题:https://www.movable-type.co.uk/scripts/latlong.html事实证明,这非常有用,但主要用于球体上的点操作,而不是用于查看。
var canvas = document.getElementById("mainCanvas");
var ctx = canvas.getContext('2d');
canvas.width = 500; canvas.height = 400; ctx.font = "20px Georgia";
ctx.fillText("Top down view", 25, 50);
ctx.fillText("Side view", 25+250, 50);
let points = [
//points half way between the equator and north pole
{point: 1, latDeg:45, lonDeg:45},
{point: 2, latDeg:45, lonDeg:135},
{point: 3, latDeg:45, lonDeg:-135},
{point: 4, latDeg:45, lonDeg:-45},
//points 3/4 of the way between the equator and the north pole
{point: 5, latDeg:67.5, lonDeg:45},
{point: 6, latDeg:67.5, lonDeg:135},
{point: 7, latDeg:67.5, lonDeg:-135},
{point: 8, latDeg:67.5, lonDeg:-45}
]
ctx.font = "13px Georgia";
//Top Down View
ctx.beginPath();
ctx.arc(100,200,100,0,2*Math.PI);
ctx.stroke();ctx.beginPath();
ctx.arc(100-50,200-50,10,0,2*Math.PI); ctx.fillText("1", 100-50-4, 200-50+3);
ctx.stroke();ctx.beginPath();
ctx.arc(100+50,200-50,10,0,2*Math.PI); ctx.fillText("2", 100+50-4, 200-50+3);
ctx.stroke();ctx.beginPath();
ctx.arc(100+50,200+50,10,0,2*Math.PI); ctx.fillText("3", 100+50-4, 200+50+3);
ctx.stroke();ctx.beginPath();
ctx.arc(100-50,200+50,10,0,2*Math.PI); ctx.fillText("4", 100-50-4, 200+50+3);
ctx.stroke();ctx.beginPath();
ctx.arc(100-25,200-25,10,0,2*Math.PI); ctx.fillText("5", 100-25-4, 200-25+3);
ctx.stroke();ctx.beginPath();
ctx.arc(100+25,200-25,10,0,2*Math.PI); ctx.fillText("6", 100+25-4, 200-25+3);
ctx.stroke();ctx.beginPath();
ctx.arc(100+25,200+25,10,0,2*Math.PI); ctx.fillText("7", 100+25-4, 200+25+3);
ctx.stroke();ctx.beginPath();
ctx.arc(100-25,200+25,10,0,2*Math.PI); ctx.fillText("8", 100-25-4, 200+25+3);
ctx.stroke();ctx.beginPath();
//Side View
ctx.beginPath();
ctx.arc(350,200,100,0,2*Math.PI);
ctx.stroke();ctx.beginPath();
ctx.arc(350-50,200-50,10,0,2*Math.PI); ctx.fillText("1/4", 350-50-10, 200-50+3);
ctx.stroke();ctx.beginPath();
ctx.arc(350+50,200-50,10,0,2*Math.PI); ctx.fillText("2/3", 350+50-10, 200-50+3);
ctx.stroke();ctx.beginPath();
ctx.arc(350-25,200-75,10,0,2*Math.PI); ctx.fillText("5/8", 350-25-10, 200-75+3);
ctx.stroke();ctx.beginPath();
ctx.arc(350+25,200-75,10,0,2*Math.PI); ctx.fillText("6/7", 350+25-10, 200-75+3);
ctx.stroke();ctx.beginPath();
<canvas id="mainCanvas"> </canvas>
我的理论是使用新的视点来平移新的笛卡尔平面,并返回相对于该新平面的xy值。一个例子是在我的图表
//(sphereRadius, pointLat, pointLon, viewX, viewY, viewZ)
//i assume that into the screen is negative; out of the screen is positive
//this example is a demonstration of the graph link
function translateSpherePoint(r,px,py,pz,vx,vy,vz){
var curZ=r*2; var curY=0; var curX=0 //there must be a beginning viewpoint to translate from
function distance2d(x1,y1,x2,y2){
return((x2-x1)**2+(y2-y1)**2)**0.5
}
function distance3d(x1,y1,z1,x2,y2,z2){
return((x2-x1)**2+(y2-y1)**2+(z2-z1)**2)**0.5
}
function intersect(m1,c1,m2,c2){
var x=(c2+(c1*-1))/(m1+(m2*-1))
var y=c1+(m1*x); return[x,y]
}
//now for the tricky parts
var m2=vy/vx; var m1=1/-m2;
var newOrigin=intersect(m2,0,m1,-1*(px*m1))
newOrigin.push(pz*(px/newOrigin[0])) //applying the z axis since a straight line is proportional and i made these lines that they MUST connect(shortcut for a 3d intersect since i know they will).. also, this part is not close to perfect but gets things similar to the example correctly :{
var newPointX=NaN
var newPointY=NaN
var newPointZ=-distance3d(px,py,pz,vx,vy,vz)
if(-newPointZ>distance3d(vx,vy,vz,0,0,0)){return(null)} //this is BEHIND your view of the sphere if this condition is true
return [newPointX, newPointY, newPointZ, newOrigin]
}
var arr=translateSpherePoint(1,1,0,0,1,2,0)
console.log(arr)
console.log(`I have yet to determine x and y, so it looks like ${arr.filter((a,i)=>i<3)}`)