How do I compute the distance in mile/meters of the displayed Map? Assuming I have the coordinates of the center of the map. I would like to know the distance/radius from the center to the left/right most displayed part of the map? I already got this using Google Map but I'm new in Openlayers. Is there a way to achieve this? Right now my computation in GoogleMap is like this
var bounds = this.instance.getBounds();
var center = bounds.getCenter();
var ne = bounds.getNorthEast();
// r = radius of the earth in statute miles
var r = 3963.0;
var to_radians_divide = 57.2958;
// Convert lat or lng from decimal degrees into radians (divide by 57.2958)
var lat1 = center.lat() / to_radians_divide;
var lon1 = center.lng() / to_radians_divide;
var lat2 = ne.lat() / to_radians_divide;
var lon2 = ne.lng() / to_radians_divide;
// distance = circle radius from center to Northeast corner of bounds
var dis = r * Math.acos(Math.sin(lat1) * Math.sin(lat2) +
Math.cos(lat1) * Math.cos(lat2) * Math.cos(lon2 - lon1));
return dis;
Is there a way to achieve this in OpenLayers? I just want to find out the distance of the left most part of the displayed map from the center
You can achieve this in openlayers also. Here is the code for that and I am using openlayers 3.20.0 version for this example.
var size = map.getSize();
var center = map.getView().getCenter();
var sourceProj = map.getView().getProjection();
var extent = map.getView().calculateExtent(size);
extent = ol.proj.transformExtent(extent, sourceProj, 'EPSG:4326');
var posSW = [extent[0], extent[1]];
var posNE = [extent[2], extent[3]];
center = ol.proj.transform(center, sourceProj, 'EPSG:4326');
var wgs84Sphere = new ol.Sphere(6378137);
var centerToSW = wgs84Sphere.haversineDistance(center, posSW);
var centerToNE = wgs84Sphere.haversineDistance(center, posNE);
console.log("centerToSW - ",centerToSW);
console.log("centerToNE - ",centerToNE);
Related
How can I get the current width of the visible area on Google map, i have read many docs but not success? I need to get real width of visible area in kilometers.
I think getBounds() is what you are looking for.
var map = new google.maps.Map(document.getElementById("map_canvas"),
myOptions);
google.maps.event.addListener(map, 'idle', function(event) {
var bounds = map.getBounds();
You will receive a LatLngBounds object (for reference https://developers.google.com/maps/documentation/javascript/reference#LatLngBounds).
This contains NortEase and SouthWest LatLng points. Using those it should be easy to get the width in kilometers using this formula. You can create 2 pairs out of LatLng points to create a NorthWest and NorthEast pair and calculate the distance between those.
var R = 6371000; // metres
var φ1 = lat1.toRadians();
var φ2 = lat2.toRadians();
var Δφ = (lat2-lat1).toRadians();
var Δλ = (lon2-lon1).toRadians();
var a = Math.sin(Δφ/2) * Math.sin(Δφ/2) +
Math.cos(φ1) * Math.cos(φ2) *
Math.sin(Δλ/2) * Math.sin(Δλ/2);
var c = 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1-a));
var d = R * c;
See this as an reference (http://www.movable-type.co.uk/scripts/latlong.html).
I am working on an application where I have the center of a circle and the radius and I am plotting the circle with the help of Leaflet.
I placed a marker on the north most end of the circumference and made it draggable.
var circle = L.circle(coords, radius).addTo(map);
convertRadiusToLatitude = parseInt(response.radius)/111111;
var coordsOnRadius = [parseFloat(response.lat) + convertRadiusToLatitude, parseFloat(response.long)];
var markerOnRadius = L.marker(coordsOnRadius, {draggable: true}).addTo(map);
Now, this adds the marker to the circumference and now I wanted it to be draggable only on the circumference itself for which I used the parametric equation.
Parametric equation
x = Xc + R * cos(theta)
y = Yc + R * sin(theta)
Code for dragging
markerOnRadius.on('drag', function(e){
bearing = marker.getLatLng().bearingTo(markerOnRadius.getLatLng());
var markerOnRadiusX = parseFloat(response.lat) + ((0.000009 * parseFloat(response.radius)) * Math.cos( toRad(bearing) ));
var markerOnRadiusY = parseFloat(response.long) + ((0.000009 * parseFloat(response.radius)) * Math.sin( toRad(bearing) ));
markerOnRadius.setLatLng([markerOnRadiusX, markerOnRadiusY]);
});
The bearingTo method:
L.LatLng.prototype.bearingTo = function(other) {
var d2r = L.LatLng.DEG_TO_RAD;
var r2d = L.LatLng.RAD_TO_DEG;
var lat1 = this.lat * d2r;
var lat2 = other.lat * d2r;
var dLon = (other.lng-this.lng) * d2r;
var y = Math.sin(dLon) * Math.cos(lat2);
var x = Math.cos(lat1)*Math.sin(lat2) - Math.sin(lat1)*Math.cos(lat2)*Math.cos(dLon);
var brng = Math.atan2(y, x);
brng = parseInt( brng * r2d );
brng = (brng + 360) % 360;
return brng;
};
Issue
When I start dragging the marker, this code is working fine and brings it back to the circumference at the bearing at which the marker is dragged to. But there is one problem, the coords on the circumference are slightly off and in terms of longitude. When the bearing is 0 (north), the coords are perfect, but when it is 90 (east), the longitude is slightly less that it should for the marker to be at the circumference.
Again at 180 (south), coords are perfect, but at 270 (west), the longitude calculated is slightly less and the marker tends towards the radius again.
So basically if you visualize the marker being dragged, it starts perfectly on the north end and starts coming inside the circle slightly increasing with the bearing till it reacher 90 and then starts going towards the circumference again till 180 when it is perfect again.
It forms more like a ellipse if you get the gist of it.
Could anyone tell me why is longitude coming a little off and why the marker moves in an elliptical path. Has it something to do with the world coordinates and window coordinates. Or are my equations slightly off somewhere?
It does look like a projection issue. In your dragging code you are basically doing
lat = a + r cos(baring)
long = b + r sin(baring)
giving a circle in the Lat-Long coordinates. This would work fine if you were at the equator with Mercator projection. You will get more distortion as you move further towards the polls.
Assume you are using the defaults for Leaflet reference doc You have the EPSG3857 Web Mercator coordinates.
If you want to ensure you have a exact circle it will be better to work using screen coordinates. You can get these using methods on the ICRS objects. First get the coordinate system L.CRS.EPSG3857 and use the latLngToPoint and pointToLatLng methods.
var crs = L.CRS.EPSG3857;
var zoom = ...; // how you calculate your zoom factor
markerOnRadius.on('drag', function(e){
var markerLL = marker.getLatLng()
var morLL = markerOnRadius.getLatLng();
var markerP = crs.latLngToPoint(markerLL,zoom);
var morP = crs.latLngToPoint(morLL,zoom);
// get the distance between the two points
var dist = markerP.distanceTo(morP);
// Get the vector from center to point
var A = morP.subtract(markerP);
// scale so its of the desired length
var B = A. multiplyBy( factor / dist);
// Add on the center
var C = markerP.add(B);
// Convert back to LatLong
var D = crs.pointToLatLng(C,zoom);
markerOnRadius.setLatLong(D);
});
I just recently started delving into ThreeJS. Currently I'm trying to plot a point on a sphere but it appears to be plotting in the southern hemispehre instead of the northern hemisphere. Vertically, it looks to be in the correct spot just on the bottom of the sphere instead of the top. I grabbed some code from this answer: https://stackoverflow.com/a/8982005/738201
In the image the yellow line with the red box is my plotted point. It should be in the upstate NY region instead of where it is now.
And lastly, the code.
function xyz(lat, lon){
var cosLat = Math.cos(lat*Math.PI/180.00);
var sinLat = Math.sin(lat*Math.PI/180.00);
var cosLon = Math.cos(lon*Math.PI/180.00);
var sinLon = Math.sin(lon*Math.PI/180.00);
var r = sphere.geometry.radius; //50
var coords = {};
coords.x = r * cosLat * cosLon;
coords.y = r * cosLat * sinLon;
coords.z = r * sinLat;
console.log(coords);
return coords;
}
// Lat/Lon from GoogleMaps
var coords = xyz(42.654162, -73.699830);
// returns {x: 10.321018160637124, y: -35.29474079777381, z: 33.878575178802286}
I suspect that the issue may be using 2D coords on a 3D sphere but if so, I'm not quite sure how to rectify that.
Try this, It will help to use directly lat and long on the map
function calcPosFromLatLon(phi, theta){
let lat = (90 - phi) * (Math.PI/180);
let lon = (theta + 180) * (Math.PI/180);
const x = -(Math.sin(lat)* Math.cos(lon))
const z = Math.sin(lat) * Math.sin(lon)
const y = Math.cos(lat)
}
calcPosFromLatLon(//coordinates here//)
I need use mercator projection to point the places by latitude and logitude in my svg application.I have serached a lot and i got these links,
http://en.wikipedia.org/wiki/Mercator_projection
Covert latitude/longitude point to a pixels (x,y) on mercator projection
CODE
//this lat and long is for chicago
var latitude = 41.850033; // (φ)
var longitude = -87.65005229999997; // (λ)
var PI = 3.14;
var mapWidth = 750;
var mapHeight = 380;
// get x value
var x = (mapWidth * (180+longitude) / 360) % mapWidth + (mapWidth / 2);
// convert from degrees to radians
var latRad = latitude * PI / 180;
// get y value
var mercN = Math.log(Math.tan((PI / 4) + (latRad / 2)));
var y = (mapHeight / 2) - (mapWidth * mercN / (2 * PI));
I've used this code in my application, but it doesn't work for me.
Please help to get x and y position from the latitude and longitude.
Any Suggestions should be appreciated.
You forgot the top left and bottom right corner of the map and the factor to multiply the x,y coordinates to give the correct map projection. You can use a fixed map coordinate, i.e. a factor or you can compute the bounding box:Convert lat/lon to pixel coordinate? and then compute the world width and height that fits the map's width and height.
Right now I have an array of locations and one of those locations will be a marker.
The second marker will be based on the location a user searches.
Right now the code is this:
function find_closest_marker( lat1, lon1 ) {
var pi = Math.PI;
var R = 6371; //equatorial radius
var distances = [];
var closest = -1;
var markers = allMyLocations;
for( i=0;i<markers.length; i++ ) {
var lat2 = markers[i][1];
var lon2 = markers[i][2];
var chLat = lat2-lat1;
var chLon = lon2-lon1;
var dLat = chLat*(pi/180);
var dLon = chLon*(pi/180);
var rLat1 = lat1*(pi/180);
var rLat2 = lat2*(pi/180);
var a = Math.sin(dLat/2) * Math.sin(dLat/2) +
Math.sin(dLon/2) * Math.sin(dLon/2) * Math.cos(rLat1) * Math.cos(rLat2);
var c = 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1-a));
var d = R * c;
distances[i] = d;
if ( closest == -1 || d < distances[closest] ) {
closest = i;
}
var closestMarker = markers[closest];
var newLat = markers[closest][1]
var newLon = markers[closest][2]
var b = new google.maps.LatLng(newLat, newLon);
map.setCenter(b);
map.setZoom(10);
google.maps.event.addListenerOnce(map, 'tilesloaded', function(){
ShowHideMenu();
if($('#newPos').length==0){
$('div.gmnoprint').last().parent().wrap('<div id="newPos" />');
}
//showInfoWindow(map, closest);
});
}
}
Right now this code gets the closest location from where a user searches and centers that on the page. What I'm trying to do is make it zoom so that the the location searched is centered and the location in the array is within the area of the maps. The map isn't a normal size, it is 790px by 400px.
Can someone please help me with the logic of zoom and how I could make this possible?
Have you tried the LatLngBounds function This function will construct a viewable are based upon the soutwest and north east corners. As a result the pins will be centered in the map. You can use zoom if you want but you could omit it to see if it gives you the desired result.
A sample of the code would be:
make your declaration
var mybounds = new google.maps.LatLngBounds();
then within your event listener where you create the markers add
mybounds.extend(b);
then finally outside of the event listener
map.fitBounds(mybounds)