finding a path in a 2 dimensional plain with obstacles - algorithm

I'm trying to solve a programming task I've been given and I don't have the slightest idea how to do it.
This is the problem:
Skinny Pete is invited to a garden birthday party. He doesn’t really
like parties too much, but heard that the birthday cake is going to be
really amazing and he wouldn’t like to miss the chance to try it.
There is only one little problem. There is a sprinkler system
installed in the garden and by knowing his friends, there is a high
chance of someone turning it on as a party prank. Pete likes cake, but
really hates getting wet. Luckily he found a sketch of the garden that
has the location of the sprinklers and how far each one can sprinkle
water.
The garden looks like a rectangle that is open on one side and has the house in the opposite side.
The cake is going to be in the house.
The other two sides have fences so one can not enter through there, and the house does not have a back entrance. Pete is interested to
know if it is possible to enter the garden and get to the house
without any risk of getting wet.
For simplicity we can think that the map of the garden is in Cartesian
coordinate system.
The garden is a rectangle that has sides parallel to the axes and having its bottom left corner at the origin (0, 0).
The entrance to the garden is the left side and the the house is at the right side.
Sprinklers are represented as circles with a center and a radius. Stepping anywhere inside such a circle might get you wet.
For the purpose of this problem, and since Pete is so skinny, we can think of him as just a point travelling in the space, with real
numbers as coordinates.
Input Specifications First line of the standard input contains two
space separated integers H and W, the height and the width of the
garden.
Next line contains the number of sprinklers N. After that N lines
follow having three space separated integers each - Xi, Yi and Ri.
This a description of a sprinkler as a circle with center (Xi, Yi) and
radius Ri.
1 ≤ N ≤ 128
1 ≤ H, W ≤ 1024
0 ≤ Xi ≤ W
0 ≤ Yi ≤ H
1 ≤ Ri ≤ 1024
Output Specifications
Output a single line containing “CAKE” (without quotes) if it is
possible to get to the house without getting wet and “NO CAKE”(without
quotes) otherwise.
thanks in advance to helpers

Since you show no code and you only implicitly ask for help, I'll give a key idea and leave the mathematics and the implementation to you.
Skinny Pete can get the cake without getting wet unless there is a chain of sprinkler circles between the bottom and the top of the garden. In other words, we can assume that Pete succeeds. But look through all the circles. We see if any circle intersects the bottom edge of the garden--that is easy mathematics. If there is none, Pete really succeeds. If there is, see if there is another circle that intersects that first one, then if there is another that intersects the second, etc. Finally, you see if the last circle in this chain intersects the top edge of the garden. If there is any such chain of intersecting circles that also intersects top and bottom of the garden, poor Pete goes hungry. (Note that just one circle that intersects both top and bottom would also frustrate Pete--consider that to be a chain of one.)
Here is a diagram of the second example in your contest PDF, where you can see there is no chain of spanning circles so Pete succeeds.
And here is a diagram of the third example, where Pete fails. Note that there is a chain of four circles on the left, colored blue, that spans the garden.
Given that idea, there is an obvious O(N^2) algorithm to find all pairs of intersecting circles and an O(N) algorithm to find the circles intersecting the top and bottom sides of the garden. You could use a path-finding algorithm from graph theory to solve your problem. Think of the top and bottom sides and your circles as nodes in the graph, with two nodes connected with an edge if they intersect. You then search for a path between the nodes representing the top and bottom sides.
Good luck on figuring the mathematics, algorithm, and code.

Related

Determine if Line Segment Between Polygon Vertices is "Inside" Polygon

