I have this coordinate: 778597.3125000001, 9148353. I am told this coordinate is Arc 1960 / UTM zone 36S.
When I go here and click "Get Position on Map" and enter in the above coordinates, it places the point in the correct place on the map (at the corner of a field).
What kind of transform/projection do I have to do to make it Latitude and Longitude, and then go to the same point in Google Maps?
I have tried various ways but seems to end up 400 - 200m diagonal offset.
The correct latitude and longitude should be: Lat: -7.699944 Long: 35.5262575 (corner of the field, see link):
I am using DotSpatial.
var Arc1960UTMZone36S = KnownCoordinateSystems.Projected.UtmOther.Arc1960UTMZone36S;
Arc1960UTMZone36S.AuthorityCode = 21036;
var WGS1984 = KnownCoordinateSystems.Geographic.World.WGS1984;
//4326 google earth
//3857 for google maps
WGS1984.AuthorityCode = 3857;
double[] xy = new double[2] { 778597.3125000001, 9148353 };
double[] z = new double[1] { 0d };
Reproject.ReprojectPoints(xy, z, Arc1960UTMZone36S, WGS1984, 0, 1);
var latitude = xy[1];
var longitude = xy[0];
Debug.WriteLine($"Lat: {latitude} Long: {longitude}");
Would anybody know why it is offset?
The solution was to use proj4 string instead of the Known Coordinate System.
Instead of
var Arc1960UTMZone36S = KnownCoordinateSystems.Projected.UtmOther.Arc1960UTMZone36S;
Arc1960UTMZone36S.AuthorityCode = 21036;
Use
String proj4_21036_str = "+proj=utm +zone=36 +south +ellps=clrk80 +towgs84=-160,-6,-302,0,0,0,0 +units=m +no_defs";
ProjectionInfo proj21036 = ProjectionInfo.FromProj4String(proj4_21036_str);
although, I don't understand why.
Related
New to GeoTools and GIS and I am trying to calculate distance between Mumbai and Durban using GeoTools library. I am getting close to accurate results for small distances but when i go for bigger ones,the calculation is way too offcourse by 2000 km, i dont completely understand the CRS system .Below is my Code to calculate the distance between Mumbai and Durban
Coordinate source = new Coordinate(19.0760, 72.8777); ///Mumbai Lat Long
Coordinate destination1 = new Coordinate(-29.883333, 31.049999); //Durban Lat Long
GeometryFactory geometryFactory = new GeometryFactory();
Geometry point1 = geometryFactory.createPoint(source);
Geometry point2 = geometryFactory.createPoint(destination1);
CoordinateReferenceSystem auto = auto = CRS.decode("AUTO:42001,13.45,52.3");
MathTransform transform = CRS.findMathTransform(DefaultGeographicCRS.WGS84, auto);
Geometry g3 = JTS.transform(point1, transform);
Geometry g4 = JTS.transform(point2, transform);
double distance = g3.distance(g4);
This is what happens when you copy code blindly from stackexchange questions without reading the question it was based on which explains why.
All the times I've answered that question (and posted code like that) the questioner is trying to use lat/lon coordinates in degrees to measure a short distance in metres. The trick shown in your question creates an automatic UTM projection centred on the position specified after the "AUTO:42001," bit (in your case 52N 13E) - this needs to be the centre of the area you are interested in, so in your case those values are probably wrong anyway.
But you aren't interested in a small region Mumbai to Durban is a significant way around the Earth so you need to allow for the curvature of the Earth's surface. Also you aren't trying to do something difficult for which JTS is the only source of process (e.g buffering). In this case you should use the GeodeticCalculator which takes the shape of the Earth into account using the library from C. F. F. Karney, Algorithms for geodesics, J. Geodesy 87, 43–55 (2013).
Anyway enough explanation that no one will read in the future, here's the code:
public static void main(String[] args) {
DefaultGeographicCRS crs = DefaultGeographicCRS.WGS84;
if (args.length != 4) {
System.err.println("Need 4 numbers lat_1 lon_1 lat_2 lon_2");
return;
}
GeometryFactory geomFactory = new GeometryFactory();
Point[] points = new Point[2];
for (int i = 0, k = 0; i < 2; i++, k += 2) {
double x = Double.valueOf(args[k]);
double y = Double.valueOf(args[k + 1]);
if (CRS.getAxisOrder(crs).equals(AxisOrder.NORTH_EAST)) {
System.out.println("working with a lat/lon crs");
points[i] = geomFactory.createPoint(new Coordinate(x, y));
} else {
System.out.println("working with a lon/lat crs");
points[i] = geomFactory.createPoint(new Coordinate(y, x));
}
}
double distance = 0.0;
GeodeticCalculator calc = new GeodeticCalculator(crs);
calc.setStartingGeographicPoint(points[0].getX(), points[0].getY());
calc.setDestinationGeographicPoint(points[1].getX(), points[1].getY());
distance = calc.getOrthodromicDistance();
double bearing = calc.getAzimuth();
Quantity<Length> dist = Quantities.getQuantity(distance, SI.METRE);
System.out.println(dist.to(MetricPrefix.KILO(SI.METRE)).getValue() + " Km");
System.out.println(dist.to(USCustomary.MILE).getValue() + " miles");
System.out.println("Bearing " + bearing + " degrees");
}
Giving:
working with a lon/lat crs
POINT (72.8777 19.076)
POINT (31.049999 -29.883333)
7032.866960793305 Km
4370.020928274692 miles
Bearing -139.53428618565218 degrees
I have a rectangular polygon and I want to extend the boundaries by 10 km for example.
How would I do that ?
I could use extend method, but how Do I find the distance of 10 km in lat lng ?
So far I have :
bounds = new google.maps.LatLngBounds();
pt = new google.maps.LatLng(lat,lng);
bounds.extend(pt)
It depends on how exact an answer you need.
You could use the following approximation:
Latitude: 1 deg = 110.57 km; Longitude: 1 deg = 111.320 km source: http://en.wikipedia.org/wiki/Latitude
For a more exact formula, you need to check http://www.movable-type.co.uk/scripts/latlong.html . It has various formulas and also some code. You are looking for the section called 'Destination point given distance and bearing from start point'
It depends where you are looking at but a longitude is 111km and a latitude 110km:http://en.m.wikipedia.org/wiki/Latitude.
I am working on an user interface that shows many pins on a map.
During the development I am randomly generating 1500 map pins just to be placed on the map to test look/feel/performance etc. issues.
The code which does that looks like this:
for (var i = 0; i <= 1500; i += 1) {
$scope.mapPins.push({
latitude: (Math.random() * 2) + 51,
longitude: (Math.random() * 4) + 3,
icon: themeImages[Math.floor(Math.random() * themeImages.length)],
title: 'Sample title',
infoContent: 'Sample content'
});
}
Naturally the area of the pins covered is a rectangle for latitudes 51-53 and longitudes 3-7. For those who are wondering where it is, it is the area roughly around Netherlands.
Now, there's a little problem that the Netherlands is not a rectangular area and a lot of these coordinates fall over the sea and I would like my coordinates to be only on the land.
Is there a witty mathematical way how I can pool coordinates from a non-rectangular area?
Of course I could make a google.maps polygon object that covers a nonrectangular shape and then via google api test every random generated pin whether it falls within the bounds of this shape etc, but that would be an overkill for UI design phase. Basically my question is whether there is a neat mathematical trick that would allow me to randomly generate coordinates from a non-rectangular space.
Leave your code as it is, the rectangle is the bounding box over your area of interest.
Then add a line
if (isPointInpolygon(polygon, longitudeOrX, latitudeOrY) {
// use this location
}
now you only need to search for a point in polygon function, which is easy to find.
you can directly use the coordinates in (long, lat) order, longitude is related to x coordinate, lat to y.
The polygon has to be filled with the coordinates of the country not insode the water.
If you have islands, then maybe you need multiple such polygons, then iterate over all.
Not to be a stickler but you're actually generating 1501 map pins :)
It is very unlikely that you'll find a simpler solution than using a simple pointinpolygon check.
Use the Google Maps Drawing library (https://developers.google.com/maps/documentation/javascript/drawing#using_the_library) to draw a polygon around the boundary of the Netherlands and save it however you want (e.g., in database, or just copy the string that defines the boundary's coordinates).
Then in your script above, define the google maps polygon (similar to what is done here in the official docs: https://developers.google.com/maps/documentation/javascript/shapes#polygons), then use the containsLocation method in the Google Maps Geometry library (https://developers.google.com/maps/documentation/javascript/examples/poly-containsLocation) to check if your random map pins lie within the boundaries of the Netherlands before adding them to the map.
For example:
var netherlandsCoords = [
// comma-separated list of coordinates defining the Netherlands boundary
];
var netherlandsBoundary = new google.maps.Polygon({
path: netherlandsCoords
});
for (var i = 0; i <= 1500; i += 1) {
var lat = (Math.random() * 2) + 51;
var lng = (Math.random() * 4) + 3;
var latlng = new google.maps.LatLng(lat, lng);
if (google.maps.geometry.poly.containsLocation(latlng, netherlandsBoundary)) {
$scope.mapPins.push({
latitude: lat,
longitude: lng,
icon: themeImages[Math.floor(Math.random() * themeImages.length)],
title: 'Sample title',
infoContent: 'Sample content'
});
}
}
I am trying to request an image from the Google Static Maps API with the borders of the map specified by a pair of latitude and longitude coordinates. I've tried centering on the center of the two coordinates, but there doesn't seem to be any parameter for doing this with the Static API. Does anyone know how to do this?
Note: this is for a desktop application, and I am not using the Javascript API.
The thing is that you cannot base the request on the map's corners because 1. zoom levels are discrete values and 2. the amount of latitude that a pixel represents varies with latitude. So, to display 2 degrees you'll need a given map height near the equator and a different height, (greater), near the poles. Are you willing to display maps of different heights in order to fit always 2 degrees?
If so, you can use the MercatorProjection object from my other post, and use the following function to calculate the necessary map size:
<script src="MercatorProjection.js"></script>
function getMapSize(center,zoom){
var proj = new MercatorProjection();
var scale = Math.pow(2,zoom);
var centerPx = proj.fromLatLngToPoint(center);
var SW = new google.maps.LatLng(center.lat()-1,center.lng()-1);
var southzWestPx = proj.fromLatLngToPoint(SW);
var NE = new google.maps.LatLng(center.lat()+1,center.lng()+1);
var northEastPx = proj.fromLatLngToPoint(NE);
// Then you can calculate the necessary width and height of the map:
var mapWidth = Math.round((northEastPx.x - southzWestPx.x) * scale);
var mapHeight = Math.round((southzWestPx.y - northEastPx.y) * scale);
}
With center = new google.maps.LatLng(49.141404, -121.960988) and zoom = 7 you get that you need a map of (W x H) 182 x 278 pixels in order to display 2 x 2 degrees.
This question already has an answer here:
Closed 10 years ago.
Possible Duplicate:
Calculate “as the crow flies” distance php
I am trying to develop a GoogleMaps page where I can get the user location and show custom marker points from an XML file that fells within the calculated area around the user.
To make things more clear :
I have a radius parameter from WebConfig file, say 5000 (in meters)
I've found the user location on map,
Using the xml list that I own (xml has the Lat-Long values of
each store) I want to put custom markers on map which fell within
the 5 km^2 area range with the user's location as center.
Is there a way to achieve this goal?
How do I calculate a point's Lat & Long values by only passing user's location coordinates and a distance parameter (say 5000 in my case)?
Edit :
My XML doc is kinda huge including whitegoods stores all around the
country. My main problem is to filter these rows of data (long,latt)
using user's current location.
I need something like:
func distanceCale(int long, int latt, int radius)
to return me some values that can help me filter my XML data.
I guess my question was not clear enough at the firs place. :)
You can achieve this using the Haversine formula. This formula has been used in a Demo from an XML file showing markers within a given radius.
For your application the javascript code is used to generate markers from XML file.
function deg2rad(degrees){
radians = degrees * (Math.PI/180);
//document.write(radians);
return radians;
}
function Haversine(lat1,lon1,lat2,lon2) {
deltaLat = lat2 - lat1 ;
deltaLon = lon2 - lon1 ;
earthRadius = 3959; // in miles 6371 in meters.
alpha = deltaLat/2;
beta = deltaLon/2;
a = Math.sin(deg2rad(alpha)) * Math.sin(deg2rad(alpha)) + Math.cos(deg2rad(lat1)) * Math.cos(deg2rad(lat2)) * Math.sin(deg2rad(beta)) * Math.sin(deg2rad(beta)) ;
c = 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1-a));
distance = earthRadius * c;
return distance.toFixed(2);
}
The Haversine function is used when parsing XML
var radius = document.getElementById('radiusSelect').value;
for (var i = 0; i < markerNodes.length; i++) {
var lat = parseFloat(markerNodes[i].getAttribute("lat"));
var lng = parseFloat(markerNodes[i].getAttribute("lng"));
var latlng = new google.maps.LatLng(
lat,
lng);
var distance = Haversine(center.lat(),center.lng(),lat,lng);
if(distance<=radius) {
createOption(name, distance, i);
createMarker(latlng, name, distance);
bounds.extend(latlng);
}