Searching area enclosed by a path - c#

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,

Related

Get Intersection line between two rectangles in 3D

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).

Determine when a polygon is closed by a new side

My program has a List<Vector3> of unique points (A, B, C, ...) which are created each time a user draws a unique line (1, 2, 3, ...). Lines are stored in a List<int> where every two ints are the indices of each point to form a single line. No two lines can have the same two points, no points can occupy the same position, and stray lines are allowed.
Diagram
Points: {A, B, C, D, E} //Each letter represents a 2d or 3d position
Sides: {0,1,1,2,1,3,3,4,4,2} //(Each int is an index in Points, every pair is a side)
I am trying to find an efficient way of determining when a new line (Green, 5) closes a polygon with any number of sides. I have a way of doing this: iterating through each line connected to each side of the new line(and all subsequent lines) until they share a point (D).
Completed Polygon
My only problem here is that the more sides a polygon has, I need to do exponentially more checks (Every two additional sides on the polygon causes me to check one layer deeper on all attached sides).
Is there a way to reduce the number of checks I need to do in order to close the polygon?
Not exactly the same as Cycles in an Undirected Graph. This knows that at least one cycle is present and connected to a given side, and is looking for only the smallest cycle possible connected to that side. Other sides are irrelevant and it should avoid them.
It all depends on the level of optimization you need. For simple pictures (some what like < 10 - 100k lines) you can get away with running a BFS every time.
High level algorithm:
First you need something to store the graph using one of the Graph representation. Then whenever the user draws a line you take either of the two points and do a BFS on that point.
If you can reach the same point with your BFS and the path length is > 2 then you have a polygon.
The catch would be that since the graph is bidirectional you need to be careful when walking thru it. Do not re-visit nodes that you have already visited.

How do I find points around a partial circle intersected by line segment

I am working on an obstacle avoidance solution for my square grid pathfinding project. I begin by performing an A* search to find the "long" path. Next, I take my unit's current position and iterate the "long" path until I no longer have line of sight, this produces the "short" path (unit's position->furthest position w/ LoS). When I reach the end of the "short" path, I repeat to find another "short" path until reaching the goal.
I want to modify my short path to add additional points unaligned to the grid if there are obstacles in the way. I find the obstacles intersecting the short path by their center position & radius, and my plan is to add additional points that go around the circumference of these obstacles. The points must be added on the side of the circle that the line intersects so that the path doesn't end up going all the way around the other side.
Here are some screenshots to explain a little better:
http://puu.sh/xFHw5/0e8f32da7a.png
http://puu.sh/xFHwU/04a4b1fe27.png
http://puu.sh/xFHxk/56f3051cc5.png
http://puu.sh/xFHxO/fcc6151a02.png
You can find path consisting of tangents to circle from both sides and arc connecting points where tangents touch the circle. As variant - use point of intersection of tangents, in this case path will contain only two straight segments.

What is the best datastructure for line segments searching?

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))

How to find a random point in a quadrangle?

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.

Categories

Resources