calculate google maps tile boundary coordinates - google-maps

I've made a lot of searches and found some useful resources but still having problems about calculation.
I want to calculate NE and SW coordinates for a specific tile.
This is my way :
Zoom = 11
x = 1188
y = 767
number of tile = 2 ^ 11 (equals 2048)
angle1 = 360 / 2048
longitude = (1188 * angle1) - 180
it works correct.
But latitude part is not :
angle2 = 170.1022575596 / (2048/2)
latitude = ((2048 / 2) - 767) * angle2
thanks in advance

The solution you are looking for is this:
z = 11
x = 1188
y = 767
pi = 3.14159
alon1 = (x /2^z)*360.0 - 180.0
alon2 = ((x+1) /2^z)*360.0 - 180.0
an = pi-2*pi*y/2^z
alat1 = 180.0/pi*atan(0.5*(exp(an)-exp(-an)))
an = pi-2*pi*(y+1)/2^z
alat2 = 180.0/pi*atan(0.5*(exp(an)-exp(-an)))
And you get the NW (alon1,alat1) & SE (alon2,alat2) coordinates for this specific tile.

Related

How do I calculate the momentum matrix element using the Fourier transform?

I am trying to calculate the momentum matrix element between the ground and first excited vibrational states for a harmonic oscillator using the Fourier transform of the eigenfunctions in position space. I am having trouble calculating the momentum matrix element correctly.
Here is my code
hbar = 1
nPoints = 501
xmin = -5
xmax = 5
dx = (xmax - xmin) / nPoints
x = np.array([(i - nPoints // 2) * dx for i in range(nPoints)])
potential = np.array([0.5 * point**2 for point in x]) # harmonic potential
# get eigenstates, eigenvalues with Fourier grid Hamiltonian approach
energies, psis = getEigenstatesFGH(x, potential, mass=1, hbar=hbar)
# should be 0.5, 1.5, 2.5, 3.5, 4.5 or very close to that
for i in range(5):
print(f"{energies[i]:.2f}")
# identify the necessary wave functions
groundState = psis[:, 0]
firstExcitedState = psis[:, 1]
# fourier transform the wave functions into k-space (momentum space)
dp = (2 * np.pi) / (np.max(x) - np.min(x))
p = np.array([(i - nPoints // 2) * dp for i in range(nPoints)])
groundStateK = (1 / np.sqrt(2 * np.pi * hbar)) * np.fft.fftshift(np.fft.fft(groundState))
firstExcitedStateK = (1 / np.sqrt(2 * np.pi * hbar)) * np.fft.fftshift(np.fft.fft(firstExcitedState))
# calculate matrix elements
xMatrix = np.eye(nPoints) * x
pMatrix = np.eye(nPoints) * p
# <psi0 | x-hat | psi1 >, this works correctly
x01 = np.dot(np.conjugate(groundState), np.dot(xMatrix, firstExcitedState))
# <~psi0 | p-hat | ~psi1 >, this gives wrong answer
p01 = np.dot(np.conjugate(groundStateK), np.dot(pMatrix, firstExcitedStateK))

Surface plot of equally spaced grid of overlapping Gaussians not plotting correctly?

I am attempting to make a surface plot in Octave based on a bunch of overlapping, offset curves. the function should be treating x and y identically but I am not seeing that in the final plot, rather it has ridges running along one axis. I cant tell if this is a plotting error or something else wrong with my code. am hoping you can provide some help/insight.
Plot with ridges following one axis
Thanks
clear;
graphics_toolkit gnuplot
V = 2500; %scan speed in mm
rr = 200000; %rep rate in Hz
Qsp = 1; %pulse energy
pi = 3.14159;
ns = 1; %scan number
w = 0.0125; %Gaussian radius in mm
dp = 0.0125; %lateral pulse distance in mm
dh = 0.0125; %hatch pitch in mm
xmax = 0.2; %ablation area x in mm
ymax = 0.2; %ablation area y in mm
np = round(xmax/dp);
nh = round(ymax/dh);
points = 50;
cof = ns*2*Qsp/(pi*w^2);
N = [0:1:np];
M = rot90([0:1:nh]);
for i = 1:points
for j = 1:points
x = (i-1)*xmax/(points-1);
y = (j-1)*ymax/(points-1);
k = exp(-(2*(x-N*dp).^2+(y-M*dh).^2)/(w^2));
H(i,j) = cof*sum(sum(k));
endfor
endfor
ii = [1:1:points];
jj = ii;
xx = (ii-1)*xmax/(points-1);
yy = (jj-1)*ymax/(points-1);
surf(xx,yy,H);
I find it helpful to space out components of complex expressions.
k = exp(-(2*(x-N*dp).^2+(y-M*dh).^2)/(w^2));
It's too hard to read with so many parentheses.
k = exp(
-(
2*(x-N*dp).^2 + (y-M*dh).^2
) / (w^2)
);
Do you see it already?
k = exp(
-(
2 * (x-N*dp).^2
+
(y-M*dh).^2
) / (w^2)
);
The x component gets multiplied by two, but the y component doesn't.

strange rotation values

I got an object (called tempEnemy) which is flying around and shooting.
The problem is that I can't keep the value tempEnemy.rotateTo positive, i.e.
it shall be between 0 and 359 degrees. Currently rotateTo ranges from:
rotateTo < 0 (bug) && rotateTo > 0 && rotateTo > 359 (bug).
tempEnemy.dX = tempEnemy.destX - tempEnemy.x;
tempEnemy.dY = tempEnemy.destY - tempEnemy.y;
//I added 180 because my tempEnemy object was looking and shooting to the wrong direction
tempEnemy.rotateTo = (toDegrees(getRadians(tempEnemy.dX, tempEnemy.dY))) + 180;
if (tempEnemy.rotateTo > tempEnemy.frame + 180) tempEnemy.rotateTo -= 360;
if (tempEnemy.rotateTo < tempEnemy.frame - 180) tempEnemy.rotateTo += 360;
tempEnemy.incFrame = int((tempEnemy.rotateTo - tempEnemy.frame) / tempEnemy.rotateSpeed);
You can always use the modulo operator (%) to keep a value positive. The module calculates the rest of a division.
E.g. (example works with integers there for a division always has a left over.)
19 % 5 = 4
Because in the number 19 5 only fits 3 times (3 * 5 = 15,, 4 * 5 = 20,, 20 is too high) the left over is 4 (19 - 15). That is the modulo.
Extra examples:
7 % 3 = 1
15 % 4 = 3
21 % 9 = 3
The output of a modulo operation is never higher then the right hand operator - 1 There for it is perfect for your problem.
If your object is rotated 1234 degrees,, then operate it with a modulo 360 to get the respective number between 0 and 360 for it.
1234 % 360 = 154
Other more easier examples:
720 % 360 = 0
360 % 360 = 0
540 % 360 = 180
-180 % 360 = 180
-720 % 360 = 0
-540 % 360 = 180
Sounds like a classic angle averaging issue. Here's a formula that works for averaging angles
private function averageNums($a:Number, $b:Number):Number {
return = (Math.atan2( Math.sin($a) + Math.sin($b) , Math.cos($a) + Math.cos($b) ));
}

Draw polygon x meters around a point

How can I create a polygon(only a square in my case) around a given point(lat/lang) x meters around the given point. It's just a visual representation of a geofence but I dont need all the calculations whether a point is outside a geofence or not. I tried using the code below but its creating a rectangle instead of a square and I'm not even sure if the 1000 meter boudaries are being rendered correctly.
var map = new GMap2(document.getElementById("map_canvas"));
map.setCenter(new GLatLng(37.4419, -122.1419), 13);
map.addControl(new GSmallMapControl());
GEvent.addListener(map, 'click', function(overlay, latlng) {
var lat = latlng.lat();
var lng = latlng.lng();
var height = 1000; //meters
var width = 1000; //meters
var polygon = new GPolygon(
[
new GLatLng(lat + height / 2 * 90 / 10000000, lng + width / 2 * 90 / 10000000 / Math.cos(lat)),
new GLatLng(lat - height / 2 * 90 / 10000000, lng + width / 2 * 90 / 10000000 / Math.cos(lat)),
new GLatLng(lat - height / 2 * 90 / 10000000, lng - width / 2 * 90 / 10000000 / Math.cos(lat)),
new GLatLng(lat + height / 2 * 90 / 10000000, lng - width / 2 * 90 / 10000000 / Math.cos(lat)),
new GLatLng(lat + height / 2 * 90 / 10000000, lng + width / 2 * 90 / 10000000 / Math.cos(lat))
], "#f33f00", 2, 1, "#ff0000", 0.2);
map.addOverlay(polygon);
});
I ported this PHP function to calculate the location an arbitrary distance and bearing from a known location, to Javascript:
var EARTH_RADIUS_EQUATOR = 6378140.0;
var RADIAN = 180 / Math.PI;
function calcLatLong(longitude, lat, distance, bearing)
{
var b = bearing / RADIAN;
var lon = longitude / RADIAN;
var lat = lat / RADIAN;
var f = 1/298.257;
var e = 0.08181922;
var R = EARTH_RADIUS_EQUATOR * (1 - e * e) / Math.pow( (1 - e*e * Math.pow(Math.sin(lat),2)), 1.5);
var psi = distance/R;
var phi = Math.PI/2 - lat;
var arccos = Math.cos(psi) * Math.cos(phi) + Math.sin(psi) * Math.sin(phi) * Math.cos(b);
var latA = (Math.PI/2 - Math.acos(arccos)) * RADIAN;
var arcsin = Math.sin(b) * Math.sin(psi) / Math.sin(phi);
var longA = (lon - Math.asin(arcsin)) * RADIAN;
return new GLatLng (latA, longA);
}
I have written a working example of this function that you can check out (source).
I use the Pythagorean Theorem to translate from a width of a square to a radius, if you want to use a simple 1000 meter radius from the center you can do that instead:
// this
var radius = 1000;
// instead of this
var radius = (Math.sqrt (2 * (width * width))) / 2;

Real (Great Circle) distance in PostGIS with lat/long SRID?

I'm using a lat/long SRID in my PostGIS database (-4326). I would like to find the nearest points to a given point in an efficient manner. I tried doing an
ORDER BY ST_Distance(point, ST_GeomFromText(?,-4326))
which gives me ok results in the lower 48 states, but up in Alaska it gives me garbage. Is there a way to do real distance calculations in PostGIS, or am I going to have to give a reasonable sized buffer and then calculate the great circle distances and sort the results in the code afterwards?
You are looking for ST_distance_sphere(point,point) or st_distance_spheroid(point,point).
See:
http://postgis.refractions.net/documentation/manual-1.3/ch06.html#distance_sphere
http://postgis.refractions.net/documentation/manual-1.3/ch06.html#distance_spheroid
This is normally referred to a geodesic or geodetic distance... while the two terms have slightly different meanings, they tend to be used interchangably.
Alternatively, you can project the data and use the standard st_distance function... this is only practical over short distances (using UTM or state plane) or if all distances are relative to a one or two points (equidistant projections).
PostGIS 1.5 handles true globe distances using lat longs and meters. It is aware that lat/long is angular in nature and has a 360 degree line
This is from SQL Server, and I use Haversine for a ridiculously fast distance that may suffer from your Alaska issue (can be off by a mile):
ALTER function [dbo].[getCoordinateDistance]
(
#Latitude1 decimal(16,12),
#Longitude1 decimal(16,12),
#Latitude2 decimal(16,12),
#Longitude2 decimal(16,12)
)
returns decimal(16,12)
as
/*
fUNCTION: getCoordinateDistance
Computes the Great Circle distance in kilometers
between two points on the Earth using the
Haversine formula distance calculation.
Input Parameters:
#Longitude1 - Longitude in degrees of point 1
#Latitude1 - Latitude in degrees of point 1
#Longitude2 - Longitude in degrees of point 2
#Latitude2 - Latitude in degrees of point 2
*/
begin
declare #radius decimal(16,12)
declare #lon1 decimal(16,12)
declare #lon2 decimal(16,12)
declare #lat1 decimal(16,12)
declare #lat2 decimal(16,12)
declare #a decimal(16,12)
declare #distance decimal(16,12)
-- Sets average radius of Earth in Kilometers
set #radius = 6366.70701949371
-- Convert degrees to radians
set #lon1 = radians( #Longitude1 )
set #lon2 = radians( #Longitude2 )
set #lat1 = radians( #Latitude1 )
set #lat2 = radians( #Latitude2 )
set #a = sqrt(square(sin((#lat2-#lat1)/2.0E)) +
(cos(#lat1) * cos(#lat2) * square(sin((#lon2-#lon1)/2.0E))) )
set #distance =
#radius * ( 2.0E *asin(case when 1.0E < #a then 1.0E else #a end ) )
return #distance
end
Vicenty is slow, but accurate to within 1 mm (and I only found a javascript imp of it):
/*
* Calculate geodesic distance (in m) between two points specified by latitude/longitude (in numeric degrees)
* using Vincenty inverse formula for ellipsoids
*/
function distVincenty(lat1, lon1, lat2, lon2) {
var a = 6378137, b = 6356752.3142, f = 1/298.257223563; // WGS-84 ellipsiod
var L = (lon2-lon1).toRad();
var U1 = Math.atan((1-f) * Math.tan(lat1.toRad()));
var U2 = Math.atan((1-f) * Math.tan(lat2.toRad()));
var sinU1 = Math.sin(U1), cosU1 = Math.cos(U1);
var sinU2 = Math.sin(U2), cosU2 = Math.cos(U2);
var lambda = L, lambdaP = 2*Math.PI;
var iterLimit = 20;
while (Math.abs(lambda-lambdaP) > 1e-12 && --iterLimit>0) {
var sinLambda = Math.sin(lambda), cosLambda = Math.cos(lambda);
var sinSigma = Math.sqrt((cosU2*sinLambda) * (cosU2*sinLambda) +
(cosU1*sinU2-sinU1*cosU2*cosLambda) * (cosU1*sinU2-sinU1*cosU2*cosLambda));
if (sinSigma==0) return 0; // co-incident points
var cosSigma = sinU1*sinU2 + cosU1*cosU2*cosLambda;
var sigma = Math.atan2(sinSigma, cosSigma);
var sinAlpha = cosU1 * cosU2 * sinLambda / sinSigma;
var cosSqAlpha = 1 - sinAlpha*sinAlpha;
var cos2SigmaM = cosSigma - 2*sinU1*sinU2/cosSqAlpha;
if (isNaN(cos2SigmaM)) cos2SigmaM = 0; // equatorial line: cosSqAlpha=0 (ยง6)
var C = f/16*cosSqAlpha*(4+f*(4-3*cosSqAlpha));
lambdaP = lambda;
lambda = L + (1-C) * f * sinAlpha *
(sigma + C*sinSigma*(cos2SigmaM+C*cosSigma*(-1+2*cos2SigmaM*cos2SigmaM)));
}
if (iterLimit==0) return NaN // formula failed to converge
var uSq = cosSqAlpha * (a*a - b*b) / (b*b);
var A = 1 + uSq/16384*(4096+uSq*(-768+uSq*(320-175*uSq)));
var B = uSq/1024 * (256+uSq*(-128+uSq*(74-47*uSq)));
var deltaSigma = B*sinSigma*(cos2SigmaM+B/4*(cosSigma*(-1+2*cos2SigmaM*cos2SigmaM)-
B/6*cos2SigmaM*(-3+4*sinSigma*sinSigma)*(-3+4*cos2SigmaM*cos2SigmaM)));
var s = b*A*(sigma-deltaSigma);
s = s.toFixed(3); // round to 1mm precision
return s;
}