I need a datastructure to find all segments falling in a rectangle (in C#, even if it is not the main problem).
For exemple, the segment [(0,0) , (10,10)] must be in the rectangle begining at (5,5) with the size (1,1).
I tried kdtree, but it returns only segment when one of his point is exactly in the rectangle. It doesn't see the segment as a continous line.
What sort of datastructure do I need to do this search efficiently?
I search but didn't find anything for this case, even if it seems very standard!
Problem Dimension : 6000 segments, average 20 line segment are in the rectangle
Sort of duplicate :
How to best store lines in a kd-tree
Data structure for fast line queries?
For non-point objects (line segment is not a point object) R-tree may be better suited than kd-tree. If you have a small number of line segments (<50), storing them in a vector and always test all of them may be the fastest way.
I don't know a standard algorithm for your problem, but the first idea that came to my mind is to represent rectangles as 4 lines and if you have many line segments - find intersections of all line segments and lines (by sorting line segments and lines and then "merging" their coordinates).
So It is N*log(N)+M*Log(M), where N - number of line segments, M - number of squares.
After that you can find line segments that intersects the square as (SquareHorizLine1Intersections UNION SquareHorizLine2Intersections) INTERSECT (SquareVerticalLine1Intersections UNION SquareVerticalLine2Intersections)
Again set intersections and unitions have a complexity of K*LogK, where K is the size of set. Or even simply log(K) if you use data structure "Binomial heap" (there is also Fibonacci heap, that could be even more efficient).
So this algorithm looks kike having N*log(N) complexity. I hope that helps... Or you need better?
You could try parametrizing the extended line segments as (y-intercept, slope) or similar. The space of extended lines intersecting a given line segment forms a shape in (y-intercept, slope) space that you can query against as if the lines were points. (Handle vertical lines as a special case.)
Take the union of the lines intersecting any of the rect's bordering line segments and then filter out segments that don't actually cross the rect when they aren't extended.
// we will intersect against three of the rect's borders (the 4th's results are redundant)
borders = {(TopLeft, TopRight), (TopRight, BottomRight), (BottomRight, BottomLeft)}
// each border forms a shape in (y, slope) space defined by two intersecting half spaces
// we query the line space using something standard like kd-trees
lines1 = Union(borders.ForEach(LineSpace.Inside(ShapeOfSegmentInIntersectSpace(?border))))
// now filter out lines that don't cross the rect when extended
// since we already know they intersect when extended, the check is pretty simple
lines2 = lines1.Where(?line.BoundingRect.Intersects(rect))
Related
I am trying to find a way to get the line (two points in 3D space) of the intersection between two rectangles.
I ran into this question: Intersection between two rectangles in 3D
But this is not my issue. In that question, the rectangle is treated as only the bounds (the perimeter), while I am looking for the rectangle as a whole (think about a picture frame vs the picture itself).
I've figured out that, in every case, there will either be an intersection line (two points), or no intersection at all. If the intersection was just on the borders, therefore just a point, it can be treated as no intersection in my case.
My scenario is that one of these rectangle represents a "static" surface, which cannot move or change. The other one represents a "dynamic" surface, which I have to adapt to avoid crossing
Example:
Once I obtain p1 and p2, which are points in the 3D space, my goal is to modify the Dynamic rectangle into a 3d polygon, which will no longer cross the static rectangle, like this:
So you can see why "edge intersections" are irrelevant to my situation. I am turning "real" intersections into edge intersections, so any edge intersection doesn't require me to do anything with it.
I am only looking for a formula, starting with two sets of 4 points (the rectangles), that would give me the two points of the line of their intersection, or would tell me that there is no (relevant) intersection.
Every formula I've found on this site or others doesn't fit my needs, or doesn't let me input arbitrary rectangles (for example, I can't fix my problem with a formula that uses planes or that treats a rectangle as simply 4 lines)
I am, of course, trying to code it (in C#), therefore any code answer is a great help, but I am confident that even a math-only answer would suffice for me to produce the code from it, therefore I will accept an answer that is only composed of pseudo-code or straight up mathematical formulas, provided they are either simple enough or explained well enough for me to understand what is happening.
If you are OK with just algorithm rather than full code here is a sketch:
Build 2 planes from the rectangles (any 3 points will do as in this answer)
Find the intersection line I of those 2 planes as in this answer or find out that the planes are parallel so there is no intersection
Find the intersections of the I line with the lines containing all sides of the rectangles as in this answer
Check whether some points found in the previous step lie inside the corresponding sides of the rectangles (line segments). This step potentially can be merged with the previous one, but I put it separately for simplicity. Now you potentially have 0, 1 or 2 segments that represent the intersections of the I line with your two rectangles (note that here point is treated as an edge case of a segment where both ends are the same). If you don't have 2 segments, there is no intersection of the rectangles.
Assuming at the previous step you found 2 segments (one in each rectangle) on the line I, you just need to find their intersection and it will be your answer (again, empty means no intersection).
I want to search areas enclosed by a complex path.
Input
var path = new []{new Point(X1,Y1),new Point(X2,Y2),new Point(X3,Y3),new Point(X4,Y4),new Point(X5,Y5)};
I want it.
(X2,Y2)-(X3,Y3)-(Xa,Ya)
(Xa,Ya)-(X4,Y4)-(Xb,Yb)
How do I search it?
there's a few steps to what you are doing here. You need to:
Perform line intersections between each of the line segments to find where your intersection points are.
Create centroid points at the average of the Start point A, Start point B, Collision point, (and then for each permutation of Start Point [A, B], end point [A, B] and collision point.
Perform a dotproduct or point in tris check to verify that your centroid point is inside a triangle and if so:
Calculate the area of the Tri using the standard area in triangle formula (I think it's 1/2 base times height off the top of my head)
Good luck!
you can use this approach in a few steps:
Break the lines where they meet other lines and create a new list of lines (or paths)
Eliminate lines with one free end (if a line doesn't meet another one at the start or the end)
Start from one point and go through lines to the other points and try to find the correct route back to the start point (if you pass a duplicate point, the route is wrong)
Save newly found closed route
Eliminate all points that are inside the newly found area and connected lines
Eliminate all points with just two connected lines and also these two lines
Eliminate all lines that their center point is inside the newly found area
Go to step 3 until there left no line in the list
Now you have a list of enclosed areas
Note: you can easily find a good approach for the calculation of the intersection point of two lines, the area of the enclosed part, the center point of a line, and Checking that a point is inside an area
Best wishes,
I have about 10'000 polygons consisting of lat/long points.
Each polygon has metadata about what it is and what it contains.
All polygons can intersect each other.
What I want to do now is to get all polygons that contain a specifc lat/long point.
What would be an efficient way to do that?
Is there a faster way than going through all the polygons and checking them all separately?
Is there some kind of intelligent indexing datastructure, where I can store the polygons so I can do such a query in C#?
First, if you do not already do this, you should give each polygon a bounding box. This is the minimum rectangle that completely contains the polygon. You assign the bounding box when you create the polygon and resize the BB if you resize the polygon.
It is quick to check whether each polygon might contain the point:
// untested code
// in scope is pointOfInterest
var candidatePolygons = from poly in allPolygons
where poly.BoundingBox.contains(pointOfInterest)
select poly;
. . .
// method of BoundingBox class
public Boolean contains(LatLongClass pointOfInterest)
{
return pointOfInterest.Longitude.AsX >= this.minX &&
pointOfInterest.Longitude.AsX <= this.maxX &&
pointOfInterest.Latitude.AsY >= this.minY &&
pointOfInterest.Latitude.AsY <= this.maxY;
}
For each polygon, this proves that the polygon definitely does not contain the point, and it should quickly eliminate most of your polygons.
There will be some polygons in which the bounding box does contain the point but the polygon does not. These will have to be checked using the slower method, but at least you are not using the slower method on all of them.
Also, if you are not already, use PLinq (from poly in allPolygons.AsParallel() ) for both filters (bounding box and the slower test).
See http://msdn.microsoft.com/en-us/library/dd997425.aspx and How exactly does AsParallel work?
Along the lines of Sinatr's comment, if you pick an axis (probably the x axis) by which to order your polygon collection (say orderby boundingbox.MinX), then you can SkipWhile pointOfInterest.Longitude.AsX < poly.boudingBox.MinX. This should give you a performance boost depending on where the pointOfInterest falls within your dataset's footprint.
One last thing: Not only should you have a bounding box for each polygon, but consider having a bounding box for your whole dataset. This way, if a caller sends you a point that is way outside of your footprint, you can eliminate all of your polygons with the very fast check against the big "global" bounding box with a not-noticable addition in processing time for in-footprint points.
I want to compress many non-overlapping rectangles into larger rectangles When they are adjacent.
Pseudo-code for my current algorithm:
do
compress horizontally using sweep and prune
compress horizontal output vertically using sweep and prune
while (this output is small than previous output)
Here's a link to sweep and prune.
This is working well, but I want to know if there are approaches which result in fewer rectangles output. I figure there's more sophisticated than what I'm doing now.
So it sounds like your problem is that you have small gaps between the rectangles preventing them from being collected together into a single piece. If you have access to the source code for the sweep and prune method, you can add a buffer to the "overlap" test, but I think it would be more optimal to consider using an R-Tree. This will index the rectangular spaces without messing with limits on gaps etc.
R-Tree Wiki
Here is a relevant paper by Sellis et. al. describing the R+ tree:
http://citeseerx.ist.psu.edu/viewdoc/download;jsessionid=50ECCC47148D9121A4B39EC1220D9FB2?doi=10.1.1.45.3272&rep=rep1&type=pdf
here is a C# implementation of an R-Tree
http://sourceforge.net/projects/cspatialindexrt/
[Edit - After Comment 1]
So let me see if I can capture the current problem.
Rectangles are joined in passes of horizontal/vertical adjacency tests.
Rectangles are only joined if the adjacent boundary for both is equal.
The intermediate result of any join must also form a valid rectangle.
The result is non-optimal because the sequence of joining.
I think you're actually looking for the minimum dissection into rectangles of a rectilinear polygon. The first step would be to join ALL the touching rectangles together, regardless of whether they form a rectangle or not. I think you are getting caught up in problems with the intermediate stages of each step in the process also needing to be complete rectangle deconstructions, leading to a sub-optimal result. If you merge them together into a single rectilinear polygon, you can use graph theory mechanisms.
You can check out Graph-Theoretic Solutions
to Computational Geometry Problems by David Eppstein
Or investigate Algorithm for finding the fewest rectangles to cover a set of rectangles without overlapping by Gareth Rees
I have to be able to set a random location for a waypoint for a flight sim. The maths challenge is straightforward:
"To find a single random location within a quadrangle, where there's an equal chance of the point being at any location."
Visually like this:
An example ABCD quadrangle is:
A:[21417.78 37105.97]
B:[38197.32 24009.74]
C:[1364.19 2455.54]
D:[1227.77 37378.81]
Thanks in advance for any help you can provide. :-)
EDIT
Thanks all for your replies. I'll be taking a look at this at the weekend and will award the accepted answer then. BTW I should have mentioned that the quadrangle can be CONVEX OR CONCAVE. Sry 'bout dat.
Split your quadrangle into two triangles and then use this excellent SO answer to quickly find a random point in one of them.
Update:
Borrowing this great link from Akusete on picking a random point in a triangle.
(from MathWorld - A Wolfram Web Resource: wolfram.com)
Given a triangle with one vertex at
the origin and the others at positions v1
and v2, pick
(from MathWorld - A Wolfram Web Resource: wolfram.com)
where A1
and A2 are uniform
variates in the interval [0,1] , which gives
points uniformly distributed in a
quadrilateral (left figure). The
points not in the triangle interior
can then either be discarded, or
transformed into the corresponding
point inside the triangle (right
figure).
I believe there are two suitable ways to solve this problem.
The first mentioned by other posters is to find the smallest bounding box that encloses the rectangle, then generate points in that box until you find a point which lies inside the rectangle.
Find Bounding box (x,y,width, height)
Pick Random Point x1,y1 with ranges [x to x+width] and [y to y+height]
while (x1 or y1 is no inside the quadrangle){
Select new x1,y1
}
Assuming your quadrangle area is Q and the bounding box is A, the probability that you would need to generate N pairs of points is 1-(Q/A)^N, which approaches 0 inverse exponentially.
I would reccommend the above approach, espesially in two dimensions. It is very fast to generate the points and test.
If you wanted a gaurentee of termination, then you can create an algorithm to only generate points within the quadrangle (easy) but you must ensure the probablity distribution of the points are even thoughout the quadrangle.
http://mathworld.wolfram.com/TrianglePointPicking.html
Gives a very good explination
The "brute force" approach is simply to loop through until you have a valid coordinate. In pseudocode:
left = min(pa.x, pb.x, pc.x, pd.x)
right = max(pa.x, pb.x, pc.x, pd.x)
bottom = min(pa.y, pb.y, pc.y, pd.y)
top = max(pa.y, pb.y, pc.y, pd.y)
do {
x = left + fmod(rand, right-left)
y = bottom + fmod(rand, top-bottom)
} while (!isin(x, y, pa, pb, pc, pd));
You can use a stock function pulled from the net for "isin". I realize that this isn't the fastest-executing thing in the world, but I think it'll work.
So, this time tackling how to figure out if a point is within the quad:
The four edges can be expressed as lines in y = mx + b form. Check if the point is above or below each of the four lines, and taken together you can figure out if it's inside or outside.
Are you allowed to just repeatedly try anywhere within the rectangle which bounds the quadrangle, until you get something within the quad? Might this even be faster than some fancy algorithm to ensure that you pick something within the quad?
Incidentally, in that problem statement, I think the use of the word "find" is confusing. You can't really find a random value that satisfies a condition; the randomizer just gives it to you. What you're trying to do is set parameters on the randomizer to give you values matching certain criteria.
I would divide your quadrangle into multiple figures, where each figure is a regular polygon with one side (or both sides) parallel to one of the axes. For eg, for the figure above, I would first find the maximum rectangle that fits inside the quadrangle, the rectangle has to be parallel to the X/Y axes. Then in the remaining area, I would fit triangles, such triangles will be adjacent to each side of the rectangle.
then it is simple to write a function:
1) get a figure at random.
2) find a random point in the figure.
If the figure chosen in #1 is a rectangle, it should be pretty easy to find a random point in it. The tricky part is to write a routine which can find a random point inside the triangle
You may randomly create points in a bound-in-box only stopping after you find one that it's inside your polygon.
So:
Find the box that contains all the points of your polygon.
Create a random point inside the bounds of the previously box found. Use random functions to generate x and y values.
Check if that point is inside the polygon (See how here or here)
If that point is inside the polygon stop, you're done, if not go to step 2
So, it depends on how you want your distribution.
If you want the points randomly sampled in your 2d view space, then Jacob's answer is great. If you want the points to be sort of like a perspective view (in your example image, more density in top right than bottom left), then you can use bilinear interpolation.
Bilinear interpolation is pretty easy. Generate two random numbers s and t in the range [0..1]. Then if your input points are p0,p1,p2,p3 the bilinear interpolation is:
bilerp(s,t) = t*(s*p3+(1-s)*p2) + (1-t)*(s*p1+(1-s)*p0)
The main difference is whether you want your distribution to be uniform in your 2d space (Jacob's method) or uniform in parameter space.
This is an interesting problem and there's probably as really interesting answer, but in case you just want it to work, let me offer you something simple.
Here's the algorithm:
Pick a random point that is within the rectangle that bounds the quadrangle.
If it is not within the quadrangle (or whatever shape), repeat.
Profit!
edit
I updated the first step to mention the bounding box, per Bart K.'s suggestion.