Referring to the first diagram, I am trying to copy the three objects, looking at them from an arbitrary angle(A1). The distance between where I'm and the first object does not matter just the relative location of the object to one another.
In the second diagram, I select a point to copy these objects, facing another arbitrary angle(B1).
Angle (C1) shows the approximate position of -90 degrees.
I can get this to work if A1 = 0,90,180,270 and even 45,135 etc but the equations I come up with only work for 0 and 180 or 90 and 270. I have to modify them to work in those directions by changing a hardcoded offset angle and putting/removing a negative sign before the offset.
I'm doing this is javascript (and its Minecraft) usually I can figure out this but I have been working on it for weeks.
Here is some pseudo-code that works some of the time in certain right-angle directions. I have updated this to be more accurate, the 1x and 2x are the blocks x coordinate, etc. - everything is relative from the (1) block.
Minecraft's coordinate system is a little different from normal - 0 is south, +90 is west, 180 is north, 270 is east.
the only difference is that I am making negative az, ax.
// works for north/south looking - A1 is either 180/0 , B1 can be anything
var x = 1x - 2x;
var z = 1z - 2z;
var direction = Math.atan2(z1, x1);
var L1 = Math.sqrt(Math.pow(x1, 2) + Math.pow(z1, 2));
var az = Math.round(L1 * Math.sin((B1 + A1 + (direction * 180 / Math.PI)) * Math.PI / 180));
var ax = Math.round(L1 * Math.cos((B1 + A1 + (direction * 180 / Math.PI)) * Math.PI / 180));
// works for east/west looking - A1 is either 90/270 , B1 can be anything
var x = 1x - 2x;
var z = 1z - 2z;
var direction = Math.atan2(z1, x1);
var L1 = Math.sqrt(Math.pow(x1, 2) + Math.pow(z1, 2));
var az = -Math.round(L1 * Math.sin((B1 + A1 + (direction * 180 / Math.PI)) * Math.PI / 180));
var ax = -Math.round(L1 * Math.cos((B1 + A1 + (direction * 180 / Math.PI)) * Math.PI / 180));
First diagram
Second diagram
Related
Trying to calculate TDOA (Time Difference Of Arrival) but I can’t get my head around it. Can someone please help me with an clear and simple example.
I have 3 microphone located at:
X0 = 0 cm
Y0 = 0 cm
-
X1 = 0 cm
Y1 = 15 cm
-
X2 = 0 cm
Y2 = 30 cm
Time different of sound arrive to the 3 microphone:
A0 = 0 sec
A1 = 0.002 sec
A2 = 0.004 sec
Speed of sound:
S = 340 m/sec
Updated after response from wessel
I am trying to make a script calc TDOA
let ? = (Y1 - Y0) / (S); // = 0.00044
let ? = (Y2 - Y0) / (S); // = 0.00088
let VX = (X1 - X0) / A0; // = NaN
let VY = (Y1 - Y0) / A0; // = Infinity
let V = Math.sqrt(VX^2 + VY^2) // = 1.4142
let alpha = atan(VY / VX) // = NaN
console.log(alpha+' deg with the x-axis.');
If you have a distance and a speed (distance / time), you get a time by doing distance / speed = distance / (distance / time ) = distance / distance * time = time.
What you omit in your question, is the direction and the shape of the sound wave. If the sound is traveling along the x-axis, the shape does not matter, and the time difference would be:
(A1 - A0) = (X1 - X0) / (340 m/s) = 0.15 / 340 s = 0.00044 s
(A2 - A0) = (X2 - X0) / (340 m/s) = 0.3 / 340 s = 0.00088 s
If the shape is a straight line, e.g. from an infinitely far point source or from a particularly shaped non-point source, the different of arrival time is given by the x-component of the direction of the sound wave:
VX = (X1 - X0) / (A1 - A0) = 37.5 m/s.
The total sound speed, which you give as 340 m/s, should equal
V = Sqrt(VX^2 + VY^2)
such that you can work out that
VY = Sqrt(V^2 - VX^2) = 338 m/s
or
VY = -Sqrt(V^2 - VX^2) = -338 m/s
such that your sound wave must in incoming under an angle alpha:
alpha = atan(VY / VX) = 83 deg
with the x-axis.
I don't see why javascript is relevant here, though. Just in case: use Math.sqrt, Math.pow or V*V, and Math.atan or Math.atan2 (beware of the order of the arguments there!).
I started a project using the raycasting technique GitHub Project
To find the length of the ray (distance from players pos to wall) I just increment by one. But there are several problems with that, its time consuming, inaccurate & will be difficult for texturing.
I tried to implement the daa algorithm, which doesnt just increments by 1 -> he goes through the grids and returns exact positions.
http://www.geeksforgeeks.org/dda-line-generation-algorithm-computer-graphics/
Has anyone experience with that or any tips?
No algorithm way:
for(let resolution = 0; resolution < display.width / 2; resolution++){ //every 2nd px gets scanned
let ray = this.pov + (-this.fov / 2 + this.fov / (display.width / 2) * resolution);
let distance = 0, hit = false;
/*ugly way of raycasting!*/
do{
let x = this.x + distance * Math.cos(ray * (Math.PI / 180));
let y = this.y + distance * Math.sin(ray * (Math.PI / 180));
if(map[Math.floor(x / block)][Math.floor(y / block)]){
distance = Math.sqrt(Math.pow(this.x - x, 2) + Math.pow(this.y - y, 2));
hit = true
}
distance += 1;
}while(!hit);
distance = convert / distance;
canvas.fillStyle = "#fff";
canvas.fillRect(resolution * 2, display.height / 2 - distance / 2, 2, distance);
}
You don't need DDA or Bresenham algorithm to find intersections of the ray with walls.
If you need one intersection with given border (or box edges) - just calculate it with ray equation and border position.
If you want to get intersections with grid cells - use voxelization algorithm like Amanatides-Woo
I have the following function, to find the angle between 3 points.
(Where a point is defined as an array containing the x position as its first element and the y position as its second element, and the angle to measure is the angle created when a line is drawn through all three points.)
findAngle: function(a, b, c) {
var ab = Math.sqrt(Math.pow(b[0] - a[0], 2) + Math.pow(b[1] - a[1], 2));
var bc = Math.sqrt(Math.pow(b[0] - c[0], 2) + Math.pow(b[1] - c[1], 2));
var ac = Math.sqrt(Math.pow(c[0] - a[0], 2) + Math.pow(c[1] - a[1], 2));
var o1 = (bc * bc + ab * ab - ac * ac) / (2 * bc * ab);
var o2 = Math.acos(o1);
var o3 = o2 * (180 / Math.PI);
return o3;
}
However, this only ever returns angles between 0 and 180 degrees. How can I have it return values between 0 - 180 degrees, and values between 180 and 360 when the angle is in fact obtuse?
Use atan2 function that has two arguments and returns result in range -Pi..Pi (add 2*Pi to negative angles if needed)
angle = Math.atan2(crossproduct(c-b,b-a), dotproduct(c-b,b-a))
where
crossproduct(c-b,b-a) = (c.x-b.x)*(b.y-a.y) - (c.y-b.y)*(b.x-a.x)
dotproduct(c-b,b-a) = (c.x-b.x)*(b.x-a.x) + (c.y-b.y)*(b.y-a.y)
This question already has answers here:
Calculate possible lines from points
(2 answers)
Closed 9 years ago.
I am calculating how far away a point is from a line segment on the earth.
My function seemed to work, but as i've increased the distances it's clear it's not working. I presume this is due to the curvature of the earth.
In my calculations Rome is shown as 5km from the line:
London, UK - 0km
Rome, Italy - 5km
Cyrene, Libya - 0km
But on Google Earth it's actually more like 61km
When I start going longer distances the calculations get even worse!
Rome, Italy - 0km
Mohenjo-daro, Pakistan - 0km
Istanbul, Turkey - 250km
I believe the problem is somewhere in the code here:
function distToSegment(lat1, lon1, lat2, lon2, lat3, lon3) {
var y = Math.sin(lon3 - lon1) * Math.cos(lat3);
var x = Math.cos(lat1) * Math.sin(lat3) - Math.sin(lat1) * Math.cos(lat3) * Math.cos(lat3 - lat1);
var bearing1 = radiansToDegrees(Math.atan2(y, x));
bearing1 = 360 - (bearing1 + 360 % 360);
var y2 = Math.sin(lon2 - lon1) * Math.cos(lat2);
var x2 = Math.cos(lat1) * Math.sin(lat2) - Math.sin(lat1) * Math.cos(lat2) * Math.cos(lat2 - lat1);
var bearing2 = radiansToDegrees(Math.atan2(y2, x2));
bearing2 = 360 - (bearing2 + 360 % 360);
var lat1Rads = degreesToRadians(lat1);
var lat3Rads = degreesToRadians(lat3);
var dLon = degreesToRadians(lon3 - lon1);
var distanceAC = Math.acos(Math.sin(lat1Rads) * Math.sin(lat3Rads) + Math.cos(lat1Rads) * Math.cos(lat3Rads) * Math.cos(dLon)) * 6371;
var min_distance = Math.abs(Math.asin(Math.sin(distanceAC / 6371) * Math.sin(degreesToRadians(bearing1) - degreesToRadians(bearing2))) * 6371);
return min_distance;
}
Here is a working fiddle you can use to test:
http://jsfiddle.net/kmturley/cfg2D/3/
Any help to figure this one out would be appreciated!
This
bearing1 = 360 - (bearing1 + 360 % 360)
looks fishy to me. Do you mean
bearing1 = 360 - (bearing1 + 360) % 360
?
Likewise for bearing2.
% is a multiplicative operator and has higher precedence than +.
This is all about mathematics. It's a shame that I'v forgotten those I learned in scool.
OK, I'm trying to get the image dimension after rotation (using canvas) with a certain angle in Javascript.
Since I don't have any tools other than MSPaint here, I'll re-use your image:
Say your original rectangle's size is R(ectangle)W(idth) * RH(eight),
in this case RW=200, RH=80;
After rotating a certain angle A, counterclockwise,
where 0deg <= A <= 90deg in degrees (or 0 <= A <= Math.PI/2 in radians),
in this case A=30deg or A=Math.PI/6,
In the new "outer" rectangle, each side is divided by two parts (for the convenience of describing; corresponding to the image).
On the left side, let's say the upper (purple) part is called N(ew)H(eight)U(p), and the lower (red) part is called NHL(ow);
Same rule on the bottom side, we have NW(idth)L(eft) (blue) and NWR(ight) (orange).
So the size (area) of new rectangle would be (NHU + NHL) * (NWL + NWR)
According to the definition of sin and cos:
NWL = RW * Math.cos(A); //where A is in radians
NHL = RW * Math.sin(A);
NHU = RH * Math.cos(A);
NWR = RH * Math.sin(A);
(if you're using A in degrees, replace A to Math.PI*A/180).
So the new "outer" width would be NWL + NWR, and new "outer" height would be NHU + NHL, and now you can calculate everything.
Here's a drop-in function that implements #Passerby's solution + a couple other safeguards:
function imageSizeAfterRotation(size, degrees) {
degrees = degrees % 180;
if (degrees < 0) {
degrees = 180 + degrees;
}
if (degrees >= 90) {
size = [ size[1], size[0] ];
degrees = degrees - 90;
}
if (degrees === 0) {
return size;
}
const radians = degrees * Math.PI / 180;
const width = (size[0] * Math.cos(radians)) + (size[1] * Math.sin(radians));
const height = (size[0] * Math.sin(radians)) + (size[1] * Math.cos(radians));
return [ width, height ];
}
// USAGE:
imageSizeAfterRotation([ 200, 80 ], 30) // [ 213.20508075688775, 169.28203230275508 ]