Tile numbers to lon./lat. in EPSG:3395 - python

I need to convert tiles number into lon./lag in EPSG:3395 but i don't find the solution.
I've found the code for EPSG:4326 but i don't find a way to adapt it for EPSG:3395.
Code for 4326 (it works well) :
$n = pow(2, $zoom);
$lon_deg = $xtile / $n * 360.0 - 180.0;
$lat_deg = rad2deg(atan(sinh(pi() * (1 - 2 * $ytile / $n))));
I need to convert tiles number into lon./lag in EPSG:3395 but i don't find a working solution. I have implemented some code based on this answer.
when I've tried to convert 4326 degrees into 3395 degrees:
def getVal(x, y, n):
lon_deg = x / n * 360.0 - 180.0
lat_rad = math.atan(math.sinh(math.pi * (1 - 2 * y / n)))
lat_deg = math.degrees(lat_rad)
#Convert in 3395
a = 6378137 #WGS84 semi-major axis
b = 6356752.3142 #WGS84 semi-minor axis
print(math.sqrt(1 - b^2 / a^2))
e = math.sqrt(1 - b^2 / a^2) #ellipsoid eccentricity
c = math.pow((1 - e*math.sin(latitude)) / (1 + e*math.sin(latitude)), e/2)
lat_deg = a * ln(math.tan(math.pi/4 + lat_deg/2) * c)
lon_deg = a * lon_deg;
I obtain the following Error message:
Unsupported operand type(s) for float and INT
Update: I have corrected to code to below by replacing ^ with **.
Code:
def getVal(x, y, n):
#Calcuate coordinates in 4326
lon_deg = x / n * 360.0 - 180.0
lat_rad = math.atan(math.sinh(math.pi * (1 - 2 * y / n)))
lat_deg = math.degrees(lat_rad)
#Convert coordinates in 3395
a = 6378137 #WGS84 semi-major axis
b = 6356752.3142 #WGS84 semi-minor axis
e = math.sqrt(1 - b**2 / a**2) #ellipsoid eccentricity
c = math.pow((1 - e*math.sin(lat_deg)) / (1 + e*math.sin(lat_deg)), e/2)
lon_deg = a * lon_deg;
lat_deg = a * math.log(math.tan(math.radians(math.pi/4 + lat_deg/2) * c))
But still the projection is strange.
I assume the problem is on this part:
lat_deg = a * math.log(math.tan(math.radians(math.pi/4 + lat_deg/2)
I had to insert math.radians as math.tan doesn't like degree angle.
Any idea?

Looks like you want to know the formulae to convert coordinates to EPSG:3395. I dont know if this is the right place for this question, but this might help.
When trying to raise to a power use the operand ** not ^.
def getVal(x, y, n):
lon_deg = x / n * 360.0 - 180.0
lat_rad = math.atan(math.sinh(math.pi * (1 - 2 * y / n)))
lat_deg = math.degrees(lat_rad)
#Convert in 3395
a = 6378137 #WGS84 semi-major axis
b = 6356752.3142 #WGS84 semi-minor axis
print(math.sqrt(1 - b**2 / a**2))
e = math.sqrt(1 - b**2 / a**2) #ellipsoid eccentricity
c = math.pow((1 - e*math.sin(latitude)) / (1 + e*math.sin(latitude)), e/2)
lat_deg = a * ln(math.tan(math.pi/4 + lat_deg/2) * c)
lon_deg = a * lon_deg;

Related

Vedo 3D-Gyroid structures STL export

I need to generate a double 3D gyroid structure. For this, I'm using vedo
from matplotlib import pyplot as plt
from scipy.constants import speed_of_light
from vedo import *
import numpy as np
# Paramters
a = 5
length = 100
width = 100
height = 10
pi = np.pi
x, y, z = np.mgrid[:length, :width, :height]
def gen_strut(start, stop):
'''Generate the strut parameter t for the gyroid surface. Create a linear gradient'''
strut_param = np.ones((length, 1))
strut_param = strut_param * np.linspace(start, stop, width)
t = np.repeat(strut_param[:, :, np.newaxis], height, axis=2)
return t
plt = Plotter(shape=(1, 1), interactive=False, axes=3)
scale=0.5
cox = cos(scale * pi * x / a)
siy = sin(scale * pi * y / a)
coy = cos(scale * pi * y / a)
siz = sin(scale * pi * z / a)
coz = cos(scale * pi * z / a)
six = sin(scale * pi * x / a)
U1 = ((six ** 2) * (coy ** 2) +
(siy ** 2) * (coz ** 2) +
(siz ** 2) * (cox ** 2) +
(2 * six * coy * siy * coz) +
(2 * six * coy * siz * cox) +
(2 * cox * siy * siz * coz)) - (gen_strut(0, 1.3) ** 2)
threshold = 0
iso1 = Volume(U1).isosurface(threshold).c('silver').alpha(1)
cube = TessellatedBox(n=(int(length-1), int(width-1), int(height-1)), spacing=(1, 1, 1))
iso_cut = cube.cutWithMesh(iso1).c('silver').alpha(1)
# Combine the two meshes into a single mesh
plt.at(0).show([cube, iso1], "Double Gyroid 1", resetcam=False)
plt.interactive().close()
The result looks quite good, but now I'm struggling with exporting the volume. Although vedo has over 300 examples, I did not find anything in the documentation to export this as a watertight volume for 3D-Printing. How can I achieve this?
I assume you mean that you want to extract a watertight mesh as an STL (?).
This is a non trivial problem because it is only well defined on a subset of the mesh regions where the in/out is not ambiguous, in those cases fill_holes() seems to do a decent job..
Other cases should be dealt "manually". Eg, you can access the boundaries with mesh.boundaries() and try to snap the vertices to a closest common vertex. This script is not a solution, but I hope can give some ideas on how to proceed.
from vedo import *
# Paramters
a = 5
length = 100
width = 100
height = 10
def gen_strut(start, stop):
strut_param = np.ones((length, 1))
strut_param = strut_param * np.linspace(start, stop, width)
t = np.repeat(strut_param[:, :, np.newaxis], height, axis=2)
return t
scale=0.5
pi = np.pi
x, y, z = np.mgrid[:length, :width, :height]
cox = cos(scale * pi * x / a)
siy = sin(scale * pi * y / a)
coy = cos(scale * pi * y / a)
siz = sin(scale * pi * z / a)
coz = cos(scale * pi * z / a)
six = sin(scale * pi * x / a)
U1 = ((six ** 2) * (coy ** 2) +
(siy ** 2) * (coz ** 2) +
(siz ** 2) * (cox ** 2) +
(2 * six * coy * siy * coz) +
(2 * six * coy * siz * cox) +
(2 * cox * siy * siz * coz)) - (gen_strut(0, 1.3) ** 2)
iso = Volume(U1).isosurface(0).c('silver').backcolor("p5").lw(1).flat()
cube = TessellatedBox(n=(length-1, width-1, height-1)).c('red5').alpha(1)
cube.triangulate().compute_normals()
cube.cut_with_mesh(iso).compute_normals()
print(iso.boundaries(return_point_ids=True))
print(cube.boundaries(return_point_ids=True))
print(iso.boundaries().join().lines())
show(iso, cube).close()
merge(iso, cube).clean().backcolor("p5").show().close()
iso.clone().fill_holes(15).backcolor("p5").show().close()

Solver Issue No Algorithm Found

Trying to replace the function U2(x,y,z) with specified values of x,y,z. Not sure how to do that with sympy because they are as "x = arange.(-h,h,0.001)" as seen in the code below.
Below you will find my implementation with sympy. Additionally I am using PyCharm.
This implementation is based on Dr. Annabestani and Dr. Naghavis' paper: A 3D analytical ion transport model for ionic polymer metal composite actuators in large bending deformations
import sympy as sp
h = 0.1 # [mm] half of thickness
W: float = 6 # [mm] width
L: float = 28 # [mm] length
F: float = 96458 # [C/mol] Faraday's constant
k_e = 1.34E-6 # [F/m]
Y = 5.71E8 # [Pa]
d = 1.03 - 11 # [m^2/s] diffiusitivity coefficient
T = 293 # [K]
C_minus = 1200 # [mol/m^3] Cation concentration
C_plus = 1200 # [mol/m^3] anion concentration
R = 8.3143 # [J/mol*K] Gas constant
Vol = 2*h*W*L
#dVol = diff(Vol,x) + diff(Vol, y) + diff(Vol, z) # change in Volume
theta = 1 / W
x, y, z, m, n, p, t = sp.symbols('x y z m n p t')
V_1 = 0.5 * sp.sin(2 * sp.pi * t) # Voltage as a function of time
k_f = 0.5
t_f = 44
k_g = 4.5
t_g = 0.07
B_mnp = 0.003
b_mnp: float = B_mnp
gamma_hat_2 = 0.04
gamma_hat_5 = 0.03
gamma_hat_6 = 5E-3
r_M = 0.15 # membrane resistance
r_ew = 0.175 # transverse resistance of electrode
r_el = 0.11 # longitudinal resistance of electrode
mu = 2.4
sigma_not = 0.1
a_L: float = 1.0 # distrubuted surface attentuation
r_hat = sp.sqrt(r_M ** 2 + r_ew ** 2 + r_el ** 2)
lambda_1 = 0.0001
dVol = 1
K = (F ** 2 * C_minus * d * (1 - C_minus * dVol)) / (R * T * k_e) # also K = a
K_hat = (K-lambda_1)/d
gamma_1 = 1.0
gamma_2 = 1.0
gamma_3 = 1.0
gamma_4 = 1.0
gamma_5 = 1.0
gamma_6 = 1.0
gamma_7 = 1.0
small_gamma_1 = 1.0
small_gamma_2 = 1.0
small_gamma_3 = 1.0
psi = gamma_1*x + gamma_2*y + gamma_3*z + gamma_4*x*y + gamma_5*x*z + gamma_6*y*z + gamma_7*x*y*z + (small_gamma_1/2)*x**2 + (small_gamma_2/2)*y**2 + (small_gamma_3/2)*x*z**2
psi_hat_part = ((sp.sin(((m + 1) * sp.pi) / 2 * h)) * x) * ((sp.sin(((n + 1) * sp.pi) / W)) * y) * ((sp.sin(((p + 1) * sp.pi) / L)) * z)
psi_hat = psi * psi_hat_part # Eqn. 19
print(psi_hat)
x1: float = -h
x2: float = h
y1: float = 0
y2: float = W
z1: float = 0
z2: float = L
I = psi_hat.integrate((x, x1, x2), (y, y1, y2), (z, z1, z2)) # Integration for a_mnp Eqn. 18
A_mnp = ((8 * K_hat) / (2 * h * W * L)) * I
Partial = A_mnp * ((sp.sin(((m + 1) * sp.pi) / 2 * h)) * x) * ((sp.sin(((n + 1) * sp.pi) / W)) * y) * ((sp.sin(((p + 1) * sp.pi) / L)) * z)
start = Partial.integrate((p, 0 , 10E9), (n, 0, 10E9), (m, 0, 10E9)) #when using infinity it goes weird, also integrating leads to higher thresholds than summation
a_mnp_denom = (((sp.sin(((m + 1) * sp.pi) / 2 * h)) ** 2) * ((sp.sin(((n + 1) * sp.pi) / W)) ** 2) * (
(sp.sin(((p + 1) * sp.pi) / L)) ** 2) + K_hat)
a_mnp = A_mnp / a_mnp_denom # Eqn. 18
U2 = sp.Function("U2")
U2 = a_mnp * ((sp.sin(((m + 1) * sp.pi) / 2 * h)) * x) * ((sp.sin(((n + 1) * sp.pi) / W)) * y) * (
(sp.sin(((p + 1) * sp.pi) / L)) * z) # Eqn. 13
x = np.arange(-h, h, 0.001)
y = np.arange(-h, h, 0.001)
z = np.arange(-h, h, 0.001)
f= sp.subs((U2), (x ,y ,z))
I currently get the error message: ValueError: subs accepts either 1 or 2 arguments. So that means I can't use the subs() method and replace() also doesn't work too well. Are there any other methods one can use?
Any help will be grateful, thank you!
Oscar is right: you are trying to deal with too much of the problem at once. That aside, Numpy and SymPy do not work like you think they do. What were you hoping to see when you replaced 3 variables, each with a range?
You cannot replace a SymPy variable/Symbol with a Numpy arange object, but you can replace a Symbol with a single value:
>>> from sympy.abc import x, y
>>> a = 1.0
>>> u = x + y + a
>>> u.subs(x, 1)
y + 2.0
>>> u.subs([(x,1), (y,2)])
4.0
You might iterate over the arange values, creating values of f and then doing something with each value:
f = lambda v: u.subs(dict(zip((x,y),v)))
for xi in range(1,3): # replace range with your arange call
for yi in range(-4,-2):
fi = f((xi,yi))
print(xi,yi,fi)
Be careful about iterating and using x or y as your loop variable, however, since that will then lose the assignment of the Symbol to that variable,
for x in range(2):
print(u.subs(x, x)) # no change and x is no longer a Symbol, it is now an int

Converting XYZ coordinates to longitutde/latitude in Python

I've got some XYZ coordinates in Kilometers (gotten using wgs) with the origin at the center of the Earth, is it possible to convert this into latitude and longitude?
In addition: how can I do this quickly inside python?
It's simply a reverse of this question here: Converting from longitude\latitude to Cartesian coordinates
Based on #daphshez answer
You can use this code,
Here, x, y and z are in Kms and R is an approximate diameter of Earth.
import numpy as np
R = 6371
lat = np.degrees(np.arcsin(z/R))
lon = np.degrees(np.arctan2(y, x))
This is how you do it. Taking into account both radiuses. Based on:
https://gist.github.com/govert/1b373696c9a27ff4c72a
and verifyed.
import math
x = float(4333216) #in meters
y = float(3193635) #in meters
z = float(3375365) #in meters
a = 6378137.0 #in meters
b = 6356752.314245 #in meters
f = (a - b) / a
f_inv = 1.0 / f
e_sq = f * (2 - f)
eps = e_sq / (1.0 - e_sq)
p = math.sqrt(x * x + y * y)
q = math.atan2((z * a), (p * b))
sin_q = math.sin(q)
cos_q = math.cos(q)
sin_q_3 = sin_q * sin_q * sin_q
cos_q_3 = cos_q * cos_q * cos_q
phi = math.atan2((z + eps * b * sin_q_3), (p - e_sq * a * cos_q_3))
lam = math.atan2(y, x)
v = a / math.sqrt(1.0 - e_sq * math.sin(phi) * math.sin(phi))
h = (p / math.cos(phi)) - v
lat = math.degrees(phi)
lon = math.degrees(lam)
print(lat,lon,h)

python Converting and solving of stiff ODE system

I have stiff system of differential equations given to the first-order ODE. This system is written in Maple. The default method used by Maple is the Rosenbrock method. Now my task is to solve these equations with python tools.
1) I do not know how to write the equations in the python code.
2) I do not know how to solve the equations with numpy, scipy, matplotlib or PyDSTool. For the library PyDSTool I did not find any examples at all, although I read that it is well suited for stiff systems.
Code:
import numpy
import scipy
import matplotlib
varepsilon = pow(10, -2); j = -2.5*pow(10, -2); e = 3.0; tau = 0.3; delta = 2.0
u0 = -math.sqrt(-1 + math.sqrt(varepsilon ** 2 + 12) / varepsilon) * math.sqrt(2) / 6
u = -math.sqrt(-1 + math.sqrt(varepsilon ** 2 + 12) / varepsilon) * math.sqrt(2) * (1 + delta) / 6
v = 1 / (1 - 2 / e) * math.sqrt(j ** 2 + (1 - 2 / e) * (e ** 2 * u ** 2 + 1))
y8 = lambda y1,y5,y7: 1 / (1 - 2 / y1) * math.sqrt(y5 ** 2 + (1 - 2 / y1) * (1 + y1 ** 2 * y7 ** 2))
E0 = lambda y1,y8: (1 - 2 / y1) * y8
Phi0 = lambda y1,y7: y1 ** 2 * y7
y08 = y8(y1=e, y5=j, y7=u0);
E = E0(y1=e, y8=y08); Phi = Phi0(y1=e, y7=u0)
# initial values
z01 = e; z03 = 0; z04 = 0; z05 = j; z07 = u0; z08 = y08;
p1 = -z1(x)*z5(x)/(z1(x)-2);
p3 = -z1(x)^2*z7(x);
p4 = z8(x)*(1-2/z1(x));
Q1 = -z5(x)^2/(z1(x)*(z1(x)-2))+(z8(x)^2/z1(x)^3-z7(x)^2)*(z1(x)-2);
Q3 = 2*z5(x)*z7(x)/z1(x);
Q4 = 2*z5(x)*z8(x)/(z1(x)*(z1(x)-2));
c1 = z1(x)*z7(x)*varepsilon;
c3 = -z1(x)*z5(x)*varepsilon;
C = z7(x)*varepsilon/z1(x)-z8(x)*(1-2/z1(x));
d1 = -z1(x)*z8(x)*varepsilon;
d3 = z1(x)*z5(x)*varepsilon;
B = z1(x)^2*z7(x)-z8(x)*varepsilon*(1-2/z1(x));
Omega = 1/(c1*d3*p3+c3*d1*p4-c3*d3*p1);
# differential equations
diff(z1(x), x) = z5(x);
diff(z3(x), x) = z7(x);
diff(z4(x), x) = z8(x);
diff(z5(x), x) = Omega*(-Q1*c1*d3*p3 - Q1*c3*d1*p4 + Q1*c3*d3*p1 + B*c3*p4 + C*d3*p3 + E*d3*p3 - Phi*c3*p4);
diff(z7(x), x) = -Omega*(Q3*c1*d3*p3 + Q3*c3*d1*p4 - Q3*c3*d3*p1 + B*c1*p4 - C*d1*p4 + C*d3*p1 - E*d1*p4 + E*d3*p1 - Phi*c1*p4);
diff(z8(x), x) = Omega*(-Q4*c1*d3*p3 - Q4*c3*d1*p4 + Q4*c3*d3*p1 + B*c1*p3 - B*c3*p1 - C*d1*p3 - E*d1*p3 - Phi*c1*p3 + Phi*c3*p1);
#features to be found and built curve
{z1(x), z3(x), z4(x), z5(x), z7(x), z8(x)}
After drifting on the Internet, I found something in principle:
import math
import matplotlib.pyplot as plt
import numpy as np
from scipy import integrate
from scipy.signal import argrelextrema
from mpmath import mp, mpf
mp.dps = 50
varepsilon = pow(10, -2); j = 2.5*pow(10, -4); e = 3.0; tau = 0.5; delta = 2.0
u0 = -math.sqrt(-1 + math.sqrt(varepsilon ** 2 + 12) / varepsilon) * math.sqrt(2) / 6
u = -math.sqrt(-1 + math.sqrt(varepsilon ** 2 + 12) / varepsilon) * math.sqrt(2) * (1 + delta) / 6
v = 1 / (1 - 2 / e) * math.sqrt(j ** 2 + (1 - 2 / e) * (e ** 2 * u ** 2 + 1))
y8 = lambda y1,y5,y7: 1 / (1 - 2 / y1) * math.sqrt(y5 ** 2 + (1 - 2 / y1) * (1 + y1 ** 2 * y7 ** 2))
E0 = lambda y1,y8: (1 - 2 / y1) * y8
Phi0 = lambda y1,y7: y1 ** 2 * y7
y08 = y8(y1=e, y5=j, y7=u0);
E = E0(y1=e, y8=y08); Phi = Phi0(y1=e, y7=u0)
# initial values
z01 = e; z03 = 0.0; z04 = 0.0; z05 = j; z07 = u0; z08 = y08;
def model(x, z, varepsilon, E, Phi):
z1, z3, z4, z5, z7, z8 = z[0], z[1], z[2], z[3], z[4], z[5]
p1 = -z1*z5/(z1 - 2);
p3 = -pow(z1, 2) *z7;
p4 = z8*(1 - 2/z1);
Q1 = -pow(z5, 2)/(z1*(z1 - 2)) + (pow(z8, 2)/pow(z1, 3) - pow(z7, 2))*(z1 - 2);
Q3 = 2*z5*z7/z1;
Q4 = 2*z5*z8/(z1*(z1 - 2));
c1 = z1*z7*varepsilon;
c3 = -z1*z5*varepsilon;
C = z7*varepsilon/z1 - z8*(1 - 2/z1);
d1 = -z1*z8*varepsilon;
d3 = z1*z5*varepsilon;
B = pow(z1, 2)*z7 - z8*varepsilon*(1 - 2/z1);
Omega = 1/(c1*d3*p3+c3*d1*p4-c3*d3*p1);
# differential equations
dz1dx = z5;
dz3dx = z7;
dz4dx = z8;
dz5dx = Omega*(-Q1*c1*d3*p3 - Q1*c3*d1*p4 + Q1*c3*d3*p1 + B*c3*p4 + C*d3*p3 + E*d3*p3 - Phi*c3*p4);
dz7dx = -Omega*(Q3*c1*d3*p3 + Q3*c3*d1*p4 - Q3*c3*d3*p1 + B*c1*p4 - C*d1*p4 + C*d3*p1 - E*d1*p4 + E*d3*p1 - Phi*c1*p4);
dz8dx = Omega*(-Q4*c1*d3*p3 - Q4*c3*d1*p4 + Q4*c3*d3*p1 + B*c1*p3 - B*c3*p1 - C*d1*p3 - E*d1*p3 - Phi*c1*p3 + Phi*c3*p1);
dzdx = [dz1dx, dz3dx, dz4dx, dz5dx, dz7dx, dz8dx]
return dzdx
z0 = [z01, z03, z04, z05, z07, z08]
if __name__ == '__main__':
# Start by specifying the integrator:
# use ``vode`` with "backward differentiation formula"
r = integrate.ode(model).set_integrator('vode', method='bdf')
r.set_f_params(varepsilon, E, Phi)
# Set the time range
t_start = 0.0
t_final = 0.1
delta_t = 0.00001
# Number of time steps: 1 extra for initial condition
num_steps = np.floor((t_final - t_start)/delta_t) + 1
r.set_initial_value(z0, t_start)
t = np.zeros((int(num_steps), 1), dtype=np.float64)
Z = np.zeros((int(num_steps), 6,), dtype=np.float64)
t[0] = t_start
Z[0] = z0
k = 1
while r.successful() and k < num_steps:
r.integrate(r.t + delta_t)
# Store the results to plot later
t[k] = r.t
Z[k] = r.y
k += 1
# All done! Plot the trajectories:
Z1, Z3, Z4, Z5, Z7, Z8 = Z[:,0], Z[:,1] ,Z[:,2], Z[:,3], Z[:,4], Z[:,5]
plt.plot(t,Z1,'r-',label=r'$r(s)$')
plt.grid('on')
plt.ylabel(r'$r$')
plt.xlabel('proper time s')
plt.legend(loc='best')
plt.show()
plt.plot(t,Z5,'r-',label=r'$\frac{dr}{ds}$')
plt.grid('on')
plt.ylabel(r'$\frac{dr}{ds}$')
plt.xlabel('proper time s')
plt.legend(loc='best')
plt.show()
plt.plot(t, Z7, 'r-', label=r'$\frac{dϕ}{ds}$')
plt.grid('on')
plt.xlabel('proper time s')
plt.ylabel(r'$\frac{dϕ}{ds}$')
plt.legend(loc='upper center')
plt.show()
However, reviewing the solutions obtained by the library scipy,
I encountered the problem of inconsistency of the solutions obtained by scipy and Maple. The essence of the problem is that the solutions are quickly oscillating and the Maple catches these oscillations with high precision using Rosenbrock's method. While Pythonn has problems with this using Backward Differentiation Methods:
r = integrate.ode(model).set_integrator('vode', method='bdf')
http://www.scholarpedia.org/article/Backward_differentiation_formulas
I tried all the modes of integrating: “vode” ; “zvode”; “lsoda” ; “dopri5” ; “dop853” and I found that the best suited mode “vode” however, still does not meet my needs...
https://docs.scipy.org/doc/scipy/reference/generated/scipy.integrate.ode.html
So this method catches oscillations in the range j ~ 10^{-5}-10^{-3}..While the maple shows good results for any j.
I present the results obtained by scipy for j ~ 10^{-2}:
enter image description here
enter image description here
and the results obtained by Maple for j ~ 10^{-2}:
enter image description here
enter image description here
It is important that oscillations are physical solutions! That is, the Python badly captures oscillations for j ~ 10^{-2}((. Can anyone tell me what I'm doing wrong?? how to look at the absolute error of integration?

Convert planar x/y to lat/long

Im trying to write a program that takes new york city x/y coords and turns them into lat/lng decimal points. Im new to planar/globe mapping. Ive included the constants that NYC has provided on their website. Also if there is a good article on how to do this I would love to learn! Below is the program I have written along with commented output at the bottom and also what the ideal values should be. Im kinda just stumbling in the dark on this.
#!/usr/bin/python
from math import *
"""
Supplied by NYC
Lambert Conformal Conic:
Standard Parallel: 40.666667
Standard Parallel: 41.033333
Longitude of Central Meridian: -74.000000
Latitude of Projection Origin: 40.166667
False Easting: 984250.000000
False Northing: 0.000000
"""
x = 981106 #nyc x coord
y = 195544 #nyc y coord
a = 6378137 #' major radius of ellipsoid, map units (NAD 83)
e = 0.08181922146 #' eccentricity of ellipsoid (NAD 83)
angRad = pi/180 #' number of radians in a degree
pi4 = pi/4 #' Pi / 4
p0 = 40.166667 * angRad #' latitude of origin
p1 = 40.666667 * angRad #' latitude of first standard parallel
p2 = 41.033333 * angRad #' latitude of second standard parallel
m0 = -74.000000 * angRad #' central meridian
x0 = 984250.000000 #' False easting of central meridian, map units
m1 = cos(p1) / sqrt(1 - ((e ** 2) * sin(p1) ** 2))
m2 = cos(p2) / sqrt(1 - ((e ** 2) * sin(p2) ** 2))
t0 = tan(pi4 - (p0 / 2))
t1 = tan(pi4 - (p1 / 2))
t2 = tan(pi4 - (p2 / 2))
t0 = t0 / (((1 - (e * (sin(p0)))) / (1 + (e * (sin(p0)))))**(e / 2))
t1 = t1 / (((1 - (e * (sin(p1)))) / (1 + (e * (sin(p1)))))**(e / 2))
t2 = t2 / (((1 - (e * (sin(p2)))) / (1 + (e * (sin(p2)))))**(e / 2))
n = log(m1 / m2) / log(t1 / t2)
f = m1 / (n * (t1 ** n))
rho0 = a * f * (t0 ** n)
x = x - x0
pi2 = pi4 * 2
rho = sqrt((x ** 2) + ((rho0 - y) ** 2))
theta = atan(x / (rho0 - y))
t = (rho / (a * f)) ** (1 / n)
lon = (theta / n) + m0
x = x + x0
lat0 = pi2 - (2 * atan(t))
part1 = (1 - (e * sin(lat0))) / (1 + (e * sin(lat0)))
lat1 = pi2 - (2 * atan(t * (part1 ** (e / 2))))
while abs(lat1 - lat0) < 0.000000002:
lat0 = lat1
part1 = (1 - (e * sin(lat0))) / (1 + (e * sin(lat0)))
lat1 = pi2 - (2 * atan(t * (part1 ^ (e / 2))))
lat = lat1 / angRad
lon = lon / angRad
print lat,lon
#output : 41.9266666432 -74.0378981653
#should be 40.703778, -74.011829
Im pretty stuck, I have a ton of these that need geo-coded
Thanks for any help!
One word answer: pyproj
>>> from pyproj import Proj
>>> pnyc = Proj(
... proj='lcc',
... datum='NAD83',
... lat_1=40.666667,
... lat_2=41.033333,
... lat_0=40.166667,
... lon_0=-74.0,
... x_0=984250.0,
... y_0=0.0)
>>> x = [981106.0]
>>> y = [195544.0]
>>> lon, lat = pnyc(x, y, inverse=True)
>>> lon, lat
([-74.037898165369015], [41.927378144152335])
These formulas should help you out:
http://www.linz.govt.nz/geodetic/conversion-coordinates/projection-conversions/lambert-conformal-conic#lbl3
owww. you'd be better using a library for this. a little searching suggests that should be the python interface to gdal
this question uses gdal, but not via the python api (they just call gdal via a command line from within python), but might help.
you might be best asking at gis stackexchange for more info.
i'm unclear where you got the code above from. if you link to it i/someone could check for obvious implementation errors.
Rather than trying to work through all the math, you could just pick a grid over your map surface and find out the lat/long of those grid points, then use interpolation to do the conversion. Depending on the linearity of the projection it might not take many points to get good accuracy.

Categories