I am trying to draw a rotated ellipse not centered at the origin (in c++).
so far my code "works":
for (double i = 0; i <= 360; i = i + 1) {
theta = i*pi / 180;
x = (polygonList[compt]->a_coeff / 2) * sin(theta) + polygonList[compt]->centroid->datapointx;
y = (polygonList[compt]->b_coeff / 2) * cos(theta) + polygonList[compt]->centroid->datapointy;
xTmp = (x - polygonList[compt]->centroid->datapointx)* cos(angle1) - (y - polygonList[compt]->centroid->datapointy)*sin(angle1) + polygonList[compt]->centroid->datapointx;
yTmp = (x - polygonList[compt]->centroid->datapointx)* sin(angle1) + (y - polygonList[compt]->centroid->datapointy)*cos(angle1) + polygonList[compt]->centroid->datapointy;
}
PolygonList is a list of "bloc" which will be replaced by an ellipse of same area.
My issue is that the angles are not quite exact, as if I had to put a protractor that'd fit the shape of my ellipse, the protractor would obviously get squeezed, and so would be the angles (is that clear ?)
Here is an example: I am trying to set a point on the top ellipse (E1) which would be lying on a line drawn between the centroid of E1, and any point on the second ellipse (E2).On this example, the point on E2 lies at an angle of ~220-230 degree. I am able to catch this angle, the angle seems ok.
The problem is that if I try to project this point on E1 by using this angle of ~225 degree, I end up on the second red circle on top. it looks like my angle is now ~265 degree, but in fact, if I shape the protractor to fit in my ellipse, I get the right angle (~225) ,cf img 2)
it is a bit hard to see the angle on that re-shaped protractor, but it does show ~225 degree.
My conclusion is that the ellipse is drawn like if I had to drew a circle and then I'd compress it, which changes the distance between the angles.
Could someone tell me how I could fix that ?
PS: to draw those ellipses I just use a for loop which plots a dot at every angle (from 0 to 360). we clearly see on the first picture that the distance between the dots are different whether we are at 0 or at 90 degree.
your parametrisation is exactly that, a circle is a case of ellipse with both axes are equal. It sounds like you need use rational representation of ellipse instead of standard: https://en.m.wikipedia.org/wiki/Ellipse
So, I've asked the question above so that I could find a possible overlap between 2 ellipses by checking the distance between any point on E2 and its projection on E1: if the distance between the centroid of E1 and the projected dot on E1 is larger than the distance between the centroid of E1 to a dot on E2 I'll assume an overlap. I reckon this solution has never been tried (or I haven't search enough) and should work fine. But before working I needed to get those angles right.
I have found a way to avoid using angles and projected dots, by checking the foci:
the sum of the distance between the focus A and B to any point around an axis is constant (let's call it DE1 for E1).
I then check the distance between my foci and any point on E2. If that distance becomes less than DE1, I'll assume a connection.
So far it seems to work fine :)
I'll put that here for anyone in need.
Flo
Related
So I am writing a game in C++, currently I am working on a 'Compass', but I am having some problems with the vector math..
Here is a little image I created to possibly help explain my question better
Ok, so as you can see the 2D position of A begins at (4, 4), but then I want to move A along the 45 degree angle until the 2D position reaches (16, 16), so basically there is a 12 distance between where A starts and where it ends. And my qustion is how would I calculate this?
the simplest way in 2D is to take angle 'ang', and distance 'd', and your starting point 'x' and 'y':
x1 = x + cos(ang) * distance;
y1 = y + sin(ang) * distance;
In 2D the rotation for any object can be just stored as a single value, ang.
using cos for x and sin for y is the "standard" way that almost everyone does it. cos(ang) and sin(ang) trace a circle out as ang increases. ang = 0 points right along the x-axis here, and as angle increases it spins counter-clockwise (i.e at 90 degrees it's pointing straight up). If you swap the cos and sin terms for x and y, you get ang = 0 pointing up along the y axis and clockwise rotation with increasing ang (since it's a mirror image), which could in fact be more convenient for making game, since y-axis is often the "forward" direction and you might like that increasing ang spins to the right.
x1 = x + sin(ang) * distance;
y1 = y + cos(ang) * distance;
Later you can get into vectors and matricies that do the same thing but in a more flexible manner, but cos/sin are fine to get started with in a 2D game. In a 3D game, using cos and sin for rotations starts to break down in certain circumstances, and you start really benefiting from learning the matrix-based approaches.
The distance between (4,4) and (16,16) isn't actually 12. Using pythagorean theorem, the distance is actually sqrt(12^2 + 12^2) which is 16.97. To get points along the line you want to use sine and cosine. E.g. If you want to calculate the point halfway along the line the x coordinate would be cos(45)(16.97/2) and the y would be sin(45)(16.97/2). This will work with other angles besides 45 degrees.
Ok so, this should be super simple, but I'm not a smart man. Technically I want to know whether a point resides inside a rectangle, however the rectangle can be in different states. In my current context when I want to draw a rectangle rotated by, lets say, 45° clockwise, what I do is rotate the entire x,y axis centered at the top-left corner of the rectangle and then I just draw the rectangle as if nothing has happened. Same goes if I want to draw the rectangle at a random coordinate. Given that is the coordinate system who gets tossed and rotated, the rectangle always thinks it's being drawn at (0,0) with 0°, therefore, the best way to find if a given point is inside the rectangle would be to find the projection for the point based on the translation + rotation of the rectangle. But I have no idea how to do that.
This is what I currently do in order to find out if a point is inside a rectangle (not taking into consideration rotation):
bool Image::isPointInsideRectangle(int x, int y, const ofRectangle & rectangle){
return x - xOffset >= rectangle.getX() && x - xOffset <= rectangle.getX() + rectangle.getWidth() &&
y - yOffset >= rectangle.getY() && y - yOffset <= rectangle.getY() + rectangle.getHeight();
}
I already have angleInDegrees stored, as long as I could use it to project the (x,y) point I receive I should be able find out if the point is inside the rectangle.
Cheers!
Axel
The easiest way is to un-rotate x,y in the reverse direction relative to the origin and rotation of the rectangle.
For example, if angleInDegrees is 45 degrees, you would rotate the point to test -45 degrees (or 315 degrees if your rotation routine only allows positive rotations). This will plot the x,y on the same coordinate system as the unrotated rectangle.
Then, you can use the function you already provided to test whether the point is within the rectangle.
Note that prior to rotating x,y, you will probably need to adjust the x,y relative to the point of rotation - the upper-left corner of the rectangle. Since the rotation is relative to that point rather than the overall coordinate origin 0,0. You can compute the difference between x,y and the upper-left corner of your rectangle (which won't change during rotation), then simply rotate the adjusted point by -angleToRotate, then add the origin point difference back into the unrotated point to get absolute coordinates on your coordinate system.
Editted:
#include <cmath>
bool Image::isPointInsideRectangle(int x, int y, const ofRectangle & rectangle){
return x*cosd(deg) - y*sin(deg) + xOffset >= rectangle.getX()
&& x*cosd(deg) - y*sin(deg) + xOffset <= rectangle.getX() + rectangle.getWidth()
&& x*sind(deg) + y*cosd(deg) + yOffset >= rectangle.getY()
&& x*sind(deg) + y*cosd(deg) + yOffset <= rectangle.getY() + rectangle.getHeight();
Like you have already told, you could translate the coordinates of your point into the space of the rectangle. This is a common task in many software products which work with geometry. Each object have it own coordinate space and works as it would be at position (0, 0) without rotation. If your rectangle is at position v and rotated about b degree/radian, than you can translate your point P into the space of the rectangle with the following formula:
| cos(-b) -sin(-b) | | P_x - v_x |
| | ⋅ | |
| sin(-b) cos(-b) | | P_y - v_y |
Many of the most important transformations can be represented as matrices. At least if you are using homogeneous coordinates. It is also very common to do that. Depending of the complexity and the goals of your program you could consider to use some math library like glm and use the transformations of your objects in form of matrices. Then you could write something like inverse(rectangle.transformation()) * point to get point translated into the space of rectangle.
Ok.... so I made a quick diagram to sorta explain what I'm hoping to accomplish. Sadly math is not my forte and I'm hoping one of you wizards can give me the correct formulas :) This is for a c++ program, but really I'm looking for the formulas rather than c++ code.
Ok, now basically, the red circle is our 0,0 point, where I'm standing. The blue circle is 300 units above us and at what I would assume is a 0 degree's angle. I want to know, how I can find a find the x,y for a point in this chart using the angle of my choice as well as a certain distance of my choice.
I would want to know how to find the x,y of the green circle which is lets say 225 degrees and 500 units away.
So I assume I have to figure out a way to transpose a circle that is 500 units away from 0,0 at all points than pick a place on that circle based on the angle I want? But yeah no idea where to go from there.
A point on a plane can be expressed in two main mathematical representations, cartesian (thus x,y) and polar : using a distance from the center and an angle. Typically r and a greek letter, but let's use w.
Definitions
Under common conventions, r is the distance from the center (0,0) to your point, and
angles are measured going counterclockwise (for positive values, clockwise for negative), with the 0 being the horizontal on the right hand side.
Remarks
Note a few things about angles in polar representations :
angles can be expressed with radians as well, with π being the same angle as 180°, thus π/2 90° and so on. π=3.14 (approx.) is defined by 2π=the perimeter of a circle of radius 1.
angles can be represented modulo a full circle. A full circle is either 2π or 360°, thus +90° is the same as -270°, and +180° and -180° are the same, as well as 3π/4 and -5π/4, 2π and 0, 360° and 0°, etc. You can consider angles between [-π,π] (that is [-180,180]) or [0,2π] (i.e. [0,360]), or not restrain them at all, it doesn't matter.
when your point is in the center (r=0) then the angle w is not really defined.
r is by definition always positive. If r is negative, you can change its sign and add half a turn (π or 180°) to get coordinates for the same point.
Points on your graph
red : x=0, y=0 or r=0 w= any value
blue : x=0, y=300 or r=300 and w=90°
green : x=-400, y=-400 or r=-565 and w=225° (approximate values, I didn't do the actual measurements)
Note that for the blue point you can have w=-270°, and for the green w=-135°, etc.
Going from one representation to the other
Finally, you need trigonometry formulas to go back and forth between representations. The easier transformation is from polar to cartesian :
x=r*cos(w)
y=r*sin(w)
Since cos²+sin²=1, pythagoras, and so on, you can see that x² + y² = r²cos²(w) + r²sin²(w) = r², thus to get r, use :
r=sqrt(x²+y²)
And finally to get the angle, we use cos/sin = tan where tan is another trigonometry function. From y/x = r sin(w) / (r cos(w)) = tan(w), you get :
w = arctan(y/x) [mod π]
tan is a function modulo π, instead of 2π. arctan simply means the inverse of the function tan, and is sometimes written tan^-1 or atan.
By inverting the tangent, you get a result betweeen -π/2 and π/2 (or -90° and 90°) : you need to eventually add π to your result. This is done for angles between [π/2,π] and [-π,π/2] ([90,180] and [-180,-90]). These values are caracterized by the sign of the cos : since x = r cos(w) you know x is negative on all these angles. Try looking where these angles are on your graph, it's really straightforward. Thus :
w = arctan(y/x) + (π if x < 0)
Finally, you can not divide by x if it is 0. In that corner case, you have
if y > 0, w = π/2
if y < 0, w = -π/2
What is seems is that given polar coordinates, you want to obtain Cartesian coordinates from this. It's some simple mathematics and should be easy to do.
to convert polar(r, O) coordinates to cartesian(x, y) coordinates
x = r * cos(O)
y = r * sin(O)
where O is theta, not zero
reference: http://www.mathsisfun.com/polar-cartesian-coordinates.html
I am programming a raycasting engine.
The starting position of a ray is given by the position of the player who is standing inside a 2D-grid.
When casting a ray into a direction, I have to determine the grids that the ray is intersecting.
(The in-depth description of the concept is here: http://www.permadi.com/tutorial/raycast/rayc7.html)
There is a small inaccuracy which causes some trouble. I believe that the problem is caused by an incorrect calculation of the grid steps.
However I lack the mathematical understanding to fix that problem.
Problem description:
When the ray is heading to the left, the grid intersection step size is slightly different than the step size when it's heading to the right.
(Why do I even care about this?: It's causing the problem that some horizontal grid intersections are further away from the player than vertical grid intersections when vertical and horizontal intersections are close to each other, specifically in corners. Since I am using different textures for vertical intersections, the look of horizontal walls are ruined, because a vertical texture is used on small parts of the wall, even though it's an horizontal wall.)
Is this problem caused by a flaw in my algorithm? This is how I calculate the first horizontal grid intersection and the grid stepsize:
Find first grid intersection:
if (current_angle > 180) {
first_grid_horizontal_y = ((int)p.pos_y / Field::width) * Field::width + Field::width;
} else {
first_grid_horizontal_y = ((int)p.pos_y / Field::width) * Field::width - 1;
}
first_grid_horizontal_x = p.pos_x + (p.pos_y - first_grid_horizontal_y) / tan( 180 - current_angle);
Calculate the step size:
if (current_angle > 180) {
grid_stepsize_horizontal_y = Field::width;
grid_stepsize_horizontal_x = Field::width / tan(current_angle - 180);
} else {
grid_stepsize_horizontal_y = -Field::width;
grid_stepsize_horizontal_x = Field::width / tan(180 - current_angle);
}
As you can see I am always using "180 - current angle" to determine the direction of the x-value. Does this cause the inaccurancy? Do I have to differentiate more between angles?
Trigonometric functions work with radians, not degrees. So
tan(180 - current_angle)
should look like
tan(Math.Pi - current_angle)
Note that it is equal to
- tan(current_angle)
If your current_angle is in degrees that:
current_angle_radians = current_angle_degrees * Math.Pi / 180
I think your inaccuracy comes from subracting 1 when going upwards.
The idea behind this is probably that you want to get the index of the last pixel of a block, but that is inneccessary: You are doing floating-point math here and the y value of the next horizontal intersection should represent the line between the grid cells. If you go downward, it represents to uppermost coordinate of a cell; if you go upwards it represents the lowermost coordinate.
(Aside: (int) y / w will round towards zero and will thus only work for non-negative numbers. You might consider using floor(x / w).)
This is quite complicated to explain, so I will do my best, sorry if there is anything I missed out, let me know and I will rectify it.
My question is, I have been tasked to draw this shape,
(source: learnersdictionary.com)
This is to be done using C++ to write code that will calculate the points on this shape.
Important details.
User Input - Centre Point (X, Y), number of points to be shown, Font Size (influences radius)
Output - List of co-ordinates on the shape.
The overall aim once I have the points is to put them into a graph on Excel and it will hopefully draw it for me, at the user inputted size!
I know that the maximum Radius is 165mm and the minimum is 35mm. I have decided that my base Font Size shall be 20. I then did some thinking and came up with the equation.
Radius = (Chosen Font Size/20)*130. This is just an estimation, I realise it probably not right, but I thought it could work at least as a template.
I then decided that I should create two different circles, with two different centre points, then link them together to create the shape. I thought that the INSIDE line will have to have a larger Radius and a centre point further along the X-Axis (Y staying constant), as then it could cut into the outside line.
So I defined 2nd Centre point as (X+4, Y). (Again, just estimation, thought it doesn't really matter how far apart they are).
I then decided Radius 2 = (Chosen Font Size/20)*165 (max radius)
So, I have my 2 Radii, and two centre points.
Now to calculate the points on the circles, I am really struggling. I decided the best way to do it would be to create an increment (here is template)
for(int i=0; i<=n; i++) //where 'n' is users chosen number of points
{
//Equation for X point
//Equation for Y Point
cout<<"("<<X<<","<<Y<<")"<<endl;
}
Now, for the life of me, I cannot figure out an equation to calculate the points. I have found equations that involve angles, but as I do not have any, I'm struggling.
I am, in essence, trying to calculate Point 'P' here, except all the way round the circle.
(source: tutorvista.com)
Another point I am thinking may be a problem is imposing limits on the values calculated to only display the values that are on the shape.? Not sure how to chose limits exactly other than to make the outside line a full Half Circle so I have a maximum radius?
So. Does anyone have any hints/tips/links they can share with me on how to proceed exactly?
Thanks again, any problems with the question, sorry will do my best to rectify if you let me know.
Cheers
UPDATE;
R1 = (Font/20)*130;
R2 = (Font/20)*165;
for(X1=0; X1<=n; X1++)
{
Y1 = ((2*Y)+(pow(((4*((pow((X1-X), 2)))+(pow(R1, 2)))), 0.5)))/2;
Y2 = ((2*Y)-(pow(((4*((pow((X1-X), 2)))+(pow(R1, 2)))), 0.5)))/2;
cout<<"("<<X1<<","<<Y1<<")";
cout<<"("<<X1<<","<<Y2<<")";
}
Opinion?
As per Code-Guru's comments on the question, the inner circle looks more like a half circle than the outer. Use the equation in Code-Guru's answer to calculate the points for the inner circle. Then, have a look at this question for how to calculate the radius of a circle which intersects your circle, given the distance (which you can set arbitrarily) and the points of intersection (which you know, because it's a half circle). From this you can draw the outer arc for any given distance, and all you need to do is vary the distance until you produce a shape that you're happy with.
This question may help you to apply Code-Guru's equation.
The equation of a circle is
(x - h)^2 + (y - k)^2 = r^2
With a little bit of algebra, you can iterate x over the range from h to h+r incrementing by some appropriate delta and calculate the two corresponding values of y. This will draw a complete circle.
The next step is to find the x-coordinate for the intersection of the two circles (assuming that the moon shape is defined by two appropriate circles). Again, some algebra and a pencil and paper will help.
More details:
To draw a circle without using polar coordinates and trig, you can do something like this:
for x in h-r to h+r increment by delta
calculate both y coordinates
To calculate the y-coordinates, you need to solve the equation of a circle for y. The easiest way to do this is to transform it into a quadratic equation of the form A*y^2+B*y+C=0 and use the quadratic equation:
(x - h)^2 + (y - k)^2 = r^2
(x - h)^2 + (y - k)^2 - r^2 = 0
(y^2 - 2*k*y + k^2) + (x - h)^2 - r^2 = 0
y^2 - 2*k*y + (k^2 + (x - h)^2 - r^2) = 0
So we have
A = 1
B = -2*k
C = k^2 + (x - h)^2 - r^2
Now plug these into the quadratic equation and chug out the two y-values for each x value in the for loop. (Most likely, you will want to do the calculations in a separate function -- or functions.)
As you can see this is pretty messy. Doing this with trigonometry and angles will be much cleaner.
More thoughts:
Even though there are no angles in the user input described in the question, there is no intrinsic reason why you cannot use them during calculations (unless you have a specific requirement otherwise, say because your teacher told you not to). With that said, using polar coordinates makes this much easier. For a complete circle you can do something like this:
for theta = 0 to 2*PI increment by delta
x = r * cos(theta)
y = r * sin(theta)
To draw an arc, rather than a full circle, you simply change the limits for theta in the for loop. For example, the left-half of the circle goes from PI/2 to 3*PI/2.