I'm making game in Unity. There's a rectangle intersected by a straight line. I need to find which part of rect is bigger and how much. Do anyone knows algorithm how to do this?
Rect and lines are set with points (4 for rect and 2 for lines)
The implicit equation of the line is
S(x,y) = (x - x0) (y1 - y0) - (y - y0) (x1 - x0) = 0
When you plug the coordinates of a corner, the sign of S(x, y) tells you on what side of the line you are. And better, if you evaluate Sa and Sb at two corners and they have different signs, the intersection is at a fraction Sa / (Sa - Sb) along the side ab.
Now, process all four edges in turn in clockwise order. For every edge, keep the starting corner if positive and keep the intersection if any. In the end, you'll get 0 to 5 points defining the convex polygon which is in the positive domain.
The area is found by the shoelace formula.
Determine if the shaded area is purely a triangle, if so, calculate the area of that triangle (a * b) / 2 , this would solve the right hand diagram.
For the left hand diagram, treat the area as a triangle and a rectangle. Compute the shaded area by adding together the triangles area and the rectangles area.
HTH
Related
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.)
Given some random w and h and 4 coordinates(x1, y1)...(x4, y4) check if x, y counters are inside those 4 coordinates.
I am trying to fill the space between those 4 coordinates, they will usually form a rectangle shape, but at different rotations.
At the moment I have a nested for loop to move over my "canvas", but I am failing to find a way to check if my counters are inside the coordinates.
I have looked at line drawing algorithms to build this, but so far no luck.
Can someone point me to some resources please.
To check if a point is inside a triangle, take the orientation
(y2 - y1)*(x3 - x2) - (y3 - y2)*(x2 - x1)
the sign is zero if the points are linear, otherwise it is negative for counter-clockwise and positive for clockwise. If orientation ABC, ABD, and ACD is the same, then A is in the triangle BCD.
So we can first check our convex hull which will either be a line, a triangle, or a quad. If it is a triangle, we can easily test for further points inside. It it is a convex quad, the test also works, but we have to add an extra point.
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 have an array of latitude/longitude coordinate pairs that represent a polygon. I'm trying to determine the total area within that polygon. How would I go about doing that in Ruby?
Here's an example array of the polygon:
[[37.7663613767094, -122.452969210084], [37.7674219449606, -122.444718340349], [37.7701838510542, -122.445330289514], [37.7709974013834, -122.439159589248], [37.7700761930893, -122.438861402472], [37.7703501163684, -122.436868738421], [37.7712650571321, -122.437078116573], [37.7736056746515, -122.437533130227], [37.7714671036087, -122.453964210266], [37.7663613767094, -122.452969210084]]
It probably doesn't matter that much on the language. You can make use of the formula mentioned in here for calculating the area of a polygon:
http://mathworld.wolfram.com/PolygonArea.html
Assuming your points are (x1, y1) (x2, y2) .. (xn, yn) and they enclose a small area:
Area = 0.5 * (x1 * y2 - x2 * y1 + x2 * y3 - x3 * y2 ..... + xn * y1 - x1 * yn)
Note: This won't work for larger areas, for which you need to use more complex method to calculate the area, which involves angular co-ordinates. But, this does the job for small areas, which can be assumed to be planar.
Edit:
To get area in sq miles, you can do the following, from there, convert to whatever units you want.
areaInSqMiles = Area * (60 * 60 * 1.15 * 1.15)
language independent solution:
GIVEN: a polygon can ALWAYS be composed by n-2 triangles that do not overlap (n = number of points OR sides). 1 triangle = 3 sided polygon = 1 triangle; 1 square = 4 sided polygon = 2 triangles; etc ad nauseam QED
therefore, a polygon can be reduced by "chopping off" triangles and the total area will be the sum of the areas of these triangles. try it with a piece of paper and scissors, it is best if you can visualize the process before following.
if you take any 3 consecutive points in a polygons path and create a triangle with these points, you will have one and only one of three possible scenarios:
resulting triangle is completely inside original polygon
resulting triangle is totally outside original polygon
resulting triangle is partially contained in original polygon
we are interested only in cases that fall in the first option (totally contained).
every time we find one of these, we chop it off, calculate its area (easy peasy, wont explain formula here) and make a new polygon with one less side (equivalent to polygon with this triangle chopped off). until we have only one triangle left.
how to implement this programatically:
create an array of points. run the array making triangles from points x, x+1 and x+2. transform each triangle from a shape to an area and intersect it with area created from polygon. IF the resulting intersection is identical to the original triangle, then said triangle is totally contained in polygon and can be chopped off. remove x+1 from the array and start again from x=0. otherwise, move to next point x+1 in array.
additionally if you are looking to integrate with mappping and are starting from geopoints, you must convert from geopoints to screenpoints. this requires deciding a modelling and formula for earths shape (though we tend to think of the earth as a sphere, it is actually an irregular ovoid (eggshape), with dents. there are many models out there, for further info wiki.
You can use this library which wraps GEOS (a C geospatial library itself a port of the JTS).
https://github.com/dark-panda/ffi-geos
This library can handle the calculations in coordinate space and takes care of the approximations.
Depending on how much accuracy you need I would project the data first to an appropriate projection (not Mercator). Then calculate your area
There is an awesome example on how to multiply verticies. Essentially exactly what you would like to do!!
http://www.wikihow.com/Calculate-the-Area-of-a-Polygon
Some techniques for this include integration (divide the polygon into latitudinal strips and integrate. You can also project onto a flat surface and calculate that area.
It does not need to be very accurate. Does anyone know a good way to do this?
any help is much appreciated.
When you say “it does not need to be very accurate” you don’t say how inaccurate a solution you’re prepared to accept. Also, you don’t say how big the geographic region under consideration is likely to be. These two criteria make a big difference to the kind of approach that needs to be taken.
With a small regions (a few kilometres, say), a flat approximation may be good enough (for example, the Mercator projection) and some of the other responses tell you how to do that. With larger regions you have to take the Earth’s sphericity into account. And if you want inaccuracy less than a percent or so, you need to take the eccentricity of Earth into account.
I’m going to assume for the purposes of this answer that a spherical approximation is good enough, and that your points are at similar enough altitudes that we don’t need to worry about their heights.
You can convert a geographical point (ψ, λ) to Cartesian Earth-centred coordinates using the transformation
(ψ, λ) → (a cos(ψ) cos(λ), a cos(ψ) sin(λ), a sin(ψ))
where a is the mean radius of the Earth (6,371 km). So let’s suppose that the two points that define your line are p₀ and p₁; then the shortest line through p₀ and p₁ is a great circle, which defines a plane that slices the Earth into two halves, with normal n = p₀ × p₁.
Now we need to find the border of the circular region. Suppose the centre of this region is at c and that the surface radius of the region is s. Then the straight-line radius of the region is r = a sin(s/a). We’ll also need the true centre of the circular region, c’ = c cos(s/a). (This point is buried deep underground!)
We’d like to intersect the two circles and solve for the points of intersection. Unfortunately, because of numerical imprecision, the chances are that this procedure will never find any solutions because the imprecise circles will miss each other in 3 dimensions. So I suggest the following procedure: intersect the planes of the two circles, getting the dotted line shown below (unless c’ × n = 0 in which case the two circles are parallel and either c’ = o, in which case they are coincident, or else they do not intersect). Then intersect the line with the circular region.
This two-step procedure reduces the problem to two dimensions, and guarantees that a solution will be found even if numerical imprecision makes the two circles miss in 3 dimensions.
If you need more accuracy than this, then you might need to use geodetic coordinates on a reference ellipsoid such as WGS 1984.
I'd say find the closest point on the line to the center of the circle, then determine whether that point is within the circle (i.e. the distance in question is less than or equal to the circle's radius).
Outline for solving the problem: assume the Earth is a sphere of radius one centered at the origin. Convert all three lat, lon points to 3D coordinates. The two points of the line plus the origin define a plane; intersect that plane with the sphere of radius d centered on the other point. If there is no plane-sphere intersection, then the answer is the line does not intersect the region. If there is a plane-sphere intersection, then the problem is simplified to intersecting the circular region defined by the plane-sphere intersection with the shortest circular arc on the plane going between the end points of the line and centered at the origin. This is a straightforward 2D problem if you convert to the coordinate system of the plane.
This question is too vague to be answered precisely. What do you mean by
a line form by 2 geo points (lat, lon)
This can be either a great circle going through them (also called orthodrome) or it a can be a linear function of spherical coordinates (loxodrome).
BTW, I assume your circle is a circle on the surface of the sphere, right?
Assuming line is formed by points (x1, y1) and (x2, y2), and circle has radius r with origin (0,0):
Calculate:
Incidence = r^2 * [(x2 - x1)^2 + (y2 - y1)^2] - (x1 * y2 - x2 * y1)^2
Then, from the value of Incidence, we can determine the following:
Incidence < 0: No intersection
Incidence = 0: Tangent (intersection at 1 point on circle)
Incidence > 0: Intersection
It's likely your circle is not at the origin (0,0), so to fix this, just add the origin coordinates from your line coordinates in the equation above. So, if the circle is at (x3, y3), x1 in the above equation would become x1 + x3. Likewise, y1 would be y1 + y3, and the same goes for x2 and y2.
For more info check out this link