Find endpoint created by a 90° angle - math

I don't really know if this is possible, but is there a way I can find the point A and B on the image bellow?
Example 1
So how can I find the coordinates of A and B if I know the coordinates of the point P, and I know that PA should form a 90 degree angle.
Here is also another example, which will maybe help you understand what I want to achieve.
Example 2

You haven't specified problem details again...
OK, let coordinate origin is rectangle center O, half-width is wh, half-height is hh
So we can write line equation in normal form
x * px/ro + y * py/ro - ro = 0
or
x * px + y * py - squared_ro = 0
where
ro = sqrt(px*px + py*py)
Now we can substitute rectangle side coordinates into this equation and find intersections
wh * px + y * py - squared_ro = 0 //to get y-coordinate of intersection with right side
-wh * px + y * py - squared_ro = 0 //y for left side
x * px + hh * py - squared_ro = 0 //x for top side
x * px - hh * py - squared_ro = 0 //x for bottom side
filter out results where abs(x)> wh or abs(y) > hh and you'll get two intersection points

Related

Point positioning inside rectangle with only two known vertexes

I'm working on a js widget, and I've come across a positioning problem, which I can't seem to solve with my limited geometry knowledge or by help of Wikipedia/google.
I have a quadrilateral rectangle, which is positioned at an angle. I know its two opposite vertexes and width/height ratio. And there's a point on it, which coordinates I also know.
I need to find how far (in %s of width/height) is that point from rectangle's sides. Is it possible to do so?
Having two corners P1 = (x1,y1) and P2 = (x2,y2) and point Q, you can find diagonal length
dx = (x2 - x1)
dy = (y2 - y1)
dlen = sqrt(dx^2 + dy^2)
and unit direction vector
dx = dx / dlen
dy = dy / dlen
and center of rectangle
cx = x1 + dx/2
cy = y1 + dy/2
Width and height (with known r = w/h ratio)
w = dlen / sqrt(1 + r^2)
h = w / r
Now we need direction of side of length w. Note that given information does not allow to choose exact rectangle orientation from two possible cases.
Angle between diagonal and side
sina = r / sqrt(1 + r^2)
cosa = 1 / sqrt(1 + r^2)
Side direction vector
wx = dx * cosa - dy * sina
wy = dx * sina + dy * cosa
and for the second orientation
wx' = dx * cosa + dy * sina
wy' = -dx * sina + dy * cosa
The second side vector
hx = -wy
hy = wx
Now we can find length of projection of point p onto sides W and H using dot product
qx = q.x - x1
qy = q.y - y1
qw = qx * wx + qy * wy
qh = qx * hx + qy * hy
The last values are coordinates in W-H basis, so value qw varies from 0 for points at the "left" to w for points at the "right" side. You can divide these values by w and h to get percent values.
Note again - there are two possible rectangles and correspondingly two positions of point Q

Minimum distance between two circles along a specified vector on a cartesian plane

