[英]How would I go about writing a program to rotate at point around a sphere based on an angle as if walking around it?
我正在做一個項目,我需要(作為 2d 點)繞着 3d 球體走動。 我無法弄清楚如何在沒有極坐標失真的情況下實現這一目標。 基本上我想要向前、向后、向左和向右移動,以及向左轉和向右轉。 我一直在嘗試使用球坐標來實現這一點,但我的函數似乎不正確。 我該怎么做才能讓它發揮作用? (我是在 JavaScript 中使用 p5.js 庫制作的)
目前,我正在嘗試將 x 和 y 變量分別映射到球面空間的 phi 和 theta。 但是,它似乎不起作用,而且我不確定如果正確實施,該點是否會在大圓圈中移動。
我還使用了一個角度變量,通過 (cos(A), sin(A)) 移動 x 和 y,但我不確定這是否有效。
我想我需要做的是與Great Circle Navigation有關,但我不了解其背后的數學原理。
鏈接到我當前的版本: https : //editor.p5js.org/hpestock/sketches/FXtn82-0k
當前代碼看起來像
var X,Y,Z;
X=0;
Y=0;
Z=0;
var A=0;
var scaler = 100;
var MOVE_FORWARD = true;
var MOVE_BACKWARD= false;
var MOVE_LEFT = false;
var MOVE_RIGHT = false;
var TURN_LEFT = false;
var TURN_RIGHT = false;
//var i=0;
var x = 0;
var y = 0;
function setup() {
createCanvas(400, 400, WEBGL);
x= 0;
y= 0;
A= 0;
background(220);
}
function keyPressed(){
if(key == "w"){
MOVE_FORWARD = true;
}else if(key == "ArrowLeft"){
TURN_LEFT = true;
}else if(key == "ArrowRight"){
TURN_RIGHT = true;
}
}
function keyReleased(){
if(key == "w"){
MOVE_FORWARD = false;
}else if(key == "ArrowLeft"){
TURN_LEFT = false;
}else if(key == "ArrowRight"){
TURN_RIGHT = false;
}
}
function draw() {
if(MOVE_FORWARD){
x+=0.005*cos(A);
y+=0.005*sin(A);
}
if(TURN_LEFT){
A+=PI/64;
}
if(TURN_RIGHT){
A-=PI/64;
}
var xyz = Sph(1,y,x);
X=xyz[0];
Y=xyz[1];
Z=xyz[2];
background(220);
sphere(scaler);
push();
translate(X*scaler,Y*scaler,Z*scaler);
sphere(5);
pop();
/*i+=PI/32;
if(i>2*PI){
i=0;
}*/
}
function Move(a,d){
//
}
function Sph(p,t,h){
//p = radius
//t (theta) = 2d rotation
//h (phi) = 3d roation
return ([p*cos(h)*cos(t),p*cos(h)*sin(t),p*sin(h)]);
//x=ρsinφcosθ,y=ρsinφsinθ, and z=ρcosφ
}
我不確定在極坐標中執行此操作的數學方法,但可以通過將位置和方向跟蹤為一對 3d 笛卡爾向量並使用Rodrigues 的旋轉公式向前移動(通過旋轉位置)和轉動(通過旋轉軸)。
// position vector let pos; // axis of rotation let axis; let scaler = 150; function setup() { createCanvas(400, 400, WEBGL); background(220); pos = createVector(1, 0, 0); axis = createVector(0, 1, 0); fill('red'); noStroke(); } function draw() { if (keyIsDown(87) || keyIsDown(UP_ARROW)) { // move "forward" rotateVector(pos, axis, PI / 64); } if (keyIsDown(LEFT_ARROW)) { // turn left rotateVector(axis, pos, -PI / 64); } if (keyIsDown(RIGHT_ARROW)) { // turn right rotateVector(axis, pos, PI / 64); } ambientLight(100); directionalLight(200, 200, 200, 1, 1, -1); push(); translate(pos.x * scaler, pos.y * scaler, pos.z * scaler); sphere(5); pop(); } function rotateVector(v, axis, angle) { // v * cos(θ) + (axis ✕ v) * sin + axis * (axis · v) * (1 - cos) return v.mult(cos(angle)) .add(axis.copy().cross(v).mult(sin(angle))) .add(axis.copy().mult(axis.dot(v) * (1 - cos(angle)))); }
<script src="https://cdnjs.cloudflare.com/ajax/libs/p5.js/1.4.0/p5.js"></script>
我不知道 javascript,但您可以實現以下功能(我在 python 中實現,希望您可以從中讀出它們背后的數學/幾何邏輯),允許您選擇球體上的運動方向,移動沿給定角度 ds 的台階沿大圓,並改變運動方向。 我假設運動在單位球面上(半徑為 1)。 如果沒有,您需要將代碼縮放到適當的半徑。
import numpy as np
import math
def direct(r, a):
'''
given position-vector r on the unit sphere and initial angle a,
measured from the meridian, i.e. direction north being a = 0,
the result is the unit vector t pointing in that direction
'''
e_z = np.array([0,0,1])
u = np.cross(e_z, r)
u = u / math.sqrt(u.dot(u))
v = np.cross(r, u)
t = math.cos(a) * v + math.sin(a) * u
return r, t
def move(r, t, ds):
'''
given unit position-vector r and unit direction vector t on the unit sphere,
make a step of arclength ds radians from point r in the direction of t along
the great circle that passes through r and tangent to t. The result is the
new position r_ and the new direction vector t_ still tangent to the same
great circle.
'''
co = math.cos(ds)
cs = math.sin(ds)
r_ = co * r + si * t
t_ = -si * r + cs * t
return t_, t_
def redirect(r, t, da):
'''
given unit position-vector r and unit direction vector t on the unit sphere,
rotate the vector t at an angle da.
The result is the new direction vector t_
when da > 0 redirect right
when da < 0 redirect left
'''
rot_axis = np.cross(r, t)
t_ = math.cos(da) * t - math.sin(da) * rot_axis
return r, t_
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.