How to find intersection of two tangent lines in javascript - javascript

I have two points(x1,y1 and x2,y2) on a circle and the center (c1,c2) of a circle
and need javascript code to calcuate the intersection point of two tangent lines thru points x1,y1 and x2,y2.
I am using it to convert from a circle (really an arc defined by the above points) to a quadratic bezier curve.

The normals of the tangents are:
n1x = x1 - c1
n1y = y1 - c2
n2x = x2 - c1
n2y = y2 - c2
Using the following parameters:
d1 = n1x * x1 + n1y * y1
d2 = n2x * x2 + n2y * y2
the equations of the tangents can be written as:
x * n1x + y * n1y = d1
x * n2x + y * n2y = d2
Solving the linear equation system yields the following result in general case:
x = (d2 * n1y - d1 * n2y) / (n1y * n2x - n1x * n2y)
y = (d1 * n2x - d2 * n1x) / (n1y * n2x - n1x * n2y)
In javascript:
var x1,y1,x2,y2,c1,c2; // inputs
var x, y; // outputs
... get the parameters somehow
var n1x = x1 - c1;
var n1y = y1 - c2;
var n2x = x2 - c1;
var n2y = y2 - c2;
var d1 = n1x * x1 + n1y * y1;
var d2 = n2x * x2 + n2y * y2;
var det = n1y * n2x - n1x * n2y;
if (det === 0) {
// The lines are parallel
} else {
x = (d2 * n1y - d1 * n2y) / det;
y = (d1 * n2x - d2 * n1x) / det;
}

The vector from the center (c₁, c₂) to a point (xᵢ, yᵢ) on a circumference is (xᵢ-c₁, yᵢ-c₂).
That means the line through (c₁, c₂) and (xᵢ, yᵢ) has slope sᵢ = (yᵢ-c₂)/(xᵢ-c₁).
Let tᵢ be the slope of the tangent line on (xᵢ, yᵢ). tᵢ = -1/sᵢ = (c₁-xᵢ)/(yᵢ-c₂).
Let oᵢ = yᵢ-tᵢxᵢ. Then the tangent line through (xᵢ, yᵢ) is
y = tᵢ(x-xᵢ) + yᵢ = tᵢx + oᵢ
Doing this for i = 1, i = 2 produces a linear equation system.
y = t₁x + o₁
y = t₂x + o₂
Solving it gives the intersection of the tangent lines
o₁-o₂
x = ─────
t₂-t₁
o₁-o₂
y = t₁ ───── + o₁
t₂-t₁

Related

Convert equations of lines solution into reusable javascript function with unknown x and y

So I have a solution to solving for location (point of intersection) of someone based on landmark angles (312.27) and (19.65) degrees and grid coordinates (1,5) and (9,7) of those landmarks. So the issue I'm having is how can I convert these formulas into something that I can dynamically plugin angles and grid coordinates and return the x and y intersection point for location?
Equations of the Lines based on land marks:
P1: y = cot(312.27)*x + 5 - cot(312.27)*1 ⇒ y = -0.91x + 5.91
P2: y = cot(19.65)*x + 7 - cot(19.65) * 9 ⇒ y = 2.80x - 18.21
solve point of intersection:
P1 = P2
-0.91x + 5.91 = 2.80x - 18.21
5.91 + 18.21 = 2.80x + 0.91x
24.12 = 3.71x
6.5 = x
y = -0.91(6.5) + 5.91
y = 0
Your position is (6.5,0).
So I'm looking at creating a function like:
function getLocation(angle1, angle2, coord1, coord2){}
but I just am having trouble trying to figure out how I can convert this solution into something that would output x and y. As I would have to pass around x or y which is unknown.
Any ideas would be appreciated.
note: angles are converted to radians.
You need to solve the system of equations in terms of the angles and the x,y coordinates:
// let phi1 be the first angle and phi2 be the second angle thus
// let P1 be the first point and P2 be the second point
y = x * cot(phi1) + P1.y - P1.x * cot(phi1)
Similarly
y = x * cot(phi2) + P2.y - P2.x * cot(phi2)
Equating both sides:
x * cot(phi1) + P1.y - P1.x * cot(phi1) = x * cot(phi2) + P2.y - P2.x * cot(phi2)
Solving for x
x * (cot(phi1) - cot(phi2)) = P2.y - P2.x * cot(phi2) - P1.y + P1.x * cot(phi1)
Thus:
x = (P2.y - P2.x * cot(phi2) - P1.y + P1.x * cot(phi1)) / (cot(phi1) - cot(phi2))
Once you get x you can plug x in any of the equations for y:
y = x * cot(phi1) + P1.y - P1.x * cot(phi1)
So to get x and y:
function getLocation(angle1, angle2, coord1, coord2) {
let num = coord2.y - coord2.x * cot(angle2) - coord1.y + coord1.x * cot(angle1)
let den = cot(angle1) - cot(angle2)
let x = num / den
let y = x * cot(angle1) + P1.y - P1.x * cot(angle1)
// do something awesome with x and y
}

