How to find area of given coordinates? [closed] - javascript

Closed. This question does not meet Stack Overflow guidelines. It is not currently accepting answers.
This question does not appear to be about programming within the scope defined in the help center.
Closed 8 years ago.
Improve this question
How to find area of given coordinates?
Requirements:
I have a polygon coordinates on a map then we want to find area of polygon in hectares and acres
Coordinates are in decimal degrees area should be in decimal degrees
we can convert hectares and acres kindly replay me
Coordinates are
(10.072642780669105,76.3268655538559),(10.078051232146612,76.32986962795258]),(10.073530110959743,76.33390367031097)
Code
arr=[ [10.075854059674523, 76.32832467556],
[10.079825860518895, 76.33338868618011],
[10.076234340596953, 76.33806645870209],
[10.07065684212598, 76.33806645870209],
[10.068924417668397, 76.33175790309906] ];
var sum=0;
for(var i=0,l=arr.length-1;i<l;i++){ sum+=(arr[i][0]*arr[i+1][1]-arr[i+1][0]*arr[i][1]); }
alert('The Area of Ploygon is:'+(sum/2));

It's quite complex and is not exactly math.
If you want to get real world result not some math theory you have to notice that earth is not sphere - look for WGS 84 in Google.
One of algorithms that can be implemented quite fast is Montecarlo:
Find the minimum bounding box of polygon (for small areas you can handle earth as flat surface)
Calculate area of MBB as for rectangle S = a*b
Get N random points inside the rectangle
Find M = points inside the polygon
Surface of your polygon is S*M/N
Increasing N gives you higher accuracy.
You should easy find algorithms for resolving each step (finding distance from one geo point to other geo point, checking if point x/y is inside of figure)

The polygon area code compares favorably with another math site where the problem is explained under 2-D polygons.
The problem is you have squared degrees.
Well, for small patches of land the Earth can be considered flat, and for converting squared degrees to hectares or acres or square meters you need to know how long a degree is.
At the Equator, a degree on Earth is 1/360th of the circumference of Earth which is 2*Pi*Rearth or ~40000km.
1 degree is approximately 1/360th of 40000 km = approximately 111 km per degree.
1km is 1000m. 1 km^2 = 10^6 m^2. But 1 hectrare = 10000 m^2, so 1km^2 is 100 hectares.
A squared degree will be approximately (111^2 km^2) (100 hectares/km^2) ~= 1232100 hectares
Ah, but I cheated, this only works near the Equator.
The Earth is a little bit fatter than 40000 km around, and also a degree of longitude becomes shorter as you get near the pole. Degrees of latitude N or S are always 1/360th of the way around the Earth from pole to pole, but degrees of longitude are widest at the equator and become narrower as cos(latitude).

Ideally you need a library to do the conversion for you.
It actually depends on where you are in the world and how precise you want to be. Bear in mind that land is neither flat nor necessarily aligned with the underlying sphereoid.
The company I work for sprays bracken from the air and produces maps of where the spraying occurred plotted on Ordnance survey maps accurate to a metre or two.
In the UK you may find these useful, they detail the complexity of these conversions which I'm not even going to try to summarise here.
http://www.ordnancesurvey.co.uk/business-and-government/help-and-support/navigation-technology/os-net/surveying.html
http://www.ordnancesurvey.co.uk/docs/support/guide-coordinate-systems-great-britain.pdf
It appears the Ordnance Survey don't have the old conversion paper that I learned from on their site but I found a copy here.
http://www.fgg.uni-lj.si/~/mkuhar/Zalozba/TM_projection.pdf

Related

Language-Agnostic way to mathematically determine HexBin of (N) size center coordinate, given Lat, Long input

