Scramble latitude longitude coordinates within 100m radius with Javascript - javascript

Title says it all, I need to scramble lat/lon coordinates within 100m radius for privacy reasons. I'm just horrible at maths and can't figure out how to convert 100m to lat/lon...
Eg I would have a location like:
lat: 52.5037086
lng: 13.434223100000054
Need to scramble this within 100m radius randomly, ie the furthest the generated coordinates can be from the original coordinates in any direction is 100m.
I've seen this formula around:
d = acos( sin(φ1)⋅sin(φ2) + cos(φ1)⋅cos(φ2)⋅cos(Δλ) ) ⋅ R
where:
φ = latitude, λ = longitude
R = radius of earth
d = distance between the points
No idea how to accomplish this in JavaScript, though. These "points" are markers within a Google Map if it makes a difference.
To be honest, it doesn't even need to be a circle, just random location within 100m x 100m square would work as well.

At such small extents, we can work with a linear approximation of the problem and a spherical earth model.
Consider, you are at a position (lat, long). Then, increasing lat by 1° results in a distance from the original point of d_lat = Pi * R * 1°/180° (simple perimeter of a circle).
Similarly, increasing long by 1° results in a distance of d_long = cos(lat) * Pi * R * 1°/180°.
Then, you can calculate the maximum change of latitude and longitude:
maxChangeLatitude = 100 m / d_lat
maxChangeLongitude = 100 m / d_long
Find a random point in this square and you have your point:
newLat = lat + (2 * Math.random() - 1) * maxChangeLatitude;
newLong = long + (2 * Math.random() - 1) * maxChangeLongitude;

Related

Mapping latitude and longitude to Canvas points in JavaScript

I'm writing an AR application in which the user sees a ship from the perspective of the captain of the ship like this
I want to use coordinates of other ships (like the one on the left) to draw the ships on top of the image using Canvas. The problem I'm having is mapping the latitude, longitude to Canvas points.
I've read about the Haversine and Bearing formulas but I can't figure out how to use them to do what I want. I know the latitude and longitude of the ship the user is looking from and tried using them to calculate the Canvas points of the other ship, but I can't get it to work. Any ideas?
Finding real world object in camera's view.
This is the most simplistic answer possible, as there are many unknowns that will affect the result.
The problem
The image illustrates the problem as I understand it.
We have 3 ships (the minimum required to find a solution) marked with a red A,B,C. We know the latitude and longitude of each ship. As they are close there is no need to correct for any distortion due to converging longitudes.
The green lines represent the camera's view, the image is projected via a lens onto the CCD (green line above A) The twp gray lines then are projected onto the camera's screen below the ship.
Triangulation and triangles.
From the longitudes we can find the distance from each ship to the other, giving us the lengths of the sides of a triangle.
var ships = {
A : { lat : ?, long : ? },
B : { lat : ?, long : ? },
C : { lat : ?, long : ? },
}
var AB = Math.hypot(ships.A.lat - ships.B.lat, ships.A.long - ships.B.long);
var BC = Math.hypot(ships.C.lat - ships.B.lat, ships.C.long - ships.B.long);
var CA = Math.hypot(ships.A.lat - ships.C.lat, ships.A.long - ships.C.long);
The inset triangle shows how to find the angle of a corner given the lengths of the sides.
For this we are after the angle pheta
var pheta = Math.acos(BC * BC - AB * AB + CA * CA) / (-2 * AB * CA));
The camera's field of view.
Now we need an extra bit of information. That is the field of view of the camera (in image as the green lines and red FOV). You will have to find those details for the camera you are using.
A typical phone camera has a focal length (fl) from 24-35mm equivalent and knowing the CCD size in relative terms you can find the FOV with var FOV = 2 * Math.atan((CCD.width / 2) / fl) But this is problematic as a modern phone is under 10mm thick and the CCD is tiny, what are the actual dimensions?
There is a long and complicated process you can use to determine the FOV without knowing the internal dimensions of the camera, but easy to look up the phone specs.
For now let's assume the camera has a FOV of 67deg (1.17radians). If the camera has a resolution of 1280 and we ignore lens distortions, and keep the camera vertical and at the same level as the targets , we can calculate the distance in pixels between the two ships via the angle between them.
var FOV = 1.17; // radians the Field of View of the camera
var pixels = (1.17 / 1280) * pheta; // 1280 is horizontal resolution of display
So now we have the distance in pixels between the two ships on the camera. Assuming that they fit on the camera we are missing one more important bit of information.
Bearings
We need to know which way the camera is pointing as a bearing. Only when we have that can we find the ships. So lets assume the GPS on the phone gives you the live bearing. What we need is the bearing to one of the ships.
I had to dig deep into my archives to find this, It had no source or referance so can only provide as is. All it had is Haversin so assuming that is the method used.
After some further digging I found a referance to what is likely the original source code that this was derived from Calculate distance, bearing and more between Latitude/Longitude points
function deg2rad(angle) { return angle * 0.017453292519943295 }
function rad2deg(angle) { return angle / 0.017453292519943295 }
//return bearing in radians.
function getBearing(lat1,lon1,lat2,lon2){
var earth = 6371e3;
var lat1 = lat1.toRadians();
var lat2 = lat2.toRadians();
var lon1 = lon1.toRadians();
var lon2 = lon2.toRadians();
var latD = lat2-lat1;
var lonD = lon2-lon1;
var a = Math.sin(latD / 2) * Math.sin(latD / 2) + Math.cos(lat1 ) * Math.cos(lat2) * Math.sin(lonD / 2) * Math.sin(lonD / 2);
var c = 2 * Math.atan2( Math.sqrt(a), Math.sqrt(1-a) );
return earth * c;
}
So now you can get the bearing from you to one of the ships. Use that and your bearing to find the difference in angle between you and it.
var yourBearing = ?; // in radians
var shipBBearing = getBearing(ships.A.lat, ships.A.long, ships.B.lat, ships.B.long);
Now get the differance in angle
var shipBAt = yourBearing - shipBBearing
Knowing the pixel FOV
var shipBPixelsFromCenter = (FOV / 1280) * shipBAt;
var shipBXpos = 1280 / 2 - shipBPixelsFromCenter;
// and from above the dif in pixels between ships is
var shipCXpos = shipBXpos + pixels.
And done.