Get second point from point and direction in 3d space

I have a point:
x1 = 100;
z1 = 100;
y1 = 100;
And 2 directions:
xDir = Math.PI;
yDir = 0.11;
And a range:
range = 100;
How can I calculate the end point when constructing a ray from this information. I have tried the following:
x2 = x1 + (range * Math.cos(xDir))
z2 = z1 + (range * Math.sin(xDir))
y2 = y1 + (range * Math.cos(yDir))
But this doesn't work when the ray is pointing anywhere but at a perfect horizontal direction. Because I don't take yDir into account in the first 2 lines. How can I find the correct end point?
Seems you want to work with azimuth/inclination angles in spherical coordinate system (specific system - with OXZ equatorial plane).
In this case you need to account for Y when working with X/Z:
x2 = x1 + (range * Math.cos(xDir) * Math.sin(yDir))
z2 = z1 + (range * Math.sin(xDir) * Math.sin(yDir))
y2 = y1 + (range * Math.cos(yDir))

Rotating a point in HTML canvas

I'm trying to learn some basic vector math, but I can't seem to get this method for rotating a point to work. The magnitude of the rotated vectors is scaling up and I don't know what's up with the angle.
Here's the relevant function. I'm working in javascript/HTML canvas.
function rotate(point, center, angle) {
var theta = (Math.PI / 180) * angle,
cX = center.pos.x,
cY = center.pos.y,
pX = point.pos.x,
pY = point.pos.y,
pCos = Math.cos(theta),
pSin = Math.sin(theta),
x = pX - cX,
y = pY - cY;
x = (x * pCos - y * pSin) + cX;
y = (x * pSin + y * pCos) + cY;
return {x: Math.floor(x), y: Math.floor(y)};
}
Here's a jsbin of the weird result
The function is almost right but you are just using the modified x value to calculate y
function rotate(point, center, angle) {
var theta = (Math.PI / 180) * angle,
cX = center.pos.x,
cY = center.pos.y,
pX = point.pos.x,
pY = point.pos.y,
pCos = Math.cos(theta),
pSin = Math.sin(theta),
x = pX - cX,
y = pY - cY;
/* You had
x = (x * pCos - y * pSin) + cX; // you change x on this line
y = (x * pSin + y * pCos) + cY; /// then used the modified x to get y
*/
// this will fix the problem
var xx = (x * pCos - y * pSin) + cX;
var yy = (x * pSin + y * pCos) + cY;
return {x: Math.floor(xx), y: Math.floor(yy)};
}

How to draw a graph using parbola equation

I am trying to create a graph using parabola equation (y=x*x). But I am bit confused to calculate the value for control point. How should I calculate the control point value.
My JavaScript function:
function drawParabola()
{
ctx.beginPath();
for(i=-2;i<=2;i++)
{
//formual y= x * x;
y = i * i;
x = i;
if (i == -2) {
ctx.moveTo((5 + x) * 30, Math.abs((-5 + y)) * 30);
}
else {
//ctx.lineTo((5 + x) * 30, Math.abs((-5 + y)) * 30);
context.quadraticCurveTo(**?**, **?**, (5 + x) * 30, Math.abs((-5 + y)) * 30);
}
ctx.strokeStyle = 'orange';
ctx.stroke();
}
}
The control point for a quadratic curve is the intersection point of the tangents.
context.beginPath();
context.strokeStyle = 'orange';
for(i=-2;i<=2;i++) {
// Current point
x1 = i;
y1 = x1 * x1;
y1p = 2 * x1; // derivitive
// Previous point
x0 = i - 1;
y0 = x0 * x0;
y0p = 2 * x0; // derivitive
// Find intersection of tangents
// line0: y - y0 = y0p * (x - x0)
// line1: y - y1 = y1p * (x - x1)
//
// line0: y = y0p * x - y0p * x0 + y0
// line1: y = y1p * x - y1p * x1 + y1
//
// y0p * x - y0p * x0 + y0 = y1p * x - y1p * x1 + y1
// y0p * x - y1p * x = y0p * x0 - y0 - y1p * x1 + y1
// x = (y0p * x0 - y0 - y1p * x1 + y1) / (y0p - y1p)
// Intersection point of tangents
xi = (y0p * x0 - y0 - y1p * x1 + y1) / (y0p - y1p);
yi = y0p * xi - y0p * x0 + y0;
// Rescale for rendering
cx = (5 + x1) * 30;
cy = (5 + y1) * 30;
cix = (5 + xi) * 30;
ciy = (5 + yi) * 30;
if (i == -2) {
context.moveTo(cx, cy);
}
else {
//context.lineTo(cx, cy);
context.quadraticCurveTo(cix, ciy, cx, cy);
}
}
context.stroke();

