I am building a road editor where one can drag predefined road segments together and combine them to a connected road. One of those segments is a right curve.
The curve is drawn as SVG (using D3 arc path function) and has two handles to change the radius and the length directly within the SVG (small black circle changes length and small black square changes the radius). I use a d3 drag handler on the handles.
To calculate the new central angle I do as follows:
get YOffset from center point of the arc
flip YOffset (to match screen y and math)
get corresponding x value with Pythagoras (x = Math.sqrt(r^2 - YOffset^2))
get the respective central angle (Math.PI / 2 - Math.atan2(YOffset, x);
This will only work if the arc starts at PI/2 like in the figure. If I add further arcs with arbitrary start angles (see next figure, red arc), my solution wont work.
I'm looking for a general solution so it will work for any arc regardless of its start angle.
To me it seems this is not much of a programming problem, but of math. What I understand is: given a start point (x₁, y₁), an end pont(x₂, y₂) and a radius r, what is the angle α?
You can compute the distance d between the two points. Half its length is the far leg of a right triangle with r as its hypothenuse. d/2r is the sinus of the near angle; double that and you have the angle between the end points.
(And, having α expressed in radians, the path length is simply α * r.)
Related
For a project I want to do a very simple Pythagoras calculation in C++. An object is equiped with an IMU sensor that gives either a Quaternion rotation or Euler angles. What I want to know is the opposite sides of the triangle underneath the object.:
I want to know these sides of the triangle for both the X and Y axis (black arrows):
This is pretty much very simple, except for the fact that the object can rotate. When the object is rotated I still want to use the X and Y axis in world space (black arrows), but when yawing the Euler angles of the IMU provide me with pitch and roll, which are in local space (red arrows):
In what way can I still get the world space angles (black arrows) while yawing, to be able to calculate my simple Pythagoras calculation? If I can't get them, is there a way to calculate the opposite sides I want using Quaternions?
We can do the calculation by taking into account the Euler angles in the following order -
Pitch
First of all, as you change the roll of the sensor, the sensor "ray" sweeps out a plane inclined to the horizon at angle pitch. We need to first calculate the closest distance between (i) the line of intersection between the plane and the ground, and (ii) the point directly below the sensor on the ground. This is given by d = h * tan(pitch).
Roll
Next we need to do another trigonometric step. As before the roll sweeps through the plane. The offset distance along the axis perpendicular to the line joining (i) and (ii) is given by f = h / cos(pitch) * tan(roll). This gives the intersection point on the ground to be (d, f)
Yaw
Previously, we considered a frame in which the yaw was zero. We now need to rotate this intersection point around the Z-axis by yaw. Thus the final intersection point is given by (x, y) = (d * cos(yaw) - f * sin(yaw), d * sin(yaw) + f * cos(yaw)). You can calculate the "space angle" you want by taking atan2(y, x).
I have a circle I want to divide up in to a number of segments all defined by X and Y coordinates. How to I test to see if a point (X, Y) is in a particular segment?
A code example would be preferable.
You don't need to use trigonometry for this (and in general, trigonometry should be avoided whenever possible... it leads to too many precision, domain, and around-the-corner problems).
To determine whether a point P is counter-clockwise of another point A (in the sense of being in the half-plane defined by the left side of a directed line going through the origin and then through A), you can examine the sign of the result of Ax*Py - Ay*Px. This is generally known as the "perpendicular dot product", and is the same as the Z coordinate of the 3D cross product.
If there are two points A and B (with B defining the CCW-most extent) defining a sector, and the sector is less than half the circle, any point which is CCW of A and CW of B can be classified as in that sector.
That leaves only a sector which is more than half of the circle. Obviously, a given set of points can only define at most one such sector. There's clever things you can do with angle bisection, but the easiest approach is probably just to classify points as in that sector if you can't classify them as being in any other sector.
Oh, forgot to mention -- determining the order of the points for the purposes of pairing them up for sectors. Not to go against my previous advice, but the most straightforward thing here is just to sort them by their atan2 (not atan... never ever use atan).
Use the polar coordinate system centred at the centre of the circle, and examine the angular coordinate (φ in the Wikipedia article).
What exactly you do with φ depends on how your segments are defined. For example, if you have n equal segments that start at 0 radians, floor(φ * n / (2 * π)) will give you the segment number.
Your segment is defined by two intersections between the circle and a line. You just have to know if:
The angle between the center of your circle and your point is between
the angles formed by the two previous points and the center.
the point is in the circle (the length from this point to the center is smaller than the radius)
from what side is the point compared to the line (it must be beyond the line).
Remark
In geometry, a circular segment (symbol: ⌓) is a region of a circle
which is "cut off" from the rest of the circle by a secant or a chord.
Here is a segment:
If x & y are not already relative to the center of the circle, subtract the coordinates of the center of the circle:
x -= circle.x
y -= circle.y
Use atan2 to get the angle of the point about the origin of the circle:
angle = atan2(y, x)
This angle is negative for points below the x-axis, so adjust to always be positive:
if (angle < 0) angle += 2 * pi
Assuming your segments are equally spaced, use this formula to get the index of the segment:
segment = floor((angle * numSegments) / (2 * pi))
If you find the result is referring to a segment on the opposite side of the circle to what you want, you might have to do y = -y in the beginning or a segment = (numSegments - 1) - segment at the end to flip it round the right way, but it should basically work.
I've just implemented collision detection using SAT and this article as reference to my implementation. The detection is working as expected but I need to know where both rectangles are colliding.
I need to find the center of the intersection, the black point on the image above (but I don't have the intersection area neither). I've found some articles about this but they all involve avoiding the overlap or some kind of velocity, I don't need this.
The information I've about the rectangles are the four points that represents them, the upper right, upper left, lower right and lower left coordinates. I'm trying to find an algorithm that can give me the intersection of these points.
I just need to put a image on top of it. Like two cars crashed so I put an image on top of the collision center. Any ideas?
There is another way of doing this: finding the center of mass of the collision area by sampling points.
Create the following function:
bool IsPointInsideRectangle(Rectangle r, Point p);
Define a search rectangle as:
TopLeft = (MIN(x), MAX(y))
TopRight = (MAX(x), MAX(y))
LowerLeft = (MIN(x), MIN(y))
LowerRight = (MAX(x), MIN(y))
Where x and y are the coordinates of both rectangles.
You will now define a step for dividing the search area like a mesh. I suggest you use AVG(W,H)/2 where W and H are the width and height of the search area.
Then, you iterate on the mesh points finding for each one if it is inside the collition area:
IsPointInsideRectangle(rectangle1, point) AND IsPointInsideRectangle(rectangle2, point)
Define:
Xi : the ith partition of the mesh in X axis.
CXi: the count of mesh points that are inside the collision area for Xi.
Then:
And you can do the same thing with Y off course. Here is an ilustrative example of this approach:
You need to do the intersection of the boundaries of the boxes using the line to line intersection equation/algorithm.
http://en.wikipedia.org/wiki/Line-line_intersection
Once you have the points that cross you might be ok with the average of those points or the center given a particular direction possibly. The middle is a little vague in the question.
Edit: also in addition to this you need to work out if any of the corners of either of the two rectangles are inside the other (this should be easy enough to work out, even from the intersections). This should be added in with the intersections when calculating the "average" center point.
This one's tricky because irregular polygons have no defined center. Since your polygons are (in the case of rectangles) guaranteed to be convex, you can probably find the corners of the polygon that comprises the collision (which can include corners of the original shapes or intersections of the edges) and average them to get ... something. It will probably be vaguely close to where you would expect the "center" to be, and for regular polygons it would probably match exactly, but whether it would mean anything mathematically is a bit of a different story.
I've been fiddling mathematically and come up with the following, which solves the smoothness problem when points appear and disappear (as can happen when the movement of a hitbox causes a rectangle to become a triangle or vice versa). Without this bit of extra, adding and removing corners will cause the centroid to jump.
Here, take this fooplot.
The plot illustrates 2 rectangles, R and B (for Red and Blue). The intersection sweeps out an area G (for Green). The Unweighted and Weighted Centers (both Purple) are calculated via the following methods:
(0.225, -0.45): Average of corners of G
(0.2077, -0.473): Average of weighted corners of G
A weighted corner of a polygon is defined as the coordinates of the corner, weighted by the sin of the angle of the corner.
This polygon has two 90 degree angles, one 59.03 degree angle, and one 120.96 degree angle. (Both of the non-right angles have the same sine, sin(Ɵ) = 0.8574929...
The coordinates of the weighted center are thus:
( (sin(Ɵ) * (0.3 + 0.6) + 1 - 1) / (2 + 2 * sin(Ɵ)), // x
(sin(Ɵ) * (1.3 - 1.6) + 0 - 1.5) / (2 + 2 * sin(Ɵ)) ) // y
= (0.2077, -0.473)
With the provided example, the difference isn't very noticeable, but if the 4gon were much closer to a 3gon, there would be a significant deviation.
If you don't need to know the actual coordinates of the region, you could make two CALayers whose frames are the rectangles, and use one to mask the other. Then, if you set an image in the one being masked, it will only show up in the area where they overlap.
Can someone provide me an algorithm to draw points on arc? I know the start-point, end-point and radius. I need to show points on the arc made by this information(start-point, end-point and radius).
See the image for more details
I have Start-Point (x,y), End-Point(a,b). I have to calculate equally distance 5 points on arc. Is it possible?
The standard algorithm for this is the Midpoint circle algorithm (sometimes called Breshenham's circle algorithm).
Note that your arc specification is incomplete. There are generally two arcs of the same radius joining two given points, one for the center on each side of the line joining the points. Also, as #In silico points out, the radius can be no smaller than half the distance between the points.
The means of specifying an arc is similar to that used in SVG, which has some detailed implementation notes which are too long to copy here. For circular arcs, the x and y radii are equal so the x axis angle is not important. As Ted Hopp noted, you need a flag to indicate which direction the arc is drawn in ( in SVG called large-arc-flag ).
Once you have the centre and angles of start and end of the arc, divide the angle into six and use the sin/cos of this angle to plot the five intermediate points.
This may be a little hard to describe since I don't have a sample. I'm trying to find a math function or full 3d function in php or a similar language that can help me with the following effect:
imagine if you were to take a flat sheet or paper and glue it on a glass of water. It wouldn't be flat any more. It would have a curve, and one of its sides might end up being slightly hidden.
Anyone can refer me to a good library or resource on the web where such functions can be found?
Lets say the center of your paper is x=0, and your cylinder is vertical along the y-axis. Your x-coordinate on the paper could be equated to an arc length on the surface of the cylinder. Arc length (s) is equal to the angle (in radians) times the radius. Your radius is given, so you can compute the angle from the arc length and radius. Angle = Arc Length / Radius. Since you now have the angle and the radius, you can compute the new x-offset, which would be (radius * cos(angle)). So your mapping functions would be:
new_x = radius * cos(old_x/radius)
new_y = old_y; //y-coordinate doesn't change
new_z = radius * sin(old_x/radius);
You'll have to enforce boundaries (keep x on the paper, and make sure it's not more than half the circumference (x must be less than or equal to PI*r). Also, watch the signs... especially the z-coordinate, which will depend on whether your coordinate system is right-handed or left-handed, or where you imagine the paper starting on the cylindar (back or front). Finally, you can use standard matrix transforms to move and position the paper/cylinder in 3D space once you have the warped coordinates.