Question: How do I get the location of a point after rotation?
Goal: I want to create a triangle given two angles. The user can manipulate two angles (a0,b0)
and the program will determine the third vertex based on the intersection of the two sides.
Explanation: To find the point of intersection of the two sides, I need four points: the endpoints for l1
and l2
. To keep track of the points, I created vertices=[]
. But the array doesn't update the location of the points after the user rotates the sides and changes (a0,b0)
.
Thus, when I retrieve my points, two of them are in their initialized position, and have not been updated after the user rotates the sides. I've searched for this problem online, but to no avail. Any help is appreciated.
MWE:
let angle = 0;
let sides = [];
let vertices = [];
function setup(){
createCanvas(600, 400);
angleMode(DEGREES);
angleOne = createSlider(0, 180, 100);
angleOne.position(10,10);
angleOne.style('width', '80px');
angleTwo = createSlider(0, 180, 100);
angleTwo.position(10,30);
angleTwo.style('width', '80px');
}
function draw(){
background(255);
let angOne = angleOne.value();
let angTwo = angleTwo.value();
strokeWeight(0);
textSize(15);
text(angOne, 90, 17);
text(angTwo, 90, 37);
let v1 = createVector(width/2 - 50, height/2);
let v2 = createVector(width/2 + 50, height/2);
sides[0] = new Side(v1.x, v1.y, v2.x, v2.y);
sides[0].show();
vertices[0] = new Vertex(v1.x, v1.y);
vertices[0].show();
vertices[1] = new Vertex(v2.x, v2.y);
vertices[1].show();
/** ROTATE TIME **/
push();
translate(v1.x, v1.y);
rotate(-1*angOne);
translate(-v1.x, -v1.y);
sides[1] = new Side(v1.x, v1.y, v2.x, v2.y);
sides[1].show();
vertices[2] = new Vertex(v2.x, v2.y);
vertices[2].show();
pop();
/** ROTATE TIME **/
push();
translate(v2.x, v2.y);
rotate(angTwo);
translate(-v2.x, -v2.y);
sides[2] = new Side(v1.x, v1.y, v2.x, v2.y);
sides[2].show();
vertices[3] = new Vertex(v1.x, v1.y);
vertices[3].show();
pop();
// const x1 = sides[0].a.x;
// const y1 = sides[0].a.y;
// const x2 = sides[1].a.x;
// const y2 = sides[1].a.y;
//
// const x3 = p3.x;
// const y3 = p3.y;
// const x4 = p4.x;
// const y4 = p4.y;
}
class Side {
constructor(x1, y1, x2, y2){
this.a = createVector(x1, y1);
this.b = createVector(x2, y2);
}
show() {
stroke(0);
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(20);
point(this.a.x, this.a.y);
}
}
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<meta http-equiv="X-UA-Compatible" content="ie=edge" />
<script src="https://cdn.jsdelivr.net/npm/p5@1.4.1/lib/p5.min.js"></script>
<title>Billiards #2</title>
</head>
<body>
</body>
</html>
In a word: trigonometry. Instead of using the rotate()
function to rotate the drawing frame of reference, use trig to calculate the various vertex positions. Here's code with comments which hopefully explain how this is done:
let angle = 0;
let sides = [];
let vertices = [];
const len = 100;
function setup() {
createCanvas(600, 400);
angleMode(DEGREES);
angleOne = createSlider(0, 180, 45);
angleOne.position(10, 10);
angleOne.style('width', '80px');
angleTwo = createSlider(0, 180, 100);
angleTwo.position(10, 30);
angleTwo.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);
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();
strokeWeight(0);
textSize(15);
text(angOne, 90, 17);
text(angTwo, 90, 37);
// Calculate vertices 2 and 3 based on angles
// We can use trigonometry to find the x and y component of a vector of known length based on the angle from some refference.
// In this case our reference will be in the positive X direction.
// The sine of an angle is, given a right triangle, equal to the ratio of the opposite side from that angle and the hypotenuse of the triangle, so that corresponds to our Y component.
// The cosine is the ratio of the adjacent side over the hypotenuse, so that represents our X component
let v2Offset = createVector(
len * cos(-angOne),
len * sin(-angOne)
);
// Our reference vector for this is in the negative X direction and we are rotating clockwise instead of counter clockwise, hence the different signs
let v3Offset = createVector(-len * cos(angTwo), -len * sin(angTwo));
// Add our offsets to the origins in order to calculate the actual positions for these vertices.
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
);
// Now that are vertices are all computed properly finding the intersection of these two lines is a simple matter:
// Calculate the slopes
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;
// y1 = m1 * x
// y2 = m2 * x + b2
// Find the x where y1 = y2
// m1 * x = m2 * x + b2
// m1 * x - m2 * x = b2
// x * (m1 - m2) = b2
// x = b2 / (m1 - 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());
vertices.forEach(v => v.show());
stroke(0, 255, 0);
strokeWeight(20);
point(vertices[0].a.x + xInt, vertices[0].a.y + yInt);
}
class Side {
constructor(x1, y1, x2, y2) {
this.a = createVector(x1, y1);
this.b = createVector(x2, y2);
}
show() {
stroke(0);
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(20);
point(this.a.x, this.a.y);
}
}
<script src="https://cdn.jsdelivr.net/npm/p5@1.4.1/lib/p5.min.js"></script>