如何将矢量旋转 90 度到垂直平面,然后再从该平面旋转 15 度?
How can I rotate a vector 90 degrees into a perpendicular plane, and then 15 degrees free from that plane?
我最终想要的是一个向量,给出下图中绿线的方向,只知道黄点和绿点的位置。
更具体地说,它的角度可以是随机的,只要它的端点在圆柱体的绿蓝色表面上的某个地方结束。因此,圆柱体周围 360° 自由,大约 15° 限制在圆柱体的边缘。
圆柱垂直于黄点和绿点的直线。
长度不重要,方向重要
我的主要问题是我不知道如何从矢量黄色到绿点,再到垂直于它的任何矢量。
PS None 这些东西在 x y z 轴上对齐。该网格不是 xyz,只是为了帮助可视化。
代码如下:给定一个角度 theta 和两个点,它将为您提供一个从 pointStart 开始的向量,该向量垂直于从 pointStart 到 pointEnd 的向量:
function perpendicularVector(pointStart,pointEnd,theta){
let vDiff = new THREE.Vector3(0, 0, 0)
.subVectors(pointEnd, pointStart)
.normalize()
let V = new THREE.Vector3(
vDiff.y + vDiff.x * vDiff.z,
vDiff.y * vDiff.z -vDiff.x,
-(vDiff.x * vDiff.x) - vDiff.y * vDiff.y
)
return
V .applyAxisAngle(vDiff, theta)
.applyAxisAngle( new THREE.Vector3().multiplyVectors(V, vDiff).normalize(), 15*Math.PI/180 )
}
这里是上面代码的一个小展示:(这个片段是故意的,因为它只是为了展示上面代码的功能)
(您可以在单击 运行 片段后出现的渲染图上使用鼠标缩放旋转和平移)
body {
font-family: sans-serif;
margin: 0;
background-color: #e2cba9;
width: 100%;
height: 100%;
overflow: hidden;
}
canvas {
width: 100%;
height: 100%;
}
<div id="app"></div>
<script type="module">
import { OrbitControls } from "https://cdn.jsdelivr.net/npm/three@0.121.1/examples/jsm/controls/OrbitControls.js";
import * as THREE from "https://cdn.jsdelivr.net/npm/three@0.121.1/build/three.module.js";
var scene = new THREE.Scene, theta = 0;
let point1 = new THREE.Vector3(4, 2, 1),
point2 = new THREE.Vector3(0, 3, 3);
function perpendicularVector(e, n, t) {
let r = new THREE.Vector3(0, 0, 0).subVectors(n, e).normalize(),
o = new THREE.Vector3(r.y, -r.x, 0),
i = new THREE.Vector3(r.x * r.z, r.y * r.z, -r.x * r.x - r.y * r.y);
var a = o.multiplyScalar(Math.cos(t)).add(i.multiplyScalar(Math.sin(t)));
return a.add(e), a
}
function pointAtCoords(e, n) {
let t = new THREE.MeshBasicMaterial({ color: n }),
r = new THREE.SphereGeometry(.1, 8, 8),
o = new
THREE.Mesh(r, t);
return o.position.add(e), o
}
function lineFromAtoB(e, n, t) {
let r = new THREE.LineBasicMaterial({ color: t }),
o = [];
o.push(e), o.push(n);
let i = (new THREE.BufferGeometry).setFromPoints(o);
return new THREE.Line(i, r)
}
var renderer = new THREE.WebGLRenderer({ antialias: !0 });
renderer.setSize(window.innerWidth, window.innerHeight), document.getElementById("app").appendChild(renderer.domElement);
var camera = new THREE.PerspectiveCamera(50, window.innerWidth / window.innerHeight,
.1, 1e3);
camera.position.set(7, 7, 8), camera.lookAt(new THREE.Vector3), camera.position.add(new THREE.Vector3(3, 0, 3));
var controls = new OrbitControls(camera, renderer.domElement);
function drawEverything(e) {
const n = new THREE.AxesHelper(30);
scene.add(n);
const t = new THREE.GridHelper(30, 30);
t.position.add(new THREE.Vector3(15, 0, 15)), scene.add(t);
const r = new THREE.GridHelper(30, 30);
r.rotateX(Math.PI / 2), r.position.add(new THREE.Vector3(15, 15, 0)), scene.add(r);
const o = new THREE.GridHelper(30, 30);
o.rotateZ(Math.PI / 2), o.position.add(new THREE.Vector3(0, 15, 15)), scene.add(o);
let i = new THREE.Vector3(0, 0, 0),
a = perpendicularVector(point1, point2, e);
scene.add(pointAtCoords(point1, 16776960)), scene.add(pointAtCoords(point2, 65280));
var d = pointAtCoords(a, 255);
scene.add(d), scene.add(lineFromAtoB(point1, point2, 16711935)), scene.add(lineFromAtoB(i, point1, 16711680)), scene.add(lineFromAtoB(i, point2, 16711680)), scene.add(lineFromAtoB(point1, a, 65280))
}
function animate() {
scene = new THREE.Scene, drawEverything(theta += .1),
setTimeout((() => {
requestAnimationFrame(animate)
}), 1e3 / 30), renderer.render(scene, camera)
}
animate();
</script>
这完全可以通过一些数学计算来实现。您要查找的术语是 "Orthogonal vectors",这意味着相互垂直的向量。圆柱体半径正交于蓝点到黄点之间的线。
但是,由于您已经在使用 Three.js,您可以让它在 an Object3D
的帮助下为您完成所有艰苦的工作。
// Declare vectorA (center, green)
const vecA = new THREE.Vector3(xA, yA, zA);
// Declare vectorB (destination, yellow)
const vecB = new THREE.Vector3(xB, yB, zB);
// Create helper object
const helper = new THREE.Object3D();
// Center helper at vecA
helper.position.copy(vecA);
// Rotate helper towards vecB
helper.lookAt(vecB);
// Move helper perpendicularly along its own y-axis
const cylinderRadius = 27;
helper.translateY(cylinderRadius);
// Now you have your final position!
console.log(helper.position);
在下图中,助手 Object3D
显示为红线只是为了让您了解它的旋转和位置,但实际上它是不可见的,除非您添加 Mesh
如果你想 add/subtract 与垂直线成 15 度,你可以沿着它自己 x-axis before translateY()
const xAngle = THREE.MathUtils.degToRad(15);
helper.rotateX(xAngle);
const cylinderRadius = 27;
helper.translateY(cylinderRadius);
我最终想要的是一个向量,给出下图中绿线的方向,只知道黄点和绿点的位置。
更具体地说,它的角度可以是随机的,只要它的端点在圆柱体的绿蓝色表面上的某个地方结束。因此,圆柱体周围 360° 自由,大约 15° 限制在圆柱体的边缘。
圆柱垂直于黄点和绿点的直线。
长度不重要,方向重要
我的主要问题是我不知道如何从矢量黄色到绿点,再到垂直于它的任何矢量。
PS None 这些东西在 x y z 轴上对齐。该网格不是 xyz,只是为了帮助可视化。
代码如下:给定一个角度 theta 和两个点,它将为您提供一个从 pointStart 开始的向量,该向量垂直于从 pointStart 到 pointEnd 的向量:
function perpendicularVector(pointStart,pointEnd,theta){
let vDiff = new THREE.Vector3(0, 0, 0)
.subVectors(pointEnd, pointStart)
.normalize()
let V = new THREE.Vector3(
vDiff.y + vDiff.x * vDiff.z,
vDiff.y * vDiff.z -vDiff.x,
-(vDiff.x * vDiff.x) - vDiff.y * vDiff.y
)
return
V .applyAxisAngle(vDiff, theta)
.applyAxisAngle( new THREE.Vector3().multiplyVectors(V, vDiff).normalize(), 15*Math.PI/180 )
}
这里是上面代码的一个小展示:(这个片段是故意的,因为它只是为了展示上面代码的功能)
(您可以在单击 运行 片段后出现的渲染图上使用鼠标缩放旋转和平移)
body {
font-family: sans-serif;
margin: 0;
background-color: #e2cba9;
width: 100%;
height: 100%;
overflow: hidden;
}
canvas {
width: 100%;
height: 100%;
}
<div id="app"></div>
<script type="module">
import { OrbitControls } from "https://cdn.jsdelivr.net/npm/three@0.121.1/examples/jsm/controls/OrbitControls.js";
import * as THREE from "https://cdn.jsdelivr.net/npm/three@0.121.1/build/three.module.js";
var scene = new THREE.Scene, theta = 0;
let point1 = new THREE.Vector3(4, 2, 1),
point2 = new THREE.Vector3(0, 3, 3);
function perpendicularVector(e, n, t) {
let r = new THREE.Vector3(0, 0, 0).subVectors(n, e).normalize(),
o = new THREE.Vector3(r.y, -r.x, 0),
i = new THREE.Vector3(r.x * r.z, r.y * r.z, -r.x * r.x - r.y * r.y);
var a = o.multiplyScalar(Math.cos(t)).add(i.multiplyScalar(Math.sin(t)));
return a.add(e), a
}
function pointAtCoords(e, n) {
let t = new THREE.MeshBasicMaterial({ color: n }),
r = new THREE.SphereGeometry(.1, 8, 8),
o = new
THREE.Mesh(r, t);
return o.position.add(e), o
}
function lineFromAtoB(e, n, t) {
let r = new THREE.LineBasicMaterial({ color: t }),
o = [];
o.push(e), o.push(n);
let i = (new THREE.BufferGeometry).setFromPoints(o);
return new THREE.Line(i, r)
}
var renderer = new THREE.WebGLRenderer({ antialias: !0 });
renderer.setSize(window.innerWidth, window.innerHeight), document.getElementById("app").appendChild(renderer.domElement);
var camera = new THREE.PerspectiveCamera(50, window.innerWidth / window.innerHeight,
.1, 1e3);
camera.position.set(7, 7, 8), camera.lookAt(new THREE.Vector3), camera.position.add(new THREE.Vector3(3, 0, 3));
var controls = new OrbitControls(camera, renderer.domElement);
function drawEverything(e) {
const n = new THREE.AxesHelper(30);
scene.add(n);
const t = new THREE.GridHelper(30, 30);
t.position.add(new THREE.Vector3(15, 0, 15)), scene.add(t);
const r = new THREE.GridHelper(30, 30);
r.rotateX(Math.PI / 2), r.position.add(new THREE.Vector3(15, 15, 0)), scene.add(r);
const o = new THREE.GridHelper(30, 30);
o.rotateZ(Math.PI / 2), o.position.add(new THREE.Vector3(0, 15, 15)), scene.add(o);
let i = new THREE.Vector3(0, 0, 0),
a = perpendicularVector(point1, point2, e);
scene.add(pointAtCoords(point1, 16776960)), scene.add(pointAtCoords(point2, 65280));
var d = pointAtCoords(a, 255);
scene.add(d), scene.add(lineFromAtoB(point1, point2, 16711935)), scene.add(lineFromAtoB(i, point1, 16711680)), scene.add(lineFromAtoB(i, point2, 16711680)), scene.add(lineFromAtoB(point1, a, 65280))
}
function animate() {
scene = new THREE.Scene, drawEverything(theta += .1),
setTimeout((() => {
requestAnimationFrame(animate)
}), 1e3 / 30), renderer.render(scene, camera)
}
animate();
</script>
这完全可以通过一些数学计算来实现。您要查找的术语是 "Orthogonal vectors",这意味着相互垂直的向量。圆柱体半径正交于蓝点到黄点之间的线。
但是,由于您已经在使用 Three.js,您可以让它在 an Object3D
的帮助下为您完成所有艰苦的工作。
// Declare vectorA (center, green)
const vecA = new THREE.Vector3(xA, yA, zA);
// Declare vectorB (destination, yellow)
const vecB = new THREE.Vector3(xB, yB, zB);
// Create helper object
const helper = new THREE.Object3D();
// Center helper at vecA
helper.position.copy(vecA);
// Rotate helper towards vecB
helper.lookAt(vecB);
// Move helper perpendicularly along its own y-axis
const cylinderRadius = 27;
helper.translateY(cylinderRadius);
// Now you have your final position!
console.log(helper.position);
在下图中,助手 Object3D
显示为红线只是为了让您了解它的旋转和位置,但实际上它是不可见的,除非您添加 Mesh
如果你想 add/subtract 与垂直线成 15 度,你可以沿着它自己 x-axis before translateY()
const xAngle = THREE.MathUtils.degToRad(15);
helper.rotateX(xAngle);
const cylinderRadius = 27;
helper.translateY(cylinderRadius);