I have latitude and longitude coordinates.
-76.054657667, 36.818969167
Is there a simple function that will translate these to a fall into the center of a hexagon (in lat/long coordinates) of whatever size within a tesselating hexagon map (units can be arbitrary, say meters if you have to)?
I understand it can ambiguous because in Uber h3 or the d3 hex model whatever, there can be variance in where one hexagon starts and ends depending on your global map. I'm looking for a vastly simplified model here.
For instance, for basic square coordinates, a simple rounding function could work on both long and lat. If you round longitude and latitude to 2 decimal places for instance, you can 'bin' them into squares of a constant size.
I'm trying to simply bin them into hexagonal shapes, but using a a vastly simplified function for now.
Perhaps this sort of simplification is not possible, but curious. Thanks!

How to translate markers into a half circle with minimal line intersection?

I have a map and a lot of markers are displayed on it. Sometimes markers are so close to each-other that they overlap. To remedy this, I have implemented a spiderfier library to remedy this situation.
The idea is to group the markers being close-enough upwards on the screen (downwards mathematically) in such a way that they will not intersect each-other.
Markers are displayed as rectangles.
Implementation:
traverses the markers and markers which intersect each-other are included into a group with the center of ((minX + maxX) / 2, maxY) and the radius is just large-enough to display the markers on the periphery without intersecting each-other
while there are semi-circles which intersect each-other, we merge them into a larger half-circle
we sort the markers by a comparator, placing "smaller" markers to the left on the periphery of the circle compared to their "greater" counterparts
we display the markers on the top-half circle, but we display a line from their modified location to their real location
So far, so good.
Problem: These lines are intersecting each-other too often and we need a comparator function with which the number of marker line intersection is minimalized.
Tries:
P1.x <= P2.x => P1 <= P2
arctan((P1.y - C.y) / (R * (P1.x - C.x))) <= arctan((P2.y - C.y) / (R * (P2.x - C.x))) => P1 <= P2
I had high hopes tied to the second try, but had to acknowledge that it is not a good idea, since the translation line and the line between the real location and the center of the circle are not necessarily collinear, in fact, their angle can become fairly big if there are many markers having their real location very close to each-other, whilst the half-circle's surface except this sub-region is fairly barren. So, this leads to intersections as well and it is much more complex than the first try. I believe Javascript's Math.atan is implemented either with Taylor series or Fourier series, which involves derivatives in the first case and integral in the second case. Or, there might be a third approach, which is highly complex as well. I would think about optimizations and stuff like that if this second approach would have significantly reduced the number of intersections, but since the improvement is barely observable if at all, I returned to the first approach.
I am thinking about the following approach:
calculate the locations of the marker slots on the periphery
try to translate all the markers to their closest possible slot
find the conflicting groups and solve all conflicts by finding the optimum, which is the translation-set with the smallest total translation
Is this idea leading to a state where spider line intersection number is minimalized and if not, how could I minimalize the number of such intersections?
This is a difficult problems, studied for a long time now.
It is sometimes called
automatic label placement.
The work cited below is typical of what is available in the literature.
Van Kreveld, Marc, Tycho Strijk, and Alexander Wolff. "Point set labeling with sliding labels." Proceedings of the fourteenth annual symposium on Computational geometry. ACM, 1998. ACM link.

Query database values based on user's location

