I'm trying to develop a small application using html5 and canvas/KineticJS. I'd like to trace a number of rays that start from a 2d point to infinite, just setting a custom angle degree. For example, if I set 90° the app should render four rays (two straight lines, one vertical and one horizontal that meet in my 2d point). If I set 60° I should see 3 straight lines, like an asterisk *
The longest line you'll ever have to draw is the size of the canvas's diagonal:
var r = Math.sqrt(Math.pow(canvas.width, 2) + Math.pow(canvas.height, 2));
Use sin and cos to calculate each of your end points at that radius:
var theta = delta * Math.PI / 180.0;
var dx = r * Math.cos(n * theta);
var dy = r * Math.sin(n * theta);
Then, just draw lines from (x, y) to (x + dx, y + dy). Simples.
Related
I want to fill this ellipse with count random points inside it any help I'd be glad.
What algorithm of actions?
To generate uniformly distributed points inside ellipse, use approach developed for disk and scale coordinates with needed ratio:
generate two random values
r = A * sqrt(random(0..1))
fi = 2 * Pi * random(0..1)
and point in ellipse with horizontal semiaxis A and vertical one B
x = center.x + r * cos(fi)
y = center.y + B / A * r * sin(fi)
If ellipse is rotated, also rotate these coordinates
I'm trying to use the answer provided here: Intersection of two Moving Objects with Latitude/Longitude Coordinates
But I have some questions..
What is this angle:
var angle = Math.PI + dir - target.dir
I was thinking that the angle that should be used in the law of cosines is already "alpha or target.dir".. What is that line doing? Also in these two steps:
var x = target.x + target.vel * time * Math.cos(target.dir);
var y = target.y + target.vel * time * Math.sin(target.dir);
Shouldn't the code be using the angle between x- or y-axis and the target velocity vector? Why is the author using alpha here?
What is this angle:
var angle = Math.PI + dir - target.dir
The variable named angle is indeed the angle alpha. Because the direction dir is the direction from chaser to target, and we need it the other way round for this calculation, we add π to it before we subtract target.dir.
Maybe using the word angle as a variable name was a bit vague; I'll change it to alpha, the name I used for this angle in the images.
Shouldn't the code be using the angle between x- or y-axis and the target velocity vector? Why is the author using alpha here?
var x = target.x + target.vel * time * Math.cos(target.dir);
var y = target.y + target.vel * time * Math.sin(target.dir);
We are indeed using target.dir, which is the direction of the target, i.e. the angle between the x-axis and the target vector, to calculate the coordinates of the interception point, and not the angle alpha.
I'm making a game in javascript, where an object is supposed to bounce from walls. I really tried to get it to work myself, but it never works correctly.
Let's say theres a ball bouncing inside this cage (blue = 30°, brown = 60°);
The ball's coordinates are known. The angle of movement is known. The point of collision (P) coordinates are known. The angle of the wall is known. The ball's position is updating it's coordinates inside a setInterval function using this function:
function findNewPoint(x, y, angle, distance) {
var result = {};
result.x =(Math.cos(angle * Math.PI / 180) * distance + x);
result.y = (Math.sin(angle * Math.PI / 180) * distance + y);
return result;
So, upon colliding, there should be a function that properly changes the ball's angle. It's a very complicated problem it seems, because even if I know that the wall is 30°, its important to know from what side the ball is colliding into it. I tried using the "Reflection across a line in the plane" formula and also some vectors, but it never worked out for me. I'm not expecting a complete answer with code, if someone could suggest in what way this should be programmed, it would help aswell.
Edit:
Thanks for your tips guys, I realized what was causing the most confustion; if I select an angle on the canvas with my mouse, the starting coordinate(0,0) is in the bottom left corner. But since the canvas' starting coordinate is in the top left corner, this has to be considered.
Basically using this formula for calculating the angle:
function angle(cx, cy, ex, ey) {
var dy = ey - cy;
var dx = ex - cx;
var theta = Math.atan2(dy, dx);
theta *= 180 / Math.PI;
return theta;
}
if the ball moved from (50,50) to (100,100), the angle would be -45.
Now, this angle changes in the following way when hitting walls:
If im honest, I got these out of trial and error, am not really understanding why exactly 60 and 120.
It is not wise to use angle for moving ball and calculate Cos/Sin again and again. Instead use unit velocity direction vector with components vx, vy like this:
new_x = old_x + vx * Velocity_Magnitude * Time_Interval
Note that vx = Cos(angle), vy = Sin(angle), but with direction approach you seldom need to use trigonometric functions.
Tilted wall with angle Fi has normal
nx = -Sin(Fi)
ny = Cos(Fi)
To find reflection , you need to calculate dot product of velocity and normal
dot = vx * nx + vy * ny
Velocity after reflection transforms:
vnewx = v.x - 2 * dot * n.x
vnewy = v.y - 2 * dot * n.y
Use these values for further moving
(note that you can use both internal and external normal direction, because direction flip changes both components, and sign of 2 * dot * n.x remains the same)
Examples:
horizontal moving right
vx=1, vy=0
30 degrees wall has normal
nx=-1/2, ny=Sqrt(3)/2
dot = -1/2
vnewx = 1 - 2 * (-1/2) * (-1/2) = 1/2
vnewy = 0 - 2 * (-1/2) * Sqrt(3)/2 = Sqrt(3)/2
(velocity direction angle becomes 60 degrees)
horizontal moving left
vx=-1, vy=0
330 degrees wall (left bottom corner) has normal
nx=1/2, ny=Sqrt(3)/2
dot = -1/2
vnewx = -1 - 2 * (-1/2) * (1/2) = -1/2
vnewy = 0 - 2 * (-1/2) * (Sqrt(3)/2) = Sqrt(3)/2
(velocity direction angle becomes 120 degrees)
Here is a function that returns the angle of reflection given an angle of incidence and a surface angle (in degrees). It also ensures that the returned angle is between 0 and 359 degrees.
function angleReflect(incidenceAngle, surfaceAngle){
var a = surfaceAngle * 2 - incidenceAngle;
return a >= 360 ? a - 360 : a < 0 ? a + 360 : a;
}
Here's a demonstration, where the blue line is the angle of incidence, the purple line is the angle of reflection, and the black line is the surface.
If you're assuming that the ball behaves like light bouncing off a mirror, then the angle of incidence equals the angle of reflection.
So your board is 30° from 0° (straight up). The means the normal (perpendicular to the board at the point the ball hits ) is 300°. Say the ball arrives from 280°, it must leave at 320° as the difference between the angle of incidence and the normal and the angle of reflection and the normal must be equal.
I'm trying to find a point that is equal distance away from the middle of a perpendicular line. I want to use this point to create a Bézier curve using the start and end points, and this other point I'm trying to find.
I've calculated the perpendicular line, and I can plot points on that line, but the problem is that depending on the angle of the line, the points get further away or closer to the original line, and I want to be able to calculate it so it's always X units away.
Take a look at this JSFiddle which shows the original line, with some points plotted along the perpendicular line:
http://jsfiddle.net/eLxcB/1/.
If you change the start and end points, you can see these plotted points getting closer together or further away.
How do I get them to be uniformly the same distance apart from each other no matter what the angle is?
Code snippit below:
// Start and end points
var startX = 120
var startY = 150
var endX = 180
var endY = 130
// Calculate how far above or below the control point should be
var centrePointX = ((startX + endX) / 2);
var centrePointY = ((startY + endY) / 2);
// Calculate slopes and Y intersects
var lineSlope = (endY - startY) / (endX - startX);
var perpendicularSlope = -1 / lineSlope;
var yIntersect = centrePointY - (centrePointX * perpendicularSlope);
// Draw a line between the two original points
R.path('M '+startX+' '+startY+', L '+endX+' '+endY);
Generally you can get the coordinates of a normal of a line like this:
P1 = {r * cos(a) + Cx, -r * sin(a) + Cy},
P2 = {-r * cos(a) + Cx, r * sin(a) + Cy}.
A demo applying this to your case at jsFiddle.
I have a number of objects that I am rendering in HTML/CSS/JavaScript. The objects all sit on the surface of an invisible sphere with radius R.
Additionally, the interaction with the user allows this invisible sphere to be rotated arbitrarily.
The obvious solution is spherical co-ordinates assigned to the objects (Theta, Phi, and fixed Radius), which is the converted to Cartesian 3D co-ordinates, and then I can either just drop the depth (Z), or apply some fancy perspective. I will worry about perspective later...
Since I'm working with graphics, X/Y is horizontal/vertical respectively, and Z is depth where +ve is sticking out of the screen and -ve is inside the monitor.
I have a JavaScript array of objects called objects[], each of which has a Theta and Phi. I assume that Theta is rotation about the Y axis, and Phi is rotation about the X axis, such that at Phi = 0 and Theta = 0, we are at (X,Y,Z) = (0,0,R);
Since I'm rotating the invisible sphere, I don't want to have to change the Theta and Phi of each individual objects, which would also just add to numerical instability. Instead, I store a global Theta and Phi which is associated with the rotation of the sphere itself.
Hence, the "effective" Theta and Phi of the points are the Theta and Phi of the points plus the global Theta and Phi.
According to Wikipedia, WolframAlpha, MathWorld, and many other resources, we can find the Cartesian co-ordinates from spherical co-ordinates in the following way:
z = r * sin(phi) * cos(theta);
y = r * sin(phi) * sin(theta);
x = r * cos(phi);
(I've swapped Theta and Phi from Wikipedia as I'm using them backwards, and my X/Y/Z co-ordinates are different too).
I'm not sure why, but when I render these objects they don't look right at all. If you imagine a point on the equator of a sphere with Theta = Pi/4, and you rotate the sphere about the Y axis, the point should only move up and down if projected onto 2D and no perspective transformations are used. However, this isn't at all what happens. The points move from the right to the left side of the screen. The whole thing looks all wrong.
Order matters. When you use your equations
z = r * sin(phi) * cos(theta);
y = r * sin(phi) * sin(theta);
x = r * cos(phi);
then you can interpret them as a rotation first by phi about y and second by theta about x (for appropriate choices of angle measurement directions):
(x1, y1, z1) = (r, 0, 0)
(x2, y2, z2) = (x1 * cos(phi) - z1 * sin(phi),
y1,
x1 * sin(phi) + z1 * cos(phi))
= (r * cos(phi), 0, r * sin(phi))
(x3, y3, z3) = (x2,
y2 * cos(-theta) - z2 * sin(-theta),
y2 * sin(-theta) + z2 * cos(-theta))
= (r * cos(phi),
r * sin(phi) * sin(theta),
r * sin(phi) * cos(theta))
When you simply add those angles, you end up with a wrong order: rotating first by phi1then by theta1 then by phi2 and then by theta2 about the different axes is not the same as rotating by phi1 + phi2 first and theta1 + theta2 afterwards. You're changing the order between theta1 and phi2, which breaks your 3D position.
Better use rotation matrices, quaternions, a library (like three.js) which encapsulates this for you, or make sure you properly combine euler angles.