I am trying to solve the following problem (I am using Matlab, though pseudo-code / solutions in other languages are welcome):
I have two circles on a Cartesian plane defined by their centroids (p1, p2) and their radii (r1, r2). circle 1 (c1 = [p1 r1]) is considered 'dynamic': it is being translated along the vector V = [0 -1]. circle 2 (c2 = [p2 r2]) is considered 'static': it lies in the path of c1 but the x component of its centroid is offset from the x component of c2 (otherwise the solution would be trivial: the distance between the circle centroids minus the sum of their radii).
I am trying to locate the distance (d) along V at which circle 1 will 'collide' with circle 2 (see the linked image). I am sure that I can solve this iteratively (i.e. translate c1 to the bounding box of c2 then converge / test for intersection). However, I would like to know if there is a closed form solution to this problem.
Shift coordinates to simplify expressions
px = p1.x - p2.x
py = p1.y - p2.y
And solve quadratic equation for d (zero, one, or two solutions)
px^2 + (py - d)^2 = (r1 + r2)^2
(py - d)^2 = (r1 + r2)^2 - px^2
d = py +/- Sqrt((r1 + r2)^2 - px^2)
That's all.
As the question title does not match the question and accepted answer which is dependent on a fixed vector {0, -1}, or {0, 1} rather than an arbitrary vector I have added another solution that works for any unit vector.
Where (See diagram 1)
dx, dy is the unit vector of travel for circle c1
p1, p2 the centers of the moving circle c1 and static circle c2
r1, r2 the radius of each circle
The following will set d to the distance c1 must travel along dx, dy to collide with c2 if no collision the d will be set to Infinity
There are three cases when there is no solution
The moving circle is moving away from the static circle. u < 0
The moving circle never gets close enough to collide. dSq > rSq
The two circles are already overlapping. u < 0 luckily the math makes
this the same condition as moving away.
Note that if you ignore the sign of u (1 and 3) then d will be the distance to first (causal) contact going backward in time
Thus the pseudo code to find d
d = Infinity
rSq = (r1 + r2) ^ 2
u = (p1.x - p2.x) * dx + (p1.x - p2.x) * dy
if u >= 0
dSq = ((p2.x + dx * u) - p1.x) ^ 2 + ((p2.y + dy * u) - p1.y) ^ 2
if dSq <= rSq
d = u - (rSq - dSq) ^ 0.5
The point of contact can be found with
cpx = p1.x + dx * d;
cpy = p1.x + dy * d;
Diagram 1

How to find the angle between 2 pairs of points?

I am doing some multi-touch support that allow 2 fingers to rotate a photos. There are four points: 2 for previous fingers and 2 for current finger positions.
I calculated a new point by subtract the 2 previous fingers, and the second new point was calculate by subtracting the other 2 current finger.
Then, I calculate the angle like this:
radian1 = atan ( p1.y / p1.x );
radian2 = atan ( p2.y / p2.x );
I subtract radian2 and radian1 to get the final angle.
The problem is I can rotate the image beautifully but sometime if I rotate to certain position the photo got flipped e.g. a photo supposed in 270 but it flipped and appeared in 90 degree.
This is the javascript I have written according to the reply below:
var x1 = this.previousMousePoint.x * this.previousMousePoint2.x + this.previousMousePoint.y * this.previousMousePoint2.y;
var y1 = this.previousMousePoint.x * this.previousMousePoint2.y - this.previousMousePoint.y * this.previousMousePoint2.x;
var x2 = center.x * point.x + center.y * point.y;
var y2 = center.x * point.y - center.y * point.x;
var radian1 = Math.atan(y1 / x1);
var radian2 = Math.atan(y2 / x2);
this.anchor.matrix = this.anchor.matrix.rotate(radian2-radian1, pivot);
Is looking ok. but it's kind of slow when i try to rotate an image
The clean way to do this is use angle-subtraction formulas to get values proportional to the sine and cosine of the difference angle, and use atan() only once:
relevant formulas:
cos(a2 - a1) = cos(a1)*cos(a2) + sin(a1)*sin(a2)
sin(a2 - a1) = cos(a1)*sin(a2) - sin(a1)*cos(a2)
p1.x = cos(a1) * len(p1)
p1.y = sin(a1) * len(p1)
p2.x = cos(a2) * len(p2)
p2.y = sin(a2) * len(p2)
-> angle-subtraction: compute values proportional to sin and cos of (a2 - a1)
c12 = p1.x*p2.x + p1.y*p2.y [ = len(p1)*len(p2) * cos(a2 - a1) ]
s12 = p1.x*p2.y - p1.y*p2.x [ = len(p1)*len(p2) * sin(a2 - a1) ]
-> final result: find resulting difference angle a12 [ = a2 - a1 ]
a12 = atan(s12 / c12)
or (if you want a full 360-degree range):
a12 = atan2(s12, c12)
Also, if you want to rotate an image with the result, you may not need to convert (c12,s12) to an angle, anyway: ultimately, your image rotator will use a matrix with the sines and cosines of the resulting rotation angle. By normalizing (c12,s12), you will end up with (cos(a12), sin(a12)), which you may be able to use more directly.
Arc tan maps between 0 and pi. 270 corresponds to 3/2 * pi and will fold over to pi. May I suggest that you incrementally find the angle using the positions of the fingers instead of just starting and the ending positions.
Even if you decide not to actually rotate the figure (to reduce computation), you can still display a tilted line / box / number to indicate the tilt that the software has registered.

