Given is a 2D are with the polygons. I need to find out the polygons visible in a perpendicular line of sight from the a given line segment lying within that area. e.g.
Further,
What can be the optimizations when the polygons have only vertical and horizontal edges.
I'd suggest the following ...
Rotate the problem so your 'line of sight' segment is aligned to the x axis.
Find the (axis aligned) bounding rectangle (BR) of each polygon.
Sort the polygons using the Y coordinate of the bottom edge of each BR
Create a clipping 'range buffer' to mark the portions of the viewing segment that will be no longer visible.
For each polygon C (current) in the sorted list do ...
Use C's left and right bounds as its initial clipping range.
Trim C's clipping range with the range already marked as clipped in the 'range buffer'.
Now for each subsequent polygon S of a similar depth (ie where S's BR bottom edge starts below C's BR top edge) ...
loop to next S if it doesn't overlap horizontally with C
determine if S is overlapping from the left or right (eg by comparing the BR horizontal midpoints of S and C). If S overlaps from the right and S's left-most vertex is below C's right-most vertex, then truncate C's clipping range accordingly. (Likewise if S overlaps from the left.)
If the residual clipping range isn't empty, then at least part of C is visible from your viewing segment. Now add C's residual clipping range to the clipping 'range buffer'.
Related
I have with me the polygon coordinates and the line coordinates for the horizontal and vertical lines? The intention is to find all the intersecting grid (rectangles) existing outside of the polygons?
Starting point is this :
(step-2)The blue and the red lines are formed by stretching each and every coordinate of the polygons in horiztonal and vertical direction until the nearest intersection.
I can find the intersections for sure but defining rectangles from it seems to be tricky.
Add grid lines on the border.
For every grid line, horizontal or vertical, list all the intersection points on it in left-to-right or top-to-bottom order.
Foe every intersection point, store its nearest neighbor along a grid line to the right, and its nearest neighbor along a grid line to the bottom.
For every intersection point A, if it has both neighbors, proceed to the right neighbor B until it has a bottom neighbor. Also, proceed to the bottom neighbor C until it has a right neighbor. The three points A, B, and C are three corners of a rectangle.
If necessary, for each rectangle, detect whether it is inside or outside one of the given polygons.
I'd go with a two-pass sweep-line algorithm.
The first pass would compute how far the horizontal lines extend to the right: sweep left to right keeping track of the active horizontal lines in a set sorted by y.
When a vertical line V is encountered, for each active horizontal line H with y coordinate between V endpoints:
extend H up to the current x coordinate (note: keep the original unextended endpoints for the next pass).
remove H from the active set.
When a horizontal line left end is encountered, add it to the active set.
In the end, extend the unterminated active lines to infinity.
The second pass would compute how far the horizontal lines extend to the left, and emit the rectangles on the go: sweep right to left, again keeping track of the active horizontal lines sorted by y.
When a vertical line V is encountered:
find the two nearest active horizontal lines H1, H2 that bound V from the top and the bottom: a line H bounds V if V.x is contained within the original unextended endpoints of H.
generate all the rectangles between the active horizontal lines between H1 and H2.
remove all the active lines between H1 and H2 with y coordinates contained within V endpoints (i.e. those that V terminates on the left).
When a horizontal line extended-to-the-right end point is encountered, add that line to the active set.
Points from (0,0) to (R,C) in the cartesian plane are colored r, g or b. Make a triangle using these points such that-
a) All three vertices are of different colors.
b) At least one side of triangle is parallel to either of the axes.
c) Area of the triangle is maximum possible.
Output the maximum possible area.
Constraints : 1<=R<=1000 , 1<=C<=1000
Can someone please let me know the approach to this question?
The area of a triangle is 1/2 * base * height. So if one side of the triangle is parallel to the
x-axis, then the base of the triangle is formed by two colors on the same row (spread as far apart as possible), and the third color should be on the row that's farthest from the base. Hence, you can preprocess the data to find:
the top-most and bottom-most row for each color
the left-most and right-most column for each color on every row
Then for every row, you have twelve possibilities for forming a triangle, e.g.
left-most-red, right-most-blue, top-most green
left-most-red, right-most-blue, bottom-most green
left-most-red, right-most-green, top-most blue
...
And of course, there's the corresponding process for triangles with one edge parallel to the y-axis.
Thus, the problem can be solved in O(R*C) time, where most of the time is spent in the preprocessing.
Given a polygon S and a point p that lies outside S, imagine an ant that can only follow a straight line towards or away from p.
For some shapes (Fig. 1), there is a choice of p such that the ant can move unobstructed in at least one of the two possibilities: towards (T) p, or away (A) from it. This condition corresponds to any ray cast from p intersecting the perimeter of S exactly 0 or 2 times.
However, for the same shape (Fig. 2) there may also be points that lead to blocked (B) regions, where the ant will bump into the polygon whichever direction it tries to move in. For yet other shapes (Fig. 3) there may be no choice of p that leads to no blocked regions. Having blocked regions corresponds to some rays cast from p that intersect the perimeter of S more than 2 times.
Is there an algorithm that determines whether a p exists that satisfies the condition for some given polygon S? If such points exist, can it also determine the region that contains them?
Find all concave corners of the polygon obstacle. For each corner, extend its two edges infinitely. The sector between these two rays, and also (as Nico Schertler pointed out) the point-reflected region of this sector, define where the point must be so that the obstacle does not hide the corner form the point's rays.
In the example with the L-shaped obstacle, there is one concave corner. The sector between its neighbouring edges (top right) and its point-reflection (bottom left), form a region (indicated in red), where the point must be.
In the example with the U-shaped obstacle, there are two concave corners, and the two corresponding regions (red and blue) have an overlap (purple). The point must be in this purple region.
In the example with the S-shaped obstacle, there are two overlapping regions (purple). The point must be in one of these two regions.
In the example with the H-shaped obstacle, the red and blue region have an overlap (purple) above the horizontal beam of the H, the blue and green region have an overlap (teal) to the right of the horizontal beam, the green and yellow region have an overlap (lime) below the horizontal beam, and the yellow and red regions have an overlap (orange) to the left of the beam; however, there is no overall overlap between the four regions, and no place where the point can be that will satisfy the constraints.
The problem is to redraw a self-intersecting 2D polygon, whose border is always a separation line between its interior and its exterior and completely crosses itself in some points (that is, in those points, the polygon interior switches the side of the border, from left to right or vice versa).
What is the simplest algorithm that can do that?
The initial polygon (left) and the redrawn one (right):
.
I added another, a little more complicated example of an initial polygon, that is still very simple (it has only one self-intersection vertex) in this third picture where the polygon interior is filled (points A,B,C,D,E appear in alphabetic order initially when drawing the polygon border).
What you are asking isn't that simple.
You can use a sweepline procedure. The general principle is as follows.
When you draw an horizontal line across the polygon, it meets an even number of edges. Sorting the intersections from left to right, and linking them in pairs, you obtain interior segments.
If you do this for all positions of the horizontal, you will decompose the polygon in a number of monotone chains, i.e. polylines always going down.
When the polygon is simple, the chains appear in pairs at a vertex, disappear in pairs at another, and live their own lifes. But when the polygon is crossed, the chains can cross each other. This can be detected by the fact that from one position of the horizontal to the next, the ordering of intersections change.
Now you have to fix that by "uncrossing" the chains, which is done by splitting the edges at the intersection point.
I can't develop more here, try and lookup "sweepline algorithm".
I'm struggling to find a rock solid solution to detecting collisions between a circle and a circle segment. Imagine a Field of View cone for a game enemy, with the circles representing objects of interest.
The diagram at the bottom is something I drew to try and work out some possible cases, but i'm sure there are more.
I understand how to quickly exlude extreme cases, I discard any targets that don't collide with the entire circle, and any cases where the center of the main circle is within the target circle are automatically true (E in the diagram).
I'm struggling to find a good way to check the rest of the cases. I've tried comparing distances between circle centers and the end points of the segments outer lines, and i've tried working out the angle of the center of the target circle from the center of the main circle and determining whether that is within the segment, but neither way seems to catch all cases.
Specifically it seems to go funky if the target circle is close to the center but not touching it (somewhere between E and B below), or if the segment is narrower than the target circle (so that the center is within the segment but both edges are outside it).
Is there a reliable method for doing this?
Extra info: The segment is described by position P, orientation O (whose magnitude is the circle radius), and a view size, S.
My most successful attempt to date involved determining the angles of the vectors ca1 and ca2, and checking if either of them lies between the angles of vectors a1 and a2. This works for some cases as explained above, but not situations where the target circle is larger than the segment.
Edit 2
After implementing the best suggestion from below, there is still a false positive which I am unsure how best to eliminate. See the pink diagram below. The circle in the lower right is reporting as colliding with the segment because it's bounds overlap both half spaces and the main circle.
Final Edit
After discovering another edge case (4th image), i've settled on an approach which combines the two top answers from below and seems to cover all bases. I'll describe it here for the sake of those who follow.
First exclude anything that fails a quick circle-to-circle test.
Then test for collision between the circle and the two outer lines of the segment. If it touches either, return true.
Finally, do a couple of point-to-halfspace tests using the center of the circle and the two outer lines (as described by Gareth below). If it passes both of those it's in, otherwise return false.
A. Check if it is intersecting the whole cirlce.
B. Check if it is intersecting either of the straight segment lines.
C. If not, check if the angle between the circle centres lies in the angular range of the segment (dot product is good for this).
Intersection requires A && (B || C)
A circular segment (with central angle less than 180°) is the intersection of three figures: a circle, and two half-planes:
So a figure intersects the circular segment only if it intersects all three of these figures. [That's only if but not if; see below.]
Circle/circle intersection is easy (compare the distance between their centres with the sum of their radii).
For circle/half-plane intersection, represent the half-plane in the form p · n ≤ k (where p is the point to be tested, n is a unit vector that's normal to the line defining the half-plane, and k is a constant). Then a circle with centre x and radius r intersects the half-plane if x · n ≤ k + r.
(If you need to handle a circular segment with central angle greater than 180°, split it into two segments with central angle less than 180°. If I understand your problem description correctly, you won't need to do this, since your field of view will always be less than 180°, but it's worth mentioning.)
Edited to add: as pointed out by beeglebug, a circle can intersect all three figures without intersecting their intersection. Oops. But I believe that this can only happen when the circle is behind the centre of the segment, as in the diagram below, and in this case we can apply the separating axis test for convex figures.
The separating axis theorem says that two convex figures fail to intersect if there exists a line such that one figure falls entirely on one side of the line, and the other figure on the other.
If any separating axis exists in this case, then the axis that's perpendicular to the line between the centre of the circle and the centre of the segment is a separating axis (as shown).
Let the centre of the segment be at the origin, let the circle have centre x and radius r, and let the two half-planes have (outward) normals n₁ and n₂. The circle is "behind" the segment if
x · n₁ > 0 and x · n₂ > 0
and the axis separates it from the segment if
|x| > r