沿垂线的反射向量
Reflecting Vector along Perpendicular
在 SO 社区的大力帮助下,我创建了一个程序,其中一个球位于具有特定位置和速度的三角形中。使用参数方程,我确定了球将击中三角形的位置。然后我找到了球击中的三角形边的垂直线,这样我就可以将球从墙上反射出来,绘制它的“弹跳”轨迹。我的目标是我可以绘制出球在 n 次迭代中如何从墙上反弹。但是我遇到了一个问题。
即使我使用 p5.js A.reflect(B)
方法沿垂线反射球,它也会产生一些非常奇怪的结果。
我尝试了很多东西(即修改 getPerp()
函数、单元测试等),但都无济于事。任何帮助将不胜感激。 MWE 低于 Codepen.
let angle = 0;
let sides = [];
let vertices = [];
const len = 100;
function setup() {
createCanvas(windowWidth, windowHeight);
angleMode(DEGREES);
angleOne = createSlider(0, 89, 60);
angleOne.position(10, 10);
angleOne.style("width", "80px");
angleTwo = createSlider(0, 89, 60);
angleTwo.position(10, 30);
angleTwo.style("width", "80px");
rotateVel = createSlider(0, 360, 60);
rotateVel.position(10, 50);
rotateVel.style("width", "80px");
// Initial vertice & side setup (these don't change)
let v1 = createVector(width / 2 - len / 2, height / 2);
let v2 = createVector(width / 2 + len / 2, height / 2);
sides[0] = new Side(v1.x, v1.y, v2.x, v2.y, "green");
vertices[0] = new Vertex(v1.x, v1.y);
vertices[1] = new Vertex(v2.x, v2.y);
}
function draw() {
background(255);
let angOne = angleOne.value();
let angTwo = angleTwo.value();
let rotVel = rotateVel.value();
fill(0);
strokeWeight(0);
textSize(15);
text(angOne, 100, 25);
text(angTwo, 100, 45);
text(rotVel, 100, 65);
let v2Offset = createVector(len * cos(-angOne), len * sin(-angOne));
let v3Offset = createVector(-len * cos(angTwo), -len * sin(angTwo));
vertices[2] = new Vertex(
vertices[0].a.x + v2Offset.x,
vertices[0].a.y + v2Offset.y
);
vertices[3] = new Vertex(
vertices[1].a.x + v3Offset.x,
vertices[1].a.y + v3Offset.y
);
// Update the sides
sides[1] = new Side(
vertices[0].a.x,
vertices[0].a.y,
vertices[2].a.x,
vertices[2].a.y
);
sides[3] = new Side(
vertices[1].a.x,
vertices[1].a.y,
vertices[3].a.x,
vertices[3].a.y
);
const m1 =
(vertices[2].a.y - vertices[0].a.y) / (vertices[2].a.x - vertices[0].a.x);
const m2 =
(vertices[3].a.y - vertices[1].a.y) / (vertices[3].a.x - vertices[1].a.x);
// Calculate the y-offset relative to vertices[0]
const b2 = (vertices[1].a.x - vertices[0].a.x) * -m2;
const xInt = b2 / (m1 - m2);
const yInt = xInt * m1;
// Note xInt and yInt are relative to vertices[0]
// draw all the things
// sides.forEach((s) => s.show());
// stroke(0, 255, 0);
// strokeWeight(20);
point(vertices[0].a.x + xInt, vertices[0].a.y + yInt);
vertices[4] = new Vertex(vertices[0].a.x + xInt, vertices[0].a.y + yInt);
sides[4] = new Side(
vertices[1].a.x,
vertices[1].a.y,
vertices[0].a.x + xInt,
vertices[0].a.y + yInt,
"blue"
);
sides[5] = new Side(
vertices[0].a.x,
vertices[0].a.y,
vertices[0].a.x + xInt,
vertices[0].a.y + yInt,
"purple"
);
scale(4); // so I can make the triangle actually *visible*
translate(-width / 3, -height / 3);
sides[0].show();
sides[4].show();
sides[5].show();
vertices[0].show();
vertices[1].show();
vertices[4].show();
strokeWeight(1);
stroke(255, 0, 0);
noFill();
arc(vertices[0].a.x, vertices[0].a.y, 40, 40, -1 * angleOne.value(), 0, PIE);
arc(
vertices[1].a.x,
vertices[1].a.y,
40,
40,
-180,
-(180 - angleTwo.value()),
PIE
);
stroke(0);
// stroke("purple"); // Change the color
strokeWeight(5); // Make the points 10 pixels in size
let P1x = vertices[0].a.x;
let P1y = vertices[0].a.y;
let P0 = createVector(P1x + 60, P1y - 40);
push();
let V0 = createVector(10 * cos(rotVel), 10 * sin(-rotVel));
pop();
point(P0.x, P0.y);
// point(P0.x + V0.x, P0.y + V0.y);
strokeWeight(2);
line(P0.x, P0.y, P0.x + V0.x, P0.y + V0.y);
let hit = wallHit(P0, V0);
// print("hit[0] is", hit[0]);
hitPoint = createVector(P0.x + V0.x * hit[0], P0.y + V0.y * hit[0]);
let A = createVector(
vertices[4].a.x - vertices[1].a.x,
vertices[4].a.y - vertices[1].a.y
);
// let B = p5.Vector.sub(vertices[1].a, vertices[2].a);
// let C = p5.Vector.sub(vertices[2].a, vertices[4].a);
// findNormal(hitPoint, A);
setLineDash([5, 5]);
stroke(0);
// let perpA = getY(vertices[1].a.x - 100, hitPoint);
// let normalA = createVector(vertices[1].a.x - 100, perpA);
// let incVec = createVector(hitPoint.x, hitPoint.y);
// let refVec = normalA.reflect(incVec);
let IOne = createVector(0, 0);
let ITwo = createVector(0, 0);
let IThree = createVector(0, 0);
// line(hitPoint.x, hitPoint.y, normalA.x, normalA.y);
let AOne = createVector(P1x, P1y);
let ATwo = createVector(vertices[1].a.x, vertices[1].a.y + 0.1);
let AThree = createVector(
(P1x + vertices[1].a.x) / 2,
(P1y + vertices[1].a.y) / 2
);
// getPerp(AOne, ATwo, hitPoint);
let BOne = createVector(P1x, P1y);
let BTwo = createVector(vertices[4].a.x, vertices[4].a.y + 0.1);
let BThree = createVector(
(P1x + vertices[4].a.x) / 2,
(P1y + vertices[4].a.y) / 2
);
// getPerp(BOne, BTwo, hitPoint);
let COne = createVector(vertices[1].a.x, vertices[1].a.y);
let CTwo = createVector(vertices[4].a.x, vertices[4].a.y + 0.1);
let CThree = createVector(
(vertices[1].a.x + vertices[4].a.x) / 2,
(vertices[1].a.y + vertices[4].a.y) / 2
);
// getPerp(COne, CTwo, hitPoint);
let incVec = createVector(hitPoint.x, hitPoint.y);
line(P0.x, P0.y, incVec.x, incVec.y);
let perp = getPerp(IOne, ITwo, IThree);
let testOne = createVector(vertices[0].a.x + 20, vertices[0].a.y + 20);
let testTwo = createVector(vertices[1].a.x + 20, vertices[1].a.y + 20);
let refVec = testOne.reflect(testTwo);
// line(testOne.x, testOne.y, testTwo.x, testTwo.y);
if (hit[1] == "t3") {
perp = getPerp(AOne, ATwo, hitPoint);
refVec = perp.reflect(incVec);
} else if (hit[1] == "t1") {
perp = getPerp(BOne, BTwo, hitPoint);
refVec = perp.reflect(incVec);
} else {
perp = getPerp(COne, CTwo, hitPoint);
refVec = perp.reflect(incVec);
}
stroke("black");
line(hitPoint.x, hitPoint.y, refVec.x, refVec.y);
setLineDash([0, 0]);
}
function setLineDash(list) {
drawingContext.setLineDash(list);
}
class Side {
constructor(x1, y1, x2, y2, col = "black") {
this.a = createVector(x1, y1);
this.b = createVector(x2, y2);
this.color = col;
}
show() {
stroke(this.color);
strokeWeight(4);
line(this.a.x, this.a.y, this.b.x, this.b.y);
}
}
class Vertex {
constructor(x1, y1) {
this.a = createVector(x1, y1);
}
show() {
stroke(255, 0, 0);
strokeWeight(10);
point(this.a.x, this.a.y);
}
}
function wallHit(pos, vel) {
let P1x = vertices[0].a.x;
let P1y = vertices[0].a.y;
let P2x = vertices[1].a.x;
let P2y = vertices[1].a.y;
let P3x = vertices[4].a.x;
let P3y = vertices[4].a.y;
let A1 = P3y - P1y;
let B1 = -(P3x - P1x);
let C1 = A1 * P1x + B1 * P1y;
let A2 = -(P3y - P2y);
let B2 = P3x - P2x;
let C2 = A2 * P2x + B2 * P2y;
let A3 = -(P2y - P1y);
let B3 = P2x - P1x;
let C3 = A3 * P2x + B3 * P2y;
let t1 = (C1 - A1 * pos.x - B1 * pos.y) / (A1 * vel.x + B1 * vel.y);
let t2 = (C2 - A2 * pos.x - B2 * pos.y) / (A2 * vel.x + B2 * vel.y);
let t3 = (C3 - A3 * pos.x - B3 * pos.y) / (A3 * vel.x + B3 * vel.y);
let times = [t1, t2, t3];
let posTimes = [];
for (let i = 0; i < times.length; i++) {
times[i] = round(times[i], 2);
}
// console.log("After rounding:", times);
for (let i = 0; i < times.length; i++) {
if (times[i] > 0) {
posTimes.push(times[i]);
}
}
let hitPoint = createVector(0, 1);
// console.log("posTimes:", posTimes);
trueTime = min(posTimes);
if (trueTime == round(t1, 2)) {
// print("Hit Purple");
return [t1, "t1"];
// hitPoint = createVector(P0.x + V0.x * t1, P0.y + V0.y * t1);
// line(P0.x, P0.y, hitPoint.x, hitPoint.y);
} else if (trueTime == round(t2, 2)) {
// print("Hit Blue");
return [t2, "t2"];
// hitPoint = createVector(P0.x + V0.x * t2, P0.y + V0.y * t2);
// line(P0.x, P0.y, hitPoint.x, hitPoint.y);
} else {
// print("Hit Green");
return [t3, "t3"];
// hitPoint = createVector(P0.x + V0.x * t3, P0.y + V0.y * t3);
// line(P0.x, P0.y, hitPoint.x, hitPoint.y);
}
}
function findNormal(pos, wall) {
let perpVector = createVector(-wall.y, wall.x);
strokeWeight(2);
stroke(0);
line(pos.x, pos.y, perpVector.x, perpVector.y);
// line(P0.x, P0.y, hitPoint.x, hitPoint.y);
}
function getY(x, HP) {
let perpY =
-((vertices[4].a.x - vertices[1].a.x) / (vertices[4].a.y - vertices[1].a.y)) *
x +
(HP.y +
((vertices[4].a.x - vertices[1].a.x) / (vertices[4].a.y - vertices[1].a.y)) *
HP.x);
return perpY;
}
function getPerp(p1, p2, p3) {
x1 = p1.x;
y1 = p1.y;
x2 = p2.x;
y2 = p2.y;
x3 = p3.x;
y3 = p3.y;
stroke(0);
strokeWeight(2);
line1 = line(x1, y1, x2, y2);
m1 = (y2 - y1) / (x2 - x1);
m2 = -1 / m1;
b2 = y3 - x3 * m2;
stroke(255, 0, 0);
line(x3, m2 * x3 + b2, x1, m2 * x1 + b2);
let final = createVector(m2 * x1 + b2 - (m2 * x3 + b2), x1 - x3);
return final;
}
html,
body {
margin: 0;
padding: 0;
overflow: hidden;
}
<script src="https://cdn.jsdelivr.net/npm/p5@1.4.1/lib/p5.min.js"></script>
你混淆了向量和点。一个点有 2 个坐标,从坐标系的原点开始测量。一个向量表示一个方向,减去2个点就可以得到。因此,入射向量为:
inVec = createVector(hitPoint.x - P0.x, hitPoint.y - P0.y);
向量(Vx,Vy)的法向量(垂直向量)为:
N = (-Vy, Vx)
因此,由 2 个点 (Ax, Ay) 和 (Bx, By) 给出的直线的法向量(垂直)为:
N = (Ay - By, Bx - Ax)
reflect()
函数通过给定的曲面法向量反映曲面上的入射向量。函数的参数是法向量:
refVec = inVec.reflect(n);
line
在两点之间画一条线。 refVec
不是一个点而是一个向量。因此,您需要绘制从 hitPoint
到 hitPoint + refVec
的直线,而不是从 hitPoint
到 refVec
.
的形式
总计:
inVec = createVector(hitPoint.x - P0.x, hitPoint.y - P0.y);
if (hit[1] == "t3") {
perp = getPerp(AOne, ATwo, hitPoint);
let n = createVector(AOne.y - ATwo.y, ATwo.x - AOne.x);
refVec = inVec.reflect(n);
} else if (hit[1] == "t1") {
perp = getPerp(BOne, BTwo, hitPoint);
let n = createVector(BOne.y - BTwo.y, BTwo.x - BOne.x);
refVec = inVec.reflect(n);
} else {
perp = getPerp(COne, CTwo, hitPoint);
let n = createVector(COne.y - CTwo.y, CTwo.x - COne.x);
refVec = inVec.reflect(n);
}
stroke("black");
line(hitPoint.x, hitPoint.y, hitPoint.x + refVec.x, hitPoint.y + refVec.y);
在 SO 社区的大力帮助下,我创建了一个程序,其中一个球位于具有特定位置和速度的三角形中。使用参数方程,我确定了球将击中三角形的位置。然后我找到了球击中的三角形边的垂直线,这样我就可以将球从墙上反射出来,绘制它的“弹跳”轨迹。我的目标是我可以绘制出球在 n 次迭代中如何从墙上反弹。但是我遇到了一个问题。
即使我使用 p5.js A.reflect(B)
方法沿垂线反射球,它也会产生一些非常奇怪的结果。
getPerp()
函数、单元测试等),但都无济于事。任何帮助将不胜感激。 MWE 低于 Codepen.
let angle = 0;
let sides = [];
let vertices = [];
const len = 100;
function setup() {
createCanvas(windowWidth, windowHeight);
angleMode(DEGREES);
angleOne = createSlider(0, 89, 60);
angleOne.position(10, 10);
angleOne.style("width", "80px");
angleTwo = createSlider(0, 89, 60);
angleTwo.position(10, 30);
angleTwo.style("width", "80px");
rotateVel = createSlider(0, 360, 60);
rotateVel.position(10, 50);
rotateVel.style("width", "80px");
// Initial vertice & side setup (these don't change)
let v1 = createVector(width / 2 - len / 2, height / 2);
let v2 = createVector(width / 2 + len / 2, height / 2);
sides[0] = new Side(v1.x, v1.y, v2.x, v2.y, "green");
vertices[0] = new Vertex(v1.x, v1.y);
vertices[1] = new Vertex(v2.x, v2.y);
}
function draw() {
background(255);
let angOne = angleOne.value();
let angTwo = angleTwo.value();
let rotVel = rotateVel.value();
fill(0);
strokeWeight(0);
textSize(15);
text(angOne, 100, 25);
text(angTwo, 100, 45);
text(rotVel, 100, 65);
let v2Offset = createVector(len * cos(-angOne), len * sin(-angOne));
let v3Offset = createVector(-len * cos(angTwo), -len * sin(angTwo));
vertices[2] = new Vertex(
vertices[0].a.x + v2Offset.x,
vertices[0].a.y + v2Offset.y
);
vertices[3] = new Vertex(
vertices[1].a.x + v3Offset.x,
vertices[1].a.y + v3Offset.y
);
// Update the sides
sides[1] = new Side(
vertices[0].a.x,
vertices[0].a.y,
vertices[2].a.x,
vertices[2].a.y
);
sides[3] = new Side(
vertices[1].a.x,
vertices[1].a.y,
vertices[3].a.x,
vertices[3].a.y
);
const m1 =
(vertices[2].a.y - vertices[0].a.y) / (vertices[2].a.x - vertices[0].a.x);
const m2 =
(vertices[3].a.y - vertices[1].a.y) / (vertices[3].a.x - vertices[1].a.x);
// Calculate the y-offset relative to vertices[0]
const b2 = (vertices[1].a.x - vertices[0].a.x) * -m2;
const xInt = b2 / (m1 - m2);
const yInt = xInt * m1;
// Note xInt and yInt are relative to vertices[0]
// draw all the things
// sides.forEach((s) => s.show());
// stroke(0, 255, 0);
// strokeWeight(20);
point(vertices[0].a.x + xInt, vertices[0].a.y + yInt);
vertices[4] = new Vertex(vertices[0].a.x + xInt, vertices[0].a.y + yInt);
sides[4] = new Side(
vertices[1].a.x,
vertices[1].a.y,
vertices[0].a.x + xInt,
vertices[0].a.y + yInt,
"blue"
);
sides[5] = new Side(
vertices[0].a.x,
vertices[0].a.y,
vertices[0].a.x + xInt,
vertices[0].a.y + yInt,
"purple"
);
scale(4); // so I can make the triangle actually *visible*
translate(-width / 3, -height / 3);
sides[0].show();
sides[4].show();
sides[5].show();
vertices[0].show();
vertices[1].show();
vertices[4].show();
strokeWeight(1);
stroke(255, 0, 0);
noFill();
arc(vertices[0].a.x, vertices[0].a.y, 40, 40, -1 * angleOne.value(), 0, PIE);
arc(
vertices[1].a.x,
vertices[1].a.y,
40,
40,
-180,
-(180 - angleTwo.value()),
PIE
);
stroke(0);
// stroke("purple"); // Change the color
strokeWeight(5); // Make the points 10 pixels in size
let P1x = vertices[0].a.x;
let P1y = vertices[0].a.y;
let P0 = createVector(P1x + 60, P1y - 40);
push();
let V0 = createVector(10 * cos(rotVel), 10 * sin(-rotVel));
pop();
point(P0.x, P0.y);
// point(P0.x + V0.x, P0.y + V0.y);
strokeWeight(2);
line(P0.x, P0.y, P0.x + V0.x, P0.y + V0.y);
let hit = wallHit(P0, V0);
// print("hit[0] is", hit[0]);
hitPoint = createVector(P0.x + V0.x * hit[0], P0.y + V0.y * hit[0]);
let A = createVector(
vertices[4].a.x - vertices[1].a.x,
vertices[4].a.y - vertices[1].a.y
);
// let B = p5.Vector.sub(vertices[1].a, vertices[2].a);
// let C = p5.Vector.sub(vertices[2].a, vertices[4].a);
// findNormal(hitPoint, A);
setLineDash([5, 5]);
stroke(0);
// let perpA = getY(vertices[1].a.x - 100, hitPoint);
// let normalA = createVector(vertices[1].a.x - 100, perpA);
// let incVec = createVector(hitPoint.x, hitPoint.y);
// let refVec = normalA.reflect(incVec);
let IOne = createVector(0, 0);
let ITwo = createVector(0, 0);
let IThree = createVector(0, 0);
// line(hitPoint.x, hitPoint.y, normalA.x, normalA.y);
let AOne = createVector(P1x, P1y);
let ATwo = createVector(vertices[1].a.x, vertices[1].a.y + 0.1);
let AThree = createVector(
(P1x + vertices[1].a.x) / 2,
(P1y + vertices[1].a.y) / 2
);
// getPerp(AOne, ATwo, hitPoint);
let BOne = createVector(P1x, P1y);
let BTwo = createVector(vertices[4].a.x, vertices[4].a.y + 0.1);
let BThree = createVector(
(P1x + vertices[4].a.x) / 2,
(P1y + vertices[4].a.y) / 2
);
// getPerp(BOne, BTwo, hitPoint);
let COne = createVector(vertices[1].a.x, vertices[1].a.y);
let CTwo = createVector(vertices[4].a.x, vertices[4].a.y + 0.1);
let CThree = createVector(
(vertices[1].a.x + vertices[4].a.x) / 2,
(vertices[1].a.y + vertices[4].a.y) / 2
);
// getPerp(COne, CTwo, hitPoint);
let incVec = createVector(hitPoint.x, hitPoint.y);
line(P0.x, P0.y, incVec.x, incVec.y);
let perp = getPerp(IOne, ITwo, IThree);
let testOne = createVector(vertices[0].a.x + 20, vertices[0].a.y + 20);
let testTwo = createVector(vertices[1].a.x + 20, vertices[1].a.y + 20);
let refVec = testOne.reflect(testTwo);
// line(testOne.x, testOne.y, testTwo.x, testTwo.y);
if (hit[1] == "t3") {
perp = getPerp(AOne, ATwo, hitPoint);
refVec = perp.reflect(incVec);
} else if (hit[1] == "t1") {
perp = getPerp(BOne, BTwo, hitPoint);
refVec = perp.reflect(incVec);
} else {
perp = getPerp(COne, CTwo, hitPoint);
refVec = perp.reflect(incVec);
}
stroke("black");
line(hitPoint.x, hitPoint.y, refVec.x, refVec.y);
setLineDash([0, 0]);
}
function setLineDash(list) {
drawingContext.setLineDash(list);
}
class Side {
constructor(x1, y1, x2, y2, col = "black") {
this.a = createVector(x1, y1);
this.b = createVector(x2, y2);
this.color = col;
}
show() {
stroke(this.color);
strokeWeight(4);
line(this.a.x, this.a.y, this.b.x, this.b.y);
}
}
class Vertex {
constructor(x1, y1) {
this.a = createVector(x1, y1);
}
show() {
stroke(255, 0, 0);
strokeWeight(10);
point(this.a.x, this.a.y);
}
}
function wallHit(pos, vel) {
let P1x = vertices[0].a.x;
let P1y = vertices[0].a.y;
let P2x = vertices[1].a.x;
let P2y = vertices[1].a.y;
let P3x = vertices[4].a.x;
let P3y = vertices[4].a.y;
let A1 = P3y - P1y;
let B1 = -(P3x - P1x);
let C1 = A1 * P1x + B1 * P1y;
let A2 = -(P3y - P2y);
let B2 = P3x - P2x;
let C2 = A2 * P2x + B2 * P2y;
let A3 = -(P2y - P1y);
let B3 = P2x - P1x;
let C3 = A3 * P2x + B3 * P2y;
let t1 = (C1 - A1 * pos.x - B1 * pos.y) / (A1 * vel.x + B1 * vel.y);
let t2 = (C2 - A2 * pos.x - B2 * pos.y) / (A2 * vel.x + B2 * vel.y);
let t3 = (C3 - A3 * pos.x - B3 * pos.y) / (A3 * vel.x + B3 * vel.y);
let times = [t1, t2, t3];
let posTimes = [];
for (let i = 0; i < times.length; i++) {
times[i] = round(times[i], 2);
}
// console.log("After rounding:", times);
for (let i = 0; i < times.length; i++) {
if (times[i] > 0) {
posTimes.push(times[i]);
}
}
let hitPoint = createVector(0, 1);
// console.log("posTimes:", posTimes);
trueTime = min(posTimes);
if (trueTime == round(t1, 2)) {
// print("Hit Purple");
return [t1, "t1"];
// hitPoint = createVector(P0.x + V0.x * t1, P0.y + V0.y * t1);
// line(P0.x, P0.y, hitPoint.x, hitPoint.y);
} else if (trueTime == round(t2, 2)) {
// print("Hit Blue");
return [t2, "t2"];
// hitPoint = createVector(P0.x + V0.x * t2, P0.y + V0.y * t2);
// line(P0.x, P0.y, hitPoint.x, hitPoint.y);
} else {
// print("Hit Green");
return [t3, "t3"];
// hitPoint = createVector(P0.x + V0.x * t3, P0.y + V0.y * t3);
// line(P0.x, P0.y, hitPoint.x, hitPoint.y);
}
}
function findNormal(pos, wall) {
let perpVector = createVector(-wall.y, wall.x);
strokeWeight(2);
stroke(0);
line(pos.x, pos.y, perpVector.x, perpVector.y);
// line(P0.x, P0.y, hitPoint.x, hitPoint.y);
}
function getY(x, HP) {
let perpY =
-((vertices[4].a.x - vertices[1].a.x) / (vertices[4].a.y - vertices[1].a.y)) *
x +
(HP.y +
((vertices[4].a.x - vertices[1].a.x) / (vertices[4].a.y - vertices[1].a.y)) *
HP.x);
return perpY;
}
function getPerp(p1, p2, p3) {
x1 = p1.x;
y1 = p1.y;
x2 = p2.x;
y2 = p2.y;
x3 = p3.x;
y3 = p3.y;
stroke(0);
strokeWeight(2);
line1 = line(x1, y1, x2, y2);
m1 = (y2 - y1) / (x2 - x1);
m2 = -1 / m1;
b2 = y3 - x3 * m2;
stroke(255, 0, 0);
line(x3, m2 * x3 + b2, x1, m2 * x1 + b2);
let final = createVector(m2 * x1 + b2 - (m2 * x3 + b2), x1 - x3);
return final;
}
html,
body {
margin: 0;
padding: 0;
overflow: hidden;
}
<script src="https://cdn.jsdelivr.net/npm/p5@1.4.1/lib/p5.min.js"></script>
你混淆了向量和点。一个点有 2 个坐标,从坐标系的原点开始测量。一个向量表示一个方向,减去2个点就可以得到。因此,入射向量为:
inVec = createVector(hitPoint.x - P0.x, hitPoint.y - P0.y);
向量(Vx,Vy)的法向量(垂直向量)为:
N = (-Vy, Vx)
因此,由 2 个点 (Ax, Ay) 和 (Bx, By) 给出的直线的法向量(垂直)为:
N = (Ay - By, Bx - Ax)
reflect()
函数通过给定的曲面法向量反映曲面上的入射向量。函数的参数是法向量:
refVec = inVec.reflect(n);
line
在两点之间画一条线。 refVec
不是一个点而是一个向量。因此,您需要绘制从 hitPoint
到 hitPoint + refVec
的直线,而不是从 hitPoint
到 refVec
.
总计:
inVec = createVector(hitPoint.x - P0.x, hitPoint.y - P0.y);
if (hit[1] == "t3") {
perp = getPerp(AOne, ATwo, hitPoint);
let n = createVector(AOne.y - ATwo.y, ATwo.x - AOne.x);
refVec = inVec.reflect(n);
} else if (hit[1] == "t1") {
perp = getPerp(BOne, BTwo, hitPoint);
let n = createVector(BOne.y - BTwo.y, BTwo.x - BOne.x);
refVec = inVec.reflect(n);
} else {
perp = getPerp(COne, CTwo, hitPoint);
let n = createVector(COne.y - CTwo.y, CTwo.x - COne.x);
refVec = inVec.reflect(n);
}
stroke("black");
line(hitPoint.x, hitPoint.y, hitPoint.x + refVec.x, hitPoint.y + refVec.y);