Computing the 3D coordinates on a unit sphere from a 2D point

I have a square bitmap of a circle and I want to compute the normals of all the pixels in that circle as if it were a sphere of radius 1:
The sphere/circle is centered in the bitmap.
What is the equation for this?
Don't know much about how people program 3D stuff, so I'll just give the pure math and hope it's useful.
Sphere of radius 1, centered on origin, is the set of points satisfying:
x2 + y2 + z2 = 1
We want the 3D coordinates of a point on the sphere where x and y are known. So, just solve for z:
z = ±sqrt(1 - x2 - y2).
Now, let us consider a unit vector pointing outward from the sphere. It's a unit sphere, so we can just use the vector from the origin to (x, y, z), which is, of course, <x, y, z>.
Now we want the equation of a plane tangent to the sphere at (x, y, z), but this will be using its own x, y, and z variables, so instead I'll make it tangent to the sphere at (x0, y0, z0). This is simply:
x0x + y0y + z0z = 1
Hope this helps.
(OP):
you mean something like:
const int R = 31, SZ = power_of_two(R*2);
std::vector<vec4_t> p;
for(int y=0; y<SZ; y++) {
for(int x=0; x<SZ; x++) {
const float rx = (float)(x-R)/R, ry = (float)(y-R)/R;
if(rx*rx+ry*ry > 1) { // outside sphere
p.push_back(vec4_t(0,0,0,0));
} else {
vec3_t normal(rx,sqrt(1.-rx*rx-ry*ry),ry);
p.push_back(vec4_t(normal,1));
}
}
}
It does make a nice spherical shading-like shading if I treat the normals as colours and blit it; is it right?
(TZ)
Sorry, I'm not familiar with those aspects of C++. Haven't used the language very much, nor recently.
This formula is often used for "fake-envmapping" effect.
double x = 2.0 * pixel_x / bitmap_size - 1.0;
double y = 2.0 * pixel_y / bitmap_size - 1.0;
double r2 = x*x + y*y;
if (r2 < 1)
{
// Inside the circle
double z = sqrt(1 - r2);
.. here the normal is (x, y, z) ...
}
Obviously you're limited to assuming all the points are on one half of the sphere or similar, because of the missing dimension. Past that, it's pretty simple.
The middle of the circle has a normal facing precisely in or out, perpendicular to the plane the circle is drawn on.
Each point on the edge of the circle is facing away from the middle, and thus you can calculate the normal for that.
For any point between the middle and the edge, you use the distance from the middle, and some simple trig (which eludes me at the moment). A lerp is roughly accurate at some points, but not quite what you need, since it's a curve. Simple curve though, and you know the beginning and end values, so figuring them out should only take a simple equation.
I think I get what you're trying to do: generate a grid of depth data for an image. Sort of like ray-tracing a sphere.
In that case, you want a Ray-Sphere Intersection test:
http://www.siggraph.org/education/materials/HyperGraph/raytrace/rtinter1.htm
Your rays will be simple perpendicular rays, based off your U/V coordinates (times two, since your sphere has a diameter of 2). This will give you the front-facing points on the sphere.
From there, calculate normals as below (point - origin, the radius is already 1 unit).
Ripped off from the link above:
You have to combine two equations:
Ray: R(t) = R0 + t * Rd , t > 0 with R0 = [X0, Y0, Z0] and Rd = [Xd, Yd, Zd]
Sphere: S = the set of points[xs, ys, zs], where (xs - xc)2 + (ys - yc)2 + (zs - zc)2 = Sr2
To do this, calculate your ray (x * pixel / width, y * pixel / width, z: 1), then:
A = Xd^2 + Yd^2 + Zd^2
B = 2 * (Xd * (X0 - Xc) + Yd * (Y0 - Yc) + Zd * (Z0 - Zc))
C = (X0 - Xc)^2 + (Y0 - Yc)^2 + (Z0 - Zc)^2 - Sr^2
Plug into quadratic equation:
t0, t1 = (- B + (B^2 - 4*C)^1/2) / 2
Check discriminant (B^2 - 4*C), and if real root, the intersection is:
Ri = [xi, yi, zi] = [x0 + xd * ti , y0 + yd * ti, z0 + zd * ti]
And the surface normal is:
SN = [(xi - xc)/Sr, (yi - yc)/Sr, (zi - zc)/Sr]
Boiling it all down:
So, since we're talking unit values, and rays that point straight at Z (no x or y component), we can boil down these equations greatly:
Ray:
X0 = 2 * pixelX / width
Y0 = 2 * pixelY / height
Z0 = 0
Xd = 0
Yd = 0
Zd = 1
Sphere:
Xc = 1
Yc = 1
Zc = 1
Factors:
A = 1 (unit ray)
B
= 2 * (0 + 0 + (0 - 1))
= -2 (no x/y component)
C
= (X0 - 1) ^ 2 + (Y0 - 1) ^ 2 + (0 - 1) ^ 2 - 1
= (X0 - 1) ^ 2 + (Y0 - 1) ^ 2
Discriminant
= (-2) ^ 2 - 4 * 1 * C
= 4 - 4 * C
From here:
If discriminant < 0:
Z = ?, Normal = ?
Else:
t = (2 + (discriminant) ^ 1 / 2) / 2
If t < 0 (hopefully never or always the case)
t = -t
Then:
Z: t
Nx: Xi - 1
Ny: Yi - 1
Nz: t - 1
Boiled farther still:
Intuitively it looks like C (X^2 + Y^2) and the square-root are the most prominent figures here. If I had a better recollection of my math (in particular, transformations on exponents of sums), then I'd bet I could derive this down to what Tom Zych gave you. Since I can't, I'll just leave it as above.

