How to get screen XY from Google maps (V3) LatLng? - javascript

I have polyline in my map. I want to know the pixel (screen) xy-coordinates, when user clicks the polyline. Click event only returns the LatLng object, so does anyone have a clue how to get the pixel coordinates from latLng?
I would appreciate very much if someone could help me!

If you have the LatLng object, you can use the google map projection object to transform it into tile coordinates and then into pixel coordinates:
For the docs on the projection class:
https://developers.google.com/maps/documentation/javascript/reference#Projection
Google's example explaining how to transform a LatLng into a pixel coordinate:
https://developers.google.com/maps/documentation/javascript/examples/map-coordinates?csw=1
There's one catch. The above will give you the pixel coordinates inside google's map div (which you may want depending on your needs). If you want the pixels relative to the top left corner of the screen, there's one more step. You need to do the same projection on the the viewport's top left corner and subtract the two. This will give you the pixel coordinates of the LatLng point.
The code I finally used looked like this (note that "latLng" is an input):
var numTiles = 1 << map.getZoom();
var projection = map.getProjection();
var worldCoordinate = projection.fromLatLngToPoint(latLng);
var pixelCoordinate = new google.maps.Point(
worldCoordinate.x * numTiles,
worldCoordinate.y * numTiles);
var topLeft = new google.maps.LatLng(
map.getBounds().getNorthEast().lat(),
map.getBounds().getSouthWest().lng()
);
var topLeftWorldCoordinate = projection.fromLatLngToPoint(topLeft);
var topLeftPixelCoordinate = new google.maps.Point(
topLeftWorldCoordinate.x * numTiles,
topLeftWorldCoordinate.y * numTiles);
return new google.maps.Point(
pixelCoordinate.x - topLeftPixelCoordinate.x,
pixelCoordinate.y - topLeftPixelCoordinate.y
)

Related

a failed attempt at placing a dot over an image based on known lat and lng points

