How to generate coordinates to represent a circle in 3D programming? - javascript

Lets say I have 10 objects. The first object is placed at x75, y0, z0. Now lets say I wanted to orient the objects so they form a circle with x0, y0, z0 at it's center. And each object is an equal distance from each other. Is there a formula I can use to generate the coordinates? I should mention the number of objects wont always be 10. It's a variable so some times it might be 15 or 20 or any other number.

You can use some formula like:
x = x0 + r * cos(theta * pi / 180);
y = y0 + r * sin(theta * pi / 180);
so x0 = 0 and y0 = 0.
For theta, it will be the degree, which depends on the number of objects. So if you have 10 objects, theta will be a multiple of 36. So basically it is a multiple of 360/num of objects.
r is the radius of the circle, so if the first one is at (75, 0, 0), then r = 75.

Related

How to draw random points inside an ellipse?

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

Intersection of two Moving Objects

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.

General formula to calculate 3d-space equal distances

it's probably not the right place to post this but i don't know where else to post it.
i have 5 lines (d1 -> d5) equally distributed from each other in 3d perspective, i have the values of (a) angle, (d1) and (b5). i need to calculate (b2, b3, b4, d2, d3, d4, d5) with jquery.
i can calculate d5 with:
d5 = d1 - ( b5 * Math.tan(a))
but i have no idea how to calculate b2, b3 and b4. (d1 is divided into 4 identical segaments (s))
any help would be appreciated.
What you're looking for is a projective scale. The easiest way to do this computationally is to use homogenous coordinates, take a rectangle (like the one in the first picture below) on which V is "infinitely far to the right" and find a projective transformation that maps this rectangle to the trapezium in the second picture. The vertices of the rectangle are (0|0), (0|d1), (b5|d1), (b5|0) and the corresponding vertices of the trapezium are (0|0), (0|d1), (b5|d5), (b5|0).
Since these are four points of which no three are collinear, we can find a unique matrix (up to scaling) M for this transformation. After some maths, it turns out that this matrix is:
[d1*b5,0,0]
[0,b5*d5,0]
[d1-d5,0,b5*d5]
If you want to find the coordinates b3 and d3, for instance, you can multiply this matrix with homogenous coordinates of the point in the middle of the line, i.e. the vector (0.5*b5,d1,1)^T and you get the homogenous coordinates of the point (b3|d3), which can be converted into Euclidean coordinates by dehomogenisation, i.e. dividing the first two components by the third.
In general, if you have two points (b1|d1) and (bn|dn) and want to know the coordinates of n-2 equidistant points inbetween on a projective scale like this, you can compute the coordinates bi and di as like this (in your case, n would be 5, of course):
let M := matrix [[d1*bn, 0, 0], [0, bn*dn, 0], [d1-dn, 0, bn*dn]]
let v := ((i-1)/(n-1)*bn, d1, 1)
let (x,y,z) := M*v
let bi := x/z and di := y/z
As you see, this is a simple algorithm for computing the coordinates of these projectively equidistant points, and it generalises nicely to arbitrary numbers of points.
If you'd rather have a closed formula, you can compute the bi and di directly as:
let bi := (bn*d1*(i-1))/(dn*n+(d1-dn)*i-d1)
let di := d1*dn*(n-1)/(dn*n+(d1-dn)*i-d1)
First we need to calculate what the length of the adjacent side of the whole triangle d1->v->c is (the left vertical side of it):
tan(Θ) = opposite / adjacent
opposite * tan(Θ) = adjacent
adjacent = opposite * tan(Θ)
adjacent = d1 * tan(a)
Next thing we need is to know how much off the ground each line from v is when it gets to line d1. Given that variable s is the same for all divisions and assuming N dividing segments (in this case 3), our counter is i that starts from 1 and goes to N:
opposite(i) = i * (d1 / N)
Now we need the angle that line from v to each marker s makes:
tan(Θi) = opposite / adjacent
Θi = arctan(opposite / adjacent)
Θi = arctan(opposite(i) / adjacent)
Θi = arctan((i * (d1 / N)) / (d1 * tan(a)))
Using some geometry/trig we can say that angle going from d1 through point c to top of d5 is (90° - a). We will call this angle a'
a' = 90° - a
Law of sines tells us that:
A' / sin(a') = opposite(i) / sin(b')
so now we solve for A' since we need some help with getting the dimensions of the orange square:
A' = (opposite(i) * sin (a')) / sin(b')
since b' = (a + Θi) this turns into:
A' = (opposite(i) * sin (90° - a)) / sin(a + Θi)
Same thing applied but solving for h in the orange triangle (see picture):
h / sin(90°-Θi) = A' / sin(90°)
h = (A' * sin(90°-Θi)) / sin(90°)
b2 = h
Putting it all together (hopefully without copy/paste mistakes on my part) and without simplifications:
b2 = (((( i * (d1 / N)) * sin (90° - a)) / sin(a + Θi)) * sin(90° - arctan((i * (d1 / N)) / (d1 * tan(a))))) / sin(90°)
Now rinse/repeat for each value of i and turn into code (I would have done that but I'm too tired) :)

Projecting points along the surface on a sphere into 2D

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.

Drawing a custom number of straight lines across 1 point with javascript

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.

Categories

Resources