I have a question about how to remove some "unnecessary" coordinates from a "maps.txt" file using segment line, projection vector or other method.
Path Created on Google Maps:
Map1
Total of 275 coordinates, extracted from the ".KML" file of Google Maps.
Map1_2
Map2
When I do it manually it stays that way (Map2), with 9 coordinates.
I have a file called "maps.txt" where its lines, with coordinates, are in this format:
Obs: A coordinate on each line: latitude, longitude.
-37.2012600, -59.8404600
-37.2000200, -59.8419600
-37.1985300, -59.8439200
-37.1970600, -59.8458500
-37.1959100, -59.8473500
-37.1957800, -59.8475200
-37.1948600, -59.8486900
-37.1939500, -59.8498600
-37.1931400, -59.8509400
-37.1928400, -59.8513100
-37.1926700, -59.8515000
-37.1924600, -59.8517200
-37.1922600, -59.8519200
Is there any way for a code to read my file "maps.txt" and do the line segment, vector projection, point distance calculation using a radius of 100 meters?
In case the code would "remove the line / unnecessary coordinate" from the file "maps.txt", leaving it this way (just an example):
-37.2012600, -59.8404600
-37.1948600, -59.8486900
-37.1922600, -59.8519200
In Python, C, C ++ or another language.
I hope I have been clear and thank you in advance for any help.
Thank you (:
I'll try to explain better.
In the following figure I have 3 coordinates (1, 2 and 3).
The coordinate "1" has a radius within 100m with respect to the "2" coordinate, but from "1" to "3" I have a value greater than 100m, ie in this case the coordinate "1", "2" "and" 3 "in my text file" maps.txt ".
Example1
In the following figure from example 2, I would need only the coordinates "1" and "3" in the file "maps.txt".
Example2
Update:
Here's a script that converts KML to GPX: https://gist.github.com/timabell/8791116
And here's a Python script that seems like it'll do what you want (for GPX files): https://wiki.openstreetmap.org/wiki/User:Travelling_salesman/gpx_reduce
Previous answer:
I don't know how far you're asking us to take our answers; this problem is slightly complex, so here's some pseudocode for starters:
Overall algorithm:
Vector from point 1 to 3. Check distance of point 2 from this vector. (Assuming threshold is okay)
Vector from point 1 to 4. Check distance of points 2 and 3 from this vector. (Assuming threshold is okay)
Vector from point 1 to 5. Check distance of points 2, 3, and 4 from this vector. (Assuming threshold is bad)
First vector is determined: it's from point 1 to 4. Second vector starts at point 4.
Vector from point 4 to 6. Check distance of point 5 from this vector.
Vector from point 4 to 7. Check distance of points 5 and 6 from this vector.
...
Distance of point from vector:
At this point, we need to make a decision:
If we want this to be (quite) exact, we have to find a line that is perpendicular to our line and goes through this point, and find the intersection of these two lines. Then, we calculate the distance using the haversine formula between the intersection and the point. (Unless we sometimes have longer distances between coordinates, I don't think we need this.)
If we don't care too much about exactness, we use the following formula to calculate the "distance", and then "experimentally" find a good threshold value that works for us. (This threshold value is just some float number that we use when checking the distance. If it's above the threshold value, we start a new line.)
https://en.wikipedia.org/wiki/Distance_from_a_point_to_a_line#Line_defined_by_two_points
(Where (x0, y0) is the point we're investigating, and the line goes through (x1, y1) and (x2, y2).)
Related
So I have a bezier curve >
Now, I would like to get a y point, value every says, 0.01 value on x-axis.
As far as I know, there is no method to "find Y given X" using bezier.
So I have to subdivide it into flat straight chunks and then get... "somehow" nearest chunk value as an approximation?
So my question is, how can I... "equally" subdivide the bezier curve so that chunk distance is more equal on... x-axis?
Right now the chunk distancing that I get is quite... "random" using https://en.wikipedia.org/wiki/B%C3%A9zier_curve as my current algo.
Regards
Dariusz
As far as I know, there is no method to "find Y given X" using bezier.
Then you probably need to look for "finding Y given X" a bit more =) https://pomax.github.io/bezierinfo/#yforx
As for the result you want, with regularly spaced intervals based on distance along the curve is the general problem of reparameterizing the curve for distance rather than time., and it's a hard problem for quadratic, and literally impossible problem for higher order Beziers.
So instead of trying to do that, what we typically do is just build a lookup table by sampling the curve, storing those "t maps to x/y and distance d along the curve", and then we use that combined with interpolation to get good-enough approximate coordinates (e.g. sub-sub-pixel accurate) rather than mathematically perfect coordinates. https://pomax.github.io/bezierinfo/#tracing
I have two dataframes. One contains a column of Polygons, taken from an image of polygon shapes. Each polygon has a set of coordinates. This dataframe also has a "segment-id" column. I have another dataframe, containing a column of Points, also with coordinates. These Points represent pixels from the same image of Polygon shapes, and therefore have the same coordinate system. I want to give every Point the "segment-id" of the Polygon which contains it. Every Polygon contains at least one Point.
Currently, I achieve this by using a nested for loop:
for i, row in enumerate(point_df.itertuples(), 0):
point = pixel_df.at[i, 'geometry']
for j in range(len(polygon_df)):
polygon = polygon_df.iat[j, 0]
if polygon.contains(point):
pixel_df.at[i, 'segment_id'] = polygon_df.at[j, 'segment_id']
else:
pass
This is extremely slow. For 100 Points, it takes around 10 seconds. I need a faster way of doing this. I have tried using apply but it is still super slow.
Hope someone can help me out, thanks very much.
For fast "is point inside polygon":
Preparation: In the code that obtains the data describing the polygons; using all the vertices, find the minimum and maximum y-coord, and minimum and maximum x-coord; and store that with the polygon's data.
1) Using the point's coords and the polygon's "minimum and maximum x and y" (pre-determined during preparation); do a "bounding box" test. This is just a fast way to find out if the point is definitely not inside the polygon (so you can skip the more expensive steps most of the time).
2) Set a "yes/no" flag to "no"
3) For each edge in the polygon; determine if a horizontal line passing through the point would intersect with the edge, and if it does determine the x-coord of the intersection. If the x-coord of the intersection is less than the point's x-coord, toggle (with NOT) the "yes/no" flag. Ignore "horizontal line passes through a vertex" during this step.
4) For each vertex, compare its y-coord with the point's y-coord. If they're the same you need to look at both edges coming from that vertex to determine if the edge's vertices are in the same y direction. If the edge's vertices are in the same y direction (if the edges form a 'V' shape or upside-down 'V' shape) ignore the vertex. Otherwise (if the edges form a '<' or '>' shape), if the vertex's x-coord is less than the point's x-coord, toggle the "yes/no" flag.
After all this is done; that "yes/no" flag will tell you if the point was in the polygon.
I'm making a program in which many weird shapes are drawn onto a canvas. Right now i'm trying to implement the last, and possebly hardest, one.
In this particular shape i need a way to find the location (on a 2d canvas) where the line hits the shape. The following image is an example of what i have right now.
The black dots are the points that a known to me (i also have the location of the center of the three open circles and the radius of these circles). Each of the three outer lines needs a line towards the center dot, ending at the point that it hits the circle. This shape can be turned 90, 180 or 270 degrees.
The shape should look something like the following:
If you need any other information, please ask me in the comments. I'm not very good at math so please be gentle, thanks!
If A and B are points forming a line, then you can describe any point on that line using coordinates:
x = t·Ax + (1−t)·Bx
y = t·Ay + (1−t)·By
0 ≤ t ≤ 1
You can also describe the circle with center M and radius r as
(x − Mx)2 + (y − My)2 = r2
So take the x and y from the equations of the line, and plug them into the equation of the circle. You obtain a quadratic equation in t. Its two solutions describe the two points of intersection between the line and circle. In your example, only one of them lies on the line segment, i.e. satisfies 0 ≤ t ≤ 1. The other describes a point on the extension of the segment past its endpoint. Take the correct value for t back to the equations of the line, and you obtain the x and y coordinates of the point of intersection.
If you don't know up front which circle you want to intersect with a given line, then intersect all three and choose the most appropriate point afterwards. Probably that is the point closest to the outside starting point of the line segment. The same goes in cases where both points of intersection lie on the segment.
I'm trying to figure out the most efficient/fast way to add a large number of convex quads (four given x,y points) into an array/list and then to check against those quads if a point is within or on the border of those quads.
I originally tried using ray casting but thought that it was a little overkill since I know that all my polygons will be quads and that they are also all convex.
currently, I am splitting each quad into two triangles that share an edge and then checking if the point is on or in each of those two triangles using their areas.
for example
Triangle ABC and test point P.
if (areaPAB + areaPAC + areaPBC == areaABC) { return true; }
This seems like it may run a little slow since I need to calculate the area of 4 different triangles to run the check and if the first triangle of the quad returns false, I have to get 4 more areas. (I include a bit of an epsilon in the check to make up for floating point errors)
I'm hoping that there is an even faster way that might involve a single check of a point against a quad rather than splitting it into two triangles.
I've attempted to reduce the number of checks by putting the polygon's into an array[,]. When adding a polygon, it checks the minimum and maximum x and y values and then using those, places the same poly into the proper array positions. When checking a point against the available polygons, it retrieves the proper list from the array of lists.
I've been searching through similar questions and I think what I'm using now may be the fastest way to figure out if a point is in a triangle, but I'm hoping that there's a better method to test against a quad that is always convex. Every polygon test I've looked up seems to be testing against a polygon that has many sides or is an irregular shape.
Thanks for taking the time to read my long winded question to what's prolly a simple problem.
I believe that fastest methods are:
1: Find mutual orientation of all vector pairs (DirectedEdge-CheckedPoint) through cross product signs. If all four signs are the same, then point is inside
Addition: for every edge
EV[i] = V[i+1] - V[i], where V[] - vertices in order
PV[i] = P - V[i]
Cross[i] = CrossProduct(EV[i], PV[i]) = EV[i].X * PV[i].Y - EV[i].Y * PV[i].X
Cross[i] value is positive, if point P lies in left semi-plane relatively to i-th edge (V[i] - V[i+1]), and negative otherwise. If all the Cross[] values are positive, then point p is inside the quad, vertices are in counter-clockwise order. f all the Cross[] values are negative, then point p is inside the quad, vertices are in clockwise order. If values have different signs, then point is outside the quad.
If quad set is the same for many point queries, then dmuir suggests to precalculate uniform line equation for every edge. Uniform line equation is a * x + b * y + c = 0. (a, b) is normal vector to edge. This equation has important property: sign of expression
(a * P.x + b * Y + c) determines semi-plane, where point P lies (as for crossproducts)
2: Split quad to 2 triangles and use vector method for each: express CheckedPoint vector in terms of basis vectors.
P = a*V1+b*V2
point is inside when a,b>=0 and their sum <=1
Both methods require about 10-15 additions, 6-10 multiplications and 2-7 comparisons (I don't consider floating point error compensation)
If you could afford to store, with each quad, the equation of each of its edges then you could save a little time over MBo's answer.
For example if you have an inward pointing normal vector N for each edge of the quad, and a constant d (which is N.p for one of the vertcies p on the edge) then a point x is in the quad if and only if N.x >= d for each edge. So thats 2 multiplications, one addition and one comparison per edge, and you'll need to perform up to 4 tests per point.This technique works for any convex polygon.
Given a starting point, a heading, a distance, and a line segment, find the first point along this heading that is the specified distance away from this line segment.
I covered two cases, but I haven't been able to cover the last one.
First case: heading away from the line. Ignore it even if the starting point is within the specified distance.
Second case: It intersects the line. I solved it using trig and triangles. Initially didn't consider the next case.
Third case: It is heading towards the line, but it does not intersect it. I think this will solve the second case as well if it's done correctly.
Three subcases:
The minimum line distance is greater than the specified distance. Ignore it.
The minimum line distance is equal to the specified distance. Found the points already.
The minimum line distance is less than the specified distance. This means there is a perpendicular line from the along the heading to an endpoint of the line segment that is less than the distance needed. This also means that on either side of this perpendicular line will be two lines of the distance needed. One is perpendicular to the heading, while the other is closest to the same endpoint and not perpendicular to the heading. Just a matter of finding those points and seeing which one is closer to the start point.
This is where I am stuck today. Drawing it up was easy, but doing the vector calc or whatever turned out tricky.
It's possible to rephrase this as:
At what time(s) is P(t) = P0 + t*v at a distance D from the line segment L((x1,y1), (x2,y2))?
v=(sin(heading), -cos(heading)) in my case.
Shoot mang your solution doesn't always work. I found a counter example:
Line Segment = (0,0) -> (0,14)
Start Point = (19, 6) # heading -159.5 or 200.5 in west/counter-clockwise
It will intersect the line at (2.952, 0.0) so I ask, where does it it come within a distance of 0.0.
The result I get is incorrect.
http://img5.imageshack.us/i/failuref.png/
How I can tell which ones will work using your solution and which ones do not work depends whether the minimum starting distance between the point and the line segment creates a perpendicular line.
If I can post another picture in the next post, I will put the successful example.
I would have liked to post some code for Sage which produced those images, but the code tags are accepting python unfortunately.
A successful result where the minimum starting distance between the point and the line segment is perpendicular to the line segment:
http://img46.imageshack.us/i/success.png/
Hi the solution I eventually came up with.
Does the ray intersect line segments that are parallel and the specified distance D away from the line segment. Just drawing a rectangle and checking the sides parallel to the line segment.
Does the ray intersect circles of radius D at each end point of the line segment.
Minimize for total unit time to find the first point along the ray that is D away from the line segment.
Possible Border case: Is the start point within D and heads away from the line? Up to the user how to handle this case.
Thanks, that works.
I found the alpha this way:
heading = 45.0*pi/180. #heading 45 degrees.
if x1 > x2: #line segment (x1,y1)<->(x2,y2)
dx = x2 - x1
dy = y2 - y1
else:
dx = x1 - x2
dy = y1 - y2
segmentHeading = atan2(dx, dy)
if heading > 0:
alpha = segmentHeading + heading
else:
alpha = -segmentHeading + heading
t = abs( (dStart - D) / -cos(alpha) ) #-cos in python, sin in C.