How to convert exact Latitude and Longitude coordinates to X,Y coordinates

I have a world map drawn in a canvas using Java script. How can I convert the exact latitude,longitude coordinates of any place into X,Y coordinates so that I can project those converted X,Y coordinates on my Canvas Map?
I have tried different solutions provided earlier, but they are not pointing to exact X,Y coordinates on my Canvas Map. Also I have tried using basic conversion formulas, but they haven't been useful as well.
For example,
var y = ((-1 * lat) + 90) * (MAP_HEIGHT / 180);
var x = (lon + 180) * (MAP_WIDTH / 360);
OR
function plot_point(lat, lng) {
// longitude_shift = number of pixels your map's prime meridian is off-center.
// Mercator projection
// longitude: just scale and shift
x = (map_width * (180 + lng) / 360) % map_width + longitude_shift;
// latitude: using the Mercator projection
lat = lat * Math.PI / 180; // convert from degrees to radians
y = Math.log(Math.tan((lat/2) + (Math.PI/4)));
y = (map_height / 2) - (map_width * y / (2 * Math.PI)) + y_pos;
I am using the following map : Map
P.S. If anybody can provide a Java script code, that would be very helpful.
EDIT Since I cannot obtain exact coordinates, thanks to explanation of
#Aki Suihkonen, please suggest a method so that I can get X,Y coordinates nearest to its true location in the map. Thanks in advance.

Lat/Long equation in Javascript

I am trying to find an equation for finding the lat/long point between two lat/long points in Javascript. It would work something like this.
getMiddle(lat1, lng1, lat2, lng2) <= would return [lat3, lat3] halfway distance wise (going around the earth obviously).
I found this:
Link
Date: 10/11/2001 at 11:41:08
From: Doctor Rick
Subject: Re: Determining lat and long of a point between two given
points
Hi, Chuck.
This will probably be a little more complicated than you think. The
easiest way for me to do it is to think in terms of vectors. Some of
the items in our Archives on the topic of latitude and longitude use
the vector approach, so you can see them for background. For example:
Distance Between Two Points on the Earth
Link
Let's call the two points A and B, and choose a rectangular coordinate
system in which the equator is in the x-y plane and the longitude of
point A is in the x-z plane. Let lat1 be the latitude of A, let lat2
be the latitude of B, and let dlat be the longitude of B minus the
longitude of A. Finally, use distance units such that the radius of
the earth is 1. Then the vectors from the center of the earth to A and
B are
A = (cos(lat1), 0, sin(lat1)) B = (cos(lat2)*cos(dlon),
cos(lat2)*sin(dlon), sin(lat2))
Point C, the midpoint of the shortest line between A and B, lies along
the sum of vectors A and B. (This works because A and B have the same
length, so the sum of the vectors is the diagonal of a rhombus, and
this diagonal bisects the angle.)
A+B = (cos(lat1)+cos(lat2)*cos(dlon),
cos(lat2)*sin(dlon),
sin(lat1)+sin(lat2))
To get the actual vector C, we need to scale this vector to length R
so it ends at the surface of the earth. Thus we have to divide it by
|A+B|, that is, the length of vector A+B. That would get pretty messy.
But we can find the latitude lat3 and longitude difference (lon3-lon1)
by looking at ratios of the coordinates of A+B, and these ratios are
the same whether we scale the vector or not. To see this, look back at
the formula for vector B. Knowing that vector, we can recover lat2 and
dlon:
dlon = tan^-1(B_y/B_x) lat2 = tan^-1(B_z/sqrt(B_x^2+B_y^2))
Here, B_x, B_y, and B_z are the x, y, and z coordinates of vector B.
We can do the same thing with vector A+B to find the latitude and
longitude of point C:
dlon3 = tan^-1(cos(lat2)*sin(dlon)/
(cos(lat1)+cos(lat2)*cos(dlon))) lat3 = tan^-1((sin(lat1)+sin(lat2))/
sqrt((cos(lat1)+cos(lat2)*cos(dlon))^2+
(cos(lat2)*sin(dlon))^2))
That's the formula you seek. Since both formulas involve division, we
must consider the special cases. The longitude calculation fails when
C_x = 0, that is, when C is 90 degrees away from A in longitude, so
dlon3 will be +90 or -90; the sign depends on the sign of dlon. The
latitude calculation fails when C_x and C_y are both zero, thus we
know that in this case, lat3 = 0. A complete algorithm will check for
these cases, but they won't occur if you're interested only in the
continental US.
When I plug in the latitudes and longitudes for LA and NYC, I get:
LA 34.122222 118.4111111 NYC 40.66972222 73.94388889 midpt 39.54707861
97.201534
I hope this is helpful to you.
Doctor Rick, The Math Forum Link
Which I believe has the answer but not as Javascript.
This is what I am working with:
I have spent some time creating map point and determining distance between them, but to find a midway point between them has been difficult for me. Converting equations I have found so far has been unsuccessful.
Once I can find the midpoint I want to use recursion + (how many points I need between two points based on distance) to build properly spaced dotted lines.
Any help on this piece would be greatly appreciated.
Answer in python: http://code.activestate.com/recipes/577713-midpoint-of-two-gps-points/
Convert to js
Profit
Additionally: For those wanting to go straight to profit (yes I know I patched Math. Borrowed shamelessly from here: https://nickthecoder.wordpress.com/2012/04/15/radian-and-degree-conversion-in-javascript/)
getMidpoint: function(lat1, lng1, lat2, lng2) {
Math.degrees = function(rad) {
return rad * (180 / Math.PI);
}
Math.radians = function(deg) {
return deg * (Math.PI / 180);
}
lat1 = Math.radians(lat1);
lng1 = Math.radians(lng1);
lat2 = Math.radians(lat2);
lng = Math.radians(lng2);
bx = Math.cos(lat2) * Math.cos(lng - lng1)
by = Math.cos(lat2) * Math.sin(lng - lng1)
lat3 = Math.atan2(Math.sin(lat1) + Math.sin(lat2), Math.sqrt((Math.cos(lat1) + bx) * (Math.cos(lat1) + bx) + Math.pow(by, 2)));
lon3 = lng1 + Math.atan2(by, Math.cos(lat1) + bx);
return [Math.round(Math.degrees(lat3), 5), Math.round(Math.degrees(lon3), 5)]
}
I think this is the formula you're looking for:
This is the half-way point along a great circle path between the two points.
Formula: Bx = cos φ2 ⋅ cos Δλ
By = cos φ2 ⋅ sin Δλ
φm = atan2( sin φ1 + sin φ2, √(cos φ1 + Bx)² + By² )
λm = λ1 + atan2(By, cos(φ1)+Bx)
JavaScript:
(all angles
in radians)
var Bx = Math.cos(φ2) * Math.cos(λ2-λ1);
var By = Math.cos(φ2) * Math.sin(λ2-λ1);
var φ3 = Math.atan2(Math.sin(φ1) + Math.sin(φ2),
Math.sqrt( (Math.cos(φ1)+Bx)*(Math.cos(φ1)+Bx) + By*By ) );
var λ3 = λ1 + Math.atan2(By, Math.cos(φ1) + Bx);
source: http://www.movable-type.co.uk/scripts/latlong.html

Conversion of lat/lng coordinates to pixels on a given map (with JavaScript)

I have put together a cities database from MaxMind and it includes the lat/lng values for each city in the database. I have also put together a map of North/America and I would like to have a icon appear on the x/y coordinates of the map which are derived from the lat/lng coordinates of the city database record.
From my understanding I need to find the left/top bounds of the map first (lat/lng -> x/y) and then use that as a difference for the linear relationship between any of the north american city x/y coords. Finally, depending on the size of the map, its just a few simple division and subtraction operations to figure out where to place the point.
However I can't seem to figure out how todo the following:
I'm not sure what the lat/lng mapping system is. How do I find this out?
Using a JavaScript library, how do I convert the lat/lng to pixels for the 0,0 coord and each of the city coords. I've tried Proj4js, but they require that you specify your coordinate map types and so on. Here is another question that asked something similar.
Convert long/lat to pixel x/y on a given picture
Any ideas?
-- EDIT --
The output map (of North America) is a continuous cylinder: "Miller cylindrical projection". http://en.wikipedia.org/wiki/Miller_cylindrical_projection
Latitude and Longitude are imaginary lines drawn on earth so that you can accurately pinpoint any location on the world . simply put they are the X and Y coords of a plane.
Latitude is a vertical line running from north to south with its 90 deg at the north pole and -90deg at the south pole.
Longitude on the other hand is a horizontal line running east to south with -180deg in the west and 180deg in the east.
you can convert the latLng into pixel coords as by assuming that the width of the html container is the width of the world and the same applies to the the height.
Formula - Longitude - pixel
(givenLng*widthOfContainerElement)/360
where 360 is the total longitude in degrees
Formula -Latitude - pixed
(givenLat*heightOfContainerElement)/180
where 360 is the total longitude in degree
//Height is calculated from the bottom
let me know if you still need any clarifications.
Here is a Javascript implementation of a Mercator projection that returns only positive values (cartesian coordinate system of screens) and accounts for the sphere > flat conversion:
// get x
var x = (lng + 180) * (mapWidth / 360);
// convert from degrees to radians
var latRad = lat * Math.PI / 180;
// get y value
var mercN = Math.log(Math.tan((Math.PI / 4) + (latRad / 2)));
var y = (mapHeight / 2) - (mapWidth * mercN / (2 * Math.PI));
This is a very old question, but the accepted answer has some... nuances...
Typically, this is done for satellite/aerial imagery, which is usually accompanied by a "zoom-level."
This zoom-level roughly (and I mean roughly) translates to the "ground-sample-distance" or GSD, which, when provided, represents the centimeters per pixel in an image.
You'll often see zoom-levels of 18, 19, 20, or 21.
One of the issues to note is that the Earth is not flat nor perfectly spherical, therefore, there are many different "projection" methods available to translate from a three-dimensional coordinate of the Earth's surface to a two-dimensional image on a screen. The most popular and widely used of these projection methods is the Mercator projection.
Google provides a method that uses the Mercator projection to provide a pixel coordinate of x and y.
We can then use the "zoom-level" to scale the coordinate to fit our image.
interface LatLngLiteral {
lat: number;
lng: number;
}
interface Coordinate {
x: number;
y: number;
}
const project = (latLng: LatLngLiteral): Coordinate => {
const TILE_SIZE: number = 256;
let siny: number = Math.sin((latLng.lat * Math.PI) / 180);
// Truncating to 0.9999 effectively limits latitude to 89.189. This is
// about a third of a tile past the edge of the world tile.
siny = Math.min(Math.max(siny, -0.9999), 0.9999);
return {
x: TILE_SIZE * (0.5 + latLng.lng / 360),
y: TILE_SIZE * (0.5 - Math.log((1 + siny) / (1 - siny)) / (4 * Math.PI))
};
};
export function formatToPoint(latLng: LatLngLiteral, zoom: number): Coordinate {
// Get the world coordinates in pixels
const worldCoordinate: Coordinate = project(latLng);
// Scale to fit our image
const scale: number = Math.pow(2, zoom);
// Apply scale to world coordinates to get image coordinates
return {
x: Math.floor(worldCoordinate.x * scale),
y: Math.floor(worldCoordinate.y * scale)
}
}

googlemaps get bounding box around marker

In googlemaps api v2 I have one marker on map and i need to calculate a bounding box around this one. How would I get a bonding box of 5 by 5 kilometers of which this marker is the center?
I'm not sure that such a functionality is provided by google map, but math will help you to survive ;) Calculate distance, bearing and more between Latitude/Longitude points is a great reference to different calculations with geographic data. Open that page, and go to "Destination point given distance and bearing from start point" part, there are formulas, as well as online calculator, so you can check them (as well as you can see points on the map). Formula has few parameters:
(lat1,lng1) - your point (marker coordinates)
d - distance (in your case it would be 2.5km)
brng - angle..
to find bound you need to find coordinates of south, north, east and west rectangle sides, so everything you will change in parameters is angle, and in your case it will be 0, 90, 180 and 270 grads. Formulas:
var lat2 = Math.asin( Math.sin(lat1)*Math.cos(d/R) +
Math.cos(lat1)*Math.sin(d/R)*Math.cos(brng) );
var lon2 = lon1 + Math.atan2(Math.sin(brng)*Math.sin(d/R)*Math.cos(lat1),
Math.cos(d/R)-Math.sin(lat1)*Math.sin(lat2));
Well, specifying angle = 0 you find north, PI/2 - east, PI - south, 3*PI/2 - west (angles should be passed in radians).
R = earth’s radius (mean radius = 6,371km)
ADD-ON: just looked at the source code of that page, because when I enter in online form bearing = 0, distance = 2 then I see map with two points and according to the map scale the distance between them is really 2km. Well, you can use this library under a simple attribution license, without any warranty express or implied, just include it
<script src="http://www.movable-type.co.uk/scripts/latlon.js"></script>
Function you need is:
/**
* Returns the destination point from this point having travelled the given distance (in km) on the
* given initial bearing (bearing may vary before destination is reached)
*
* see http://williams.best.vwh.net/avform.htm#LL
*
* #param {Number} brng: Initial bearing in degrees
* #param {Number} dist: Distance in km
* #returns {LatLon} Destination point
*/
LatLon.prototype.destinationPoint = function(brng, dist) {
dist = typeof(dist)=='number' ? dist : typeof(dist)=='string' && dist.trim()!='' ? +dist : NaN;
dist = dist/this._radius; // convert dist to angular distance in radians
brng = brng.toRad(); //
var lat1 = this._lat.toRad(), lon1 = this._lon.toRad();
var lat2 = Math.asin( Math.sin(lat1)*Math.cos(dist) +
Math.cos(lat1)*Math.sin(dist)*Math.cos(brng) );
var lon2 = lon1 + Math.atan2(Math.sin(brng)*Math.sin(dist)*Math.cos(lat1),
Math.cos(dist)-Math.sin(lat1)*Math.sin(lat2));
lon2 = (lon2+3*Math.PI)%(2*Math.PI) - Math.PI; // normalise to -180...+180
return new LatLon(lat2.toDeg(), lon2.toDeg());
}
and when I enter in online form bearing = 0, distance = 2, this method is executed with arguments latLonCalc.destinationPoint( 0, "2" );
try it, otherwise give me input parameters so I could check what's wrong
UPDATE2 that library works with grads,and converts them to radians for calculations and then back to grads. Just performed simple test:
var latLonCalc = new new LatLon( 25, 45 );
var point = latLonCalc.destinationPoint( 0, "2" );
console.info( point );
// prints 25°01′05″N, 045°00′00″E { _lat=25.01798643211838, _lon=45.00000000000005, _radius=6371}
so the distance between entry point and final destination is a bit more than 1 minute;
earth = 2 * PI * 6371; // 40 009.98km
=> 40 009.98km / 360grad =~111.14
=> 111,14 / 60 = 1.85 (km/minute) ~2km
it was round calculation, which tells me that final point is not far away then entry point, and distance should be 2km ;)
Not the real one you required but check this article
http://www.svennerberg.com/2008/11/bounding-box-in-google-maps/

Categories