I have some circles, I know their X,Y and r. I want to check if ANY of them colide with ANY other... The way to check is easy:
r1+r2 < sqrt((x1-x2) 2 +(y1-y2)2)
but do I have to check all with all? It gives me O(n2) complexity, and I want to avoid this :/
Try looking at KD-tree acc-struct. first you have to consider circles as squares way less complexity for computing intersection , than you put these squares in the modified KD-tree ,it will need some thinking but hopefully nothing too extreme ... Way kd-tree works is that it cancels out half of the possible matches based on some criteria for each tree level. Look it up on wiki. Good luck with your problem :)
You can divide your space into regions, like:
Compute 2D AABB - axis aligned bounding box for all the circles
Divide it into four sub boxes
To each of sub boxes assign circle, if circle even slightly crosses such box then it must be put into such box. This means that circle can be assigned to multiple boxes.
Iterate each circle, then check to which box it was assigned, and compute collision only with circles from that box.
In 2. you can do many subdivisions, depending on your space size, also if to many circles are assigned to one box then subdivide it further.
Use square bounding boxes as a simple initial test. Only then move on to circles.
Also
r1+r2 < sqrt((x1-x2)² + (y1-y2)²)
can be re-written as:
(r1+r2)² < (x1-x2)² + (y1-y2)²
which removes that nasty sqrt()
Are there alot of circles?
The best thing in my opinion is to be setting your circles in arrays.
So therefore you would have an array of Circles that not only makes them easier to initalise but are all in one place.
Next part is to take the circle and give it a function to test collision.
e.g.
void isCol(Array [circles], the current vectors this circle is on. etc);
If a lot of circles
make a for loop that goes through the array checking each ones X, Y
and radius values and see whether or not they are in a certain
vacinity of the circle.
However you should always check whether the
circle your looking at is you, if it is then skip that circle. if
they are in a region then calculate whether or not any of them are
colliding with you and (insert if collision aftermath here).
If theres only a few circles then skip right to checking for collison.
I think what your after is the checking whether the all of the circles are in a range and only dealing with those that are.
Hope this helps.
Related
I'm using the centroid of polygons to attach a marker in a map application. This works definitely fine for convex polygons and quite good for many concave polygons.
However, some polygons (banana, donut) obviously don't produce the desired result: The centroid is in these cases outside the polygons area.
Does anybody know a better approach to find a suitable point within any polygons area (which may contain holes!) to attach a marker?
One approach would be to generate and refine a skeleton of the polygon, then use the midpoint of the skeleton to place your marker (and if it's text, to orient the text correctly). This works well for most shapes, including ones with holes, and banana-shaped or tadpole-shaped crescents.
The CGAL library has a 2D Straight Skeleton and Polygon Offsetting module, or you could use PostGIS, for example.
To rephrase comment of ChristopheRoussy we may look for the largest circle inside of the polygon.
The largest circle is the one which cannot grow anymore because it touches three vertices or edges (if it touches only two, it can become bigger or just moved until it touches third).
So if you have few vertices, you can just enumerate all possible triples of vertices/edges, find for each one a circle and then select the largest one.
But it will require creating four functions:
Circle(vertex,vertex,vertex)
Circle(vertex,vertex,edge)
Circle(vertex,edge,edge)
Circle(edge,edge,edge)
All of them are possible, but may require some effort.
Find the extreme ordinates and draw an horizontal line in the middle. It is guaranteed to cross the polygon.
Find the intersection with the sides and sort them by increasing abscissa. Pick a point in the middle of two intersections.
This is an O(N + K Log K) process where K is the number of intersections (usually a very small even number). Pretty straightforward to write.
To increase the chances of a nice placement, you can try three horizontals instead of one an pick the longest intersection segment.
I have no idea how to solve this for any possible shape (and not doing heavy computation), but maybe for simpler shapes like the ones you have shown:
https://en.wikipedia.org/wiki/Force-directed_graph_drawing
Heuristic: This could converge to a reasonable approximation after a while
transform shape border into many points (more = more precise)
start out with many random points inside the polygon
push them until they are furthest away from border points, or just compute distance ... (can be done in parallel)
take best point
Another way could be to use multiple algorithms depending on the nature of the shape (like another one for donuts ...). Also perhaps relying on measuring 'fattest' sections first ?
IMHO would ask this on a math forum.
Similar: Calculate Centroid WITHIN / INSIDE a SpatialPolygon
Similar: How to find two most distant points?
To get a point for a marker I would use Yves Daoust's method.
To get a point that is reliably "within any polygon with holes" I would split polygon into triangles with a reliable library (e.g. OpenGL's GLUtessellator), and then get centroid of triangle with largest area.
If I had time for developing and testing, and I wanted good performance, then I would use a hybrid method: First use Yves Daoust's method to get some candidate points and then test candidates to see if they are within polygon. If all candidates fail, then fall back to slower reliable method (e.g. GLUtesselator).
for (int i = 0; i < n; /*++i*/) {
p = RandomPointInsideConvexHull();
if (IsInsidePolygon(p)) {
++i;
d = DistanceToClosestEdge(p);
if (d > bestD) {
bestP = p;
}
}
}
After running this loop you will approximate solution by bestP. n is parameter to choose. If you want more accurate result you can restart search, but now instead of picking a point inside polygon's convex hull you can pick one in the neighborhood of bestP, say not farther than bestD / 5 (this time you don't need to check if random point is inside polygon).
I am working on small project that requires me to quickly find which triangles within a set of triangles is either partially or entirely contained within a given rectangular region. I am interested in optimizing for fast searches - I am not memory limited.
This is not an area I am too familiar with, so all I've been able to do thus far is to poke around on Google for standard algorithms for dealing with this problem. The closest I've gotten to so far is to use two interval trees. This is a bit clumsy, since I have to perform a test for interval overlap between the edges of each triangle and the edges of the rectangular region in both directions x and y.
Can someone point me to any resource where the 'correct' way of dealing with this problem is?
Thanks!
Edit: I forgot to mention that the rectangular regions I am currently using are parallel to the coordinate axes x and y. For the time being, I am happy with any solution that exploits this constraint. Generally, though, a solution with completely arbitrary rectangles would be great to know about.
You can use an AABBTree (AABB stands for Axis Aligned Bounding Box tree), the
idea is to enclose each triangle in its axis aligned bounding box, then build a tree that has the initial triangles as leafs, and where upper nodes have a bounding box that is the union of the bounding boxes of its children. Then when searching which triangles have a non-empty intersection with "something", you check whether the "something" has an intersection with the bounding box of a node, and go down the tree to test its children when it's the case (recursive function).
You can find efficient implementations of AABBTrees in:
CGAL: http://doc.cgal.org/latest/AABB_tree/
the GEOGRAM library that I am writing: http://alice.loria.fr/software/geogram/doc/html/classGEO_1_1MeshFacetsAABB.html
OpCode: http://www.codercorner.com/Opcode.htm
Assuming the rectangle is axis aligned, I'd do this:
Compare the bounding box of a triangle to the region. If it is inside, the triangle is inside. If there is no overlap at all, it's not. Use an interval tree for each dimension for this step if you need to check the same set of triangles with different regions.
We have checked the two simple cases in step one, so we know the region and bounding box overlap. Check if any of the points of the triangle is inside the rectangle. If so, the triangle is inside.
Check the four sides of the rectangle with the three sides of the triangle for line segment intersections
If no preprocessing of the set of triangles is allowed, there is nothing better you can do than comparing exhaustively every triangle to the window.
To solve the triangle/rectangle overlap problem easily (or just to reason about it), you can form the Minkowski sum of the two polygons, to turn the problem in a "point-in-convex-polygon" instance.
Of course, an initial axis-aligned bounding box test is welcome.
If your window is a rotated rectangle, you can "unrotate" the whole scene to make the window axis-aligned and revert to the first problem.
Imagine lots of points like of order 10M.
Now I randomly draw a circle in a given space.
This circle will now enclose some points depending on the center and radius.
Now, I want to select all the points which are present inside this circle.
The brute force approach is very inefficient.
Is there a better way to solve this.
P.S- I am coding in python.
Thanks
Edit:
Brute Force Approach:
Select a point from the space , calculate the distance from the center and if it is less than the radius, then it lies inside otherwise outside.
The brute force is, well I have to go thru all the points and this is problametic because in the next iteration I am going to again select a point in random and repeat above steps.So this is like O(n^2)..
Can I do better?
Arrange points in advance in some space partitioning structure.
For example, quad-tree. Traverse the tree. As each node corresponds to a square on the plane, you can quickly check if that square intersects with your circle (having at least one corner inside the circle or circle being entirely inside the square). If it does intersect, continue traversing down that node, if it does not intersect, skip all of its children, potentially eliminating a large number of individual checks against the points in that square.
I am looking for a sound algorithm that would randomly place a given number of rectangles of the same size into a bigger rectangle (canvas).
I see two ways to do it:
create an empty array that will contain the rectangles already placed on canvas. start with the empty canvas. in a loop, pick a position at random for a new rectangle to be placed. check if the array has a rectangle that overlaps with the new rectangle. if it does not, put the new rectangle in to the array and repeat the loop. otherwise, pick a new position, and rerun the check again. and so on. This might never terminate (theoretically) I think. I do not like it.
use a grid and place rectangles into the cells randomly. This might still look like a grid placement. I do not like it either.
any better ways to do it? "better" meaning more efficient, or more visually "random" than the grid approach. better in any respect.
Here is a simple heuristic. It will be non-overlapping and random.
Place a rectangle randomly. Then, calculate the intersections of extensions of the the two parallel edges of the first rectangle with the edges of the canvas. You will obtain four convex empty regions. Place other rectangles in these empty regions one-by-one independently and calculate the similar divisions for placements. And try to put the remaining rectangles in empty regions.
You can try different strategies. You can try to place the rectangles close to the corners. Or, you can place them around the center of the regions. We cannot discuss optimality because you introduced randomness.
You might find Quadtrees or R-trees useful for your purpose.
I create internal room-like dungeons using the following method.
1) Scatter N points at random, but not within a few pixels of each other.
2) For each point in turn, expand if possible in all four directions. Cease
expanding if you hit another rectangle.
3) Cease the algorithm when no rooms can expand.
The result is N rectancles with just a few rectangular small spaces.
Code is in the binary image library
https://github.com/MalcolmMcLean/binaryimagelibrary/blob/master/dungeongenerator3.c
#
What is the most efficient way to randomly fill a space with as many non-overlapping shapes? In my specific case, I'm filling a circle with circles. I'm randomly placing circles until either a certain percentage of the outer circle is filled OR a certain number of placements have failed (i.e. were placed in a position that overlapped an existing circle). This is pretty slow, and often leaves empty spaces unless I allow a huge number of failures.
So, is there some other type of filling algorithm I can use to quickly fill as much space as possible, but still look random?
Issue you are running into
You are running into the Coupon collector's problem because you are using a technique of Rejection sampling.
You are also making strong assumptions about what a "random filling" is. Your algorithm will leave large gaps between circles; is this what you mean by "random"? Nevertheless it is a perfectly valid definition, and I approve of it.
Solution
To adapt your current "random filling" to avoid the rejection sampling coupon-collector's issue, merely divide the space you are filling into a grid. For example if your circles are of radius 1, divide the larger circle into a grid of 1/sqrt(2)-width blocks. When it becomes "impossible" to fill a gridbox, ignore that gridbox when you pick new points. Problem solved!
Possible dangers
You have to be careful how you code this however! Possible dangers:
If you do something like if (random point in invalid grid){ generateAnotherPoint() } then you ignore the benefit / core idea of this optimization.
If you do something like pickARandomValidGridbox() then you will slightly reduce the probability of making circles near the edge of the larger circle (though this may be fine if you're doing this for a graphics art project and not for a scientific or mathematical project); however if you make the grid size 1/sqrt(2) times the radius of the circle, you will not run into this problem because it will be impossible to draw blocks at the edge of the large circle, and thus you can ignore all gridboxes at the edge.
Implementation
Thus the generalization of your method to avoid the coupon-collector's problem is as follows:
Inputs: large circle coordinates/radius(R), small circle radius(r)
Output: set of coordinates of all the small circles
Algorithm:
divide your LargeCircle into a grid of r/sqrt(2)
ValidBoxes = {set of all gridboxes that lie entirely within LargeCircle}
SmallCircles = {empty set}
until ValidBoxes is empty:
pick a random gridbox Box from ValidBoxes
pick a random point inside Box to be center of small circle C
check neighboring gridboxes for other circles which may overlap*
if there is no overlap:
add C to SmallCircles
remove the box from ValidBoxes # possible because grid is small
else if there is an overlap:
increase the Box.failcount
if Box.failcount > MAX_PERGRIDBOX_FAIL_COUNT:
remove the box from ValidBoxes
return SmallCircles
(*) This step is also an important optimization, which I can only assume you do not already have. Without it, your doesThisCircleOverlapAnother(...) function is incredibly inefficient at O(N) per query, which will make filling in circles nearly impossible for large ratios R>>r.
This is the exact generalization of your algorithm to avoid the slowness, while still retaining the elegant randomness of it.
Generalization to larger irregular features
edit: Since you've commented that this is for a game and you are interested in irregular shapes, you can generalize this as follows. For any small irregular shape, enclose it in a circle that represent how far you want it to be from things. Your grid can be the size of the smallest terrain feature. Larger features can encompass 1x2 or 2x2 or 3x2 or 3x3 etc. contiguous blocks. Note that many games with features that span large distances (mountains) and small distances (torches) often require grids which are recursively split (i.e. some blocks are split into further 2x2 or 2x2x2 subblocks), generating a tree structure. This structure with extensive bookkeeping will allow you to randomly place the contiguous blocks, however it requires a lot of coding. What you can do however is use the circle-grid algorithm to place the larger features first (when there's lot of space to work with on the map and you can just check adjacent gridboxes for a collection without running into the coupon-collector's problem), then place the smaller features. If you can place your features in this order, this requires almost no extra coding besides checking neighboring gridboxes for collisions when you place a 1x2/3x3/etc. group.
One way to do this that produces interesting looking results is
create an empty NxM grid
create an empty has-open-neighbors set
for i = 1 to NumberOfRegions
pick a random point in the grid
assign that grid point a (terrain) type
add the point to the has-open-neighbors set
while has-open-neighbors is not empty
foreach point in has-open-neighbors
get neighbor-points as the immediate neighbors of point
that don't have an assigned terrain type in the grid
if none
remove point from has-open-neighbors
else
pick a random neighbor-point from neighbor-points
assign its grid location the same (terrain) type as point
add neighbor-point to the has-open-neighbors set
When done, has-open-neighbors will be empty and the grid will have been populated with at most NumberOfRegions regions (some regions with the same terrain type may be adjacent and so will combine to form a single region).
Sample output using this algorithm with 30 points, 14 terrain types, and a 200x200 pixel world:
Edit: tried to clarify the algorithm.
How about using a 2-step process:
Choose a bunch of n points randomly -- these will become the centres of the circles.
Determine the radii of these circles so that they do not overlap.
For step 2, for each circle centre you need to know the distance to its nearest neighbour. (This can be computed for all points in O(n^2) time using brute force, although it may be that faster algorithms exist for points in the plane.) Then simply divide that distance by 2 to get a safe radius. (You can also shrink it further, either by a fixed amount or by an amount proportional to the radius, to ensure that no circles will be touching.)
To see that this works, consider any point p and its nearest neighbour q, which is some distance d from p. If p is also q's nearest neighbour, then both points will get circles with radius d/2, which will therefore be touching; OTOH, if q has a different nearest neighbour, it must be at distance d' < d, so the circle centred at q will be even smaller. So either way, the 2 circles will not overlap.
My idea would be to start out with a compact grid layout. Then take each circle and perturb it in some random direction. The distance in which you perturb it can also be chosen at random (just make sure that the distance doesn't make it overlap another circle).
This is just an idea and I'm sure there are a number of ways you could modify it and improve upon it.