Finding points with various radiuses around user location - ios

I'm using Firebase for one of my projects and was wondering if the following would be possible to achieve using Geofire.
I have a list of points with radiuses in which they are available (lat, lng, radius). In the image attached, the blue circle is created by the point and its radius.
I want to find all of the circles that reach user's location (red circle - just a point). The final effect I want to achieve is similar to seeing all the wifi networks around you - some of which might have a stronger signal.
Can it be done using Geofire? If yes, how should I approach the query?

Firebase can't handle a query like this, as you can't have logic in an orderBy. I'm not sure geofire can get around that limitation (from the docs I've browsed it cannot) so then we must come up with another way of doing it. If you know the max size one of the circles can be we might be able to figure out roughly which circles to select.
(Side note, I'm going to assume you only want things in the top hemisphere, there's a bit more math if you want to handle both but I won't go into details here)
I'm going to describe roughly how to do it, latitude/longitude are tricky as you move closer to poles and radius does not always translate 1 - 1 with a circle near the equator as it does farther north. For the most part this idea will work but the math for determining the min/max will change as well as the final step where you loop.
Based on the red point and max circle radius create the following variables
minLatitude: (red circle latitude) - (max circle radius)
maxLatitude: (red circle latitude) + (max circle radius)
minLongitutde: (red circle longitude) - (max circle radius)
maxLongitutde: (red circle longitude) + (max circle radius)
you'll have to update your databse to have an index that is searchable for each of the blue circles that contains both latitude and longitude with a certain decimal precision.
Something like LATITUDE_LONGITUDE.
Do a query like: ... orderByChild('_latitude_longitude').startAt(minLatitude + '_' + minLatitude).endAt(maxLatitude + '_' + maxLongitutde) (don't forget to make sure these all have the same precision)
This will return to you all circles that will be within a max radius of your red circle
You'll then have to loop through all of the circles returned and see if based on their own radius if the red circle is contained (very simple math formula here, plenty of examples online)
That's the only method I can think of that has no server side processing.

Related

Calculate how many boxes and their center coordinate given an area of map

I have given a location defined by an area, example is Singapore area. Now I want to divide it into a circle given that each has radius of 50 KM. My objective is to find how many circles do I need to cover all the area of Singapore and what are the circle center coordinate.
Does someone know the formula of it and how do I do it in Python?
I found quite similar example here :
https://codesandbox.io/s/subbounds-8j0p6?file=/src/index.js:722-728
But I do need to know the idea behind it.

Anonymising/aggregating lat/long coordinates

I'm looking to display coordinates on a map. The coordinates are at a relatively fine resolution (3 decimal places), but I need to anonymise and aggregate them to a coarser resolution.
All the approaches I've seen run the risk of the coarse coordinates being the same as, or very close to, the original coordinates, since they rely on rounding or adding random noise to the original.
For example, with rounding:
53.401, -2.899 -> 53.4, -2.9 # less than 100m
With adding 'noise', e.g.:
lat = 53.456
// 'fuzz' in range -0.1 to 0.1
rnd = (Math.random() * 2 - 1) * 0.1
newLat = lat + (Math.random() * 2 - 1) * 0.1
However if rnd is close to 0, then the coordinates don't 'move' much.
Is there a (simple) way to 'move' a coordinate in a random way a certain (minimum) distance from it's original location?
I've looked at other answers here but they don't seem to solve this issue of the new coordinates overlapping with the original coordinates:
Rounding Lat and Long to Show Approximate Location in Google Maps
Is there any easy way to make GPS coordinates coarse?
To add random noise, you could displace every point by a fixed distance in a random direction. On a flat projection, for a radius r:
angle = Math.random() * 2 * PI
newLat = lat + (r * sin(angle))
newLon = lon + (r * cos(angle))
That would guarantee a fixed displacement (r) for every point, in an unpredictable direction.
Alternatively, you could anonymise by joining to a polygon at a coarser grain, and then plot the data by the polygon rather than the points. It could be as simple as a grid on a flat projection. Or something more sophisticated such as the Australian Statistical Geography Standard which offers multiple choices, the most granular being a "mesh block" which they guarantee to always contain 30-60 dwellings.
All the approaches I've seen run the risk of the coarse coordinates
being the same as, or very close to, the original coordinates, since
they rely on rounding or adding random noise to the original.
Could you explain, what's the risk that you are concerned about here? Yes, the coarse coordinate might happen to be the same, but it is still anonymized - whoever sees the coarse data would not know if it is coincidentally close or not. All they know is that the actual location is within some distance R_max from the coarse location.
Re the other solution,
displace every point by a fixed distance in a random direction
I would say it is much worse: here it would be easy to discover the fixed displacement distance by knowing just a single original location. Then, for any "coarse" location, we would know the original is on thin unfilled circle centered on the "coarse" location - much worse than the filled circle or rectangle in the original solution.
At the very least, I would use random radius, maybe don't allow it to be zero, if you are concerned about coincidental collision (but you should not be). E.g. this varies the radius from r_max / 2 to r_max:
r = (Math.random() + 1) * r_max / 2;
and then you can use this random radius with Schepo's solution.

Find outer checkerboard corners

In the below picture, I have the 2D locations of the green points and I want to calculate the locations of the red points, or, as an intermediate step, I want to calculate the locations of the blue points. All in 2D.
Of course, I do not only want to find those locations for the picture above. In the end, I want an automated algorithm which takes a set of checkerboard corner points to calculate the outer corners.
I need the resulting coordinates to be as accurate as possible, so I think that I need a solution which does not only take the outer green points into account, but which also uses all the other green points' locations to calculate a best fit for the outer corners (red or blue).
If OpenCV can do this, please point me into that direction.
In general, if all you have is the detection of some, but not all, the inner corners, the problem cannot be solved. This is because the configuration is invariant to translation - shifting the physical checkerboard by whole squares would produce the same detected corner position on the image, but due to different physical corners.
Further, the configuration is also invariant to rotations by 180 deg in the checkerboard plane and, unless you are careful to distinguish between the colors of the squares adjacent each corner, to rotations by 90 deg and reflections with respect the center and the midlines.
This means that, in addition to detecting the corners, you need to extract from the image some features of the physical checkerboard that can be used to break the above invariance. The simplest break is to detect all 9 corners of one row and one column, or at least their end-corners. They can be used directly to rectify the image by imposing the condition that their lines be at 90 deg angle. However, this may turn out to be impossible due to occlusions or detector failure, and more sophisticated methods may be necessary.
For example, you can try to directly detect the chessboard edges, i.e. the fat black lines at the boundary. One way to do that, for example, would be to detect the letters and numbers nearby, and use those locations to constrain a line detector to nearby areas.
By the way, if the photo you posted is just a red herring, and you are interested in detecting general checkerboard-like patterns, and can control the kind of pattern, there are way more robust methods of doing it. My personal favorite is the "known 2D crossratios" pattern of Matsunaga and Kanatani.
I solved it robustly, but not accurately, with the following solution:
Find lines with at least 3 green points closely matching the line. (thin red lines in pic)
Keep bounding lines: From these lines, keep those with points only to one side of the line or very close to the line.
Filter bounding lines: From the bounding lines, take the 4 best ones/those with most points on them. (bold white lines in pic)
Calculate the intersections of the 4 remaining bounding lines (none of the lines are perfectly parallel, so this results in 6 intersections, of which we want only 4).
From the intersections, remove the one farthest from the average position of the intersections until only 4 of them are left.
That's the 4 blue points.
You can then feed these 4 points into OpenCV's findPerspectiveTransform function to find a perspective transform (aka a homography):
Point2f* srcPoints = (Point2f*) malloc(4 * sizeof(Point2f));
std::vector<Point2f> detectedCorners = CheckDet::getOuterCheckerboardCorners(srcImg);
for (int i = 0; i < MIN(4, detectedCorners.size()); i++) {
srcPoints[i] = detectedCorners[i];
}
Point2f* dstPoints = (Point2f*) malloc(4 * sizeof(Point2f));
int dstImgSize = 400;
dstPoints[0] = Point2f(dstImgSize * 1/8, dstImgSize * 1/8);
dstPoints[1] = Point2f(dstImgSize * 7/8, dstImgSize * 1/8);
dstPoints[2] = Point2f(dstImgSize * 7/8, dstImgSize * 7/8);
dstPoints[3] = Point2f(dstImgSize * 1/8, dstImgSize * 7/8);
Mat m = getPerspectiveTransform(srcPoints, dstPoints);
For our example image, the input and output of findPerspectiveTranform looks like this:
input
(349.1, 383.9) -> ( 50.0, 50.0)
(588.9, 243.3) -> (350.0, 50.0)
(787.9, 404.4) -> (350.0, 350.0)
(506.0, 593.1) -> ( 50.0, 350.0)
output
( 1.6 -1.1 -43.8 )
( 1.4 2.4 -1323.8 )
( 0.0 0.0 1.0 )
You can then transform the image's perspective to board coordinates:
Mat plainBoardImg;
warpPerspective(srcImg, plainBoardImg, m, Size(dstImgSize, dstImgSize));
Results in the following image:
For my project, the red points that you can see on the board in the question are not needed anymore, but I'm sure they can be calculated easily from the homography by inverting it and then using the inverse for back-tranforming the points (0, 0), (0, dstImgSize), (dstImgSize, dstImgSize), and (dstImgSize, 0).
The algorithm works surprisingly reliable, however, it does not use all the available information, because it uses only the outer points (those which are connected with the white lines). It does not use any data of the inner points for additional accuracy. I would still like to find an even better solution, which uses the data of the inner points.

Minimum circle that cover circular arc

I want to find that minimum circle radius that cover circular arc. here is a api link that i need but i think it is not open source:http://reference.mapinfo.com/common/docs/mapxtend-dev-web-none-eng/miaware/doc/apidoc/com/mapinfo/miAware/geom/CircArc.html
A function should be like that and it will return Circle.
public Circle CircArc(double x, double y, double inRadius, double outRadius, double startAngle, double stopAngle)
after i will be able to get center of circle coordinates and radius like that:
circle.getXCoord();
circle.getYCoord();
circle.getRadius();
Is there any api?If not how can i implement CircArc function?
Compute the locations of the two endpoints of the outer circle. There are two cases:
if the arc aperture is smaller than a half turn: the diameter of the requested circle is the line segment between these endpoints,
otherwise: the circle is just the circle of support of the arc.
Anyway, there remains a difficult configuration with arcs of a small aperture such that the inner arc might pass the circle defined above.

Keeping Squares Along A Circle's Circumference

I'm drawing squares along a circular path for an iOS application. However, at certain points along the circle, the squares start to go out of the circle's circumference. How do I make sure that the squares stay inside?
Here's an illustration I made. The green squares represent the positions I need the squares to actually be in. The red squares are where they actually appear given the following values for each square's upper-left corner:
x = origin.x + radius * cos(DEGREES_TO_RADIANS(angle));
y = origin.y + radius * sin(DEGREES_TO_RADIANS(angle));
Origin refers to the center of the circle. I have a loop that repeats this for every angle from 1 till 360 degrees.
EDIT: I've changed my design to position the centers of the squares along the circular path rather than their upper left corners.
why not just draw the centers of the squares along a smaller circle inside of the bigger one?
You could do the math to figure out exactly what the radius would have to be to ensure an exact fit, but you could probably trial and error your way there quickly too.
Doing it this way ensures that your objects would end up laid out in an actual circle too, which is not the case if you were merely making sure that one and only one corner of each square touched the larger bounding circle (that would create a slightly octagonal shape instead of a circle)
ryan cumley's answer made me realize how dumb I was all along. I just needed to change each square's anchor point to its center & that solved it. Now every calculated value for x & y would position every square's center exactly on the circular path.
Option 1) You could always find the diameter of the circle and then using Pythagorean Theorem, you could create a square that would fit perfectly within the circle. You could then loop through the square that was just made in the circle to create smaller squares, but I doubt this is what you are aiming for.
Option2) Find out what half of the length of one of the diagonals of the squares should be, and create a ring within the first ring. Then lay down squares at key points (like ever 30 degrees or 15 degrees, etc) along the inner path. Ex: http://i.imgur.com/1XYhoQ0.png
As you can see, the smaller (inner) circle is in the center of each green square, and that ensures that the corners of each square just touches the larger (outer) circle. Obviously my cheaply made picture in paint is not perfect, but mathematically it will work.

Resources