how to detect collison between a circle and a block? [duplicate] - ruby

This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
Circle-Rectangle collision detection (intersection)
How to determine the collision of a circle with a rectangle?
I want to detect the intersection or collision of a circle with an generaly positioned block.
The block is rectangular and may be any size or rotation.
What is the math behind this?

Write one function that checks if an arbitrary segment ab intersects a circle C. Write a second function that checks if a point p is inside a circle C. Then call the 1st function four times, for the four rectangle sides, and if all those fail, call the 2nd function on one corner (to check if the rectangle is entirely inside the circle). Depending on your definition of "collision," you might have to also check if the circle is entirely inside the rectangle!
There are various ways to speed up the computations, in case you are going to invoke this millions of times in a real-time simulation. The most obvious is to first check against the square S circumscribing the circle C, and only then proceed to the (slightly) more costly circle test.

Related

Detecting openings/holes in a closed triangular mesh?

I want to detect (and close) openings and holes/hollowed out parts of a closed mesh. I know that for an open mesh, this can be done by finding the boundary edges (edges belonging to only one triangle) as described here.
But what about a closed mesh, where such boundary edges don't exist? Below is an example image. The box has an opening at the top, while the cylinder has a complete hole. Is there an algorithm to detect these things?
This sort of problem is studied in a field called computational topology. To distinguish the torus (or multi-torus) from the sphere, it suffices to determine whether (in the language of homology) there exists a 1-cycle that is not a boundary. Assuming you have an orientable manifold, this can be done by comparing the rank/nullity of the matrices corresponding to the relevant boundary operators.
To repair the hole, my intuition would be that finding the shortest cycle that's not a boundary, filling it in, and repeating would give reasonable results, but I don't know off the top of my head how to do that algorithmically.

How do I detect bounded regions of closed-loop polygons?

I am given an ordered set of points in 2D space as an output of a previous process. Coordinate points will be given in the form ((x0,y0),(x1,y1),...,(xn,yn)), where the very last coordinate pair will be a repetition of the first pair (i.e x0 = xn and y0 = yn). In this way, I know that when I re-encounter the same coordinate, I have made a closed loop. I would like to be able to detect the enclosed area by the polygon. If a single closed loop is given, the output should be the enclosed area of that closed loop. Now say I have a separate set of points, similar to to the first set. If a set of many closed looped polygons is given, then if each polygon is separated in space from each other, the output should be each enclosed area. However, if some of the polygons enclose each other, it should be the area bounded between both of them. For example, if I have one closed loop polygon inside another, the output area should between both of them (or in other words, the area enclosed by the larger one minus the area enclosed by the smaller one). If I have more than one closed loop polygon inside of a single larger one, it should be the area enclosed by the larger one minus all the areas enclosed by the smaller ones).
For a case where I have a region A enclosed by a region B, where B is enclosed by a region C, there are three distinct regions.
Region C minus region B (bounded on the outside by polygon 1)
Region B minus region A (bounded on the outside by polygon 2)
Region A (bounded on the outside by polygon 3)
Of the three regions, I only want region 1) and region 3). The reason I do not take region 2) is because for all the bounded areas on my 2D plane, the outermost polygons always represent the boundaries of a relevant region, and the input that produced my sets of coordinates representing my closed loop polygons would never have given me the points for polygon 2 if in the end region 1) and region 2) were meant to be combined. It instead would have given me only polygon 1 and polygon 3, similar to the case I described above.
In summary,
- I am given enough information to know all the coordinate points for a set of closed loop polygons on a 2D plane and they are distinguishable from each other.
- I need to develop an algorithm that will take in the entire set of closed loops polygons and return enough information to describe a bounded area. In thinking about the problem, I think the output that I would want is to know whether for a each and every line segment of the a closed loop polygon, on which side of that line segment is inside and outside of the polygon.
- It should be able to resolve the case where I have polygons inside of polygons.
- Closed loop polygons will never share any points. Each set of coordinate points will be unique to a polygon.
My initial thoughts were calculate the centroid of the polygon and then compare all line segments to the centroid, but I don't think this would work for all cases.
Judging by the description of your input, splitting your input stream into separate polygons is a trivial task.
After that, in order to "return enough information to describe a bounded area" you can build the following data structure out of your polygons:
Separate all polygons into two classes: main polygons and hole polygons.
Main polygon is... well, the exterior border of a bounded area. It separates the interior of the bounded area from the "outside world".
Hole polygon is a polygon that describes a hole in some main polygon.
Each hole polygon is associated with exactly one main polygon
Each main polygon is associated with zero or more hole polygons
Optionally, you can order the vertices in main polygons counterclockwise and vertices in hole polygons clockwise. But this is not strictly necessary to satisfy the formal requirement of "describing a bounded area"
The resulting structure is two-tiered: you end you with a list of main polygons, and each main polygon might contain a list of its holes.
In your example, you have 4 main polygons. One of them contains two hole polygons.
So, all you need to do is to recognize hole polygons and properly associate them with their main polygons.
An industrial-strength approach for solving this task would be an application of sweep-line algorithm to the input polygons. It would easily perform the classification into main and hole polygons as well as build the proper association between them.
An ad-hoc algorithm might look as follows
Sort all polygons in order of increasing area
For each polygon p in the sorted order
Take any vertex v of p
Perform an "inside" test of v against all polygons of greater area than p (for example, by using a simple even-odd intersection test: How can I determine whether a 2D Point is within a Polygon?)
If the number of polygons that contain v is odd, p is a hole polygon. Otherwise, p is a main polygon
If p is a hole polygon, then the smallest-area polygon that contains v is its associated main polygon.
That's it.
I think the output that I would want is to know whether for a each and every line segment of the a closed loop polygon, on which side of that line segment is inside and outside of the polygon.
Compute the normal for the line segment (perpendicular line).
Compute the mid-point of the line segment (any point will do).
Intersect every other line segment with a ray projected from the mid-point in the direction of the normal.
Intuitively, each intersection means either entering or exiting another polygon. Since finally the ray will be outside all polygons, we can deduce that if the ray intersects an even number of other line segments, then the side of the line segment indicated by the normal is on the outside of the polygon. If odd, it's on the inside.
There are a couple of tricky cases: one is where the ray exactly intersects the end-point of two connected line segments. Be careful to only count this as one intersection. The other case is where the ray is parallel to and exactly overlaps another line segment. This should count as two intersections.
There are more efficient algorithms (e.g. involving triangulation), but this one is simplest.