I'm trying to find an efficient algorithm that can check if a line between two vertices in a simple (edit: simple concave) polygon contains points that lie outside the domain of the polygon. The closest question I could find is this one: https://stackoverflow.com/a/36378838/12135804
But I'm not sure the answer is quite right. It might be, in which case if someone could clarify that would be great.
The basic idea is illustrated in the below picture:
Where I would like the red line to fail and the green line to succeed. I know one can't naively test the midpoint as that wont work in every case, but finding any point on the line outside the polygon's domain should disqualify it.
I appreciate any and all help!
Edit: Forgot to include cross-post link to mathematics stack exchange:
https://math.stackexchange.com/q/4040059/892519
Let's assume that the topmost point is A and the others are named B, C ... counter-clockwise, so we know what we're talking about.
If you take the red segment B-D, the one point in between is on the left. If you take the green segment D-F, the one point in between is on the right. Now, a more interesting segment would be B-E, where C is on the left while D is on the right.
In order to determine left and right, use the vector product. The length depends on the sin function, so if you get a value less than zero it's one side and more than zero is the other side.
After a lot of googling, I finally found this answer to a stackoverflow question from ~12 years ago: https://stackoverflow.com/a/693877/12135804
Assuming the edges in the polygon follow a certain order, a simple ccw test can be created using a line's starting point (p), the next ccw point in the polygon from that starting point as an inflection point (q), and the endpoint of the line (r). For the red line BD, the test would check if B,C,D is ccw (it's not). For the green line DF, test if D,E,F is ccw (it is!). This would work even if the points are non-consecutive. However, this would fail when the order of the red-green lines is reversed. For instance, if the red line became DB, the test would check D,E,B, which would pass the ccw test.
I think a more robust solution is to search for the pair of two edges in the concave polygon that share the endpoints of the line to test. For both pairs, calculate the angle between the two edges to the x-axis. Calculate the angle of the line to the x-axis as well. If the line is within the polygon, the line's angle should lie between the max and min of the polygon edges' angles for both endpoints.
Whether to test the obtuse or acute range of angles depends on some factors, I think. The red line's angle at B w.r.t. to the x axis would be in the obtuse bound between AB and BC, and the same is true at point C. Visually, it's plain to see the acute bound is what needs to be used for the max/min test at both points. If the baseline to compute the bounds from can be chosen logically, then it can be done.
Of course, this doesn't work if the line crosses outside the polygon on the way between both endpoints, but this does handle the degenerate case for a normal line-polygon intersection test. Assuming it works in every degenerate case, that is.
I won't mark this an answer because I can't prove it.
Edit: Well, I came back to thinking about this again and decided to search for questions similar to the angular bounding I posed above, and found this: https://stackoverflow.com/a/17497339/12135804
This answer satisfies not knowing the orientation of the lines! However, it assumes the minimum bound between A and B should be tested. This doesn't work for concave vertices, when AxB is < 0. In this case, a line attached to the vertex shared by lines A and B will return true if it's pointing outside the polygon, and conversely false if it's inside. I think flipping the result based on the sign of AxB should be enough to account for this, though. (a hunch that is verified in this related answer: https://stackoverflow.com/a/43384516/12135804)

Check if a Circle fits through a maze in non-quantized 2d space

