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.
Related
I am trying to develop sweep line algorithm for given list of circles. by checking different sources I am able to understand the algorithm .
here are the links that i am referring ,
http://www.stolerman.net/studies/cs623/cs623_winter_2012_sol2.pdf
https://www.cs.cmu.edu/~15451-f17/lectures/lec21-sweepline.pdf
As the solution in given links says that We need to represent the circle in two halves because every sweep line intersect a given circle at most two point at any given time.
I am not able to understand how can we represent any circle in two halves e.g., bottom half and top half . It will be great help if someone can explain the data structure to represent a circle into two halves and how the ordering will be defined for semicircles in binary search tree ?
The algorithm you linked to uses the fact that, if you have two opposite points on a circle, the segment between them uniquely defines a circle, and that segment is a diameter of the circle.
Hence, if you keep a list of all rightmost and leftmost points for all your circle, you will have a representation of all your circles.
More generally, you just need to make sure that the two points you are keeping for each circle make a diameter that is perpendicular to the sweep line you are using in the algorithm.
Depending on what the expected input for the algorithm is, you will need to translate that representation into those two points, but then, with a list of couple of points: [(p1, p2), ..., (p_{2n-1}, p_{2n})] where you have n circles.
Rather than storing a circle in the tree, you can store two half-circles. They result from splitting the circle so that the sweep-line meets a half-circle only once. Whether you indeed store two half circles, or two references to the same circle with a way to tell which half is a matter of ease of implementation.
Beware that two half-circles may intersect even if the segments that join the same endpoints do not intersect.
Pretty straightforward: given N triangles T1, ... ,Tn and a point P, what is the best approach to find an i such that P is inside Ti?
PS: Don't know if this is important, but the triangles are disposed as if they were part of the map of a country (for example, get any country and draw it only with triangles, thats how the given triangles should be placed like).
If preprocessing is an option, you can consider inserting your triangles in an R-tree.
https://en.wikipedia.org/wiki/R-tree
Update:
If there is a single point, there is no shortcut. Exhaustive comparison is mandated. Otherwise the algorithm could "guess" the position of some triangles without even looking at them.
Make use of Sweepline algorithm. You need to order triangles from their left to right co-ordinates.
Make a Minpriority queue and put all triangles(co-ordinates , left and right, so each trinangle will be inserted twice, the first point is begin point(x-min) and the second point is end point(x-max)) in priotity queue and the co-ordinates of point also.
Remove the first co-ordinate:
if it is left point then put it in binary search tree along witht triangle whose co-ordinate is this.
If it is right co-ordinate then remove the triangle from the binarysearchtree.
If it is co-ordinates of point then the your point must lie in only those triangles who are in binarysearchtree.
What is the best way of combining overlapping circles into polygons?
I am given a list of centre points of circles with a fixed diameter.
I need to join any overlapping circles together and output a list of points in the resulting polygon.
This seems like a fairly common problem (GIS systems, vectors, etc.). This is possible to do through the Google Maps API but I am looking for the actual algorithm.
I have tried to solve this problem by calculating points around each circle.
Then removing any points located inside any circle.
This gives me the correct list of points in the desired polygon.
However, the order of the points is a problem with this solution. Each circle has its points stored in an array. To merge them correctly with 2 overlapping circles is relatively straight forward. However, when dealing with multiple overlapping circles it gets complicated.
Hopefully you have some ideas to either make this solution work or of another algorithm that will achieve the desired result.
Thanks in advance!
You should be able to use an appraoch like the following:
First, identify circles that belong to the same group of overlapping circles. Obviously, two circles overlap if the absolute distance of their centres is less than their combined radii. For each circle, store the circles it itersecs with in a hashmap/dictionary. (You can extend this to entire groups of circles using the union-find algorithm, or disjoint sets, but this is not really needed.)
When creating the points belonging to one circle, memorize the left and right neighbor of each point. You get this for free by just storing them in an ordered array.
Remove the "inner" points, i.e. those that are closer than one radius to any of the centres of the circles intersecting the first circle.
Mark the neighbors to those inner points that were not removed the "loose ends" of the circles.
Connect the points that were not removed, including the loose ends, to their original left and right neighbors.
For each loose end point, find the closest loose end of a different circle in the same group and connect them.
Here's a picture to illustrate the approach.
Red dots are "inner" points that are removed
Blue dots are "loose ends" by being neighbors to "inner" points; each "loose end" has another "loose end" of a different circle that's less than two "point-distances" away
Green dots can easily be connected to their neighbors (including the "loose ends") by the order in which they were arranged around the circle.
You can further decrease the number of possible combinations by distinguishing left and right loose ends, and using the fact that each left loose end of one circle has to be connected to a right loose end of another circle. For n circles in a group, that leaves just (n-1)! ways to connect those circles, irrespective of the number of points per circle.
And even this can be reduced further if you consider only those circles in the group that actually intersect the circle with the loose end (just store those in a hashmap/dictionary). So if you have n circles that on average intersect with k other circles, then there are only n*k possible combinations.
You could also use the fact that the other loose end can not be farther away than two times the distance between two point on the circle. Let's call this distance d, then you can create a spatial map with resolution d (e.g. a hashmap, or just a 2D array) and assign each loose end to cells in that map, then the other loose end must be in the same of one of the surrounding cells of the first loose end.
Thus, the number of ways in which points can be connected to each other is greatly reduced (in particular, the way they are connected in your final image would not be allowed to begin with): This should be doable even with brute force unless you have lots of overlapping circles in the same group, and there are smarter algorithms for nearest-neighbor search that you can use.
Update: Reviewing this answer after some time, it seems that you can determine the matching pairs of "loose end" points rather easily: Say you have a "right" loose end in circle A, then the matching "left" loose end has to belong to the circle whose radius overlapped the next "inner" point to the first "loose end". So if you store that relation in another map, you can immediately determine the matching loose end. (If an inner point is overlapped by multiple other circles, the map should contain the circle that overlaps it the most.)
Here's a sketch of an O(n log n)-time algorithm.
Use your favorite algorithm/library to compute a Delaunay triangulation on the circle centers.
Delete the edges between circles that do not overlap.
Walk around the infinite face of each connected component. This is easy to do with a doubly connected edge list representation, where the ordering of the edge lists is used to indicate the topology of the planar graph. Every half-edge on this boundary turns into a vertex where an arc segment belonging to its tail point ends and an arc segment belonging to its head point begins.
(Optional) Approximate each arc segment by a polygonal line.
If anyone from Google is reading this, please note that I have not looked at the relevant code.
I'm trying to workout how to efficiently calculate the layout of a dynamic/random view.
The view will contain a number of circles. Each circle has a predetermined size. These sizes are all between a given maximum and minimum size.
I'm trying to find an efficient way of laying out the circles within a rect with a couple of conditions.
The circles mustn't overlap with the edge of the rect and the circles must have a minimum "spacing" between them.
The first method I came up with is to randomly generate coordinate pairs and place the biggest circle. Then randomly generate more coordinate pairs until a suitable one is generated for the next circle. And the next, and the next, and so on until all are drawn.
The problems with this are that it could potentially take a long time to complete. Each subsequent circle will take longer to place as there are fewer places that it can go.
Another problem is that it could be impossible to layout the view.
I'm sure there must be more efficient ways of doing this but I'm not sure where to begin.
The Formula must deal between the smallest possible square they need or from a other point of view, with an arrangement with the smallest possible density between the edgepoints. But your problem could be solved by sorting the circles by size and then start with the largest and arrange them step by step to the smallest because the larger are more bulky and the smaller fit easier in small corners by there nature.
Build triangles of circles, where 3 circles have a discribing space they use together. This triangle has 3 corners right? :) so messure/calc the angle of that corners and the corner with the nearest 90degree angle should be placed in a square corner, better to say the three circles should be places mirrored so that the circle with the fittest 90degree corner behind is the one who goes in the corner. If a 4th circle fits into the rest of this triangle, wonderful, if not you place exact this circle in it which is taken minimum outerspace of that triangle. because its not said that the next smaller circle is the one who fit's perfect, which also means you have a stack of not placed circles until one is found who fits better. after you find one you go upwards your circle-stack again and try to fit the next of it in one of the corners or you try to build the next triangle. and here you see how complex this is, damn! http://en.wikipedia.org/wiki/Malfatti_circles
But anyway, the more one of this triangles corners is 90° the less space it would take with this 3 circles in it.
An other concept could be to think about larger circles like space who leftover a triangle in one of its corners in relation to the rectangle. This triangle has a maximum space availible for a smaller circle. If there is no perfectly fitting circle your taken square-space grows up. So as far as i think about to handle this problem with imagined triangles to compare with fitting circles in it or taking triangle ranges from the square is the solutions base.
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.