Commit 96767c13 authored by Daniel Scheffler's avatar Daniel Scheffler
Browse files

Merge branch 'enhancement/revise_projection' into 'master'

Enhancement/revise projection

See merge request !21
parents 372c696f 12ac4061
Pipeline #11909 passed with stages
in 16 minutes and 14 seconds
...@@ -24,6 +24,7 @@ test_py_tools_ds: ...@@ -24,6 +24,7 @@ test_py_tools_ds:
- source activate ci_env - source activate ci_env
- export GDAL_DATA=/root/miniconda3/envs/ci_env/share/gdal - export GDAL_DATA=/root/miniconda3/envs/ci_env/share/gdal
- export PYTHONPATH=$PYTHONPATH:/root # /root <- directory needed later - export PYTHONPATH=$PYTHONPATH:/root # /root <- directory needed later
- conda install -c conda-forge 'pyproj>=2.1' # FIXME remove as soon as docker container is rebuilt
- make nosetests - make nosetests
- make docs - make docs
artifacts: artifacts:
...@@ -66,7 +67,7 @@ test_py_tools_ds_install: ...@@ -66,7 +67,7 @@ test_py_tools_ds_install:
# - conda config --set channel_priority strict # otherwise gdal or libgdal may be installed from defaults channel # - conda config --set channel_priority strict # otherwise gdal or libgdal may be installed from defaults channel
# resolve some requirements with conda # resolve some requirements with conda
- conda install --yes -q -c conda-forge numpy gdal pyproj shapely geopandas - conda install --yes -q -c conda-forge numpy gdal 'pyproj>=2.1.0' shapely geopandas
# run installer # run installer
- python setup.py install - python setup.py install
......
...@@ -62,7 +62,7 @@ Using conda_, the recommended approach is: ...@@ -62,7 +62,7 @@ Using conda_, the recommended approach is:
# create virtual environment for py_tools_ds, this is optional # create virtual environment for py_tools_ds, this is optional
conda create -y -q -c conda-forge --name py_tools_ds python=3 conda create -y -q -c conda-forge --name py_tools_ds python=3
source activate py_tools_ds source activate py_tools_ds
conda install -c conda-forge numpy gdal pyproj shapely scikit-image pandas conda install -c conda-forge numpy gdal 'pyproj>=2.1.0' shapely scikit-image pandas
Then install py_tools_ds using the pip installer: Then install py_tools_ds using the pip installer:
......
...@@ -21,8 +21,6 @@ ...@@ -21,8 +21,6 @@
# You should have received a copy of the GNU Lesser General Public License along # You should have received a copy of the GNU Lesser General Public License along
# with this program. If not, see <http://www.gnu.org/licenses/>. # with this program. If not, see <http://www.gnu.org/licenses/>.
from functools import partial
import pyproj import pyproj
import numpy as np import numpy as np
from shapely.ops import transform from shapely.ops import transform
...@@ -35,8 +33,6 @@ except ImportError: ...@@ -35,8 +33,6 @@ except ImportError:
import osr import osr
import gdal import gdal
from .projection import get_proj4info
__author__ = "Daniel Scheffler" __author__ = "Daniel Scheffler"
...@@ -73,16 +69,9 @@ def transform_any_prj(prj_src, prj_tgt, x, y): ...@@ -73,16 +69,9 @@ def transform_any_prj(prj_src, prj_tgt, x, y):
:param y: :param y:
:return: :return:
""" """
from pyproj import __version__ as ver transformer = pyproj.Transformer.from_crs(pyproj.CRS.from_user_input(prj_src),
if ver.startswith('2') and int(ver.split('.')[1]) >= 1: pyproj.CRS.from_user_input(prj_tgt))
transformer = pyproj.Transformer.from_crs(get_proj4info(proj=prj_src), return transformer.transform(x, y)
get_proj4info(proj=prj_tgt))
x, y = transformer.transform(x, y)
else:
prj_src = pyproj.Proj(get_proj4info(proj=prj_src))
prj_tgt = pyproj.Proj(get_proj4info(proj=prj_tgt))
x, y = pyproj.transform(prj_src, prj_tgt, x, y)
return x, y
def transform_coordArray(prj_src, prj_tgt, Xarr, Yarr, Zarr=None): def transform_coordArray(prj_src, prj_tgt, Xarr, Yarr, Zarr=None):
...@@ -313,8 +302,8 @@ def reproject_shapelyGeometry(shapelyGeometry, prj_src, prj_tgt): ...@@ -313,8 +302,8 @@ def reproject_shapelyGeometry(shapelyGeometry, prj_src, prj_tgt):
:param prj_src: GDAL projection as WKT string or EPSG code ('epsg:1234' or <EPSG_int>) :param prj_src: GDAL projection as WKT string or EPSG code ('epsg:1234' or <EPSG_int>)
:param prj_tgt: GDAL projection as WKT string or EPSG code ('epsg:1234' or <EPSG_int>) :param prj_tgt: GDAL projection as WKT string or EPSG code ('epsg:1234' or <EPSG_int>)
""" """
project = pyproj.Transformer.from_proj(
pyproj.CRS.from_user_input(prj_src),
pyproj.CRS.from_user_input(prj_tgt))
project = partial(pyproj.transform, pyproj.Proj(get_proj4info(proj=prj_src)), return transform(project.transform, shapelyGeometry) # apply projection
pyproj.Proj(get_proj4info(proj=prj_tgt)))
return transform(project, shapelyGeometry) # apply projection
...@@ -27,6 +27,7 @@ import warnings ...@@ -27,6 +27,7 @@ import warnings
import os import os
from typing import Union # noqa F401 # flake8 issue from typing import Union # noqa F401 # flake8 issue
from pyproj import CRS
import numpy as np import numpy as np
try: try:
from osgeo import osr from osgeo import osr
...@@ -37,7 +38,7 @@ except ImportError: ...@@ -37,7 +38,7 @@ except ImportError:
import gdal import gdal
from .coord_trafo import transform_any_prj from .coord_trafo import transform_any_prj
from .projection import get_proj4info, proj4_to_dict, isLocal from .projection import isLocal
__author__ = "Daniel Scheffler" __author__ = "Daniel Scheffler"
...@@ -130,14 +131,17 @@ class Geocoding(object): ...@@ -130,14 +131,17 @@ class Geocoding(object):
if isLocal(prj): if isLocal(prj):
self.prj_name = 'Arbitrary' self.prj_name = 'Arbitrary'
else: else:
# get prj_name and datum with warnings.catch_warnings():
proj4 = proj4_to_dict(get_proj4info(proj=prj)) # type: dict warnings.filterwarnings("ignore", message="You will likely lose important projection information")
self.prj_name = \
'Geographic Lat/Lon' if proj4['proj'] == 'longlat' else \ # get prj_name and datum
'UTM' if proj4['proj'] == 'utm' else proj4['proj'] proj4 = CRS(prj).to_dict() # FIXME avoid to convert to proj4
# FIXME there is no 'datum' key in case of, e.g., LAEA projection self.prj_name = \
self.datum = 'WGS-84' if proj4['datum'] == 'WGS84' else proj4['datum'] # proj4['ellps']? 'Geographic Lat/Lon' if proj4['proj'] == 'longlat' else \
self.units = proj4['unit'] if 'unit' in proj4 else self.units 'UTM' if proj4['proj'] == 'utm' else proj4['proj']
# FIXME there is no 'datum' key in case of, e.g., LAEA projection # still true?
self.datum = 'WGS-84' if proj4['datum'] == 'WGS84' else proj4['datum'] # proj4['ellps']?
self.units = proj4['unit'] if 'unit' in proj4 else self.units
if self.prj_name == 'UTM': if self.prj_name == 'UTM':
self.utm_zone = srs.GetUTMZone() self.utm_zone = srs.GetUTMZone()
...@@ -249,11 +253,16 @@ def geotransform2mapinfo(gt, prj): ...@@ -249,11 +253,16 @@ def geotransform2mapinfo(gt, prj):
fdir = os.path.join(os.path.abspath(os.curdir)) fdir = os.path.join(os.path.abspath(os.curdir))
try: try:
if int(gdal.__version__[0]) < 3:
prj = CRS(prj).to_wkt(version="WKT1_GDAL") # noqa
ds_out = gdal.GetDriverByName('ENVI').Create(fn_bsq, 2, 2, 1, gdal.GDT_Int32) ds_out = gdal.GetDriverByName('ENVI').Create(fn_bsq, 2, 2, 1, gdal.GDT_Int32)
ds_out.SetGeoTransform(gt) ds_out.SetGeoTransform(gt)
ds_out.SetProjection(prj) ds_out.SetProjection(prj)
ds_out.FlushCache() ds_out.FlushCache()
del ds_out
# noinspection PyUnusedLocal
ds_out = None
with open(fn_hdr, 'r') as inF: with open(fn_hdr, 'r') as inF:
content = inF.read() content = inF.read()
...@@ -296,7 +305,9 @@ def mapinfo2geotransform(map_info): ...@@ -296,7 +305,9 @@ def mapinfo2geotransform(map_info):
ds_out = gdal.GetDriverByName('ENVI').Create(fn_bsq, 2, 2, 1) ds_out = gdal.GetDriverByName('ENVI').Create(fn_bsq, 2, 2, 1)
ds_out.GetRasterBand(1).WriteArray(np.array([[1, 2], [2, 3]])) ds_out.GetRasterBand(1).WriteArray(np.array([[1, 2], [2, 3]]))
ds_out.FlushCache() ds_out.FlushCache()
del ds_out
# noinspection PyUnusedLocal
ds_out = None
with open(fn_hdr, 'r') as InHdr: with open(fn_hdr, 'r') as InHdr:
lines = InHdr.readlines() lines = InHdr.readlines()
......
...@@ -22,16 +22,14 @@ ...@@ -22,16 +22,14 @@
# with this program. If not, see <http://www.gnu.org/licenses/>. # with this program. If not, see <http://www.gnu.org/licenses/>.
import re import re
import pyproj from pyproj import CRS
from typing import Union # noqa F401 # flake8 issue from typing import Union # noqa F401 # flake8 issue
# custom # custom
try: try:
from osgeo import osr from osgeo import osr
from osgeo import gdal
except ImportError: except ImportError:
import osr import osr
import gdal
from ..environment import gdal_env from ..environment import gdal_env
...@@ -42,25 +40,15 @@ __author__ = "Daniel Scheffler" ...@@ -42,25 +40,15 @@ __author__ = "Daniel Scheffler"
gdal_env.try2set_GDAL_DATA() gdal_env.try2set_GDAL_DATA()
def get_proj4info(ds=None, proj=None): def get_proj4info(proj=None):
# type: (gdal.Dataset, Union[str, int]) -> str # type: (Union[str, int]) -> str
"""Returns PROJ4 formatted projection info for the given gdal.Dataset or projection respectively, """Returns PROJ4 formatted projection info for the given projection.
e.g. '+proj=utm +zone=43 +datum=WGS84 +units=m +no_defs ' e.g. '+proj=utm +zone=43 +datum=WGS84 +units=m +no_defs '
:param ds: <gdal.Dataset> the gdal dataset to get PROJ4 info for
:param proj: <str,int> the projection to get PROJ4 formatted info for (WKT or 'epsg:1234' or <EPSG_int>) :param proj: <str,int> the projection to get PROJ4 formatted info for (WKT or 'epsg:1234' or <EPSG_int>)
""" """
assert ds or proj, "Specify at least one of the arguments 'ds' or 'proj'" return CRS.from_user_input(proj).to_proj4().strip()
srs = osr.SpatialReference()
proj = ds.GetProjection() if ds else proj
if isinstance(proj, str) and proj.startswith('epsg:'):
proj = EPSG2WKT(int(proj.split(':')[1]))
elif isinstance(proj, int):
proj = EPSG2WKT(proj)
srs.ImportFromWkt(proj)
return srs.ExportToProj4().strip()
def proj4_to_dict(proj4): def proj4_to_dict(proj4):
...@@ -68,8 +56,7 @@ def proj4_to_dict(proj4): ...@@ -68,8 +56,7 @@ def proj4_to_dict(proj4):
"""Converts a PROJ4-like string into a dictionary. """Converts a PROJ4-like string into a dictionary.
:param proj4: <str> the PROJ4-like string :param proj4: <str> the PROJ4-like string
""" """
items = [item for item in proj4.replace('+', '').split(' ') if '=' in item] return CRS.from_proj4(proj4).to_dict()
return {k: v for k, v in [kv.split('=') for kv in items]}
def dict_to_proj4(proj4dict): def dict_to_proj4(proj4dict):
...@@ -77,7 +64,7 @@ def dict_to_proj4(proj4dict): ...@@ -77,7 +64,7 @@ def dict_to_proj4(proj4dict):
"""Converts a PROJ4-like dictionary into a PROJ4 string. """Converts a PROJ4-like dictionary into a PROJ4 string.
:param proj4dict: <dict> the PROJ4-like dictionary :param proj4dict: <dict> the PROJ4-like dictionary
""" """
return pyproj.Proj(proj4dict).srs return CRS.from_dict(proj4dict).to_proj4()
def proj4_to_WKT(proj4str): def proj4_to_WKT(proj4str):
...@@ -85,9 +72,7 @@ def proj4_to_WKT(proj4str): ...@@ -85,9 +72,7 @@ def proj4_to_WKT(proj4str):
"""Converts a PROJ4-like string into a WKT string. """Converts a PROJ4-like string into a WKT string.
:param proj4str: <dict> the PROJ4-like string :param proj4str: <dict> the PROJ4-like string
""" """
srs = osr.SpatialReference() return CRS.from_proj4(proj4str).to_wkt()
srs.ImportFromProj4(proj4str)
return srs.ExportToWkt()
def prj_equal(prj1, prj2): def prj_equal(prj1, prj2):
...@@ -100,7 +85,16 @@ def prj_equal(prj1, prj2): ...@@ -100,7 +85,16 @@ def prj_equal(prj1, prj2):
if prj1 is None and prj2 is None or prj1 == prj2: if prj1 is None and prj2 is None or prj1 == prj2:
return True return True
else: else:
return get_proj4info(proj=prj1) == get_proj4info(proj=prj2) from pyproj import __version__ as ver
if ver.startswith('2') and int(ver.split('.')[1]) >= 5:
# CRS.equals was added in pyproj 2.5 which does not exist for Python 2.7 in conda-forge channel
crs1 = CRS.from_user_input(prj1)
crs2 = CRS.from_user_input(prj2)
return crs1.equals(crs2)
else:
return get_proj4info(proj=prj1) == get_proj4info(proj=prj2)
def isProjectedOrGeographic(prj): def isProjectedOrGeographic(prj):
...@@ -112,17 +106,9 @@ def isProjectedOrGeographic(prj): ...@@ -112,17 +106,9 @@ def isProjectedOrGeographic(prj):
if prj is None: if prj is None:
return None return None
srs = osr.SpatialReference() crs = CRS.from_user_input(prj)
if prj.startswith('EPSG:'):
srs.ImportFromEPSG(int(prj.split(':')[1]))
elif prj.startswith('+proj='):
srs.ImportFromProj4(prj)
elif prj.startswith('GEOGCS') or prj.startswith('PROJCS'):
srs.ImportFromWkt(prj)
else:
raise RuntimeError('Unknown input projection.')
return 'projected' if srs.IsProjected() else 'geographic' if srs.IsGeographic() else None return 'projected' if crs.is_projected else 'geographic' if crs.is_geographic else None
def isLocal(prj): def isLocal(prj):
...@@ -139,7 +125,11 @@ def isLocal(prj): ...@@ -139,7 +125,11 @@ def isLocal(prj):
srs.ImportFromEPSG(int(prj.split(':')[1])) srs.ImportFromEPSG(int(prj.split(':')[1]))
elif prj.startswith('+proj='): elif prj.startswith('+proj='):
srs.ImportFromProj4(prj) srs.ImportFromProj4(prj)
elif 'GEOGCS' in prj or 'PROJCS' in prj or 'LOCAL_CS' in prj: elif 'GEOGCS' in prj or \
'GEOGCRS' in prj or \
'PROJCS' in prj or \
'PROJCS' in prj or \
'LOCAL_CS' in prj:
srs.ImportFromWkt(prj) srs.ImportFromWkt(prj)
else: else:
raise RuntimeError('Unknown input projection: \n%s' % prj) raise RuntimeError('Unknown input projection: \n%s' % prj)
...@@ -149,80 +139,26 @@ def isLocal(prj): ...@@ -149,80 +139,26 @@ def isLocal(prj):
def EPSG2Proj4(EPSG_code): def EPSG2Proj4(EPSG_code):
# type: (int) -> str # type: (int) -> str
if EPSG_code is not None: return CRS.from_epsg(EPSG_code).to_proj4() if EPSG_code is not None else ''
srs = osr.SpatialReference()
srs.ImportFromEPSG(EPSG_code)
proj4 = srs.ExportToProj4()
if not proj4:
raise EnvironmentError(gdal.GetLastErrorMsg())
return proj4
else:
return ''
def EPSG2WKT(EPSG_code): def EPSG2WKT(EPSG_code):
# type: (int) -> str # type: (int) -> str
if EPSG_code is not None: return CRS.from_epsg(EPSG_code).to_wkt(pretty=False) if EPSG_code is not None else ''
srs = osr.SpatialReference()
srs.ImportFromEPSG(EPSG_code)
wkt = srs.ExportToWkt()
if not wkt:
raise EnvironmentError(gdal.GetLastErrorMsg())
return wkt
else:
return ''
def WKT2EPSG(wkt, epsgfile=''): def WKT2EPSG(wkt):
# type: (str, str) -> Union[int, None] # type: (str) -> Union[int, None]
""" Transform a WKT string to an EPSG code """ Transform a WKT string to an EPSG code
:param wkt: WKT definition :param wkt: WKT definition
:param epsgfile: the proj.4 epsg file (automatically located if no path is provided)
:returns: EPSG code :returns: EPSG code
http://gis.stackexchange.com/questions/20298/is-it-possible-to-get-the-epsg-value-from-an-osr-spatialreference-class-using-th
""" """
# FIXME this function returns None if datum=NAD27 but works with datum=WGS84, e.g.:
# FIXME {PROJCS["UTM_Zone_33N",GEOGCS["GCS_North_American_1927",DATUM["D_North_American_1927",SPHEROID
# FIXME ["Clarke_1866",6378206.4,294.9786982]],PRIMEM["Greenwich",0.0],UNIT["Degree",0.0174532925199433]],
# FIXME PROJECTION["Transverse_Mercator"],PARAMETER["False_Easting",500000.0],PARAMETER["False_Northing",0.0],
# FIXME PARAMETER["Central_Meridian",15.0],PARAMETER["Scale_Factor",0.9996],PARAMETER["Latitude_Of_Origin",0.0],
# FIXME UNIT["Meter",1.0]]}
if not isinstance(wkt, str): if not isinstance(wkt, str):
raise TypeError("'wkt' must be a string. Received %s." % type(wkt)) raise TypeError("'wkt' must be a string. Received %s." % type(wkt))
code = None # default
if not wkt: if not wkt:
return None return None
p_in = osr.SpatialReference()
s = p_in.ImportFromWkt(wkt) return CRS.from_wkt(wkt.replace('\n', '').replace('\r', '').replace(' ', '')).to_epsg()
if s == 5: # invalid WKT
raise Exception('Received an invalid WKT string: %s' % wkt)
if p_in.IsLocal():
raise Exception('The given WKT is a local coordinate system.')
cstype = 'GEOGCS' if p_in.IsGeographic() else 'PROJCS'
p_in.AutoIdentifyEPSG()
an = p_in.GetAuthorityName(cstype)
assert an in [None, 'EPSG'], "No EPSG code found. Found %s instead." % an
ac = p_in.GetAuthorityCode(cstype)
if ac is None: # try brute force approach by grokking proj epsg definition file
p_out = p_in.ExportToProj4()
if p_out:
epsgfile = epsgfile or gdal_env.find_epsgfile()
with open(epsgfile) as f:
for line in f:
if line.find(p_out) != -1:
m = re.search('<(\\d+)>', line)
if m:
code = m.group(1)
break
code = int(code) if code else None # match or no match
else:
code = int(ac)
return code
def get_UTMzone(ds=None, prj=None): def get_UTMzone(ds=None, prj=None):
...@@ -240,12 +176,10 @@ def get_prjLonLat(fmt='wkt'): ...@@ -240,12 +176,10 @@ def get_prjLonLat(fmt='wkt'):
"""Returns standard geographic projection (EPSG 4326) in the WKT or PROJ4 format. """Returns standard geographic projection (EPSG 4326) in the WKT or PROJ4 format.
:param fmt: <str> target format - 'WKT' or 'PROJ4' :param fmt: <str> target format - 'WKT' or 'PROJ4'
""" """
assert re.search('wkt', fmt, re.I) or re.search('Proj4', fmt, re.I), 'unsupported output format' if not re.search('wkt', fmt, re.I) or re.search('Proj4', fmt, re.I):
srs = osr.SpatialReference() raise ValueError(fmt, 'Unsupported output format.')
srs.ImportFromEPSG(4326)
out = srs.ExportToWkt() if re.search('wkt', fmt, re.I) else srs.ExportToProj4()
if not out:
raise EnvironmentError(gdal.GetLastErrorMsg())
return out if re.search('wkt', fmt, re.I):
return CRS.from_epsg(4326).to_wkt()
else:
return CRS.from_epsg(4326).to_proj4()
...@@ -36,8 +36,8 @@ version = {} ...@@ -36,8 +36,8 @@ version = {}
with open("py_tools_ds/version.py") as version_file: with open("py_tools_ds/version.py") as version_file:
exec(version_file.read(), version) exec(version_file.read(), version)
requirements = ['gdal>=2.1.0', 'numpy', 'shapely', 'six', 'pandas', 'scikit-image>=0.16.0', 'geopandas', 'pyproj', requirements = ['gdal>=2.1.0', 'numpy', 'shapely', 'six', 'pandas', 'scikit-image>=0.16.0', 'geopandas',
'spectral'] 'pyproj>=2.1.0', 'spectral']
setup_requirements = [] # TODO(danschef): put setup requirements (distutils extensions, etc.) here setup_requirements = [] # TODO(danschef): put setup requirements (distutils extensions, etc.) here
test_requirements = requirements + ["coverage", "nose", "nose2", "nose-htmloutput", "rednose"] test_requirements = requirements + ["coverage", "nose", "nose2", "nose-htmloutput", "rednose"]
......
...@@ -10,7 +10,7 @@ dependencies: ...@@ -10,7 +10,7 @@ dependencies:
- gdal>=2.1.0 - gdal>=2.1.0
- conda-forge::libgdal # force to use conda-forge for libgdal to avoid package version incompatiblies due to mixed channels (libkea.so.1.4.7: cannot open shared object file: No such file or directory) - conda-forge::libgdal # force to use conda-forge for libgdal to avoid package version incompatiblies due to mixed channels (libkea.so.1.4.7: cannot open shared object file: No such file or directory)
# - kealib # fix for libkea.so.1.4.7: cannot open shared object file: No such file or directory (not needed as long as libgdal and gdal are conda-forge packages) # - kealib # fix for libkea.so.1.4.7: cannot open shared object file: No such file or directory (not needed as long as libgdal and gdal are conda-forge packages)
- pyproj - pyproj>=2.1.0
- scikit-image>=0.16.0 - scikit-image>=0.16.0
- geopandas - geopandas
- pip: - pip:
......
#!/usr/bin/env python
# -*- coding: utf-8 -*-
# py_tools_ds
#
# Copyright (C) 2019 Daniel Scheffler (GFZ Potsdam, daniel.scheffler@gfz-potsdam.de)
#
# This software was developed within the context of the GeoMultiSens project funded
# by the German Federal Ministry of Education and Research
# (project grant code: 01 IS 14 010 A-C).
#
# This program is free software: you can redistribute it and/or modify it under
# the terms of the GNU Lesser General Public License as published by the Free
# Software Foundation, either version 3 of the License, or (at your option) any
# later version.
#
# This program is distributed in the hope that it will be useful, but WITHOUT
# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
# FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
# details.
#
# You should have received a copy of the GNU Lesser General Public License along
# with this program. If not, see <http://www.gnu.org/licenses/>.
"""
test_coord_trafo
----------------
Tests for `py_tools_ds.geo.coord_trafo` module.
"""
import unittest
from shapely.geometry import Polygon
from py_tools_ds.geo.coord_trafo import reproject_shapelyGeometry
poly_local = Polygon([(5708.2, -3006), (5708, -3262), (5452, -3262), (5452, -3006), (5708, -3006)])
class Test_reproject_shapelyGeometry(unittest.TestCase):
def test_reproject_shapelyGeometry(self):
poly_lonlat = reproject_shapelyGeometry(poly_local, 32636, 4326)
self.assertTrue(isinstance(poly_lonlat, Polygon))
...@@ -71,6 +71,7 @@ wkt_utm = \ ...@@ -71,6 +71,7 @@ wkt_utm = \
AXIS["Northing", NORTH], AXIS["Northing", NORTH],
AUTHORITY["EPSG", "32633"]] AUTHORITY["EPSG", "32633"]]
""" """
wkt_utm = ' '.join(wkt_utm.split())
class Test_geotransform2mapinfo(unittest.TestCase): class Test_geotransform2mapinfo(unittest.TestCase):
......
...@@ -65,10 +65,10 @@ wkt_utm = \ ...@@ -65,10 +65,10 @@ wkt_utm = \
class Test_WKT2EPSG(unittest.TestCase): class Test_WKT2EPSG(unittest.TestCase):
def setUp(self): def setUp(self):
self.wkt_utm = wkt_utm