I know the angle at point A and that the circle goes through point A and point B. There should be a unique solution that gives me the circle center (C) and radius (R) from this information. I've tried to find a formula as follows.
R^2 = (Bx - Cx)^2 + (By - Cy)^2
Cx = Ax - R*dy
Cy = Ay + R*dx
(dx,dy) is a unit vector for the tangent to the circle at point A, which can be found from the angle at point A with sin,cos. The center of the circle is distance R from point A in the direction perpendicular to (dx,dy).
Putting this together gives me
R^2 = (Bx - Ax + R*dy)^2 + (By - Ay - R*dx)^2
Multiplying this out gives me a quadratic for R, but the denominator of the quadratic (the /2a part) is
dx^2 + dy^2 - 1
Since (dx,dy) is a unit vector, the denominator is always 0 and I get a divide by zero error. Where have I gone wrong?
The formulation seems fine to me. Lets expand the expression
R^2 = (Bx - Ax + R dy)^2 + (By - Ay - R dx)^2
this gives
R^2 = Bx^2 + Ax^2 + R^2 dy^2 + 2 Bx R dy - 2 Ax Bx - 2 Ax R dy
+ By^2 + Ay^2 + R^2 dx^2 - 2 By R dx - 2 Ay By + 2 Ay R dx
Rearrange
(1 - dx^2 - dy^2) R^2 + 2 (Ax dy - Ay dx - Bx dy + By dx) R + 2 (Ax Bx + Ay By) = 0
You are correct in that if (dx,dy) is a unit vector the R^2 term vanishes. This is not a problem it just means you have a linear equation to solve.
2 (Ax dy - Ay dx - Bx dy + By dx) R + 2 (Ax Bx + Ay By) = 0
which is easy to solve
R = - (Ax Bx + Ay By) / (Ax dy - Ay dx - Bx dy + By dx)
Things are a little simpler if you let U = (u,v) = (Bx-Ax,By-Ay) be the vector from A to B our equation becomes
R^2 = (u + R dy)^2 + (v - R dx)^2
= u^2 + 2 u dy R + dy^2 R^2 + v^2 - 2 v dx R + dx^2 R^2
Rearrange
(1-dx^2-dy^2) R^2 + 2 (v dx - u dy) R - u^2 - v^2 = 0
Let T=(dx,dy) be the tangent, and N=(dy,-dx) is normal. If they are unit length it simplifies to
2 (N . U) R - U . U = 0
giving
R = (U . U)/ 2 (N . U)
Assuming you mean the angle between the line AB and the tangent line. l, of the circle at A:
The key is to draw the perpendicular bisector of AB and the line perpendicular to l through A, and find the intersection. That will be the center of your circle.
I have solved from my theory.
The slope of the circle is the radius equal 1.
Therefore: the slope=(rise^2+run^2)^(1/2)=1,
so dy^2+dx^2=1^2 and (dy^2+dx^2)^(1/2)=1.
Related
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
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
Is it possible to find he center of sphere and its radius from 3 points on the surface ?
I'm building a model for a segmented brain structure were the three points would be within the structure; head, tail and middle.
Thank you,
Express that the center of the sphere is equidistant to the three given points and coplanar with them (assuming that the three given points are on a great circle).
(X - Xa)² + (Y - Ya)² + (Z - Za)² = R²
(X - Xb)² + (Y - Yb)² + (Z - Zb)² = R²
(X - Xc)² + (Y - Yc)² + (Z - Zc)² = R²
|X Y Z 1|
|Xa Ya Za 1|
|Xb Yb Zb 1| = 0
|Xc Yc Zc 1|
Subtracting the first equation from the second and the third, you get rid of the quadratic terms.
(2X - Xb - Xa)(Xb - Xa) + (2Y - Yb - Ya)(Yb - Ya) + (2Z - Zb - Za)(Zb - Za) = 0
(2X - Xc - Xa)(Xc - Xa) + (2Y - Yc - Ya)(Yc - Ya) + (2Z - Zc - Za)(Zc - Za) = 0
Now you have an easy linear system of 3 equations in 3 unknowns.
For conciseness you can translate the three points so that Xa=Ya=Za=0, and the equations simplify as
|X Y Z |
|Xb Yb Zb| = 0
|Xc Yc Zc|
(2X - Xb) Xb + (2Y - Yb) Yb + (2Z - Zb) Zb = 0
(2X - Xc) Xc + (2Y - Yc) Yc + (2Z - Zc) Zc = 0
or
(Yb Zc - Yc Zb) X + (Zb Xc - Zc Xb) Y + (Xb Yc - Xc Yb) Z = 0
2 Xb X + 2 Yb Y + 2 Zb Z = Xb² + Yb² + Zb²
2 Xc X + 2 Yc Y + 2 Zc Z = Xc² + Yc² + Zc²
Then, R² = X² + Y² + Z², and don't forget to translate back.
It is indeed possible, but it will always give you a sphere which the surface input points will be on its equator (meaning there are other, larger spheres that have these 3 points on it's surface if there's a fourth not coplanar point given).
But I think the smallest sphere is what you want. The following code written in C# gives you a Vector3 with the center of the sphere. The distance can then be obtained with Vector3.Distance (or a simple pithagorean distance) between any of the input points and the resulting center.
static public Vector3 BarycentricToWorld3D(Vector3 p1, Vector3 p2, Vector3 p3, float u, float v, float w) {
return (u * p1 + v * p2 + w * p3) / (u + v + w);
}
static public Vector3 CircleBariCenter3D(Vector3 p1, Vector3 p2, Vector3 p3) {
Vector3 a = p3 - p2;
Vector3 b = p1 - p3;
Vector3 c = p2 - p1;
float u = Vector3.Dot(a, a) * Vector3.Dot(c, b);
float v = Vector3.Dot(b, b) * Vector3.Dot(c, a);
float w = Vector3.Dot(c, c) * Vector3.Dot(b, a);
return BarycentricToWorld3D(p1, p2, p3, u, v, w);
}
Notice there's no checking for colinear points, which will make this fail. It should be trivial to add such checking by simply feeding this colinear points and watching it fail in the debugger.
Credits: I got a maxscript source for this 10+ years ago and lost the original author and location, and translated it into C# quite recently.
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.
I have two points in space, L1 and L2 that defines two points on a line.
I have three points in space, P1, P2 and P3 that 3 points on a plane.
So given these inputs, at what point does the line intersect the plane?
Fx. the plane equation A*x+B*y+C*z+D=0 is:
A = p1.Y * (p2.Z - p3.Z) + p2.Y * (p3.Z - p1.Z) + p3.Y * (p1.Z - p2.Z)
B = p1.Z * (p2.X - p3.X) + p2.Z * (p3.X - p1.X) + p3.Z * (p1.X - p2.X)
C = p1.X * (p2.Y - p3.Y) + p2.X * (p3.Y - p1.Y) + p3.X * (p1.Y - p2.Y)
D = -(p1.X * (p2.Y * p3.Z - p3.Y * p2.Z) + p2.X * (p3.Y * p1.Z - p1.Y * p3.Z) + p3.X * (p1.Y * p2.Z - p2.Y * p1.Z))
But what about the rest?
The simplest (and very generalizable) way to solve this is to say that
L1 + x*(L2 - L1) = (P1 + y*(P2 - P1)) + (P1 + z*(P3 - P1))
which gives you 3 equations in 3 variables. Solve for x, y and z, and then substitute back into either of the original equations to get your answer. This can be generalized to do complex things like find the point that is the intersection of two planes in 4 dimensions.
For an alternate approach, the cross product N of (P2-P1) and (P3-P1) is a vector that is at right angles to the plane. This means that the plane can be defined as the set of points P such that the dot product of P and N is the dot product of P1 and N. Solving for x such that (L1 + x*(L2 - L1)) dot N is this constant gives you one equation in one variable that is easy to solve. If you're going to be intersecting a lot of lines with this plane, this approach is definitely worthwhile.
Written out explicitly this gives:
N = cross(P2-P1, P3 - P1)
Answer = L1 + (dot(N, P1 - L1) / dot(N, L2 - L1)) * (L2 - L1)
where
cross([x, y, z], [u, v, w]) = x*u + y*w + z*u - x*w - y*u - z*v
dot([x, y, z], [u, v, w]) = x*u + y*v + z*w
Note that that cross product trick only works in 3 dimensions, and only for your specific problem of a plane and a line.
This is how I ended up doing it in come code. Luckily one code library (XNA) had half of what I needed, and the rest was easy.
var lv = L2-L1;
var ray = new Microsoft.Xna.Framework.Ray(L1,lv);
var plane = new Microsoft.Xna.Framework.Plane(P1, P2, P3);
var t = ray.Intersects(plane); //Distance along line from L1
///Result:
var x = L1.X + t * lv.X;
var y = L1.Y + t * lv.Y;
var z = L1.Z + t * lv.Z;
Of course I would prefer having just the simple equations that takes place under the covers of XNA.