I'm a high school student and I went to a coding competition recently and got this problem that I had no idea how to solve:
Given a maze enclosed in a 100x100 area, determine if a circle with a given radius could fit through the maze given the locations of all the walls. Walls will be defined as lines connecting two points within the space, and you will be given start and destination points for the circle. The circle must start with its center at the start point and touch the destination point for it to successfully fit through the maze. There will be a maximum of 20 walls. The radius of the circle and the locations of the walls can be "arbitrarily" precise. ("arbitrarily" for this case just means within far limits - let's say, up to a max of 10 digits after the decimal).
Here is an example. If this were the input:
Radius = 2.8
Start = (5,5), Destination = (95,95)
Walls (a wall connects each pair of points):
(20,0) to (27.5,22.6)
(27.5,22.6) to (55.1,35.5)
(55.1,35.5) to (80.3,80,4)
(80.3,80,4) to (95,63.9)
(1.7,25.8) to (17.5,53.2)
(17.5,53.2) to (56.4,69)
(56.4,69) to (67.9,90.6)
(85.6,98.94512) to (87.3,92.5)
then this (made on desmos) is what the maze would look like (the blue circle is just to show how big the circle is):
I would know how to solve the problem if it were in a quantized grid, but the exact locations of the walls and the radius of the circle can be arbitrarily precise. I've thought about using the "right-hand rule" to find a path, but I don't know how to implement that in a non-quantized space (nor am I very familiar with the method).
How would I go about solving this? Can someone point me to an algorithm, a link, some pseudocode, or just an intuition that could help me get an understanding of how I might solve this? Any help is appreciated. Thanks!
Thickennig/moving walls by r in each side like in the other answer (+1 btw) sounds simple but to code it its not trivial to do. For more info see
draw outline for some connected lines
The direction of normal in 2D is easy if dx,dy is line direction then (-dy,dx) and (dy,-dx) are normals to it ...
However I would encourage to do slower but safe and easier approach by computing the closest distance to wall for each vertex of the maze and close paths that are closer than 2r ...
Something like this:
So:
for each vertex
check all lines that does not belong to vertex path
compute perpendicular and min distance d to line and its vertexes
use the smallest d the distance can be computed easily see:
helix central axis angle
just look there for Perpendicular distance of any point P to AB so:
d = min
(
perpendicular_distance(line,vertex),
|line_vertex1-vertex|,
|line_vertex2-vertex|
)
if d<2r close the path. For example by adding a line that joins the wall its too close to tested vertex
ideally by joining tested vertex and the found closest point. Do not forget in such case to split the opposing wall line to two by the closest point so your graph algorithms still work...
As you can see this is O(n^2) instead of O(n) like in the other answer but its foul proof... enlarging polygons is not and in matters of fact its one of the hardest things in 2D geometry to code (IIRC even still open problem)...
It's quite a task and not easy to code, but here's a way that works:
Let r be the radius of the circle. That means that the center of the circle can't get within r of any obstacle.
Move the walls of your maze area in by r on each side.
Replace every wall endpoint with a circle of radius r.
Replace every wall with a rectangle of width 2r.
Now you don't need to worry about the circle -- only its center point, which must remain within the new boundaries and outside of any of the circles or rectangles you made from the walls.
Now, there is a path from the start to the end if they are in the same enclosed area. To find that out...
Cut the scene horizontally at every intersection and vertical maximum or minimum to create strips, with each strip divided into regions by a line or circular arc that passes all the way through it. A region does not connect direction to the regions to its left and right, but may connect to zero or more regions in the strips above and below it. The connections between regions form a graph.
Starting at the region containing the start point, run a BFS or DFS on this graph to see if you can reach the region containing the end point.

Understanding algorithm for finding the smallest circle enclosing points

At the moment I try to learn and understand geometric algorithms and I found the smallest-circle-problem quite interesting. I found many solutions and different algorithms including this one of which I'm not sure if it is Emo Welzl's.
However, I don't understand one specific (important) part:
You're given N points on a (XY)-Plane.
You order those points randomly
Choose 3 points and create the circle where they are on the circle boundary.
Get the next point and check if it is enclosed by the circle:
a) If it is enclosed, repeat 4 until there are no more points left.
b) If is not enclosed, create a new circle where the new point is on the circle boundary and still all other points are inside or on the circle.
Steps 1) to 4a) are simple, my problem is step 4b). How can I find this new circle? To me, it seems like this is the same problem just with a smaller (sub)set of points. (Divide-et-Impera)
I guessed I have to replace one of the 3 original points (the first 3 points, that made up the first circle) with the new point, but I'm not sure
if this really works...
From the 3 points A,B,C you can calculate the centre O of the circle: the point that is equidistant to those three. Its coordinates xO and yO are the means of xA,xB,xC and yA, yB, yC respectively.
Let's call D the 4th point, trace the circle of centre 0 and radius OD.
OD > OA (and OA=OB=OC) so A, B and C are in the circle.
EDIT
The solution I proposed above is not optimal.
I found a good explanation of Welzl's algorithm: see link
Of course, you can get his paper easily by looking on Google Scholar, but it is quite hard to read.
The basic principle is that in 4b) the circle is computed from all the possible circles having D on the boundary as well as two other points that were on the boundary before (or one point if that doesn't work and it will be diametrically opposed to D).

Programming puzzle related to binary search

I am trying to solve the following question which was part of a programming contest:
PROBLEM ID : CIELLAND
Chef Ciel develops a new island with her restaurants. In the island, Ciel intends to built N restaurants, and the coordinate of the i-th restaurant will be (xi, yi). In addition, Ciel is going to create K roads, whose location is not decided yet. Each road must be a infinitely long straight line.
Let di be the distance between the i-th restaurant and the nearest road from the i-th restaurant. Ciel would like to create K roads which minimize max(d1, d2, ..., dN). Your task is to calculate the minimal value of max(d1, d2, ..., dN).
Any ideas as to how I should approach it? Also, the contest editorial is out ( http://www.codechef.com/wiki/march-2012-cook-problem-editorials ) but I cannot understand the solution.
Any help regarding the approach to be followed would be much appreciated.
At a high level, they are reformulating the problem so that it is easier to solve. By casting in the light below, they limit the number of possible lines to consider.
Problem A: There are N circles. The center of the i-th circle is (xi,
yi) and all circles have the radii R. And let we can draw X lines such
that any circle intersects with at least one line. What is the minimal
X?
To explain further, lets rephrase the problem A in words: The restaurants are sticklers for rules and there is a rule that says all restaurants must agree on a single maximum distance from the road - this'll be R. The circle created by the restaurant and R represents the place where a line needs to intersect to satisfy this requirement. The new problem asks the minimum number of roads to do this.
If this is not possible in under K roads, then something has to change. We can't add roads per the original problem, but we can modify R. This is where binary search comes in, but we have to solve problem A first.
Now, let's consider solving Problem A. At first, the lines can be
limited to common tangents to two circles. Because if a line
intersects with some (at least 2) circles, we can move the line such
that a moved line intersects with the same circles, and the moved line
is one of common tangents. If a line intersects less than 2 circles,
it is useless (but be careful of the case N = 1). There are at most 4
lines that is common tangents to two circles, so we consider at most 2
* N * (N-1) lines.
The important part is this, we need to find lines that intersect more than one circle. At most four lines from each pair of circle need be considered, check the source codes for implementation.
The next big step is the dynamic programming which find the minimum number of lines to cover all the circles. The 'mask' is a bitmask indicating which circles have been hit as each line is considered.
This solves the problem, but now we have to convert back. Remember R? We can now binary search to find the minimum R such that X<=K. In terms of my reformulation of Problem A, its the smallest distance all restaurant will agree to and still be serviced by a road
Hope that helps, tricky, but interesting problem.
You should be able to solve it as k means clustering problem. Initially seed with a bunch of lines. Then iteratively update points assignment to lines and optimalline given points.

Is there a simple algorithm for calculating the maximum inscribed circle into a convex polygon?

I found some solutions, but they're too messy.
Yes. The Chebyshev center, x*, of a set C is the center of the largest ball that lies inside C. [Boyd, p. 416] When C is a convex set, then this problem is a convex optimization problem.
Better yet, when C is a polyhedron, then this problem becomes a linear program.
Suppose the m-sided polyhedron C is defined by a set of linear inequalities: ai^T x <= bi, for i in {1, 2, ..., m}. Then the problem becomes
maximize R
such that ai^T x + R||a|| <= bi, i in {1, 2, ..., m}
R >= 0
where the variables of minimization are R and x, and ||a|| is the Euclidean norm of a.
Perhaps these "too messy" solutions are what you actually looking for, and there are no simplier ones?
I can suggest a simple, but potentially imprecise solution, which uses numerical analysis. Assume you have a resilient ball, and you inflate it, starting from radius zero. If its center is not in the center you're looking for, then it will move, because the walls would "push" it in the proper direction, until it reaches the point, from where he can't move anywhere else. I guess, for a convex polygon, the ball will eventually move to the point where it has maximum radius.
You can write a program that emulates the process of circle inflation. Start with an arbitrary point, and "inflate" the circle until it reaches a wall. If you keep inflating it, it will move in one of the directions that don't make it any closer to the walls it already encounters. You can determine the possible ways where it could move by drawing the lines that are parallel to the walls through the center you're currently at.
In this example, the ball would move in one of the directions marked with green:
(source: coldattic.info)
Then, move your ball slightly in one of these directions (a good choice might be moving along the bisection of the angle), and repeat the step. If the new radius would be less than the one you have, retreat and decrease the pace you move it. When you'll have to make your pace less than a value of, say, 1 inch, then you've found the centre with precision of 1 in. (If you're going to draw it on a screen, precision of 0.5 pixel would be good enough, I guess).
If an imprecise solution is enough for you, this is simple enough, I guess.
Summary: It is not trivial. So it is very unlikely that it will not get messy. But there are some lecture slides which you may find useful.
Source: http://www.eggheadcafe.com/software/aspnet/30304481/finding-the-maximum-inscribed-circle-in-c.aspx
Your problem is not trivial, and there
is no C# code that does this straight
out of the box. You will have to write
your own. I found the problem
intriguing, and did some research, so
here are a few clues that may help.
First, here's an answer in "plain
English" from mathforum.org:
Link
The answer references Voronoi Diagrams
as a methodology for making the
process more efficient. In researching
Voronoi diagrams, in conjunction with
the "maximum empty circle" problem
(same problem, different name), I came
across this informative paper:
http://www.cosy.sbg.ac.at/~held/teaching/compgeo/slides/vd_slides.pdf
It was written by Martin Held, a
Computational Geometry professor at
the University of Salzberg in Austria.
Further investigation of Dr. Held's
writings yielded a couple of good
articles:
http://www.cosy.sbg.ac.at/~held/projects/vroni/vroni.html
http://www.cosy.sbg.ac.at/~held/projects/triang/triang.html
Further research into Vornoi Diagrams
yielded the following site:
http://www.voronoi.com/
This site has lots of information,
code in various languages, and links
to other resources.
Finally, here is the URL to the
Mathematics and Computational Sciences
Division of the National Institute of
Standards and Technology (U.S.), a
wealth of information and links
regarding mathematics of all sorts:
http://math.nist.gov/mcsd/
-- HTH,
Kevin Spencer Microsoft MVP
The largest inscribed circle (I'm assuming it's unique) will intersect some of the faces tangentially, and may fail to intersect others. Let's call a face "relevant" if the largest inscribed circle intersects it, and "irrelevant" otherwise.
If your convex polygon is in fact a triangle, then the problem can be solved by calculating the triangle's incenter, by intersecting angle bisectors. This may seem a trivial case, but even when
your convex polygon is complicated, the inscribed circle will always be tangent to at least three faces (proof? seems geometrically obvious), and so its center can be calculated as the incenter of three relevant faces (extended outwards to make a triangle which circumscribes the original polygon).
Here we assume that no two such faces are parallel. If two are parallel, we have to interpret the "angle bisector" of two parallel lines to mean that third parallel line between them.
This immediately suggests a rather terrible algorithm: Consider all n-choose-3 subsets of faces, find the incenters of all triangles as above, and test each circle for containment in the original polygon. Maximize among those that are legal. But this is cubic in n and we can do much better.
But it's possible instead to identify faces that are irrelevant upfront: If a face is tangent
to some inscribed circle, then there is a region of points bounded by that face and by the two angle bisectors at its endpoints, wherein the circle's center must lie. If even the circle whose center lies at the farthest tip of that triangular region is "legal" (entirely contained in the polygon), then the face itself is irrelevant, and can be removed. The two faces touching it should be extended beyond it so that they meet.
By iteratively removing faces which are irrelevant in this sense, you should be able to reduce the
polygon to a triangle, or perhaps a trapezoid, at which point the problem will be easily solved, and its solution will still lie within the original polygon.

Resources