Drawing a line through 180 degrees longitude on the Bing Maps control doesn't work as I expect. 180 degrees longitude runs from north to south through the Pacific Ocean, so if I wanted to draw a line from (10, 175) to (-10, -175) - expecting a small (10 degrees) line crossing the equator somewhat north of New Zealand - I get a line stretching all the way around the globe, crossing the equator at 0 degrees long (south of Greenwich). How can I draw a line that transverses 180 deg long?
It is possible to approximate this by drawing two lines, from point a almost on the 180 degree meridian then from just past the 180 degree meridian to point b. So in a method that returns an IEnumerable<MapPolyLine>, where a is the closest point with a negative longitude and b is the closest point with a positive longitude:
var aa = Math.Abs(b.Longitude - a.Longitude - 360);
var bb = Math.Abs(b.Latitude - a.Latitude);
var aaa = 180 + a.Longitude;
var bbb = (bb / aa) * aaa;
var line1 = new MapPolyline
{
Color = Color.FromArgb(255, 0, 255, 0),
Width = 5
};
line1.Locations.Add(a);
line1.Locations.Add(new Location(a.Latitude - bbb, -179.999));
yield return line1;
var line2 = new MapPolyline
{
Color = Color.FromArgb(255, 0, 0, 255),
Width = 5
};
line2.Locations.Add(new Location(b.Latitude + bb - bbb, 179.999));
line2.Locations.Add(b);
yield return line2;
This could be cleaned up further and is just a workaround. Also some artifacts can appear but this seems pretty reliable.
Related
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.
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 am trying to calculate bearing between two lat/lon points as given in this link. I see that the bearing we get initially using the below equation is initial bearing.
public static double GetBearing(double latitude1, double longitude1, double latitude2, double longitude2)
{
var lat1 = ToRadians(latitude1);
var lat2 = ToRadians(latitude2);
var longdiff = ToRadians(longitude1 - longitude2);
var X = Math.Cos(lat2) * Math.Sin(longdiff);
var Y = Math.Cos(lat1) * Math.Sin(lat2) - Math.Sin(lat1) * Math.Cos(lat2) * Math.Cos(longdiff);
var bearing =ToDegrees(Math.Atan2(X, Y));
return (bearing+360)%360;
}
It is given that
For final bearing, simply take the initial bearing from the end point to the start point and reverse it (using θ = (θ+180) % 360).
I am confused about the difference between initial bearing and final bearing.
What is this initial and final bearing and which bearing should we take as the final answer for bearing between two points.
The bearing is the angle between direction along the shortest path to destination and direction to North. The reason we have initial and final one is that we live on sphere, so the shortest path is geodesic line. It is a straight line on globe, bit if you draw it on flat map - it will be a curve.
There are two ways to think about it. Thinking on flat map: as you travel from A to B, this curve changes direction slightly, so the angle between this line and North changes, i.e. bearing changes.
Or you can think on sphere, and then think about triangle A - B - North Pole. The bearing is angle between between AB and appropriate meridian. Initial bearing is angle between AB and meridian crossing A. Final one is angle between AB and meridian crossing B. They are different.
The single "final answer" bearing only makes sense when distance between A and B is short. Then the curvature of Earth does not matter much, and the initial and final bearings are very close to each other, so depending on precision needed one can talk about single bearing.
FYI: bearing and many related computations are implemented in the R package geosphere
The bearing function returns the initial bearing, but you can invert the coordinates to get the final bearing.
library(geosphere)
bearing(cbind(0,0),cbind(20,20))
#[1] 43.4035
finalb <- bearing(cbind(20,20),cbind(0,0))
(finalb + 180) %% 360
#[1] 46.9656
(these results should be more precise than the ones you get with algorithm you refer to)
def bearing(lat1, lon1, lat2, lon2):
# Convert latitude and longitude to radians
lat1 = math.radians(lat1)
lon1 = math.radians(lon1)
lat2 = math.radians(lat2)
lon2 = math.radians(lon2)
y = math.sin(lon2-lon1) * math.cos(lat2)
x = math.cos(lat1)*math.sin(lat2) - math.sin(lat1)*math.cos(lat2)*math.cos(lon2-lon1)
initial_bearing = math.degrees(math.atan2(y, x))
final_bearing = (initial_bearing + 180) % 360 if initial_bearing < 180 else (initial_bearing - 180) % 360
return initial_bearing, final_bearing
I'm trying to develop heat map, now initially I would have to draw the intensity mask, and since I'm using GWT so I have randomly generated some coordinates and placed my circles ( with required gradience ) at those locations so the output comes out to be circles overlapping each other. And If I look at the intensity mask from Dylan Vester, it comes to be very smooth How can I draw my heat map ?? Also how the output is achieved similar to Dylan Vester?? Question also is if I'm drawing circles then how to decide the intensity at the intersection of two or more circles, how they have achieved ?? Here is my code
// creating the object for the heat points
Heat_Point x = new Heat_Point();
// Variables for random locations
int Min = 1,Max = 300;
int randomx,randomy;
// Generating set of random values
for( int i = 0 ; i < 100 ; i++ ) {
// Generating random x and y coordinates
randomx = Min + (int)(Math.random() * ((Max - Min) + 1));
randomy = Min + (int)(Math.random() * ((Max - Min) + 1));
// Drawing the heat points at generated locations
x.Draw_Heatpoint(c1, randomx, randomy);
}
And Here is how I'm plotting my heat point that is Heat_Point class
Context con1 = c1.getContext2d(); // c1 is my canvas
CanvasGradient x1;
x1 = ((Context2d) con1).createRadialGradient(x,y,10,x,y,20);
x1.addColorStop(0,"black");
x1.addColorStop(1,"white");
((Context2d) con1).beginPath();
((Context2d) con1).setFillStyle(x1);
((Context2d) con1).arc(x,y,20, 0, Math.PI * 2.0, true);
((Context2d) con1).fill();
((Context2d) con1).closePath();`
here I was supposed to add some images but I didn't have enough reputation :D :P
I took a quick look at HeatmapJS (http://www.patrick-wied.at/static/heatmapjs/) and it seems he uses radial gradients (like you have above) and he also uses opacity and a color filter called "multiply blend" to smooth out the intensity of the colors in the heat map.
His code is quite impressive. It's open source, so you might want to check it out!
I am reading this: http://www.panoramio.com/api/widget/api.html#photo-widget to build a JavaScript photo widget.
Under Request -> request object table, it is written:
name: rect
example value: {'sw': {'lat': -30, 'lng': 10.5}, 'ne': {'lat': 50.5, 'lng': 30}}
meaning: This option is only valid for requests where you do not use the ids option. It indicates that only photos that are in a certain area are to be shown. The area is given as a latitude-longitude rectangle, with sw at the south-west corner and ne at the north-east corner. Each corner has a lat field for the latitude, in degrees, and a lng field for the longitude, in degrees. Northern latitudes and eastern longitudes are positive, and southern latitudes and western longitudes are negative. Note that the south-west corner may be more "eastern" than the north-east corner if the selected rectangle crosses the 180° meridian
But usually we are only given one latitude point, and one longitude point.
What kind of expressions should I write to build the four points as stated above, to cover the pictures around the area given two points I have in hand?
For example, I have in Paris:
lat: 48.8566667
lng: 2.3509871
I want to cover pictures around it 10km rectangle.
Thanks.
Here's the answer I got from Panoramio Forum by QuentinUK.
Can't do a 10km distance because this implies a circular region. It can only do rectangular.
So you might as well approximate (best is use Vincenty's formulae) and calculate an angle +/- around the point.
function requestAroundLatLong(lat,lng,km){
// angle per km = 360 / (2 * pi * 6378) = 0.0089833458
var angle=km* 0.0089833458;
var myRequest = new panoramio.PhotoRequest({
'rect': {'sw': {'lat': lat-angle, 'lng': lng-angle}, 'ne': {'lat': lat+angle, 'lng': lng+angle}}
});
return myRequest;
}
var widget = new panoramio.PhotoWidget('wapiblock', requestAroundLatLong(48.8566667, 2.3509871,10), myOptions);
If you want to use REST api:
var Lattitude = "48.8566667";
var Longitude = "2.3509871";
var angle = km * 0.0089833458;
testo.Text = "<script src=\"http://www.panoramio.com/map/get_panoramas.php?order=popularity&set=full&from=0&to=14&minx=" + clon - angle + "&miny=" + clat - angle + "&maxx=" + clon + angle + "&maxy=" + clat + angle + "&callback=mostrareFotos&size=medium\" type=\"text/javascript\"></script>";