Intersection on circle of vector originating inside circle

I have a circle. Inside the circle is a point. I have a vector originating at this point. I'd like to know what point on the circle this vector intersects. Here is a drawing:
http://n4te.com/temp/circle.png http://n4te.com/temp/circle.png
The red dot is the point I am trying to determine.
I know these things: the center of the circle, the origin of the vector, and the direction of the vector.
I know this is basic stuff, but I'm still having trouble. Most of the Googlings bring me to line-circle collision, which is related but not quite the same. Thanks for any help you can provide!
Elementary vector algebra.
O — center of circle (vector)
r — its radius (scalar)
A — origin of ray (vector)
k — direction of ray (vector)
Solve (A + kt - O)² = r² for scalar t, choose positive root, and A + kt is your point.
Further explanation:
. is dot product, ² for a vector is dot product of the vector with itself. Expand LHS
(A + kt - O)² = (A - O)² + 2(k.(A - O))t + k²t².
The quadratic is k²t² + 2(k.(A - O))t + (A - O)² - r² = 0. In terms of your variables, this becomes (rayVX² + rayVY²)t² + 2(rayVX(rayX - circleX) + rayVY(rayY - circleY))t + (rayX - circleX)² + (rayY - circleY)² - r² = 0.
Much thanks to Anton Tykhyy for his detailed answer. This was the resulting Java code:
float xDiff = rayX - circleX;
float yDiff = rayY - circleY;
float a = rayVX * rayVX + rayVY * rayVY;
float b = 2 * (rayVX * (rayX - circleX) + rayVY * (rayY - circleY));
float c = xDiff * xDiff + yDiff * yDiff - r * r;
float disc = b * b - 4 * a * c;
if (disc >= 0) {
float t = (-b + (float)Math.sqrt(disc)) / (2 * a);
float x = rayX + rayVX * t;
float y = rayY + rayVY * t;
// Do something with point.
}

Resources