I am making a java program that classifies a set of lat/lng coordinates to a specific rectangle of a custom size, so in effect, map the surface of the earth into a custom grid and be able to identify what rectangle/ polygon a point lies in.
The way to do this I am looking into is by using a map projection (possibly Mercator).
For example, assuming I want to classify a long/lat into 'squares' of 100m x 100m,
44.727549, 10.419704 and 44.727572, 10.420460 would classify to area X
and
44.732496, 10.528092 and 44.732999, 10.529465 would classify to area Y as they are within 100m apart.
(this assumes they lie within the same boundary of course)
Im not too worried about distortion as I will not need to display the map, but I do need to be able to tell what polygon a set of coordinates belong to.
Is this possible? Any suggestions welcome. Thanks.
Edit
Omitting projection of the poles is also an acceptable loss
Here is my final solution (in PHP), creates a bin for every square 100m :
function get_static_pointer_table_id($lat, $lng)
{
$earth_circumference = 40000; // km
$lat_bin = round($lat / 0.0009);
$lng_length = $earth_circumference * cos(deg2rad($lat));
$number_of_bins_on_lng = $lng_length * 10;
$lng_bin = round($number_of_bins_on_lng * $lng / 360);
//the 'bin' unique identifier
return $lat_bin . "_" . $lng_bin;
}
If I understand correctly, you are looking for
a way to divide the surface of the earth into approximately 100m x 100m squares
a way to find the square in which a point lies
Question 1 is mission impossible with squares but much less so with polygons. A very simple way to create the polygons would to use the coordinates themselves. If each polygon is 0.0009° in latitude and longitude, you will have approximately square 100m x 100m grid on the equator, put the slices will become very thin close to the poles.
Question 2 depends on the approximation used to solve the challenge outlined above. If you use the very simple method above, then placing each coordinate into a bin is just a division by 0.0009 (and rounding down to the closest integer).
So, first you will have to decide what you can compromise. Is it important to have equal area in the polygons, equal longitudinal distance, equal latitude distance, etc.? Is it important to have four corners in the polygon? Is it important to have similar or almost similar polygons close to the poles and close to the equator? Once you know the limitations set by your application, choosing the projection becomes easier.
What you are trying to do here is a projection onto a flat surface of an ellipsoid. So as long as your points are close together, and, well, you don't mind getting the answer slightly wrong you can assume that your projection plane intersects in the centre of your collection of points, and, each degree of lat and lon are a constant number of metres. Then the problem is a simple planar calculation.
This is wrong, of course. I would actually recommend that you look into map projections, pick one that makes sense, and go for that. Remember that you can move the centre of the projection to the centre to your set of points which will reduce distortion.
I suspect that PROJ.4 might help you in terms of libraries. There also must be a good Java one but that is not my speciality.
Finally you can could assume that the earth is a sphere and do your calculations on the sphere. Or, if you really want to get it right you can pick a standard earth ellipsoid and do the calculations on that.
Related
I'm not quite sure the best way to articulate this question, but I am trying to find a relatively simple way programmatically (in Java ideally, though theory is welcome too) to iterate through voxels one at a time starting from a center point and radiating out spherically. The idea is that I can specify a final radius (r) and starting coordinate <x, y, z> and at any given point in the process, the code will have iterated through each point within a radius that grows from 0 to r over the course of the function.
To be clear, I know how to search every coordinate in a spherical volume using spherical coordinates, but I don't know how to do it in the right order (starting from the center and moving outward.) Also, because it's voxels, I don't want to waste a bunch of time rounding iterations in the center just so the resolution can be complete on the outer surface. Ideally, each iteration should cover a new voxel and each voxel should be iterated exactly once (although I am open to compromise if that isn't possible).
Thanks for your help, let me know if I need to specify any further.
I have a position given in decimal degrees (x.xxxxxxxx and y.yyyyyyyy). I need to draw a rectangle around it. The center of the rectangle matches the position. The dimensions of the rectangle is given in meters and it has a rotation ranging from 0-360 degrees.
Question
How can I calculate the four corners of the rectangle and return the result as four decimal degree values? Like arrayOf<LatLon> getRectangle(LatLon position, int rectWidthCm, int rectLengthCm, double rectRotation).
Example
I have a position given in LatLon format with two two values: latitude and longitude. We will assume this location is precise.
The main task is to draw a rectangle based on this position in a Google Maps chart. The rectangle can have any dimentions but let's use these in this example: Width = 0.9 meter and Length = 1.2 meters. Any heading may also be given so lets use this heading: 45. 0 Is north and going clockwise round (east = 90, south = 180 and west = 270). When the rectangle is pointing north it has the length in the north/south direction. Finally, the rectangle center should be equal to the given position.
Note: The project setup is an Android application with Kotlin support and a google maps chart. I am interested in a modern approach to this problem. Regarding precision loss it should at most be within centimeters.
I understand that you are looking for a function geo_rect(x,y,w,h,a) with the following parameters
x is the longitude according to WGS84
y is the latitude
w is the width of the rectangle in meters
h is the height of the rectangle in meters
a is the angle to which the rectangle is turned from w being horizontal (meaning pointing exactly West to East). I suggest to allow values ranging within the open interval (-90°,90°) as this makes the math either to understand.
Your function getRectangle(LatLon position, int rectWidthCm, int rectLengthCm, double rectRotation) deliver all the required information, you need a small wrapper function which determines w, h, and a from rectWidthCm, rectLengthCm and rectRotation, with the latter being within [0°,360°).
The function geo_rect() will return an arrayOf<LatLon> of length four, namely the coordinates of all four corners, starting on the top left and then going clockwise. We will refer to the points as P_NE,P_NW,P_SE, and P_SW respectively.
Assumptions
In order to keep things mathematically feasible, we make some assumptions
We assume that we can use as approximation that the rectangle is a plane, which is okay if w ~ h << r with r = 6378 km being the radius of the Earth.
We further assume that the Earth is a ideal sphere rather than an ellipsoid or even more bumpy. For an accessible article on that issue, see e.g. Zachary C. Eilon's blog
Basic structure of the algorithm
The algorithm could be structured as follows:
Determine the distance d from (x,y) to all four end points. Because of our first assumption we can use simple Euclidian geometry rather than intricate Spherical geometry. Pythagoras holds: d^2 = (w/2)^2 + (h/2)^2.
We also need the four bearings, e.g. b_NW for the angle between the vector pointing to the North Pole and the vector pointing from (x,y) to point P_NW.
Given the information (x,y,d,b_NW, b_NE, b_SW, b_SE) from the previous steps, we can now follow Get lat/long given current point, distance and bearing to calculate the position of all four points. This is the mathematically hard part where I suggest to use a well-established and tested library for.
Last but not least, let us double-check whether the calculation went well by evaluating Great circle distances between some or all pairs of points. For instance d(P_NE,P_NW) should approximately be w, d(P_NW,P_SW) should approximately be h. Don't be surprised if there is actually a difference - this errors are due the assumptions we made. Normal GPS under usual conditions will anyhow not allow you to determine your position up to the centimeter, you will need DPGS for that.
Further reading
At https://www.movable-type.co.uk/scripts/latlong-vectors.html you can experiment online to determine a destination point along a great-circle given the distance and bearing from a start point (in our case: the center of the rectangle).
Old, but amazingly documented and well tested tool kit for geo-applications in general are the https://www.generic-mapping-tools.org/ - you might want to look at the command gmtvector.
If you are looking for java implementations, I found e.g.
https://introcs.cs.princeton.edu/java/12types/GreatCircle.java.html on of many implementations for calculating great circle distances
Need a standalone Java library for performing spatial calculations on lat/lon data
Calculate point based on distance and direction
I am trying to practice my skills with using latitude and longitude and I'm attempting to determine the following: given a center point X on a map and a point around it called Y, how do I tell whether or not the points around the center are moving away from the center object or towards it using latitude and longitude?
Right now I have the center latitude and longitude and am focusing on one of the points around it. I have used the Haversine method to calculate distance in miles between two lats and longs. Using this I measured the initial distance the from X to Y and assigned it to a variable. Upon Y's first move I recalculated the overall distance from X to Y and compared it with the initial. If the new measurement is greater than the old then your distance from the point X is increasing, if not it's decreasing. Also, I have check to make sure what I'm working with the point Y is ACTUALLY moving some distance with each move, not just going around the radius of point X in some weird fashion.
Is the way I'm doing things sound alright? I keep feeling like I need to fine tune something but I just can't put my finger on it.
Hopefully everything I'm saying makes sense and is not falling on deaf ears and this doesn't get flagged as an non-constructive question. It definitely is.
Yes, this is the correct way, I have done this some years ago:
In praxis you get the coordinates from a GPS device. Therfore you may consider additional filtering, e.g ignore situtions where the device stands still. Because this may introduce positional jumps.
In your question I saw that you already use a filtering by distance moved: this is suitable!
You can use the haversine formula, like you propose. For high load situations, there are faster distance formulas, for your task (small distances), which do not need so much trigonometric calls, but this is a minor topic.
I'm working on an Android game and would like to implement a 2D grid to visualize the effects of gravity on the playing field. I'd like to distort the grid based on various objects on my playing field. The effect I'm looking for is similar to the following from the Processing library:
Except that my grid will be simpler- 2D, and viewed strictly from the top, as if looking down at the playfield.
Can someone point me to an algorithm for drawing such a grid?
The one idea that I came up with was to draw the lines as if they were "particles"- start at one end of the screen and draw the line in multiple segments, treating each segment as a particle, calculating the effect of gravity at each segment's location.
The application is intended to run on Android.
Thanks
I would draw each line as a separate segment, as you mentioned. If the grid is sparse, it might be fastest.
If you are viewing the grid from above, you would need to calculate x and y coordinate displacements. The easiest way would be to actually do displacement along the z axis and then fake perspective with x_result = x/z and y_result = y/z . You set z=1 and make sure to vary it only relatively slightly (+- 0.1 for instance).
Your z should be proportional to the sum of 1/(distance to the sphere)^2. This simulates how gravity works - it tapers off with square of the distance. Great news - square of the distance means to calculate delta_x^2 + delta_y^2 - so you save yourself that square root calculation == faster.
I have two geo-spatial simple convex polygon areas, in latitudes and longitudes (decimal degrees) that I want to compute using Javas Polygon class. I basically want to see if these two lat,long polygons intersect, and to calculate the areas (in sq meters) of both.
Now java.awt.Polygon class only uses x,y co-ordinate system, but I need to use lats,longs.
How can I do this, and/or is there any other classes/libraries available?
Why not use Polygon class multiplying coordinates for 10^n making them integers? Polygon accepts arrays of int as points.
Just an Idea
All you need to do is convert from spherical to rectangular coordinates if you think that really matters.
I'm not sure that it does, because the java.awt.Polygon is merely a data structure holding for pairs of values. If you read the javadocs, they say
The Polygon class encapsulates a description of a closed, two-dimensional region within a coordinate space. This region is bounded by an arbitrary number of line segments, each of which is one side of the polygon. Internally, a polygon comprises of a list of (x,y) coordinate pairs, where each pair defines a vertex of the polygon, and two successive pairs are the endpoints of a line that is a side of the polygon. The first and final pairs of (x,y) points are joined by a line segment that closes the polygon.
They happen to label those points as x and y, which makes all of us think rectangular coordinates, but they need not be from your point of view. A bug on the service of your sphere would view it as a 2D space. Your radius is large and constant. You just can't count on using any of Polygon's methods (e.g., contains(), getBounds2D(), etc.)
In this case, the important thing is your area calculation. You can use a Polygon for your area calculation, storing lats and longs, as long as you view Polygon as a data structure.
You might also thing of abandoning this idea and writing your own. It's not too hard to create your own Point and Polygon for spherical coordinates and doing it all with that coordinate system in mind from the start. Better abstraction, less guessing for clients. Your attempt to reuse java.awt.Polygon is admirable, but not necessary.
You can perform the area calculation easily by converting it to a contour integral and using Gaussian quadrature to integrate along each straight line boundary segment. You can even include the curvature of each segment at each integration point, since you know the formula.
Going off my intuition here.
If the polygons are small in ratio to the size of the planet you can treat them as flat polygons. The steps involved would be converting the lat/long into absolute x/y/z, taking any three of the points and finding the normal of the plane the polygons lie on and then using this to project the points into two dimensions. Once you have the 2D points it's easy to calculate the area or if they intersect.
Probably not the best answer but hopefully it will motivate some people to make better ones because it's a good question.
Maybe you could use GeoTools for this. It allows you to create Geometry objects, and check wether they intersect (see: Geometry Relationships)
Here is a solution that works like a charm:
Class PolygonArea from net.sf.geographiclib
Refer link below with sample code:
https://geographiclib.sourceforge.io/html/java/net/sf/geographiclib/PolygonArea.html
gradle dependency:
compile group: 'net.sf.geographiclib', name: 'GeographicLib-Java', version: '1.42'