From a8aad24a13eabc2b4abc06194dca117578334433 Mon Sep 17 00:00:00 2001 From: Karim Bahgat Date: Tue, 30 Jun 2015 04:14:12 +0200 Subject: [PATCH] Added almost all params, made front API usable, and added crs transform draw testing. Next step figure out more stable proj4 parsing of datums and proj etc, with adding more specific names. Then consistently make to_esriwkt work. --- pycrs/datums.py | 28 +++++ pycrs/datums.pyc | Bin 388 -> 1468 bytes pycrs/ellipsoids.py | 25 +++++ pycrs/ellipsoids.pyc | Bin 454 -> 1350 bytes pycrs/loader.py | 32 ++++-- pycrs/loader.pyc | Bin 1189 -> 1361 bytes pycrs/parameters.py | 102 ++++++++++++----- pycrs/parameters.pyc | Bin 22395 -> 25122 bytes pycrs/parser.py | 250 ++++++++++++++++++++++++++++-------------- pycrs/parser.pyc | Bin 4218 -> 5079 bytes pycrs/projections.py | 4 + pycrs/projections.pyc | Bin 636 -> 892 bytes pycrs/webscrape.py | 4 +- pycrs/webscrape.pyc | Bin 2416 -> 2352 bytes tester.py | 44 +++++++- 15 files changed, 365 insertions(+), 124 deletions(-) diff --git a/pycrs/datums.py b/pycrs/datums.py index 77ef7cb..ac77fee 100644 --- a/pycrs/datums.py +++ b/pycrs/datums.py @@ -2,4 +2,32 @@ class WGS84: proj4 = "WGS84" ogc_wkt = "WGS_1984" + esri_wkt = "D_WGS_1984" + ellipsdef = "" # ellipsoids.WGS84() + to_wgs84 = None + +class WGS72_BE: + proj4 = "" # no datum name, just ellips + towgs84 params... + ogc_wkt = "WGS_1972_Transit_Broadcast_Ephemeris" + esri_wkt = "D_WGS_1972_BE" + + ellipsdef = "" # ellipsoids.WGS72() + to_wgs84 = 0,0,1.9,0,0,0.814,-0.38 + +class NAD83: + proj4 = "NAD83" # no datum name, just ellips + towgs84 params... + ogc_wkt = "North_American_Datum_1983" + esri_wkt = "D_North_American_1983" + + ellipsdef = "" # ellipsoids.WGS72() + to_wgs84 = None + + +class Unknown: + proj4 = "unknown" # no datum name, just ellips + towgs84 params... + ogc_wkt = "Unknown" + esri_wkt = "Unknown" + + ellipsdef = "" # ellipsoids.WGS72() + to_wgs84 = None,None diff --git a/pycrs/datums.pyc b/pycrs/datums.pyc index 8e66f59de16f0d258c467cf7e653318f76ea9955..bdf7a950f8eaadb39cf48bbdb9ff1c78b59359d7 100644 GIT binary patch literal 1468 zcmc&!UyIW~5TCTyzt=-hd=No=5b2YkSGg);y@ARZLKq&wZ2o&D|3Z)Q^dw$;4;{r%Xdlc$XTM;Pi5LgLpT zY0+DvH$*QS=p~X(lI7fFk=!7;NwSig;8G>oB3a8#Ws-FowYLDOD-h2QM%_++s0B+O zL*0Z3h#Y`I0>>f;TTA5Nj50YDKFq0+J!&(GjX}B&0X%X0Ubmy0PzEAb*Cdw#!ZMgmGdd93^vQs*BxEMEDe3Jm}s*jP+4S@1{Q+pG@23d3x{n>F42U(;vr|y(kbAbp33Xjb5qZjt>zWn&4^`#fuAFjRo`tCby?Cf7Fkt@4aNH(+enQj4$NiH(Yrw?}r-R+#_wQKYOp!5~SOEY~e zc9~A!OT>WF%|*MdFJpBe3hTULa62FNRb93 TkO*R!e4g2R@&Z;NkR$^DH)R$? diff --git a/pycrs/ellipsoids.py b/pycrs/ellipsoids.py index 112a64e..101bf89 100644 --- a/pycrs/ellipsoids.py +++ b/pycrs/ellipsoids.py @@ -3,7 +3,32 @@ class WGS84: proj4 = "WGS84" ogc_wkt = "WGS_1984" + esri_wkt = "WGS_1984" semimaj_ax = 6378137 inv_flat = 298.257223563 + +class WGS72: + proj4 = "WGS72" + ogc_wkt = "WGS 72" + esri_wkt = "WGS_1972" + + semimaj_ax = 6378135 + inv_flat = 298.26 + +class International: + proj4 = "intl" + ogc_wkt = "International_1924" + esri_wkt = "International_1924" + + semimaj_ax = 6378388.0 + inv_flat = 297.0 + +class GRS80: + proj4 = "GRS80" + ogc_wkt = "GRS_1980" + esri_wkt = "GRS_1980" + + semimaj_ax = 6378137.0 + inv_flat = 298.257222101 diff --git a/pycrs/ellipsoids.pyc b/pycrs/ellipsoids.pyc index 0699d29e2f3d51c5ec1cb130176b4588d17a55a5..0249cb047d8719b0899ac0628c7b73682595752d 100644 GIT binary patch literal 1350 zcmchXO^Xvj5Qb~=F`Hy}Js6J)o+Kw(Lm*KWiLMa6$kOAYhJj&BkD+(xBTRSHob}*M z1yQ_<_&fYBo;-?zH{a?_W@SKF2y7-*GgVz(-StfMRDW)_c7MM+n9%Z9#eE3T`%n`9 zCP{~05xpdOJceB%*&ZiLK|~bCYNj(K z_0`$J*245PFX%eA;-0p8vgq)dRj=3Z)|JPnP?(l9P2r{Q4<6mJ5A=4~N@opZ6T7$oDFfjbF%sTjXKfJT98%dnKt4V}J6!Sb z3zz=&&yV-TDLU)Yd0!VHrPA-08t&LEz6G|!1!J>?m4esmP77)G_``9N&xAcl?Pj~t GZu|x29|Dj7 delta 130 zcmX@cb&T1Z`7_1tHRfq*71_0-e6z2c{ diff --git a/pycrs/loader.py b/pycrs/loader.py index f370358..07d35d0 100644 --- a/pycrs/loader.py +++ b/pycrs/loader.py @@ -1,5 +1,7 @@ import json +import urllib2 +from . import parser ################# @@ -10,37 +12,43 @@ import json def from_url(url, format=None): # first get string from url - # ... + string = urllib2.urlopen(url).read() + + # then determine parser + if format: + # user specified format + format = format.lower().replace(" ", "_") + func = parser.__getattr__("from_%s" % format) + else: + # unknown format + func = parser.from_unknown_text # then load - if format: - # load string using specified format - pass - else: - from_unknown_text(string) + crs = func(string) + return crs def from_file(filepath): if filepath.endswith(".prj"): string = open(filepath, "r").read() - from_esri_wkt(string) + return parser.from_esri_wkt(string) elif filepath.endswith((".geojson",".json")): crsinfo = json.load(filepath)["crs"] if crsinfo["type"] == "name": string = crsinfo["properties"]["name"] - from_unknown_text(string) + return parser.from_unknown_text(string) elif crsinfo["type"] == "link": url = crsinfo["properties"]["name"] type = crsinfo["properties"].get("type") - from_url(url, format=type) + return from_url(url, format=type) else: raise Exception("invalid geojson crs type: must be either name or link") - elif filepath.endswith((".tif",".tiff",".geotiff")): - pass - # ... +## elif filepath.endswith((".tif",".tiff",".geotiff")): +## pass +## # ... diff --git a/pycrs/loader.pyc b/pycrs/loader.pyc index 17d0b89353f3cb07f16ca7a91c058f1068e5003d..89e06c86baf4920cf9832dbc1fc7214b3d8b5c12 100644 GIT binary patch literal 1361 zcmbtU%Wl&^6uo07P12?>RjpbU$QvZDB7tC2Ap|N2*i^_-H&rCdu_vt^zce!;jg+z= z{QtUq(^*Wb%fat+Jo*Jhf?H5dbbhA` zIv12Ul(>{TRJe5Rl7Lgvpc}kvQqrUw1gvpn-(N$P^e3*j1rV2%B!hV z_O+6A9>p?%k<11}7+y#d8Kc6`?BZ;bPs(vwP0P^8E8}wl!;_ljFe|)~E;Lw5SFzt9VkNLp^w%nm3c-;N9#b=nv`{0ta~& zB~tb3nc?Y{&8U16y552yXWw0O4#k1nal0bs&2W1>ti|OU6d;mWMqrWZAz^W_EFoCI z1Rz|71}MO%zY6H`L493;w8RxOIbu}7q%}H9S~PY@eX!@YJs&ZuNY=VbwsP%Q*Ux{r zT6hx#W^K-gasb+N824nI5nl+=H|vya@Vk$KN=xXz&-0&Zp0Zb~%u+#VUQq8sR++9! z&0FZP7Vw%ZAZAuetCUe8krixKpoTK3)YhJ-&g;{EqhSRaJPCUu7 zNAMx&a3W?Ps2XhZfi17DVp*HCDwhnkd`WXzN9Ho9D zT;29OLcRMq=z9<(w#B~KbhgEwvm>^kvD_0oj?bM0hb(vs{Bhh)Z$I#=ly<6sQ~mDm ZKbveL+0&v*Cb@iehf-H`#ZITY`wMH`9A5wc literal 1189 zcmb_b&2AGh5FT&-nzSW_s-RxbUXXG?i7LURLI^2TaEj1Iy;PN|H0z{JcJ0M>Xd|T@ zXrG8j;0<_&9(VvA0KRdWqF%T_l%1XVJpMf2c((L&vvDwfemJDtUxfD?Jnk7xioc+Y z=qNa8MAw3jB1%hi4Y0(k{Z<*7>KA^!A@5#2U1oU#vk+wKq#NXkyr3&V0>u56z*?`x z>HZk}_8ysrXv-YPv_W|a`nY!>j5vH8HafKV{*1-$Nl=g>*(I#ZRK z&Ra8_!_ri+b@ zdHb>~uSUxn;Ee7{;~)&o9df_eRyaE7`U?Tq9cDx7)SaV(APG8jaI74peiJ!ibfmND zIe=lhO+R==oa^IIfE*b#lW8>+-P5eK_`?RnS?)) zgn|Dt?tFTvd4%&GBXCb)NHoQc*o>NDJK7Qt;IZ9C)C3kj@uZ2gAh2h&3{sLEK!1t~ X-oJf_uX2;lGWnV%hdbV=Z>;|YzKZ@f diff --git a/pycrs/parameters.py b/pycrs/parameters.py index 1614863..6bdd155 100644 --- a/pycrs/parameters.py +++ b/pycrs/parameters.py @@ -25,6 +25,7 @@ from . import directions +# ONLY PURE VALUES INSIDE ELLIPSOID... ##+a Semimajor radius of the ellipsoid axis class SemiMajorRadius: @@ -32,24 +33,37 @@ class SemiMajorRadius: def __init__(self, value): pass -##+alpha ? Used with Oblique Mercator and possibly a few others -class Azimuth: - proj4 = "+alpha" - esri_wkt = "azimuth" - ogc_wkt = "azimuth" - geotiff = "AzimuthAngle" - def __init__(self, value): - pass - ##+b Semiminor radius of the ellipsoid axis class SemiMinorRadius: proj4 = "+b" def __init__(self, value): pass + + +################# + +##+alpha ? Used with Oblique Mercator and possibly a few others +class Azimuth: + proj4 = "+alpha" + esri_wkt = "azimuth" + ogc_wkt = "azimuth" + geotiff = "AzimuthAngle" + def __init__(self, value): + self.value = value + + def to_proj4(self): + return "+alpha=%s" % self.value + + def to_ogc_wkt(self): + return 'PARAMETER["Azimuth",%s]' % self.value + + def to_esri_wkt(self): + return self.to_ogc_wkt() + ##+datum Datum name (see `proj -ld`) class Datum: - def __init__(self, name, ellipsoid): + def __init__(self, name, ellipsoid, datumshift=None): """ Arguments: @@ -58,12 +72,19 @@ class Datum: """ self.name = name self.ellips = ellipsoid + self.datumshift = datumshift def to_proj4(self): - return "+datum=%s %s" % (self.name.proj4, self.ellips.to_proj4()) + if self.datumshift: + return "%s %s" % (self.ellips.to_proj4(), self.datumshift.to_proj4()) + else: + return "+datum=%s %s" % (self.name.proj4, self.ellips.to_proj4()) def to_ogc_wkt(self): - return 'DATUM["%s", %s]' % (self.name.ogc_wkt, self.ellips.to_ogc_wkt()) + if self.datumshift: + return 'DATUM["%s", %s, %s]' % (self.name.ogc_wkt, self.ellips.to_ogc_wkt(), self.datumshift.to_ogc_wkt()) + else: + return 'DATUM["%s", %s]' % (self.name.ogc_wkt, self.ellips.to_ogc_wkt()) def to_esri_wkt(self): return self.to_ogc_wkt() @@ -122,7 +143,6 @@ class GeogCS: self.twin_ax = twin_ax def to_proj4(self): - # axis excluded because not sure if should be set from geogcs or projcs return "%s %s %s" % (self.datum.to_proj4(), self.prime_mer.to_proj4(), self.angunit.to_proj4() ) #+axis= AND #, self.twin_ax[0].proj4, self.twin_ax[1].proj4 ) def to_ogc_wkt(self): @@ -151,8 +171,8 @@ class ProjCS: def to_proj4(self): string = "%s %s " % (self.proj.to_proj4(), self.geogcs.to_proj4()) string += " ".join(param.to_proj4() for param in self.params) - # axis excluded because not sure if should be set from geogcs or projcs - #string += " +axis=" + self.twin_ax[0].proj4 + self.twin_ax[1].proj4 + "u" # up set as default because only proj4 can set it I think... + # in proj4, axis only applies to the cs, ie the projcs (not the geogcs, where wkt can specify with axis) + string += " +axis=" + self.twin_ax[0].proj4 + self.twin_ax[1].proj4 + "u" # up set as default because only proj4 can set it I think... return string def to_ogc_wkt(self): @@ -164,7 +184,6 @@ class ProjCS: def to_esri_wkt(self): return self.to_ogc_wkt() - ##+k Scaling factor (old name) ##+k_0 Scaling factor (new name) class ScalingFactor: @@ -193,6 +212,7 @@ class LatitudeOrigin: return "+lat_0=%s" %self.value def to_ogc_wkt(self): + # SAME AS LATITUDE OF CENTER??? return 'PARAMETER["latitude_of_origin", %s]' %self.value def to_esri_wkt(self): @@ -204,15 +224,39 @@ class LatitudeOrigin: ##+lat_1 Latitude of first standard parallel class LatitudeFirstStndParallel: - proj4 = "+lat_1" def __init__(self, value): + self.value = value + + def to_proj4(self): + return "+lat_1=%s" %self.value + + def to_ogc_wkt(self): + return 'PARAMETER["standard_parallel_1", %s]' %self.value + + def to_esri_wkt(self): + return self.to_ogc_wkt() + + def to_geotiff(self): pass + #return "StdParallel1" ##+lat_2 Latitude of second standard parallel class LatitudeSecondStndParallel: - proj4 = "+lat_2" def __init__(self, value): + self.value = value + + def to_proj4(self): + return "+lat_2=%s" %self.value + + def to_ogc_wkt(self): + return 'PARAMETER["standard_parallel_2", %s]' %self.value + + def to_esri_wkt(self): + return self.to_ogc_wkt() + + def to_geotiff(self): pass + #return "StdParallel2" ##+lat_ts Latitude of true scale class LatitudeTrueScale: @@ -250,12 +294,20 @@ class CentralMeridian: pass #return "ProjCenterLong" - ##+lonc ? Longitude used with Oblique Mercator and possibly a few others -class LongitudeSpecial: +class LongitudeCenter: proj4 = "+lonc" def __init__(self, value): - pass + self.value = value + + def to_proj4(self): + return "+lonc=%s" %self.value + + def to_ogc_wkt(self): + return 'PARAMETER["Longitude_Of_Center", %s]' %self.value + + def to_esri_wkt(self): + return self.to_ogc_wkt() ##+lon_wrap Center longitude to use for wrapping (see below) @@ -294,6 +346,7 @@ class Projection: def to_esri_wkt(self): return self.to_ogc_wkt() +##+zone UTM zone ##+south Denotes southern hemisphere UTM zone @@ -303,10 +356,10 @@ class DatumShift: self.value = value def to_proj4(self): - return "+towgs84=%s" %"".join((str(val) for val in self.value)) + return "+towgs84=%s" %",".join((str(val) for val in self.value)) def to_ogc_wkt(self): - return "TOWGS84[%s]" %"".join((str(val) for val in self.value)) + return "TOWGS84[%s]" %",".join((str(val) for val in self.value)) def to_esri_wkt(self): raise Exception("Paramater not supported by ESRI WKT") @@ -416,8 +469,7 @@ class FalseNorthing: def to_esri_wkt(self): return self.to_ogc_wkt() - - + # then the final CRS object which is instantiated with all of these? # remember to use +no_defs when outputting to proj4 # ... diff --git a/pycrs/parameters.pyc b/pycrs/parameters.pyc index c4bf0daef0c425ff97eadee6372746198ef88222..952d45194634621bbb1dbdf5ebe6c903219b4436 100644 GIT binary patch delta 3768 zcma)9du)@}760z%_%qJajd7fZ6DOu2&O34QAR!4cX;PpNoSUR9R^ZMymEjLwB1D~o-TiuGH=s8HB&HO91 zPJvKc%)Ac2YvH7+0scAage#`??r@Isq@qk&l(3m6>y)s@6RRS}y%zYu)B&Hlo)R5! zd4nC!dfmBJ)X^AK4IgU` zXe_aU+47t)!HX7W3xf-j68%7AF7BlmN>U^3Na6%wHX4mA>aj>zI>7JWeT)rgC{Qd` zVHGn1XEaPWhH&URkUXv^^NO-muY?89g)*-yClh>QKBp=r<6)KMCS^Y7wuOdJQO3Qb zcT^{5YxU|{y-uenH8SRY=6Fda9Yod>;V9bSQs>k$n(o4(GhRenttRo3tBiLXCu?|p zx8Wrw14{wVAt&ZcDd6l_`oeVJ6@;7ud9QzBa@Vw{R`)ca3p5^rR;!~tg`8GNI%dNM z%8$unN(DlfgkKNAv1U%5Npm3zzKkh&9Nx<<5)VFWD|g4qr_tELtmJb{ODE(@C*_o* z7^i+5I;Ev1^7E{kRa-rp*Cnisp%mG0DZeg{zsm7TR?xYNeXzA4W@D~}xN9QBX(mHD zS3^tTn6ZRiNn1j$JeEv-1N~v#a>7i-^Z2v2T3a@_<}#FqR=;8M3So!UyQUospc1*V ziU?J{^f16D;IOj-P8C03V==2U)=)4Rx5??H|DudqdNb|1x}6IeRy;O|Z;@?o%a zA#ee8>ts|@bOKP_82U;??~mYAiBSE%!klqwMMLpmJ6>8r#_~}@ z2z%>`a`kv#M1z4cGBy#n}UmvKcKeaeR4E;!XP%Qo$Iwh3>y<*1rieX7wU)G|Zq z>rD~1;W9p_n@_L}cZLnmZ8mD}Y-6AU0heN}re^^?2a1rtGq$il5?>C_4$UsaXP0J> z#eY=VTXE<<*rJxgRhK81Z`8(UY+(le;X0)@F+3~vFN2Ah!?;@$u_>}AwFh_41q}I-vw2H5}5MMF@g~T!Kc1M z9J%c&OI)ZsA=vHC?8xwOUykU9lO4CzG1^`M7yM;#q4OYXoJg@Iy4)hw?e}Epp30`% z+>Q7H@cZst_?Q4!VFldW)MKU)H^H}i``|!Np{R#LJ$sAylatiFw6#vw1pdGjHss?Y zPG~8#;>PBJiQRkd8{gD1jc)?k126Rs+In$ETJPMP=$*y$S@mhuS|Wx^RU5XYb(LsV z`1Cm32cPu)M}5?YY|TKF!xA@itPE6&UINPDJ_L6zAt4pH-IYv&fNE{a>E>c@+;JM7^guv4=-+OvcyrYc$K92 zm!V;McJr@fm|w|i-jC|e!52GL#1Qy5omO9?Fm}OXJNI!^UpEe|XxG>HeBQ{2;7{OB zV{SJ!1LHY)7tJ!CgY;-I5255D{9yElVubCyW!UM#u1f*E3TFeavWZ`3n0WX9HZg*F zeg;S61+jz9Ouc4g#F_DSWW>6r*r7ipm@ar|B449_A0)qj+4%L0n0=HrX4`So2k_qH zGcDBSBo0MVMM`RD(n_S52t6kyz1AeX4`d6ReW0$M>RD1%NJ?W#*(NCmB%Oq$FiCPm rZpX0ghR!|CR?V*2bM3|UYW$VkJvg)DFn&12S)skiz8;4SX~};9C7t_$ delta 2971 zcma)8Yiv|i5WZ(0ciBF7d%JyiciU3gz9@ZH`UFbLqd+~ipdfwFS6bWMLbo&|0>v7@ z5J5T#r~##-38G-IM*e6t!5IC6lo%70m})fsPy_?fpfNZzx9yg)P0Y=iJ$ufXZ)U!k zx#zzAsrcujuo&-zhdg`Y#Y>i32H}Rk3`c|$uA4GN2K;NvG|5Jf32M!S@UwB)kfFeV z+<1stv=pMX4ca0_Q5NGE3_+m^dfn(&yr;OKdp%TX+fhhB=*dMY2_Ap0k0GMp*z{C&&`?}j(hM)Emv^g4=RzRzzSVV)p z;&J%ZVl&hz@JI1}Xs|4@c6a*xJzZUOM7h&Oen`@g4iYh7*BTs=I4!_2&A&CoYP1?B zwnr3;aAu4g+353j!l}q5p|m37NhH7u=Xz*JFo_M|wE1kj!yHU++bfz>GT5xZ?V3cW zwRxb-?$*z7NP%-4McZr?O)9z9K~apDV{qCHABQI-$~dyiyaWpb29}sa{Y01M5yA$? zqPIENr6f{HCgCKJGV69fY;x?h@ixQhXOP6ENc#T_4n1E6D2%zB5CCHW=OXquZ{-L^ z0uh)gf>H3e(nII?N_=aHxYI}AR3@qji?o_14#&lj)8p|uB`#c*ZW1XdJk029`N}lf zSWF@v1sD8~x5qyxtiu>qA`B#ii(1&1u*OK8cPBv#4Qdm;nJ=RjN2MwrY9t+tT_k7* z?Dh3{WjdIWS~c1@Nh;J(ibxf1BkW1~-9{8}M@SFOWCn~|*1Ce8Dy^M5eEcFUk()(OVDpk_ug&V<~jr->(uBRD=_-ITmf$;PW2K|IU&!vwt=#{b5 zc7x2JGGXk`0@z}gb=$~eQo}hJh)*T5!dL=XV1mO ztE55|&u>LrcHV=>^ZEGKe0&+6`s#t>G0X0X@5uLxyj~9Ed!{NU5^m-VaWFpw3YLTU zDG6v}=7Iki0Kc~|cy>O5|3-1>*8%ZF zkDqF)-skP^@eg%$HV$;Q_q6pvwxPgEWt`RL^R^Qi1|gu?*IE30O&_yRrL)kqHd&OiS48bfIIuy#o%DvT4T`xOPnJ#mxUNZv z^_Zk2WHui9>%AOUBTUtos}zzn!pz%ta{yO3K&(uAC|hNyunvxIyrNc+YUS*!zXi^3 zdLon;`PElR?aY?ip}V0)-yz>ohZ>!xUGr1f6Eu!;JlYIp^0frrCjOoC3G$#HVP47w zRj4AYFqs+`A(ZJ44OxPVFcP(ez1jtnjlsRzJ>RQ6LA|O%w0?NA>7uEcaCe%I8b^{!xEE5k z$HVR?&p_kmF~iA#wW+PTwO90|J=^xPwbS#gjsI_JtI*nUw01$%&1Bf{7J(;1S#zFR z#~yMX$q#^d`TRN#GERU?sgeL zf8fg3N`Awk0kqeo56TseB}5OIDMh&}1!gx(RNy#paqdRkPxV f*W6m7mZnAFqv8{#X<7&lyB48EYSB1sC}aNvt4=5R diff --git a/pycrs/parser.py b/pycrs/parser.py index 3eca539..311da53 100644 --- a/pycrs/parser.py +++ b/pycrs/parser.py @@ -9,59 +9,59 @@ from . import ellipsoids from . import parameters from . import units from . import projections +from . import webscrape -def from_epsg_code(string): +def from_epsg_code(code): # must go online (or look up local table) to get crs details - pass + code = str(code) + proj4 = webscrape.crscode_to_string("epsg", code, "proj4") + crs = from_proj4(proj4) + return crs -def from_esri_code(string): +def from_esri_code(code): # must go online (or look up local table) to get crs details - pass + code = str(code) + proj4 = webscrape.crscode_to_string("esri", code, "proj4") + crs = from_proj4(proj4) + return crs -def from_sr_code(string): +def from_sr_code(code): # must go online (or look up local table) to get crs details - pass + code = str(code) + proj4 = webscrape.crscode_to_string("sr-org", code, "proj4") + crs = from_proj4(proj4) + return crs -def from_esri_wkt(string): - # parse arguments into components - # use args to create crs - pass - -def from_ogc_wkt(string): - # parse arguments into components - # use args to create crs - pass - -def from_unknown_wkt(string): - # detect if ogc wkt or esri wkt - # TIPS: esri wkt datums all use "D_" before the datum name - # then load with appropriate function - pass +##def from_esri_wkt(string): +## # parse arguments into components +## # use args to create crs +## pass +## +##def from_ogc_wkt(string): +## # parse arguments into components +## # use args to create crs +## pass +## +##def from_unknown_wkt(string): +## # detect if ogc wkt or esri wkt +## # TIPS: esri wkt datums all use "D_" before the datum name +## # then load with appropriate function +## pass def from_proj4(string): # parse arguments into components # use args to create crs - -## proj=robin +lon_0=0 +x_0=0 +y_0=0 +ellps=WGS84 +datum=WGS84 +units=m +no_defs -## -## PROJCS["World_Robinson", -## GEOGCS["GCS_WGS_1984", -## DATUM["WGS_1984", -## SPHEROID["WGS_1984",6378137,298.257223563]], -## PRIMEM["Greenwich",0], -## UNIT["Degree",0.017453292519943295]], -## PROJECTION["Robinson"], -## PARAMETER["False_Easting",0], -## PARAMETER["False_Northing",0], -## PARAMETER["Central_Meridian",0], -## UNIT["Meter",1], -## AUTHORITY["EPSG","54030"]] + + # SLIGTHLY MESSY STILL, CLEANUP.. params = [] partdict = dict([part.split("=") for part in string.split() if not part.startswith("+no_defs")]) + # INIT CODES...? + # eg, +init=epsg code...? + # DATUM # datum param is required @@ -71,26 +71,58 @@ def from_proj4(string): if partdict["+datum"] == "WGS84": datumdef = datums.WGS84() - # ELLIPS - - # ellipse param is required - if "+ellps" in partdict: - - # get predefined ellips def - if partdict["+ellps"] == "WGS84": - ellipsdef = ellipsoids.WGS84() + elif partdict["+datum"] == "NAD83": + datumdef = datums.NAD83() else: - raise Exception("Could not find required +ellps element") - - ## create datum and ellips param objs - ellips = parameters.Ellipsoid(ellipsdef, - semimaj_ax=partdict.get("+a"), - inv_flat=partdict.get("+f")) - datum = parameters.Datum(datumdef, ellips) + datumdef = datums.Unknown() else: - raise Exception("Could not find required +datum element") + datumdef = datums.Unknown() + + # ELLIPS + + # ellipse param is required + if "+ellps" in partdict: + + # get predefined ellips def + if partdict["+ellps"] == "WGS84": + ellipsdef = ellipsoids.WGS84() + + elif partdict["+ellps"] == "WGS72": + ellipsdef = ellipsoids.WGS72() + + elif partdict["+ellps"] == "intl": + ellipsdef = ellipsoids.International() + + elif partdict["+ellps"] == "GRS80": + ellipsdef = ellipsoids.GRS80() + + else: + raise Exception("Could not find required +ellps element") + + # TO WGS 84 COEFFS + if "+towgs84" in partdict: + coeffs = partdict["+towgs84"].split(",") + datumshift = parameters.DatumShift(coeffs) + + # if no datum, use ellips + towgs84 params to create the correct datum + # ...?? + + # COMBINE DATUM AND ELLIPS + + ## create datum and ellips param objs + ellips = parameters.Ellipsoid(ellipsdef, + semimaj_ax=partdict.get("+a"), + inv_flat=partdict.get("+f")) + if "+datum" in partdict: + datum = parameters.Datum(datumdef, ellips) + + elif "+towgs84" in partdict: + datum = parameters.Datum(datumdef, ellips, datumshift) + + else: + datum = parameters.Datum(datumdef, ellips) # PRIME MERIDIAN @@ -99,7 +131,7 @@ def from_proj4(string): # overwrite with user input if "+pm" in partdict: - # for now only support longitude, later add name support: + # for now only support longitude, later add name support from below: ## greenwich 0dE ## lisbon 9d07'54.862"W ## paris 2d20'14.025"E @@ -134,6 +166,9 @@ def from_proj4(string): if partdict["+proj"] == "robin": projdef = projections.Robinson() + elif partdict["+proj"] == "omerc": + projdef = projections.ObliqueMercator() + elif partdict["+proj"] == "longlat": projdef = None # set geogcs axis in correct order @@ -177,6 +212,56 @@ def from_proj4(string): obj = parameters.FalseNorthing(val) params.append(obj) + # SCALING FACTOR + + if "+k_0" in partdict or "+k" in partdict: + if "+k_0" in partdict: val = partdict["+k_0"] + elif "+k" in partdict: val = partdict["+k"] + obj = parameters.ScalingFactor(val) + params.append(obj) + + # LATITUDE ORIGIN + + if "+lat_0" in partdict: + val = partdict["+lat_0"] + obj = parameters.LatitudeOrigin(val) + params.append(obj) + + # LATITUDE TRUE SCALE + + if "+lat_ts" in partdict: + val = partdict["+lat_ts"] + obj = parameters.LatitudeTrueScale(val) + params.append(obj) + + # LONGITUDE CENTER + + if "+lonc" in partdict: + val = partdict["+lonc"] + obj = parameters.LongitudeCenter(val) + params.append(obj) + + # AZIMUTH + + if "+alpha" in partdict: + val = partdict["+alpha"] + obj = parameters.Azimuth(val) + params.append(obj) + + # STD PARALLEL 1 + + if "+lat1" in partdict: + val = partdict["+lat1"] + obj = parameters.LatitudeFirstStndParallel(val) + params.append(obj) + + # STD PARALLEL 2 + + if "+lat2" in partdict: + val = partdict["+lat2"] + obj = parameters.LatitudeSecondStndParallel(val) + params.append(obj) + # UNIT ## set default @@ -208,33 +293,32 @@ def from_proj4(string): return crs -def from_ogc_urn(string): - # hmmm, seems like ogc urn could be anything incl online link, epsg, etc... - # if necessary, must go online (or lookup local table) to get details - # maybe test which of these and run their function? - # examples urn:ogc:def:crs:OGC:1.3:CRS1 - # or with EPSG instead of OGC - - # If OGC, 1.3 is pdf version, and after that is a name from list below - # as found in pdf: "Definition identifier URNs in OGC namespace" - # OGC crs definitions - # URN | CRS name | Definition reference - # urn:ogc:def:crs:OGC:1.3:CRS1 Map CS B.2 in OGC 06-042 - # urn:ogc:def:crs:OGC:1.3:CRS84 WGS 84 longitude-latitude B.3 in OGC 06-042 - # urn:ogc:def:crs:OGC:1.3:CRS83 NAD83 longitude-latitude B.4 in OGC 06-042 - # urn:ogc:def:crs:OGC:1.3:CRS27 NAD27 longitude-latitude B.5 in OGC 06-042 - # urn:ogc:def:crs:OGC:1.3:CRS88 NAVD 88 B.6 in OGC 06-042 - # urn:ogc:def:crs:OGC:1.3:AUTO42001:99:8888 Auto universal transverse mercator B.7 in OGC 06-042 - # urn:ogc:def:crs:OGC:1.3:AUTO42002:99:8888 Auto transverse mercator B.8 in OGC 06-042 - # urn:ogc:def:crs:OGC:1.3:AUTO42003:99:8888 Auto orthographic B.9 in OGC 06-042 - # urn:ogc:def:crs:OGC:1.3:AUTO42004:99:8888 Auto equirectangular B.10 in OGC 06-042 - # urn:ogc:def:crs:OGC:1.3:AUTO42005:99 Auto Mollweide B.11 in OGC 06-042 - - - pass +##def from_ogc_urn(string): +## # hmmm, seems like ogc urn could be anything incl online link, epsg, etc... +## # if necessary, must go online (or lookup local table) to get details +## # maybe test which of these and run their function? +## # examples urn:ogc:def:crs:OGC:1.3:CRS1 +## # or with EPSG instead of OGC +## +## # If OGC, 1.3 is pdf version, and after that is a name from list below +## # as found in pdf: "Definition identifier URNs in OGC namespace" +## # OGC crs definitions +## # URN | CRS name | Definition reference +## # urn:ogc:def:crs:OGC:1.3:CRS1 Map CS B.2 in OGC 06-042 +## # urn:ogc:def:crs:OGC:1.3:CRS84 WGS 84 longitude-latitude B.3 in OGC 06-042 +## # urn:ogc:def:crs:OGC:1.3:CRS83 NAD83 longitude-latitude B.4 in OGC 06-042 +## # urn:ogc:def:crs:OGC:1.3:CRS27 NAD27 longitude-latitude B.5 in OGC 06-042 +## # urn:ogc:def:crs:OGC:1.3:CRS88 NAVD 88 B.6 in OGC 06-042 +## # urn:ogc:def:crs:OGC:1.3:AUTO42001:99:8888 Auto universal transverse mercator B.7 in OGC 06-042 +## # urn:ogc:def:crs:OGC:1.3:AUTO42002:99:8888 Auto transverse mercator B.8 in OGC 06-042 +## # urn:ogc:def:crs:OGC:1.3:AUTO42003:99:8888 Auto orthographic B.9 in OGC 06-042 +## # urn:ogc:def:crs:OGC:1.3:AUTO42004:99:8888 Auto equirectangular B.10 in OGC 06-042 +## # urn:ogc:def:crs:OGC:1.3:AUTO42005:99 Auto Mollweide B.11 in OGC 06-042 +## +## pass def from_unknown_text(text): - # detect type and load with appropriate function + """Detect type and load with appropriate function""" if string.startswith("urn:"): from_ogc_urn(string) @@ -246,15 +330,15 @@ def from_unknown_text(text): from_unknown_wkt(string) elif string.startswith("EPSG:"): - from_epsg_code(string) + from_epsg_code(string.split(":")[1]) elif string.startswith("ESRI:"): - from_esri_code(string) + from_esri_code(string.split(":")[1]) elif string.startswith("SR-ORG:"): - from_sr_code(string) + from_sr_code(string.split(":")[1]) else: raise Exception("Could not detect which type of crs") -def from_geotiff_parameters(**params): - pass +##def from_geotiff_parameters(**params): +## pass diff --git a/pycrs/parser.pyc b/pycrs/parser.pyc index b5fa8243ab24e883e11198135552556423918b2d..ca4af7889853556105edb7ec0b232117b8643c86 100644 GIT binary patch literal 5079 zcmc&&&u<)89skbE?%Hdwv(CnL;v_Ab)Je8+8?{ZK!D=bNPMo5~v1Suha!ps0o$-3? z*_rjcw{?tmF9eAT93pXqOOb$6|AmSRh!Zy?B&3`o4qOmiKuEyn`+YlWTS7KR!Ry1+(yy4zM}J%)7(phiK8~T8s%GK`4V^Rq595~R9d4vayJ6UvL&Pze zJHjglfv<)il0jX=Y;j@zzQX?3x5IX_zLYe(?I6}_eL2*(yARe^_ZHpydS?%e>u?q* zuXOhGF))fUHnzbk7@|fokX^E-t&;U6I7X$R>_mLxvNCaq%Ln4}{>6(fADYm)C5GYo z;TjHlk-)nZ1?PQw>twUN7f=^--gXClGv6BqJ0Yy zPPFu$IqFN4n`?kup=LPff#&;Q(Z@FJ%*bVM$j8NSXuCk^Pk4gmte>N8o6?vgcq_*u z`#IYAD6X?w?FZH1w>Kaw8FwB>2%_7FWH z+Wsl%Q4xO#Ju2wa7IPP$MHdBqThL?sXtocD3=oUH2e*u8X6=dIahhdkmBdE{(k0rO zpdNOE1T#W0?lvIDsFx=naO}HG{xQb-oM=Bk<_%{|aP7?gl!(MFa7b*VQ z0rh`AM9>?N>;;;NXgtiwqK=b)T&zNRu4H?-VjC1YxI(jR^jKzeh5Qr3FfI~Lke;Hg zX?6^g!7C7oU@1{=T1WZW1pUPJ5pak2W(D#0eT1PH93mviA@<6Y&J}nAX9;uO&m{S0 zGAln6GtSU#|G4bwCF&X1!EbnDyiC0c^H?}t9|Fvs_@OYJ9Ws682qp+LOurJQmxfH$ zBbcC8nA9H}AHt1*%Q-)Tr+*b;FN?5vmiCFpbD+kO_cMsdb4MtG5k`1J_^Lze&L6=9 zfrjbF!gOxP^vV%T5NMcwD@^ByOmjytL7-v!moU9DWV&z!69gKjt9eZPxgpcVBbXr2 zFl`Fcg(1_W7c+5C;pSYFpgMSSYWp|G2fq>gS>DjIO_$958|NePYZ=8;QC-80c~wID zsc@LfctGUN)BNCMUp;UoK?ZX!%aue9LQ+7fgG-&K{*<8RsW&B-PE%aYAd;T?xU~zC4@T>E}Uk#!_>K?8t=5?~$QqaUkye5^E z3ff`Y+iG|Z6&J$uo@T-@{-m)HdD_4>LV!p)jPJBtU;nB5>8&S^-@}`L=zhE%C%duY z0&bowG_fvC9>7wDCG8+>3T2eUEr>L8PxDe;0L2UKXK6$8xp0^VPvZ^6h2#9gY_gY4 zwlR?{Y#aAM7a(loJWsVUHbO?z5O`5%(;EOi{pN7?7T)&!_m}q+7hrH&!&K5@gA~!? zz;^95pygQnu&HIcsuP9UI97Y9R=c6zbXk~N;o$@ir+MHLaHlY6F7V%vQK`os*WzB} za`~ZI_05OPpu<3yHzs12xc0Aah8x;YWTn3p!L7hpAw(j0H4WRrogfYU(2I2$Qtoh5 zaHkvT5T*vH9QS=R2KV+lfy+lMEyhyNN`nBeZlW7;s~dSK(+FxgNLq_^SIT!ORr#z{ zVx-@F5QRHk*4XrPl8SRyk~k3CSBDLUSh9$6JoTcXb?jcR(+Of9_m1e67pdT;r!+SK z>?8rKKC@K za^t&UyQ??#>;bM@VXAap$NnlBswfH~&BvF?tOv~`_79;s=*7pf_o3H#?~8RgCG;IN zIbz=MpvmE>v}{V)Fx7H0JdxmHPfNZ)5|NWPO&_nAx0wVRNG{wf2$hluVT_@Z;1rB7 zcQ`B%)#msS-E9sC(a7vfTmv}kg73gYmcHoEa<02mQ1Os|+E|#UcPS29I86uU`=NV4Aj`TYB1R3sU8O~wa z^d2Xy4EKW!hvoygJ|Rq4OM!g!8_k3(=*H&b1xH~w zjTcN-=V*IZ(*CM@_uGs0k0h_(T&*uJNY-AEk0}ONci&$S(z^TlU3YmworkFX_mOYx z*xd}9o5q@Cql)hZD>c4n?zebg4oO$iRpN#;V2Z@3o&-vuUGt7?>~3q96PbIC2TsN= z)3|dO%-0-As=-5D1LS}0?K$@yQm-NS2BJ!F1|z3zP1yU-Y0S;DQseB4LxW{9a3IPH zNL~+;_|4}D*~|Vm#3>(vc;9-N{r6vEIO)C9PW)~Ze1j7-+H0aoT$RB;8`pEBc(V9! GD*p#*Y64RL literal 4218 zcmc&%&2Jk;6o30=XB|6soaVCyS$s9fDk@SBC8D&I(}oWs)&9m`W zA@}!#&o-Md`lsXfHT;P0u<`J}23>%j23s0vr0cBfu%#>AVBLT%L+K{#CTy8Xw^+Ae z%R)T^p8#xSz{|3b1#g0d3Gi$dZ18d{E>( zM#zDN%`!DILpyL~zbBNQL*4IogIGj?cdRdV6SwC}KNhVg0xas3-%sDn5SHW zxeXWj7!hWnGXVpOk{mA5!IU;ZCd_anHAm`^rVlghoP&W0101fyFq_Ucd2BXLfwTim zlZ6!4d5spDWN-yoRAvNDy_hPeX#CJ-wE&nrIz`$Xb>_IU1Or^y=2a)TXPVOK06`;q zT;7Bs&Vz1>v7a?!tb{a7Gh<(CvJ9OWW~=~vzm3ghHvd46#qeK-88-a*$e=t%^qm=P zcu;`ku0gw)1(XRe=6RGAjMsI7F$;^sB7??Y615qt8Zp1}-0 zWaseSt&0h4t6|je{FadP;$0E+q*nP¦ScddT;lIp~VH5TF(?5suou2%^oS!o5K zS4sT6evtTHrOGZ9zw6UuC+Rg7elO^`orZhB&qmdiv}O?AZ?w9uRDG>yPs(7@Ndp`W z0&@ja<6irX2hKM)fBF0>vJJ4QGL0bEReH{O14(o*2-)6^!Zxm{WLJ_ZUPj-i?uO<_ z*HskYn8rn}2C4_CaM-wrd5ix2c~#i>Rh3ag6&uVY*BMN1Z<%tk zx``C~f!uLuGKZcQhpQZ#^u|HckEuFws2Y&ml@>af*Dz)JYQj}2ha?T&NP?b!%TEF? za6?(do?BD`-RgH`fUEimhhh`UpgV`L@6aS%P_6py#P=l?Mc2c2zw0LC!=^PqYS-!x z?SKb6M6QTJ-qU&%`W*9(aVf>C*6=JOZg-4?SaIXn4?Rh5)=jr7{2Q*2SVS>y?pTi! zxkEh^O~%b@jFHe9wL0${E2(9AO1SJ{m|X4&9)O}`s3dsAI-Ng0Qh4Z@M^!MAM#z-L z%c@&IRL4Xm231jp!R--=JQamkB7c0WT;wa|s*PMV1$WayqWOt8k{R}Wx69wry$&13 z1IYsiQarFcJc&AvE+SVdH1(xdQ4DXyl7? zR#BVP%I1Q}UV2Hh(c8}2MqbYtMKiDE(7*KfH;uxX=Cr(4(#{%X^Q>7$?`B$6(|3(< z@MU;HWqo2b?7zyQeiHsft8zs>KSo0;qxl{MEI+XDP=!Wv4x~;!{N8+#+PLaSE>l5~ z+6Jl3Am8K;UGvoTQEJ2D18p%?7pZMEwOMTYl&)ZETTX3UcO+PqWXCovNU&7M(jY8I zJYtXz_Bs=a+gwozivoT{PJTVr0UPxLjWdUTAWz~{ z({B+z)oF<-apFI)Q!HTvMo}y1Px>^;njXaWP=5L$ynxn|fJz)OR7?soXtf%gq4)=> zfk@PO)Yg}&YR2dzW!w-*&i9<0Iqg19EyscGw<7);NgND1&(10~kMOhf|9_oM;AC(1 gBCp@|-=f$Gsv$~vzxhwMP5!fN%g)%}+Kcx5KOdWDP5=M^ diff --git a/pycrs/projections.py b/pycrs/projections.py index 2eefd9d..529bde2 100644 --- a/pycrs/projections.py +++ b/pycrs/projections.py @@ -8,3 +8,7 @@ class UTM: proj4 = "utm" ogc_wkt = "Transverse_Mercator" +class ObliqueMercator: + proj4 = "omerc" + ogc_wkt = "Hotine_Oblique_Mercator" + diff --git a/pycrs/projections.pyc b/pycrs/projections.pyc index d9ad95bf139e1808c0497623b4d3baa2f02f14a2..c6e9fe168eeac7ff097610cdd55cf33480366cbf 100644 GIT binary patch delta 205 zcmeyv@`o*!`709 zAg4qeDCv=3l9`tp4^cC@nz4|T6DZ0(`6Hu*1dzd?0di9ih!w;JB0#be&-+eJVG`nC K0kVZzgjoPA+$p~R delta 122 zcmeyv_J_rb`7RW#NMT_J)?nWlyO~kkPXnln0YWeVSwSFf5ZmN_rhv&w%tCA+F<}+}LMjti diff --git a/pycrs/webscrape.py b/pycrs/webscrape.py index 43f914f..7cb8d3c 100644 --- a/pycrs/webscrape.py +++ b/pycrs/webscrape.py @@ -71,7 +71,7 @@ def crsstring_to_string(string, newformat): return result -if __name__ == "__main__": - build_crs_table("crstable.txt") +##if __name__ == "__main__": +## build_crs_table("crstable.txt") diff --git a/pycrs/webscrape.pyc b/pycrs/webscrape.pyc index e0123809e2017ceece0bc49c7ff92207f02105db..ca30c968aa99af978b554e27b4743553dc46e48f 100644 GIT binary patch delta 262 zcmew$v_VLk`796pBSWwT>&Ajv%tFO1K+)8K;&ce3 zxF~b82ulW|Y)oizYEf}ac4lsVj7xrUX>Mv>NpXyOW{F2>Qq1HJY?7Ndu__W!w)q2F z76Bz7lO|8#&|=bHoqUT!##jUB8U_SWY!2i)TM=~3WPeUU9uA;d9!4G}PE$@+044oQ AUH||9 delta 326 zcmdlW^g&3P`7jQeq(AvSo8;z&tcnDbZNATzML-G2q{;OhS_&l`K&#{9a}zW3;^T{XfSlx_;*!Lq zoK(G%iV_XB$*VbJ9H5Hw5_41I<28V47!X9UIgsmYMbO=og*gQUK<4u>@-T6la