I have a cylinder of 2f length, and the data for RotX and RotZ, given by user. I also know that the "bottom" of my cylinder is at (0,0,0) (the center of the circle forming the "bottom")
What I need is to calculate the "top" point (the center of the circle at the other end) having the data exposed in the upper lines.
In my second image, the A point is calculated as follows (sin(zAngle),cos(zAngle),sin(xAngle) with zAngle=PI/4 (alpha angle) and xAngle=0.
Point B is calculated as (sin(xAngle),cos(xAngle),sin(zAngle)) with xAngle=PI/4 (beta angle) and zAngle=0;
C point is the "top" of a cylinder with xAngle=PI/4 and zAngle=PI/4.
I need to find an algorithm to determine the "top" point for any given xAngle and zAngle.
I'd be extremly thankful if anyone could help me.
Before your rotations, the top is at 2f*(0,1,0).
After you rotate the cylinder around the z axis by angle alpha, the top is at 2f*(sin alpha, cos alpha, 0).
If you now rotate the cylinder by angle beta around the x axis, the top goes to 2f*(sin alpha, cos alpha*cos beta, cos alpha*sin beta).
Related
I have a Canvas on which I've drawn a circle / 360 degree arc. I have the arc start drawing from -90 (the top) rather than the right (0) as is default.
I want to place a rectangle at the top of the same canvas and to reduce the sweep of the arc so that the two do not intersect. I've attached an image to illustrate
So what I need to do is work out what angle is represented by half of the rectangle so that I can adjust where to start drawing my arc. The centre of the circle is at the centre of my Canvas:
[canvas.width /2, canvas.height /2]
I've read some resources like this question but they haven't helped to do much more than make me feel like I know nothing. I tried a few failing formulas ending with this
double adjustment = Math.atan2(rectangleY - circleY, rectangleX - circleX) - Math.atan2(rectangleY - circleY, (rectangleX + rectangleWidth) - circleX);
Can somebody tell me what is the right way to calculate this in Java? I'd also like to know how to find where the rectangle intersects if that's possible (I.e. the width of the shaded orange part on the image) although this is of lesser importance to me right now
Let W be the width of the rectangle, R be radius of the circle, and A be the angle you're looking for.
There's a right-angle triangle with angle A at the center, R as the hypotenuse and W/2 as the side opposite angle A, so
W/2R = sin(A)
so
A = Math.asin(0.5*W/R);
Of course you can't use asin(0.5W/R) when W > 2R
EDIT
To answer the second problem (finding the intersection)
Let H be the distance from the center of the circle to the rectangle. When the rectangle is wide enough that the circle intersects the lower side, there's a right angle triangle with A at the center, R as the hypotenuse, and H as the side adjacent to A
H/R = cos(A) and A = Math.acos(H/R). Calculate both angles and use the smaller one.
I would like to know more about the coordinates of a Rectangle,
in particular:
lower left X
lower left Y
upper right X
upper right Y
Every time, I get confused about how to make dimensions based on these coordinates to draw rectangle.
If possible, can I get a graphical representation briefly about these coordinates positions?
Before someone can explain what the lower-left X, lower-left Y, upper-right X and upper-right Y of a rectangle are about, you need to know about the coordinate system: Where is the Origin (x,y) of a PDF page?
The answer to that question contains all the information you need, except for the graphical representation you are asking for. This is a simple representation of the coordinate system:
The origin of the coordinate system is (0, 0). Positive X values are to the right of the origin, positive Y values are above the origin.
I have drawn a Rectangle and indicates where you can find the lower-left corner (with coordinate (llx, lly)) and the upper-right corner (with coordinate (urx, ury)).
The sides of the rectangle are always in parallel with the X and the Y axis, hence you only need two coordinates to define the rectangle.
I tried to post a different topic for this but people didn't really seem to understand what I was trying to do, so, now I've closed that one and opened this one to give more detail and rephrase the question as a whole.
Ok.
So basically, I have an application which draws an Ellipse. Now, I have a certain number of points (that can be random) in which I have to rotate an image and draw at.
Using Maths I know that to get a point on an Ellipse based by using an angle I use the following equation;
final int radiusW = (width / 2);
final int radiusH = (height / 2);
final int angle = 120;
int pointX = (int) (radiusW + (radiusW * Math.cos(Math.toRadians(angle))));
int pointY = (int) (radiusH + (radiusH * Math.sin(Math.toRadians(angle))));
And that works fine, I can locate an absolute point around the perimeter of the Ellipse.
However, now I'm trying to draw an image on this point so that the image is rotated facing the center of ellipse and is centered on the point.
So, to get the image rotated to the center of the point I do the following;
final AffineTransform at = new AffineTransform();
at.rotate(Math.toRadians(angle - 90), image.getWidth() / 2, image.getHeight() / 2);
final AffineTransformOp ato = new AffineTransformOp(at, AffineTransformOp.TYPE_BILINEAR);
And then I get my new rotated BufferedImage using;
BufferedImage rotated = ato.filter(image, null);
However, I can't seem to be able to get the central point of the image anymore.
If the angle was 0 so that the Image was the original direction then I would simply do;
graphics.drawImage(rotated, pointX - rotated.getWidth() / 2, pointY - rotated.getHeight() / 2, this);
However I'm not sure how to find the central point and draw it based upon that on a rotated image.
I know it involves using cos and sin to multiply the original pointX and pointY by the rotation matrix but everytime I try and work out a solution it always draws completely wrong.
Any help would be very much appreciated as I've spent the best part of a day trying to resolve this.
Thank you.
The thing is that if you just use sin and cos to rotate the corner of the image you will end up with the new rotated position of that corner - when actually what you want to find is the new width and height.
The center is width/2, height/2
Use this to calculate your new width and height:
Calculate Bounding box coordinates from a rotated rectangle
I have done this with OpenCV, and there the image have been rotated but the resulted image was having the same width and height as the initial on. The image was cropped if it was getting out of the initial dimentions and there were black pixels if no information (the rotated image has no pixels in that place).
If you think that rotated has more pixels than the initial image you can verify with size() or length(). Or you can play with the diagonals of the initial rectangle (image size): compute the projection of the diagonals and thake the greatest or what you think. But I am sure that it is similar to the OpenCV case.
I don't know if this can help you, but I hope so.
Your question is not entirely clear but it seems to me that you have a misunderstanding of the nature of the angle used to parametrise your ellipse. The angle as you have it is merely used to parametrise the form of an ellipse equation. It is not the same as the polar angle (except at particular angles). That is to say if you evaluate a point on your ellipse using an angle of (pi/4) radians (45 degrees), then measured the angle that the line from the ellipse centre to your point makes with the axis, it will not measure 45 degrees (except for the case where the ellipse is actually a circle).
That is to say that
int pointX = (int) (radiusW + (radiusW * Math.cos(Math.toRadians(angle))));
int pointY = (int) (radiusH + (radiusH * Math.sin(Math.toRadians(angle))));
is just a parametrisation of an ellipse and that angle is not a polar angle and treating this angle as a rotation angle will not give accurate results (except at integer multiples of (pi/2) radians)
It seems to me that you require the polar form of an ellipse relative to its centre in order for your code to make sense in the context of using this angle for rotation.
It is also possible that I have misunderstood your question though, in which case this answer will be downvoted on a grand scale and I will delete it.
I'm facing issue for a class where I need to convert and draw GPS coordinates dynamically into a JPanel. I have this local library data in a file that I parse. The structure is ID, County, Library Name, Latitude, Longitude.
R1,Ramsey,Maplewood,45.0327,-93.0262
R2,Ramsey,Mounds View,45.1059,-93.2104
R3,Ramsey,New Brighton,45.06604,-93.19125
R4,Ramsey,North St. Paul,45.0105,-92.9968
R5,Ramsey,Roseville,45.0072,-93.1558
R6,Ramsey,Shoreview,45.0805,-93.1345
R7,Ramsey,White Bear Lake,45.0831,-93.0092
As you can see, the locations are very close together (7 locations in 170 sq miles, Max Distance apart: 15.5 miles). My code currently can draw and link the nodes properly from hardcoded coordinates instead of the GPS data. I have found algorithms for converting the GPS lat and long to XY coordinates, but once the calculations happen, all the objects print on top of each other since the calculation leads to the same XY because of it being so close. The process needs to be dynamic because I anticipate that the test files to be use will be using 42 locations. What can I do for an equation that will give me XY coordinates that have enough variety to make a decent graphic rendering instead of using random points?
What can I do for an equation that will give me XY coordinates that have enough variety to make a decent graphic rendering instead of using random points?
Find the bounding box. In other words, find the smallest x and smallest y coordinate in your list. Find the largest x and largest y coordinate in your list. Those two points define the bounding box.
Now, translate these location x, y coordinates to drawing x, y coordinates. Your smallest location x, y coordinate becomes drawing coordinate 0, 0. Your largest location x, y coordinate becomes drawing coordinate width, height.
In order to keep the scaling from distorting the image, we have to first calculate the scaling factor for the x coordinate and the y coordinate.
scaling factor x = drawing width / (location maximum x - location minimum x)
scaling factor y = drawing height / (location maximum y - location minimum y)
Then we use the smaller of the two scaling factors.
scaling factor = Math.min(scaling factor x, scaling factor y)
The equations for converting location coordinates to drawing coordinates are:
drawing x = location x * scaling factor
drawing y = location y * scaling factor
Location and scaling factor are doubles, so you don't drop any precision. You have to convert drawing x and drawing y to integers so you can plot them.
Drawing x increases from west to east. Location x probably increases from west to east.
Drawing y increases from north to south. If location y increases from south to north, then you have to take that into account when doing the conversion.
drawing y = drawing height - drawing y
You'll probably will want to add a margin to your drawing area so that none of the locations are drawn on the edge of the drawing area.
Let's say you want a margin of 10 pixels. That would make the actual drawing area 20 pixels larger in width and 20 pixels larger in height.
You then add 10 pixels to the drawing x and the drawing y before you plot your location.
The ideal way to go about this is to find the min-longitude and min-latitude , max-longitude and max-latitude and map them to the [0,0] and [JPanels.width , Jpanels.Height].
this map can be done just
Point map(cure_location){
int X = (curr_location.longitude-min_longitude)*(scalelog);
int Y = (curr_location.latitude-min_latitude)*(scalelon);
return new Point(X,Y);
}
and scalelog and scalelon are
scalelog = (JPanels.width)/(max_longitude-min_longitude)
scalelat = (JPanels.height)/(max_latitude-min_latitude)
I'm writing a game in Java using OpenGL (the LWJGL binding, to be specific). Each entity, including the camera, has a quaternion that represents it's rotation. I've figured out how to apply the quaternion to the current OpenGL matrix and everything rotates just fine. The issue I'm having is getting the camera to rotate with the mouse.
Right now, every frame, the game grabs the amount that the mouse has moved on one axis, then it applies that amount onto the quaternion for the camera's rotation. Here is the code that rotates the quaternion, I'll post it since I think it's where the problem lies (although I'm always wrong about this sort of stuff):
public void rotateX(float amount){
Quaternion rot = new Quaternion(1.0f, 0.0f, 0.0f, (float)Math.toRadians(amount));
Quaternion.mul(rot, rotation, rotation);
rotation.normalise();
}
This method is supposed to rotate the quaternion around the X axis. 'rotation' is the quaternion representing the entity's rotation. 'amount' is the amount that I want to rotate the quaternion (aka the amount that the mouse was moved). 'rot' is a normalized vector along the X axis with a w value of the amount converted to radians (I guess the goal here is to give it an angle- say, 10 degrees- and have it rotate the quaternion along the given axis by that angle). Using Quaternion.mul takes the new quaternion, multiplies it by the rotation quaternion, and then stores the result as the rotation quaternion. I don't know if the normalization is necessary, since 'rot' is normal and 'rotation' should already by normalized.
The rotateY and rotateZ methods do the same thing, except for changing the vector for 'rot' (0.0, 1.0, 0.0 for y and 0.0, 0.0, 1.0 for z).
The code appears to work fine when the game starts and the camera is looking down the negative Z axis. You can spin all the way around on the Y axis OR all the way around the X axis. But as soon as you try to rotate the camera while not looking down the Z axis, everything gets really screwy (I can't even describe it, it rotates very oddly).
My end goal here is to have something to use for controlling a ship in a space with no up vector. So when you move the mouse on the Y axis, no matter what angle the ship is at, it changes the pitch of the ship (rotation along the X axis). Similarly, when you move the mouse on the X axis, it changes the yaw (rotation along the Y axis). I might be going about this the wrong way and I probably just need a push (or shove) in the right direction.
If you need more details on anything (how my rendering is done, any other maths that I'm trying to do) just ask and I'll put it up. I understood everything when I was using euler angles (which apparently are a big no-no for 3D application development... wish somebody would have told me that before I sunk a lot of time into getting them to work) but as soon as I switched over to quaternions, I got in over my head really fast. I've spent the past few months just playing with this code and reading about quaternions trying to get it to work, but I haven't really gotten anywhere at all :'(
Very, very frustrating... starting to regret trying to make something in 3D >_<
Quaternion rot = new Quaternion(1.0f, 0.0f, 0.0f, (float)Math.toRadians(amount));
OK, this is flat-out wrong.
The constructor that takes four floats assumes that they represent an actual quaternion. What you give that constructor is not a quaternion; it's a vec3 axis and an angle that you expect to rotate around.
You can't shove those into a quaternion class and expect to get a legitimate quaternion out of it.
Your quaternion class should have a constructor or some other means of creating a quaternion from an angle and an axis of rotation. But according to the documentation you linked to, it does not. So you have to do it yourself.
A quaternion is not a vec3 axis with a fourth value that is an angle. A unit quaternion representation a change in orientation is a vec3 that is the axis of rotation * the sine of half of the angle of rotation, and a scalar component that is the cosine of half the angle of rotation. This assumes that the angle of rotation is clamped on the range [-pi/2, pi/2].
Therefore, what you want is this:
float radHalfAngle = ... / 2.0; //See below
float sinVal = Math.Sin(radHalfAngle);
float cosVal = Math.Cos(radHalfAngle);
float xVal = 1.0f * sinVal;
float yVal = 0.0f * sinVal; //Here for completeness.
float zVal = 0.0f * sinVal; //Here for completeness.
Quaternion rot = new Quaternion(xVal, yVal, zVal, cosVal);
Also, converting amount to radians directly doesn't make sense, particularly so if amount is just a pixel-coordinate delta that the mouse moved. You need some kind of conversion scale between the distance the mouse moves and how much you want to rotate. And toRadians is not the kind of scale you want.
One more thing. Left-multiplying rot, as you do here, will perform a rotation about the camera space X axis. If you want a rotation about the world-space X axis, you need to right-multiply it.