Learning the math behind WebGL

Like the masochistic I am, I'm trying to learn all the matrix math behind creating modelview and perspective matrices so that I can write my own functions for generating them without the use of JS libraries.
I understand the concept of the matrices, but not how to actually generate them. I've been looking very closely at the glMatrix library, and I have the following questions:
1) What is going on in the following mat4.perspecive method?
/**
* Generates a perspective projection matrix with the given bounds
*
* #param {mat4} out mat4 frustum matrix will be written into
* #param {number} fovy Vertical field of view in radians
* #param {number} aspect Aspect ratio. typically viewport width/height
* #param {number} near Near bound of the frustum
* #param {number} far Far bound of the frustum
* #returns {mat4} out
*/
mat4.perspective = function (out, fovy, aspect, near, far) {
var f = 1.0 / Math.tan(fovy / 2),
nf = 1 / (near - far);
out[0] = f / aspect;
out[1] = 0;
out[2] = 0;
out[3] = 0;
out[4] = 0;
out[5] = f;
out[6] = 0;
out[7] = 0;
out[8] = 0;
out[9] = 0;
out[10] = (far + near) * nf;
out[11] = -1;
out[12] = 0;
out[13] = 0;
out[14] = (2 * far * near) * nf;
out[15] = 0;
return out;
};
Specifically, I get what Math.tan(fovy / 2) is calculating, but why take the inverse of it? Likewise, why take the inverse of the difference between the near boundary and the far boundary? Also, why is out[11] set to -1 and what is the value stored in out[14] for?
2) The following mat4.lookAt method in the library is also confusing me:
/**
* Generates a look-at matrix with the given eye position, focal point,
* and up axis
*
* #param {mat4} out mat4 frustum matrix will be written into
* #param {vec3} eye Position of the viewer
* #param {vec3} center Point the viewer is looking at
* #param {vec3} up vec3 pointing up
* #returns {mat4} out
*/
mat4.lookAt = function (out, eye, center, up) {
var x0, x1, x2, y0, y1, y2, z0, z1, z2, len,
eyex = eye[0],
eyey = eye[1],
eyez = eye[2],
upx = up[0],
upy = up[1],
upz = up[2],
centerx = center[0],
centery = center[1],
centerz = center[2];
if (Math.abs(eyex - centerx) < GLMAT_EPSILON &&
Math.abs(eyey - centery) < GLMAT_EPSILON &&
Math.abs(eyez - centerz) < GLMAT_EPSILON) {
return mat4.identity(out);
}
z0 = eyex - centerx;
z1 = eyey - centery;
z2 = eyez - centerz;
len = 1 / Math.sqrt(z0 * z0 + z1 * z1 + z2 * z2);
z0 *= len;
z1 *= len;
z2 *= len;
x0 = upy * z2 - upz * z1;
x1 = upz * z0 - upx * z2;
x2 = upx * z1 - upy * z0;
len = Math.sqrt(x0 * x0 + x1 * x1 + x2 * x2);
if (!len) {
x0 = 0;
x1 = 0;
x2 = 0;
} else {
len = 1 / len;
x0 *= len;
x1 *= len;
x2 *= len;
}
y0 = z1 * x2 - z2 * x1;
y1 = z2 * x0 - z0 * x2;
y2 = z0 * x1 - z1 * x0;
len = Math.sqrt(y0 * y0 + y1 * y1 + y2 * y2);
if (!len) {
y0 = 0;
y1 = 0;
y2 = 0;
} else {
len = 1 / len;
y0 *= len;
y1 *= len;
y2 *= len;
}
out[0] = x0;
out[1] = y0;
out[2] = z0;
out[3] = 0;
out[4] = x1;
out[5] = y1;
out[6] = z1;
out[7] = 0;
out[8] = x2;
out[9] = y2;
out[10] = z2;
out[11] = 0;
out[12] = -(x0 * eyex + x1 * eyey + x2 * eyez);
out[13] = -(y0 * eyex + y1 * eyey + y2 * eyez);
out[14] = -(z0 * eyex + z1 * eyey + z2 * eyez);
out[15] = 1;
return out;
};
Similar to the mat4.perspecive method, why is the inverse of the length of the vector being calculated? Also, why is that value then multiplied by the z0, z1 and z2 values? The same thing is being done for the x0-x2 variables and the y0-y2 variables. Why? Lastly, what is the meaning of the values set for out[12]-out[14]?
3) Lastly, I have a few questions about the mat4.translate method. Specifically, I bought the book Professional WebGL Programming: Developing 3D Graphics for the Web, and it says that the following 4x4 matrix is used to translate a vertex:
1 0 0 x
0 1 0 y
0 0 1 z
0 0 0 1
However, when I look at the following mat4.translate method in the glMatrix library, I see that out[12]-out[15] are set via some complex equations. Why are these values set at all?
/**
* Translate a mat4 by the given vector
*
* #param {mat4} out the receiving matrix
* #param {mat4} a the matrix to translate
* #param {vec3} v vector to translate by
* #returns {mat4} out
*/
mat4.translate = function (out, a, v) {
var x = v[0], y = v[1], z = v[2],
a00, a01, a02, a03,
a10, a11, a12, a13,
a20, a21, a22, a23;
if (a === out) {
out[12] = a[0] * x + a[4] * y + a[8] * z + a[12];
out[13] = a[1] * x + a[5] * y + a[9] * z + a[13];
out[14] = a[2] * x + a[6] * y + a[10] * z + a[14];
out[15] = a[3] * x + a[7] * y + a[11] * z + a[15];
} else {
a00 = a[0]; a01 = a[1]; a02 = a[2]; a03 = a[3];
a10 = a[4]; a11 = a[5]; a12 = a[6]; a13 = a[7];
a20 = a[8]; a21 = a[9]; a22 = a[10]; a23 = a[11];
out[0] = a00; out[1] = a01; out[2] = a02; out[3] = a03;
out[4] = a10; out[5] = a11; out[6] = a12; out[7] = a13;
out[8] = a20; out[9] = a21; out[10] = a22; out[11] = a23;
out[12] = a00 * x + a10 * y + a20 * z + a[12];
out[13] = a01 * x + a11 * y + a21 * z + a[13];
out[14] = a02 * x + a12 * y + a22 * z + a[14];
out[15] = a03 * x + a13 * y + a23 * z + a[15];
}
return out;
};
Thank you all for your time, and sorry for all the questions. I come from a JS background, not an OpenGL/3D programming background, so it's hard for me to understand the math behind all the matrices.
If there are any great resources out there that explain the math used for these equations/methods, then that would be great too. Thanks.
Specifically, I get what Math.tan(fovy / 2) is calculating, but why
take the inverse of it?
Because the focal distance d comes from the formula
Math.tan(fovy / 2) = y / d
to get the focal length you need to multiply by
1 / Math.tan(fovy / 2)
why take the inverse of the difference between the near boundary and
the far boundary? Also, why is out[11] set to -1 and what is the value
stored in out[14] for?
You can project (x,y,z) into (x*d/z, y*d/z) using the focal distance d. This is enough but OpenGL requires a linear transformation to (x,y,z) such as the projection gives coordinates in [-1,1]. Such normalized coordinates simplify clipping and retain the z information used to remove hidden surfaces.
out[11] is set to -1 because there's no linear transformation that gives normalized coordinates unless a reflection is applied. This -1 causes the handedness of the system to be switched with normalized coordinates.
out[14] is used with out[10] to transform z from [-n -f] to [-1 1] after projection.
Similar to the mat4.perspecive method, why is the inverse of the
length of the vector being calculated? Also, why is that value then
multiplied by the z0, z1 and z2 values? The same thing is being done
for the x0-x2 variables and the y0-y2 variables. Why?
To normalize the vectors x, y and z
what is the meaning of the values set for out[12]-out[14]?
A camera is composed of a base of vectors and a position.
out[12]-out[14] apply an inverse translation to set the camera position.
However, when I look at the following mat4.translate method in the
glMatrix library, I see that out[12]-out[15] are set via some complex
equations. Why are these values set at all?
The equations look complex because it's a product of a translation matrix and an existing matrix a.
Professional WebGL Programming: Developing 3D Graphics for the Web
I don't know this book, it might explain some math but if you need detailed explanation you should consider Eric Lengyel's book that explains and derivates the important math used in 3d raster graphics.

Categories