How can I perform a query on the database as per the user's location value? The application was developed with HTML5, CSS, Javascript, PHP has a database with columns as in the below table.
On the html webpage the users geo coordinates are collected and are to be compared with the values in the database to find the nearest place to the user with the places in the database.
Please let me know how to achieve this. Any examples / samples will be appreciated.
There is a question that compares the capabilities of various spatial databases, GIS: PostGIS/PostgreSQL vs. MySql vs. SQL Server?, where Postgis comes out a pretty clear winner over MySQL.
Whether you use MySQL or Postgis, you would be much better off, if you can, storing your latitude and longitude values as a geometry/geography (Point), as the functions that can be used to find things nearby, ST_Distance, ST_Distance_Sphere and the more obscure <-> operator, see Find n Nearest Neighbors for given Point using PostGIS? (for example usage) work directly on geometry/geography columns. Even more importantly, you can add a spatial index, which these functions need to work properly, which will outperform searches on separately indexed latitude and longitude columns by a large margin (this will depend on table size, but will grow as table size grows),
In Postgis, you can convert lat and lon to a geometry with:
alter table mytable add column geom (Geometry, 4326);
update mytable set geom = ST_SetSRID(ST_MakePoint(lon, lat), 4326)
create index ix_spatial_mytable_geom on mytable using gist(geom);
At this point, you will be able to very efficient queries to find points near other points, using any of the examples in the above links.
You can do similar things in MySQL, although, it does not support a spatial reference system, ie, the 4326 above, which means lat/lon, and it lacks a ST_MakePoint function, so you would need to use STGeomFromText and concatenate the lat/lon together to make a POINT. It also does everything in planar coordinates, as Claudio and others have stated, which is not an issue with Postgis.
I apologize for a long and somewhat tangential answer, but having done various migrations between databases on large amounts of data (MySQL, SQL Server and Postgres/GIS) and made lots of mistakes on the way, I hope I can set you off in the right direction (and add a bit of future proofing, if you want to start using some other spatial functionality, which Postigs has in spades).
For a rough measure I would try something like the following (only Euclidean geometry, it doesn't take into account the Earth curvature or problems like this).
First you could compute the difference between the user's coordinates and the coordinates of places in the database. Like this:
distLat = abs(userLat - placeLat)
distLong = abs(userLong - placeLong)
Then I would compute the distance between the two points using Pythagora's theorem. So:
distance = squareRoot(distLat * distLat + distLong * distLong)
You can compare the distances of all places in the database and take the minimum, which teoreticaly is the place nearest to the user's position.
If you use MySQL I think that a query like this should work:
SELECT * FROM places ORDER BY MIN(SQRT((p.latitude - userLatitude) * (p.latitude - userLatitude) + (p.longitude - userLongitude) * (p.longitude - userLongitude))) LIMIT 1
Beware that this query could be very slow depending on how many places you have, because it needs to read all the rows in the table and compute the distance for each one. Indexes have no effects.
Anyway, for this kind of problems you should better use GIS or databases with good geospatial extensions. MySQL geospatial extension is not very powerful, even in MySQL 5.6. It has a ST_DISTANCE function but still uses Euclidean geometry which is not very accurate for calculation on a spherical surface like the Earth. Anyway, if you use MySQL 5.6, I think that it should be better to use the ST_DISTANCE function, which is for sure much more optimized than doing calculations "manually" in the query.
See also this article for a deep explanation and more examples: http://www.plumislandmedia.net/mysql/haversine-mysql-nearest-loc
EDIT
As requested by the OP, I add more details on how to deal with negative coordinates.
Negative coordinates are generally not a big issue. I will try to explain this with some examples.
Take for example the coordinates of the Brooklyn bridge: 40.704391, -73.994675.
With the above formula, the distance of the Brooklyn bridge from the Statue of Liberty is:
sqrt((40.704391 - 40.689167)^2 + (-73.994675 - -74.044444)^2) = 0.052045399
Now consider the distance between the Statue of Liberty and the Brooklyn Bowl (coordinates 40.7179666, -73.9670125), that is:
sqrt((40.7179666 - 40.689167)^2 + (-73.9670125 - -74.044444)^2) = 0.082613886
As you can see the distance of the Brooklyn Bowl from the Statue of Liberty is bigger than the distance of the Brooklyn Bridge. It is correct since the Brooklyn Bowl is 4 miles away from the Statue of Liberty, while the Brooklyn Bridge is only 1 mile away from it.
In this example both the two points has a negative longitude. But the formula works even if one of the two has positive coordinates. For example, the distance between the Statue of Liberty and the Tour Eiffel (Paris, coordinates 48.858360, 2.294460), is:
sqrt((48.858360 - 40.689167)^2 + (2.294460 - -74.044444)^2) = 76.77476134
Then calculate also the distance between the Statue of Liberty and the Colosseum (Rome, coordinates 41.890238, 12.492242):
sqrt((41.890238 - 40.689167)^2 + (12.492242 - -74.044444)^2) = 86.54502063
As you can see it works, the distance of the Colosseum is bigger since it is about 8000km away from the Statue of Liberty, while the Tour Eiffel is about 800 km closer.
The only issue I see is when you have to calculate the distance between two places that are in the far east and in the far west respectively. The above formula will give you a very high distance, but actually the they could be very close. Take for example Anchorage, a city in Alaska (coordinates 61.252240, -149.896769), and Beringovskij, a city in the very east of Russia (coordinates 63.049797, 179.310011). They have a distance of only about 1500 km but with the above formula you get:
sqrt((61.252240 - 63.049797)^2 + (-149.896769 - 179.310011)^2) = 329.2116875
Definitely a too high value for only 1500 km: I would expect something less than 50.
The problem is that the formula calculates the distance taking the central meridian as a reference point, that is the meridian with a 0 degrees latitude. This is good until the distance is "no more that half the Earth".
I think that a solution could be to calculate two distances.
The first with a reference point of 0 degrees: it is what the above formula does.
The second with a reference point of 180 degrees. It's like calculating the distance on a world map shifted by 180 degrees, like this: http://www.bouwman.com/world/Formilab-180.html.
And then take the minimum of these two distances.
Thus the formula becomes a little more complex:
distance = squareRoot(min((userLat - placeLat)^2, (userLat - placeLat - 360)^2) + (userLong - placeLong)^2)
Note that we subtract 360 because it is the distance between the degree -180 and the degree 180.
With this new formula we get correct results for places that are more then 180 degrees away from each other, and we get also the same result given by the previous formula when comparing places that are less then 180 degrees away from each other. The calculate distance Anchorage - Beringovskij is now: 30.84564166.
Of course, as I have already said, this is not an exact method for calculating distances. You can take a look at this article for more "scientific" techniques: https://en.wikipedia.org/wiki/Geographical_distance :D

Google Maps Javascript and working with Polygons crossing +/-180 meridian [duplicate]

This question already has answers here:
Google Maps API v3 Polygon closing
(2 answers)
Closed 8 years ago.
When working with polygons on google maps, there can be cases where a polygon will cross the map overlap. For example, when going to the right edge of the map, and placing points to create a box, with the left points on the right edge of the map, and the right points on the left edge of the repetition of the map (as the map can pan infinitely horizontally).
That said, I would see points close to the +180 and -180 extremes such as:
[50, 178] top left
[50, -178] top right
[-50, -178] bottom right
[-50, 178] bottom left
This is the data provided when pulled out from looping the polygon.getPath() points.
google.maps.event.addListener(drawingManager, 'polygoncomplete', function(polygon) {
polySelected = true;
coords = new Array();
polygon.getPath().forEach(function (l, index) {
coords[index]="("+l.lat()+","+l.lng()+")"
});
}
With this data, it is impossible to tell if the points actually cross the 180 meridian line. If I took out the 'upper left', 'upper right', you would have no way of discerning if the users second point was to the right (crossing 180) or left (making a very large box).
Is there any way around this? Such as not having 'wrapped' coordinates [50, 182] like that? What is the standard way of dealing with crossing the boundaries and having data representing that?
Thanks!
Edit - This is not a case of closing the polygon and having coordinates snap to a very large area. This case is for a normal polygon manual closure, creating a small square polygon, but one that crosses the map horizontal repeat and having the resultant coordinates be indistinguishable from a polygon that crosses the repeat 180 meridian line, or one that is very wide (but no different vertically) and covering the opposite area. I wish I could demonstrate with pictures to help explain but I do not have this functionality yet.
Answer
I do not see a way to answer my own question, however I have figured it out and want to share. I realized that you cannot draw an edge of a polygon that extends more than 180 degrees longitudinally. Knowing that, if you have two points that have a different of greater than 180, it crosses the +/-180 meridian.
Thanks to all who were offering support!
You can do this:
var longitude = l.lng();
while (longitude > 180)
longitude -= 360; // e.g. 182 and 542 become -178, which is the equivalent longitude
while (longitude < -180)
longitude += 360;
coords[index]="("+l.lat()+","+longitude+")";
As long as your latitude is between 90 and -90. If it isn't you need to fix that too... let me know if you need help with that.

GPS coordinates: 1km square around a point

I was hoping someone out there could provide me with an equation to calculate a 1km square (X from a.aaa to b.bbb, Y from c.ccc to c.ccc) around a given point, say lat = 53.38292839 and lon = -6.1843984? I'll also need 2km, 5km and 10km squares around a point.
I've tried googling around to no avail... It's late at night and was hoping someone might have quick fix handy before I delve into the trigonometry...
I'll be running all this in Javascript, although any language is fine.
If the world were a perfect sphere, according to basic trigonometry...
Degrees of latitude have the same linear distance anywhere in the world, because all lines of latitude are the same size. So 1 degree of latitude is equal to 1/360th of the circumference of the Earth, which is 1/360th of 40,075 km.
The length of a lines of longitude depends on the latitude. The line of longitude at latitude l will be cos(l)*40,075 km. One degree of longitude will be 1/360th of that.
So you can work backwards from that. Assuming you want something very close to one square kilometre, you'll want 1 * (360/40075) = 0.008983 degrees of latitude.
At your example latitude of 53.38292839, the line of longitude will be cos(53.38292839)*40075 = [approx] 23903.297 km long. So 1 km is 1 * (360/23903.297) = 0.015060 degrees.
In reality the Earth isn't a perfect sphere, it's fatter at the equator. And the above gives a really good answer for most of the useful area of the world, but is prone to go a little odd near the poles (where rectangles in long/lat stop looking anything like rectangles on the globe). If you were on the equator, for example, the hypothetical line of longitude is 0 km long. So how you'd deal with a need to count degrees on that will depend on why you want the numbers.
Here is something from my notes to be used on Android with its decimal GPS.
Lat Long:
NY City 40N 47 73W 58 40.783333 73.966667
Wash DC 38N 53 77W 02 38.883333 77.033333
yields = 209 miles !! VERY CLOSE
Distance (miles) (x) = 69.1 (lat2-lat1)
Distance(miles) (y) = 53.0 (long2 - long1)
As crow flys sqrt (x2 + y2) ... duh!#
delta(LAT) / Mile = .014472
delta(LONG) / Mile = .018519
Using a box as approximation
To find someone within 100 miles (100 north / 100 south, 100 E / 100 W)
From 0,0
-14.472 / + 14.472 , -18.519 / 18.519
A simpler way of generating a gps square given the centre would be to use the indirect Vincenty algorithm.The Javascript code here shows how to do it http://www.movable-type.co.uk/scripts/latlong.html.
Creating a square using a circle isn't to hard. Squares are equal distance to each point. So given a centre point, distance from the centre, change the bearing from 0 or any number depending on rotation of the square and increment by 90 degrees or PI/2 radians. By incrementing by 90 degrees each time and you will up with a square in circular space.
I use this myself for generating GPS points around a centre point with a given distance
.---.
--/-
--0--
-/--
.---.
TL;DR
10 km = 0.08999 radius from a certain geopoint. This calculation is only based on latitude values and applies only to geopoints with WGS84 projection.
More details
If you want a more accurate answer you must have to calculate it by building a function of some sort. However it still don't guarantee because people even quarrel for the degrees of error. Taking altitude into account, mercator or not, etc.
Caution
The value above is just a rule of a thumb so don not use it for critical applications.
Reference
GIS StackExchange, How do I calculate the bounding box for given a distance and latitude/longitude, answer by David the Australian developer

Categories