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).
Related
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 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))
I'm thinking of creating a program to let me play or solve slitherlink puzzles, like on krazydad.com. It consists of tiles of 4, 5, 6, 7 and 8 sides. All but the seven sided tiles seem to have sides with the same length, with the sides between two seven sided tiles (and therefore connecting five-sided tiles to 4 sided tiles) having sides of approximately 70% of the normal length. As you can see in the picture below, octagons are surrounded by alternating pentagons and hexagons. These are attached to others a by the far sides of the hexagons. Attached to the tips of the pentagons are smaller lines connecting to squares connecting to other groups. Around the squares are then formed seven-sided figures with two short sides. I think the outer edge is defined by just omitting tiles that are too far away from the center.
For a data structure I think I need a graph connecting all nodes. I can let the user click to place a solid line on the closest link, and I can check for loops or too many lines entering a node fairly easily. I'll also need to create tiles and associate lines to them, with inner lines being assigned to both tiles, but treated as one line.
As for setting it up, I am thinking of manually figuring out the points and defining the minimal set of repeated tiles (1 8, 4 5, 4 6, 4 7 and 1 4), then placing them next to each other. When placing, I would check for existing close points to each one I'm placing and combine them if found. Then I would need to check for duplicate lines and merge them as well.
Is there an easier or cleaner way to A) generate the tiling or B) merge the nodes and links when doing my tiling?
some observations that might help:
if you join the centres of neighbouring polygons you have a delaunay triangulation (1).
the dual (2) of the delaunay triangulation is the graph above (with slightly different edge lengths, but you can adjust that if necessary)
there's a discussion here (3) of how to generate graphs from delaunay triangulations
so, putting that together, you could:
generate the centres of the tiles (see below)
construct the delaunay triangulation from the tile centres (by joining neigbours).
find the dual to get the graph you want (the process of finding the dual should be supported by a good graph library)
to generate the pattern of tile centres, take the minimal set and start with the centre 8. for each 90 degree rotation about there, add the (rotated) minimal set (plus an 8 in addition to the one you're rotating around), removing duplicates. then do the same on the 8s that you have added (either recurse or use a stack).
once you have the centres, i'm not sure what the best way to connect neighbours would be - you want some efficient way of generating a set of candidates. but it's not a hard problem, just fiddly (a "fancy" solution would be quadtree or spatial hashes, but just a crude binning would probably be enough).
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.
This seems non-trivial (it gets asked quite a lot on various forums), but I absolutely need this as a building block for a more complex algorithm.
Input: 2 polygons (A and B) in 2D, given as a list of edges [(x0, y0, x1, y2), ...] each. The points are represented by pairs of doubles. I do not know if they are given clockwise, counter-clockwise or in any direction at all. I do know that they are not necessarily convex.
Output: 3 polygons representing A, B and the intersecting polygon AB. Either of which may be an empty (?) polygon, e.g. null.
Hint for optimization: These polygons represent room and floor boundaries. So the room boundary will normally fully intersect with the floor boundary, unless it belongs to another floor on the same plane (argh!).
I'm kind of hoping someone has already done this in c# and will let me use their strategy/code, as what I have found so far on this problem is rather daunting.
EDIT: So it seems I'm not entirely chicken for feiling faint at the prospect of doing this. I would like to restate the desired output here, as this is a special case and might make computation simpler:
Output: First polygon minus all the intersecting bits, intersection polygons (plural is ok). I'm not really interested in the second polygon, just its intersection with the first.
EDIT2: I am currently using the GPC (General Polygon Clipper) library that makes this really easy!
Arash Partow's FastGEO library contains implementations of many interesting algorithms in computational geometry. Polygon intersection is one of them. It's written in Pascal, but it's only implementing math so it's pretty readable. Note that you will certainly need to preprocess your edges a little, to get them into clockwise or counterclockwise order.
ETA: But really, the best way to do this is to not do this. Find another way to approach your problem that doesn't involve arbitrary polygon intersections.
If you are programming in .NET Framework, you may want to take a look at SqlGeometry class available in .NET assemblies shipped as Microsoft SQL Server System CLR Types
The SqlGeometry class provides STIntersection method
SqlGeometry g1 = SqlGeometry.Parse("POLYGON ((...))");
SqlGeometry g2 = SqlGeometry.Parse("POLYGON ((...))");
SqlGeometry intersection = g1.STIntersection(g2);
What I think you should do
Do not attempt to do this yourself if you can possibly help it. Instead, use one of the many available polygon intersection algorithms that already exist.
I was strongly considering the following codebase on the strength of their demonstration code and the fact that they mentioned their handling of most/all of the weird cases. You would need to donate an amount (of you/your company's choice) if you use it commercially, but it's worth it to get a robust version of this kind of code.
http://www.cs.man.ac.uk/~toby/gpc/
What I actually did was to use a polygon-intersection algorithm that is part of the Java2D libraries. You can possibly find something similar in MS's own C# libraries to use.
There are other options out there as well; look for "polygon clipper" or "polygon clipping", since the same basic algorithms that handle polygon intersection also tend to be usable for the general clipping cases.
Once you actually have a polygon clipping library, you just need to subtract polygon B from polygon A to get your first piece of output, and intersect polygons A and B to get your second piece of output.
How to roll your own, for the hopelessly masochistic
When I was considering rolling my own, I found the Weiler-Atherton algorithm to have the most potential for general polygon-cutting. I used the following as a reference:
http://cs1.bradley.edu/public/jcm/weileratherton.html
http://en.wikipedia.org/wiki/Weiler-Atherton
The details, as they say, are too dense to include here, but I have no doubt that you'll be able to find references on Weiler-Atherton for years to come. Essentially, you split all the points into those that are entering the final polygon or exiting the final polygon, then you form a graph out of all the points, and then walk the graph in the appropriate directions in order to extract all the polygon pieces you want. By changing the way you define and treat the "entering" and "exiting" polygons, you can achieve several possible polygon intersections (AND, OR, XOR, etc.).
It's actually fairly implementable, but like with any computational geometry code, the devil is in the degeneracies.
You may also want to have a look at the NetTopologySuite or even try importing it into Sql server 2008 & it's spatial tools.
Clipper is an open source freeware polygon clipping library (written in Delphi and C++) that does exactly what you're asking - http://sourceforge.net/projects/polyclipping/
In my testing, Clipper is both significantly faster and far less prone to error than GPC (see more detailed comparisons here - http://www.angusj.com/delphi/clipper.php#features). Also, while there's source code for both Delphi and C++, the Clipper library also includes a compiled DLL to make it very easy to use the clipping functions in other (Windows) languages too.
A polygon is fully described by an ordered list of points (P1, P2, ..., Pn). The edges are (P1 - P2), (P2 - P3), ..., (Pn - P1). If you have two polygons A and B which overlaps, there will be a point An (from the list on points describing polygon A) which lies within the area surrounded by polygon B or vice versa (a point of B lies in A). If no such point is found, then the polygons does not overlap. If such a point is found (i.e. Ai) check the adjacent points of the polygon A(i-1) and A(i+1). Repeat until you find a point outside the area or all points are checked (then the first polygon lies completly within the second polygon). If you found a point outside then you can calculate the crossing point. Find the corresponding edge of polygon B and follow it with resersed roles = now check if the points of polygon B lie within polygon A. This way you can build a list of points which describe the overlapping polygon. If needed you should check if the polygons are identical, (P1, P2, P3) === (P2, P3, P1).
This is just an idea and there maybe better ways. If you find a working and tested solution I would recommend that you use it...
narozed
Try to use GIS tools for that, such as ArcObjects, TopologySuite, GEOS, OGR, etc. I'm not sure if all of these distributions are availuable to .net, but they all do the same.
This academic paper explains how to do this.
If you dare to take a look to other people's GPL C++ code, you can see how do they do it in Inkscape:
http://bazaar.launchpad.net/~inkscape.dev/inkscape/trunk/view/head:/src/2geom/shape.cpp (line 126)