Randomly placing a polygon inside of polygon

I have two polygons defined as a series of 2D floating point values. They are not guaranteed to be concave or convex. They do not cross over themselves. They cannot rotate. I want to place one randomly inside the other should it be possible based on it's size. The main problem is efficiency. I have to do this about 200 or so times in a few seconds.
I've been looking into this for a couple of days now, and have made no discernible headway. Any leads would be appreciated.
Disclaimer: If you are trying to pack multiple polygons inside a bigger polygon then I think, this problem is NP hard so it is unlikely that an efficient and exact algorithm can be developed to solve this problem. The polygon can continuously translate and rotate in a plane, which means the placements may be infinite and this makes the solution space of the problem also infinite. If you are just trying to find if the smaller polygon can fit inside the bigger one, I am short of an efficient answer, but as you have asked - "Any leads would be appreciated" - here is one.
Let the bigger polygon be B and smaller polygon (the one to be inserted) is S. B has a total of b points and S has a total of s points.
The image below shows a Bounding Box and a Minimum Bounding Rectangle. We use this to get the Fast Fail Filter (very simple idea... defined in next para). The box (a) shown below is faster to compute while box (b) is more accurate for filtering. Draw that box which gives better return on investment for your case. Though in the figure below they both are bounding an ellipse instead of a polygon but you get the idea.
(Image taken from: http://portal.ku.edu.tr/~cbasdogan/Tutorials/imageU21.JPG)
Crux: If any line of B intersects with any line of S, or if all lines of S are outside B, B cannot take S in.
Fast fail filter: Get the bounding rectangles of B and S. If you are not able to place the bounding rectangle of S inside the bounding rectangle of B, then you cannot place the polygon S inside polygon B. This way you fail faster if there is no chance of B to enclose S. Following image illustrates the three cases.
(Image taken from: http://www.cs.berkeley.edu/~ug/slide/pipeline/assignments/as4/figures/boundcull.gif)
Preprocessing: Determine the equation of lines that form B. Store them in a HashMap<<Point, Point>, Line> for a step that will be done later. You can uniquely define the line by slope m and intercept c and the end points of your line are going to be the key (<Point, Point>) of the HashMap.
The Algorithm:
For every S which has passed the above filter:
Read the points of S and determine the lines that form S
For every line of S, see if it intersects with any line of B† (they are stored in the HashMap already)
If there is no intersection, S is inside B and all you have to do is just draw the lines without any worry of intersection.
In the worst case, the complexity of this algorithm will be O(bs) for drawing each polygon.
†This step is written brute-force to keep the algo easy to understand. Otherwise a critical optimization that will give result faster is possible here. You can filter lines of B. You need not consider a line of B for intersection with S if the endpoints of the line of B are to the left of the leftmost point of S, or to the right of the rightmost point of S or above S or below S. This can save a lot of calculations.
If the other answer here is useful, this is an addendum to it. It shows another approach to see if smaller polygon is inside bigger one.
To test a polygon containment, you see if all the edges of the polygon are contained. To test all the edges, you test if all the points of every edge are contained.
Densify the smaller polygon by adding vertices between existing vertices. The image below shows densification of a line.
Now for the densified polygon, test if its points are all lying within the outer polygon. This test can be done by drawing lines from the point emanating to infinity on both sides and then counting how many times that line intersected with the bigger polygon.
If all points are within, then the polygon is within.
First Image source.
Second Image source.

Checking convexity from outside [closed]

Closed. This question does not meet Stack Overflow guidelines. It is not currently accepting answers.
Questions asking for code must demonstrate a minimal understanding of the problem being solved. Include attempted solutions, why they didn't work, and the expected results. See also: Stack Overflow question checklist
Closed 9 years ago.
Improve this question
Is there any method or algorithm to determine convex (or non-convexity) property of a region from outside (perimeter) ?
One way is plotting tangent line in each point of perimeter and discuss how many times this line intersect the perimeter points. If no intersect shown (for all points of perimeter ) we can conclude region is convex. In otherwise region is non-convex.
Second way is determine interior angel of each point of perimeter and discuss if it's bigger than 180 or not. The region is non-convex if at least one point in perimeter exist it's interior angel bigger than 180.
Are there another simpler ways?
Any ideas or solution would be appreciated, thanks.
One thing to observe when doing this is that as you traverse the sides of a convex polygon, all the turns will be to the same side. That is, if you are traversing around the vertices in a counter-clockwise direction, all of the turns will be to the left; if you are traversing around the vertices in a clockwise direction, all of the turns will be to the right. If you ever observe a turn to the opposite side of any others observed, then you know you're dealing with a non-convex polygon. If all of the turns are to one side, then it is a convex polygon.
So, all you need to do is take look three vertices at a time, call them vn, vn+1 and vn+2. You can then determine which side of the line segment connecting vn and vn+2 the vertex vn+1 sits on. For CCW, vn+1 should be on the right of the line segment, and for CW it should be on the left. There is an answer to another question which provides a method for determining this.
There are additional implementation details you should work out (like how to deal with n=N, the number of points in your polygon, but this should provide you with a place to start.
An implementation based on this approach will run in O(N) time and space.
UPDATE: In response to the question below, "how about non-polygonal regions"? In general this is much harder. Mathematically, a region can be shown to be non-convex by finding a line segment with endpoints in the interior of the region but which has some portion of the line segment exterior to the region. I suspect you're looking for a way of implementing this using a digital computer, and so the pure mathematical approach is not practical.
So, you're going to have to offer some sort of constraints as to the types regions before the problem becomes intractable. That is, you have to constrain your problem space so that things like Nyquist sampling of the perimeter of the boundary do not incorrectly identify a non-convex region as being convex.
Assuming you can properly constrain the problem, any solution you can come up with, which can be implemented on a digital computer will have to approximate the region. You can either generate a piece-wise linear approximation of the region in question and run the algorithm above, or pick the proper set of points along the boundary of the region and calculate their derivative. Each successive sample should rotate the angle of the tangent line by some increment in the same direction. But again, it gets downs to sampling.
If you have other information about the nature of any nonlinearities which comprise the boundary of your region, you may be able to symbolically demonstrate whether a segment of the boundary is convex. The problem then reduces to showing that it remains convex when joined to the adjacent sections, which again is going to be problem specific.
So, my suggestion is, for digital computer implementation, approximate as needed the boundary of the region by a polygon and run the method defined above on that approximation.
An algorithm I've used (in pseudo code):
function isConvex(vertices[Count] V):
convex = true
if Count <= 3 return convex
for N = 0 to Count while convex:
// line segment between previous and subsequent vertices
LineSegment segment1 = new LineSegment(
V[(N + Count - 1) % Count], V[(N + 1) % Count]);
// line segment between the point and any other point
LineSegment segment2 = new LineSegment((V[N], V[N+2 % Count]);
if not segment1.intersects(segment2) then convex = false;
return convex
I don't know if this is optimal or simpler than the algorithms you've already tried.
The LineSegment.intersects() method already existed making this really easy to write.
The actual code used segment2 from the previous iteration as segment 1 of the current iteration making it faster but more complex to write even in pseudo code.
And also, for what it's worth, the original of this algorithm was written in assembly language on a processor that no longer exists, so I won't be providing actual code ;-).

Bresenham algorithm [duplicate]

This question already has answers here:
Closed 11 years ago.
Possible Duplicate:
how do I create a line of arbitrary thickness using Bresenham?
How can I use Bresenham algorithm to draw lines of more than a pixel thick?
Do i have to run the algorithm many times with an offset from x and y?
One thing you can do is to calculate using the slope of the line, a unit offset in both orthogonal directions. Multiply this by your thickness, and take the offsets at both endpoints. You now have effectively the bounds of a rotated rectangle. Then, rather than using Bresenham to draw the line, use a fast polygon fill.
No, the simple way is just plot a stencil at every (x, y) location produced by the algorithm that is larger than one pixel, e.g. a disc.
But that's of course inefficient in the sense that you plot the same pixel many times. It's however easy to implement and works robustly with even odd-shaped or multicolored stencils.

Resources