A graphic of this problem is here:
http://dl.dropbox.com/u/13390614/Question2.jpg
Take an axis aligned ellipse with a fixed minor axis, and stretch the ellipse along its major axis till the ellipse's perimiter coincides with a point (A in the graphic). What is the new major axis length?
I can solve this problem when both axis are to be modified, but am stumped when only one axis is modified.
Any insights would be appreciated.
Gary
First, let's pretend the ellipse is at the origin to simplify things.
Imagine it was a circle where the diameter is your minor axis. What would be the width of the circle along the line where y = P's y? Equivalently, what is the x of the point on the circle's diameter where y = P's y. (There are two solutions to this. Either will do, though you may need to adjust a sign later on.) You can compute this using either trig or Pythagorean theorem.
Your major axis is now minor axis * ((P's x) / x).
Many thanks for the help Laurence, that does seem to work.
Gary
// In code
Since the ellipse and point are axis aligned,
the point is a vector.
Translate the point P onto a circle of minor axis
radius using the fixed minor axis length and the
Point's constant rise.
double y = fabs( P.y );
double x = sqrt( semiMnrAxLen * semiMnrAxLen - y * y );
// Calc the new Semi Major Axis length.
newSemiMajAxis = fabs( semiMnrAxLen * ( P.x / x ) );
Related
I have asked a question similar to this before but have since got further and also didn't tag the question right and wanted to get a bit of help on the maths around the question if possible.
I have a 3D sphere with points evenly spaced on its surface of which I know the coordinates. From these coordinates I am trying to define the orientation of some spikes that are coming out of the surface of my sphere along the vector between the centre of the sphere and the point at which the coordinates lie.
The idea is these euler angles will be very helpful in later aligning the spikes so they are all in roughly the same orientation if I am am to box out all of the spikes from an image.
Since the coordinates on the sphere are evenly spaced i can just take the average x, y and z coordinates to give me the centre and I can then draw a vector from the centre to each coordinate in turn.
The euler angles I need to calculate in this case are initially around the z axis, then around the new y axis, and finally again around the new z axis.
My centre point is currently being defined as the average coordinate of all my coordinates. This works as the coordinates are evenly spaced around the sphere.
I then use the equation that states
cos(theta) = dot product of the two vectors / magnitude of each vector multiplied together
on the x and y axis. One of my vectors is the x and y of the vector i am interested in whilst the other is the y axis (0,1). This tells me the rotation around the z axis with the y axis being 0. I also calculate the gradient of the line on this 2D plane to calculate whether I am working between 0 and +180 or 0 and -180.
I then rotate the x axis about the angle just calculated to give me x' using a simple 2D rotation matrix.
I then calculate the angle in the same way above but this time around the y axis using x' and z' as my second vector (where z' = z).
Finally I repeat the same as stated above to calculate the new z'' and x'' and do my final calculation.
This gives me three angles but when I display in matlab using the quiver3 command I do not get the correct orientations using this method. I believe I just do not understand how to calculate euler angles correctly and am messing something up along the way.
I was hoping someone more knowledgeable than me could take a glance over my planned method of euler angle calculation and spot any flaws.
Thanks.
i am scratching my head for some time now how to do this.
I have two defined vectors in 3d space. Say vector X at (0,0,0) and vector Y at (3,3,3). I will get a random point on a line between those two vectors. And around this point i want to form a circle ( some amount of points ) perpendicular to the line between the X and Y at given radius.
Hopefuly its clear what i am looking for. I have looked through many similar questions, but just cant figure it out based on those. Thanks for any help.
Edit:
(Couldnt put everything into comment so adding it here)
#WillyWonka
Hi, thanks for your reply, i had some moderate success with implementing your solution, but has some trouble with it. It works most of the time, except for specific scenarios when Y point would be at positions like (20,20,20). If it sits directly on any axis its fine.
But as soon as it gets into diagonal the distance between perpendicular point and origin gets smaller for some reason and at very specific diagonal positions it kinda flips the perpendicular points.
IMAGE
Here is the code for you to look at
public Vector3 X = new Vector3(0,0,0);
public Vector3 Y = new Vector3(0,0,20);
Vector3 A;
Vector3 B;
List<Vector3> points = new List<Vector3>();
void FindPerpendicular(Vector3 x, Vector3 y)
{
Vector3 direction = (x-y);
Vector3 normalized = (x-y).normalized;
float dotProduct1 = Vector3.Dot(normalized, Vector3.left);
float dotProduct2 = Vector3.Dot(normalized, Vector3.forward);
float dotProduct3 = Vector3.Dot(normalized, Vector3.up);
Vector3 dotVector = ((1.0f - Mathf.Abs(dotProduct1)) * Vector3.right) +
((1.0f - Mathf.Abs(dotProduct2)) * Vector3.forward) +
((1.0f - Mathf.Abs(dotProduct3)) * Vector3.up);
A = Vector3.Cross(normalized, dotVector.normalized);
B = Vector3.Cross(A, normalized);
}
What you want to do first is to find the two orthogonal basis vectors of the plane perpendicular to the line XY, passing through the point you choose.
You first need to find a vector which is perpendicular to XY. To do this:
Normalize the vector XY first
Dot XY with the X-axis
If this is very small (for numerical stability let's say < 0.1) then it must be parallel/anti-parallel to the X-axis. We choose the Y axis.
If not then we choose the X-axis
For whichever chosen axis, cross it with XY to get one of the basis vectors; cross this with XY again to get the second vector.
Normalize them (not strictly necessary but very useful)
You now have two basis vectors to calculate your circle coordinates, call them A and B. Call the point you chose P.
Then any point on the circle can be parametrically calculated by
Q(r, t) = P + r * (A * cos(t) + B * sin(t))
where t is an angle (between 0 and 2π), and r is the circle's radius.
I'm learning Unity3d + some basic maths I've forgotten by messing around.
Heres what I'm doing now..
As you can probably tell the sides of this shape form a parabola.
The distance they are out from the centre is the base radius + the height squared * by a constant (0.05 in this image)
The code generating this is very simple..
for (int changer = 1; changer > -2; changer-=2) {
Vector3 newPos = new Vector3(
transform.position.x
,transform.position.y + currentheight*changer
,transform.position.z - RadiusAtZero -(Mathf.Pow(currentheight,2)*CurveMultiplier)
);
var newFleck = Instantiate(Fleck, newPos, Quaternion.identity)as GameObject;
newFleck.transform.RotateAround(transform.position,Vector3.up,angle*changer);
FleckList.Add(newFleck );
}
Btw the for loop and 'changer' mirror everything so 'currentheight' is really just the distance from the centreline of the parabola.
Anyway I'd like to make the cubes (or flecks as I've called them) be angled so that they are tangentional to the parabola I have made.
I need to determine the angle of a tangent to the parabola at particular point.
I found this
to find the line tangent to y=x^2 -3 at (1, -2) we can simultaneously solve
y=x^2 -3 and y+2=m(x-1) and set the discriminant equal to zero
But I dont know how to implement this. Also I reckon my 'CurveMultiplier' constant makes my parabola equation different from that one.
Can someone write some code that determines the angle? (and also maybe explain it)
Update.
Here is fixed version using the derivative of the equation. (Also I have changed from boxes to tetrahedrons and few other superficial things)
The easiest solution is to use a derivative for the parabolic equation.
In your picture then I'll assume Y is vertical, X horizontal, and Z in/out of the screen. Then the parabola being rotated, based upon your description, is:
f(h) = 0.05*h^2 + R
(h is height, R is base radius). If you imagine a plane containing the Y axis, you can rotate the plane around the Y axis at any angle and the dual parabola looks the same.
The derivative of a parabolic equation of the form f(x) = C*h^2 + R is f'(x) = 2*C*h, which is the slope of the tangent at h. In this specific case, that would be:
f'(h) = 0.1*h
Since the cross-sectional plane has an angle relative to X and Z axes, then that tangent will also have the same angular component (you have a rotated parabola).
Depending upon the units given for the constants in f(h), particularly the 0.05 value, you may have to adjust this for the correct results.
I have a start point in 3D coordinates, e.g. (0,0,0).
I have the direction I am pointing, represented by three angles - one for each angle of rotation (rotation in X, rotation in Y, rotation in Z) (for the sake of the example let's assume I'm one of those old logo turtles with a pen) and the distance I will travel in the direction I am pointing.
How would I go about calculating the end point coordinates?
I know for a 2D system it would be simple:
new_x = old_x + cos(angle) * distance
new_y = old_y + sin(angle) * distance
but I can't work out how to apply this to 3 dimensions
I suppose another way of thinking about this would be trying to find a point on the surface of a sphere, knowing the direction you're pointing and the sphere's radius.
First of all, for positioning a point in 3D you only need two angles (just like you only needed one in 2D)
Secondly, for various reasons (slow cos&sin, gimbal lock, ...) you might want to store the direction as a vector in the first place and avoid angles alltogether.
Anyway, Assuming direction is initially z aligned, then rotated around x axis followed by rotation around y axis.
x=x0 + distance * cos (angleZ) * sin (angleY)
Y=y0 + distance * sin (Anglez)
Z=z0 + distance * cos (angleZ) * cos (angleY)
Based in the three angles you have to construct the 3x3 rotation matrix. Then each column of the matrix represents the local x, y and z directions. If you have a local direction you want to move by, then multiply the 3x3 rotation with the direction vector to get the result in global coordinates.
I made a little intro to 3D coordinate transformations that I think will answer your question.
3D Coordinates
First, it is strange to have three angles to represent the direction -- two would be enough. Second, the result depends on the order in which you turn about the respective axes. Rotations about different axes do not commute.
Possibly you are simply looking for the conversion between spherical and Cartesian coordinates.
I need to calculate the 2 angles (yaw and pitch) for a 3D object to face an arbitrary 3D point. These rotations are known as "Euler" rotations simply because after the first rotation, (lets say Z, based on the picture below) the Y axis also rotates with the object.
This is the code I'm using but its not working fully. When on the ground plane (Y = 0) the object correctly rotates to face the point, but as soon as I move the point upwards in Y, the rotations don't look correct.
// x, y, z represent a fractional value between -[1] and [1]
// a "unit vector" of the point I need to rotate towards
yaw = Math.atan2( y, x )
pitch = Math.atan2( z, Math.sqrt( x * x + y * y ) )
Do you know how to calculate the 2 Euler angles given a point?
The picture below shows the way I rotate. These are the angles I need to calculate.
(The only difference is I'm rotating the object in the order X,Y,Z and not Z,Y,X)
This is my system.
coordinate system is x = to the right, y = downwards, z = further back
an object is by default at (0,0,1) which is facing backward
rotations are in the order X, Y, Z where rotation upon X is pitch, Y is yaw and Z is roll
Here are my working assumptions:
The coordinate system (x,y,z) is such that positive x is to the right, positive y is down, and z is the remaining direction. In particular, y=0 is the ground plane.
An object at (0,0,0) currently facing towards (0,0,1) is being turned to face towards (x,y,z).
In order to accomplish this, there will be a rotation about the x-axis followed by one around the y-axis. Finally, there is a rotation about the z-axis in order to have things upright.
(The terminology yaw, pitch, and roll can be confusing, so I'd like to avoid using it, but roughly speaking the correspondence is x=pitch, y=yaw, z=roll.)
Here is my attempt to solve your problem given this setup:
rotx = Math.atan2( y, z )
roty = Math.atan2( x * Math.cos(rotx), z )
rotz = Math.atan2( Math.cos(rotx), Math.sin(rotx) * Math.sin(roty) )
Hopefully this is correct up to signs. I think the easiest way to fix the signs is by trial and error. Indeed, you appear to have gotten the signs on rotx and roty correct -- including a subtle issue with regards to z -- so you only need to fix the sign on rotz.
I expect this to be nontrivial (possibly depending on which octant you're in), but please try a few possibilities before saying it's wrong. Good luck!
Here is the code that finally worked for me.
I noticed a "flip" effect that occurred when the object moved from any front quadrant (positive Z) to any back quadrant. In the front quadrants the front of the object would always face the point. In the back quadrants the back of the object always faces the point.
This code corrects the flip effect so the front of the object always faces the point. I encountered it through trial-and-error so I don't really know what's happening!
rotx = Math.atan2( y, z );
if (z >= 0) {
roty = -Math.atan2( x * Math.cos(rotx), z );
}else{
roty = Math.atan2( x * Math.cos(rotx), -z );
}
Rich Seller's answer shows you how to rotate a point from one 3-D coordinate system to another system, given a set of Euler angles describing the rotation between the two coordinate systems.
But it sounds like you're asking for something different:
You have: 3-D coordinates of a single point
You want: a set of Euler angles
If that's what you're asking for, you don't have enough information. To find the Euler angles,
you'd need coordinates of at least two points, in both coordinate systems, to determine the rotation from one coordinate system into the other.
You should also be aware that Euler angles can be ambiguous: Rich's answer assumes the
rotations are applied to Z, then X', then Z', but that's not standardized. If you have to interoperate with some other code using Euler angles, you need to make sure you're using the same convention.
You might want to consider using rotation matrices or quaternions instead of Euler angles.
This series of rotations will give you what you're asking for:
About X: 0
About Y: atan2(z, x)
About Z: atan2(y, sqrt(x*x + z*z))
I cannot tell you what these are in terms of "roll", "pitch" and "yaw" unless you first define how you are using these terms. You are not using them in the standard way.
EDIT:
All right, then try this:
About X: -atan2(y, z)
About Y: atan2(x, sqrt(y*y + z*z))
About Z: 0
Talking about the rotation of axes, I think step 3 should have been the rotation of X'-, Y''-, and Z'-axes about the Y''-axis.