I apologize for the vague title, I really can't figure out a batter way to sum it up. Suggestions are more than welcome.
I'm working on a project that really doesn't NEED a google map, it'd just create extra overhead for this project. But, I can't figure out how to do this WITHOUT google maps... so far.
If I were to place a graphical overlay of a floor plan into google maps, I could use a browser location to approximate a users position. For this, it's a VERY large place, so there's room for some poor accuracy.
Now what I'm trying to do is knowing the bounding of that overlay, place the image into a div, then calculate the users position in the div based on their browser lat/lng.
I'm able to get close using an image that is square in that the top of the sides are horizontal and vertical, because that crates my area. But since none of the world works like that, I need an area that isn't square to appear squared. I'm really struggling on the math.
Here's what I'm trying to do!
And here's a link that tests my concept, but doesn't account for an image that needs to be rotated on a map: http://www.freeptools.com/mapster/singlerun/maptest.php
Like I said, I'm sure that this can be done, but I haven't been able to figure out the math for it just yet. It's driving me crazy.
Here's my code that's doing the magic. A function gets the browser coordinates and sends them to the initialize function. Then based on mapping it myself earlier, I have the bounds of the image I'm trying to map. I'm using the haversine formuls to try to get the height and width at the points of the user (since the map curves, it'll be inaccurate anywhere else) position, then the distance from the top and left most points, then taking the distance from the left/top and dividing it by the width/height to get a percentage of how far they are from the left/top to position the dot. This idea, while I can't get it to be super accurate, works in this example, because the image lines up horizontally on a map. My problem is how do I calculate those distances when the image is rotated on a map? I can't figure out that math.
function initialize(y3, x3) { //lat, lon
//var overlayBounds = new google.maps.LatLngBounds(new google.maps.LatLng(41.11246878918085, -90.5712890625), new google.maps.LatLng(47.68652571374621, -82.001953125));
var box = $("#map_canvas");
//image bounds
var x1 = -82.001953125;
var x2 = -90.5712890625;
var y1 = 41.11246878918085;
var y2 = 47.68652571374621;
var boxWidth = x2 - x1;
var boxHeight = y2 - y1;
//now we need to figure out where this rests, first we get the percentage
//var posLeft = haversine(y3, x1, y3, x3); //(x3 - x1);
var posLeft = (x3 - x1);
var posLeftPct = (posLeft/boxWidth)*100;
//var posTop = haversine(y2, x3, y3, x3); //(y2 - y3);
var posTop = (y2 - y3);
var posTopPct = (posTop/boxHeight)*100;
box.append('<img src="http://www.freeptools.com/mapster/icons/icon23.png" style="position:absolute; z-index:200; right:'+posLeftPct+'%; top:'+posTopPct+'%">');
}
Assuming the area is a parallelogram, you'll need to know 3 of the vertices of the area and the width/height of the area where you want to draw the pin(e.g. the floorplan-image).
The following will use the Geo-and LatLon-libraries from http://www.movable-type.co.uk/scripts/latlong.html
An image for better understanding:
initially calculate some values:
bearings(nw to sw and nw to ne) via LatLon.bearingTo
distances(sw to nw and ne to nw) via LatLon.distanceTo
now calculate the intersections(marked as intersection-x and intersection-y in the image) via LatLon.intersection
The calculation would be:
intersection-x:
LatLon.intersection(ne, bearingNWtoSW, target, bearingNWtoNE)
intersection-y:
LatLon.intersection(sw, bearingNWtoNE, target,bearingNWtoSW)
now calculate percentual values for the distance of border-north to target and border-west to target:
border-north to target:
((distanceNWtoNE-(target.distanceTo(intersection-x)))*100)/distanceNWtoNE
border-west to target:
((distanceNWtoSW-(target.distanceTo(intersection-y)))*100)/distanceNWtoSW
Finally calculate the coordinates based on the width/height of the given floorplan and the results of the previous calculation
x=((width*distanceBorderNorthToTargetInPercent)/100);
y=((height*distanceBorderWestToTargetInPercent)/100);
A method(extension of the mentioned LatLon-library) that performs all these calculations:
/**
*#param w int width of the drawing
*#param h int height of the drawing
*#param sw object LatLon of southwest of the drawing
*#param nw object LatLon of northwest of the drawing
*#param ne object LatLon of northeast of the drawing
*#return mixed object with x/y-coordinates or null when LatLon is outside of the area
**/
LatLon.prototype.translate = function(w,h,sw,nw,ne) {
var x = {distance:nw.distanceTo(ne),bearing:nw.bearingTo(ne)},
y = {distance:nw.distanceTo(sw),bearing:nw.bearingTo(sw)},
intersectionY = LatLon.intersection(sw, x.bearing, this, y.bearing),
intersectionX = LatLon.intersection(ne, y.bearing, this, x.bearing),
distanceX,distanceY;
if(intersectionX && intersectionY){
distanceX=((x.distance-(this.distanceTo(intersectionX)))*100)/x.distance,
distanceY=((y.distance-(this.distanceTo(intersectionY)))*100)/y.distance;
return {x:((w*distanceX)/100),y:((h*distanceY)/100)};
}
return null;
};
Demo:http://jsfiddle.net/doktormolle/nsbqpcvg/embedded/result/
Hover the highlighted floorplan on the google-map to see the result of the calculation(the google-Maps-API is only used for the demonstration, the calculation will be done without using the Maps-API)

find the bounds of my map given its center point with google maps api v3

I am trying to determine if a marker which is being animated is within the viewable area of my map. If it is not, I want to tell my map to pan to the marker position as a center position. How do I do this? This is my code:
var curPoint = racePath.GetPointAtDistance(curDist);
var curZoom = self.map.zoom;
var mapBounds = new google.maps.LatLngBounds(currentCenter);
var isInBounds = mapBounds.contains(curPoint);
This is not working, because mapBounds needs the southwest and northeast point of your map, but I don't know how to calculate those, without getting them from the mapBounds.getNorthEast() and mapBounds.getSouthWest() methods - documented here: https://developers.google.com/maps/documentation/javascript/reference#LatLngBounds.
Any ideas on how to solve this?
To determine the current bounds of the map, call getBounds() on you map variable:
https://developers.google.com/maps/documentation/javascript/reference#Map
If you want to know if a point is within the the current view area, call 'contains(LatLng)' on the LatLngBounds. Like so:
var currentBounds = myMap.getBounds();
var isInSight = currentBounds.contains(myPointLatLng);
if(isInSight){
//Your point is within the current bounds
}
If you want to pan so the map is centered on your point, call 'panTo(LatLng)' on you map variable:
var currentBounds = myMap.getBounds();
var isInSight = currentBounds.contains(myPointLatLng);
if(isInSight){
myMap.panTo(myPointLatLng);
}

Openlayers - Getting Incorrect LonLat while transform?

I have trying to get Latitude and Longitude of a Point.
But While transforming it's not returning the correct LonLat. It's big number that is not a lonlat point for sure.
I have tried for some solutions but didn't get result.
What else could be failing?
JS Code I have Tried
map = createMap("deviceMap");
var fromProjection = new OpenLayers.Projection("EPSG:4326");
var toProjection = new OpenLayers.Projection("EPSG:900913");
map.events.register('click', map, function handleMapClick(e) {
lonLat = self.map.getLonLatFromViewPortPx(e.xy).
transform(map.getProjectionObject(), toProjection);
prompt("",lonLat);
});
Finally got answer
map.events.register('click', map, function handleMapClick(e) {
var toProjection = new OpenLayers.Projection("EPSG:4326");
var lonLat = map.getLonLatFromPixel(e.xy).
transform(map.getProjectionObject(), toProjection);
});
EPSG:4326
should refer to WGS 84,
has decimal degree values
EPSG:900913
refers to WGS84 Web Mercator
has metric values, it is x/y axis coordinate system, so "high numbers" are expected
If I understand you right, you should have in variable lonLat a high number.
"LonLat" in OpenLayers does not mean, it will be only longitude/latitude, see documentation here:
lon {Number} The x-axis coordinate in map units. If your map is in a
geographic projection, this will be the Longitude. Otherwise, it will
be the x coordinate of the map location in your map units.
lat {Number} The y-axis coordinate in map units. If your map is in a
geographic projection, this will be the Latitude. Otherwise, it will
be the y coordinate of the map location in your map units.
So if you want to get a real LonLat coordinates, you should not convert it (and use EPSG:4326) or convert it to the other coordinate system, not EPSG:900913.
By the way, OpenLayers started to use 900918 (numeric equivalent to GOOGlE), It was define by Mr. Christopher Schmidt, firstly it was not accepted by European Petroleum Survey Group (EPSG). Then EPSG changed their mind and gave them number: 3857 - WGS84 Pseudo-Mercator.

How to get distance between a marker and the center in googlemaps

I'd like to calculate the distance between a marker and the the very center of the map - can anyone explain how I do this?
You can use the geometry library to solve this. You'll need to specify it when loading the Maps JS:
<script type="text/javascript" src="http://maps.googleapis.com/maps/api/js?libraries=geometry&sensor=false"></script>
Then, in your application's code:
var center = map.getCenter();
var markerLatLng = marker.getPosition();
var distance = google.maps.geometry.spherical.computeDistanceBetween(center, markerLatLng);
This returns the distance in meters.
The marker is usually set using coordinates, like this:
http://code.google.com/apis/maps/documentation/javascript/overlays.html#Markers
And here's a great thread about getting bounds and identifying where the map is centered:
Google Map API v3 — set bounds and center
So, now that you have two sets of coordinates, use this formula to calculate the distance:
http://www.movable-type.co.uk/scripts/latlong.html

Openlayers - Projection issues when getting latitude/longitude from a point

I'm trying to get the latitude/longitude from a draggable marker with Openlayers and OSM but I can't find the good settings for the projection conversion, what I am doing wrong ?
Here is the code: http://pastie.org/2300321 (see addMarker l140 & updateTargets l153) & and a little demo test.
If you submit an address, then drag the marker, the longitude and latitude are wrong. I tested a few different projections but I'm not sure what I've to use…
I think the problem is inside updateTargets method:
var point = this.feature.geometry;
var pixel = new OpenLayers.Pixel(point.x, point.y);
var coord = this.map.getLonLatFromPixel(pixel).transform(
new OpenLayers.Projection("EPSG:900913"),
new OpenLayers.Projection("EPSG:4326")
);
this.feature.geometry is already specified in lon/lat coordinates, not in pixels. So I suggest that you skip second line and do the conversion from OpenStreetMap projection to lon/lat directly on geometry object:
var coord = this.feature.geometry.transform(
new OpenLayers.Projection("EPSG:900913"),
new OpenLayers.Projection("EPSG:4326")
);

Categories

Resources