Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix wrong Antarctica coastline boundary with newer GEOS #560

Merged
merged 10 commits into from
Oct 24, 2022
8 changes: 8 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,10 @@ https://semver.org/spec/v2.0.0.html
### Fixed
- Fix broken array slicing inside `addcyclic` (PR [#559], solves issue
[#555], thanks to @fragkoul).
- Fix `GeosLibrary` wrapper to also work with GEOS >= 3.7.0 on Windows
and GNU/Linux.
- Fix wrong Antarctica coastline boundary with GEOS >= 3.9.0 (PR [#560],
solves issue [#522]).

## [1.3.4] - 2022-08-10

Expand Down Expand Up @@ -930,6 +934,8 @@ https://semver.org/spec/v2.0.0.html
- Fix glitches in drawing of parallels and meridians.


[#560]:
https://github.com/matplotlib/basemap/pull/560
[#559]:
https://github.com/matplotlib/basemap/pull/559
[#555]:
Expand Down Expand Up @@ -966,6 +972,8 @@ https://github.com/matplotlib/basemap/issues/527
https://github.com/matplotlib/basemap/issues/526
[#525]:
https://github.com/matplotlib/basemap/issues/525
[#522]:
https://github.com/matplotlib/basemap/issues/522
[#521]:
https://github.com/matplotlib/basemap/issues/521
[#518]:
Expand Down
2 changes: 1 addition & 1 deletion packages/basemap/src/mpl_toolkits/basemap/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -1336,7 +1336,7 @@ def _readboundarydata(self,name,as_polygons=False):
b2 = b.copy()
# fix Antartica.
if name == 'gshhs' and south < -89:
b = b[4:,:]
b = b[3:,:]
b2 = b.copy()
poly = Shape(b)
# if map boundary polygon is a valid one in lat/lon
Expand Down
151 changes: 98 additions & 53 deletions packages/basemap/utils/GeosLibrary.py
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@

import io
import os
import sys
import ssl
import glob
import shutil
Expand Down Expand Up @@ -126,8 +127,7 @@ def extract(self, overwrite=True):
if os.path.exists(zipfold):
if not overwrite:
raise OSError("folder '{0}' already exists".format(zipfold))
else:
shutil.rmtree(zipfold)
shutil.rmtree(zipfold)

# Decompress zip file.
with contextlib.closing(ZipFile(zippath, "r")) as fd:
Expand All @@ -137,16 +137,6 @@ def extract(self, overwrite=True):
for path in sorted(glob.glob(os.path.join(zipfold, "tools", "*.sh"))):
os.chmod(path, 0o755)

# Patch CMakeLists so that libgeos_c.so does not depend on libgeos.so.
cmakefile = os.path.join(zipfold, "capi", "CMakeLists.txt")
with io.open(cmakefile, "r", encoding="utf-8") as fd:
lines = fd.readlines()
with io.open(cmakefile, "wb") as fd:
oldtext = "target_link_libraries(geos_c geos)"
newtext = "target_link_libraries(geos_c geos-static)"
for line in lines:
fd.write(line.replace(oldtext, newtext).encode())

# Apply specific patches for GEOS < 3.6.0.
if self.version_tuple < (3, 6, 0):
# The SVN revision file is not created on the fly before 3.6.0.
Expand All @@ -166,66 +156,121 @@ def extract(self, overwrite=True):
for line in lines:
fd.write(line.replace(oldtext, newtext).encode())

# Apply specific patches for 3.6.0 <= GEOS < 3.7.0 on Windows.
if (3, 6, 0) <= self.version_tuple < (3, 7, 0) and os.name == "nt":
autogen_file = os.path.join(zipfold, "autogen.bat")
subprocess.call([autogen_file], cwd=zipfold)
cppfile = os.path.join(zipfold, "src", "geomgraph", "DirectedEdgeStar.cpp")
with io.open(cppfile, "r", encoding="utf-8") as fd:
lines = fd.readlines()
with io.open(cppfile, "wb") as fd:
oldtext = "DirectedEdgeStar::print() const"
newtext = oldtext.replace(" const", "")
for line in lines:
fd.write(line.replace(oldtext, newtext).encode())
hfile = os.path.join(zipfold, "include", "geos", "geomgraph", "DirectedEdgeStar.h")
with io.open(hfile, "r", encoding="utf-8") as fd:
lines = fd.readlines()
with io.open(hfile, "wb") as fd:
oldtext = "virtual std::string print() const;"
newtext = oldtext.replace(" const", "")
for line in lines:
fd.write(line.replace(oldtext, newtext).encode())

# Patch CMakeLists to link shared geos_c with static geos.
if self.version_tuple < (3, 8, 0):
cmakefile = os.path.join(zipfold, "capi", "CMakeLists.txt")
oldtext = "target_link_libraries(geos_c geos)"
newtext = "target_link_libraries(geos_c geos-static)"
else:
cmakefile = os.path.join(zipfold, "CMakeLists.txt")
oldtext = 'add_library(geos "")'
newtext = 'add_library(geos STATIC "")'
with io.open(cmakefile, "r", encoding="utf-8") as fd:
lines = fd.readlines()
with io.open(cmakefile, "wb") as fd:
found_sharedline = False
shared_oldtext = "if(BUILD_SHARED_LIBS)"
shared_newtext = "if(FALSE)"
for line in lines:
if not found_sharedline and shared_oldtext in line:
line = line.replace(shared_oldtext, shared_newtext)
found_sharedline = True
fd.write(line.replace(oldtext, newtext).encode())

# Patch doc CMakeLists in GEOS 3.8.x series.
if (3, 8, 0) <= self.version_tuple < (3, 9, 0):
cmakefile = os.path.join(zipfold, "doc", "CMakeLists.txt")
oldtext1 = "target_include_directories(test_geos_unit\n"
newtext1 = "if(BUILD_TESTING)\n {0}".format(oldtext1)
oldtext2 = "$<BUILD_INTERFACE:${CMAKE_CURRENT_LIST_DIR}>)\n"
newtext2 = "{0}endif()\n".format(oldtext2)
with io.open(cmakefile, "r", encoding="utf-8") as fd:
lines = fd.readlines()
with io.open(cmakefile, "wb") as fd:
for line in lines:
line = line.replace(oldtext1, newtext1)
line = line.replace(oldtext2, newtext2)
fd.write(line.encode())

def build(self, installdir=None, njobs=1):
"""Build and install GEOS from source."""

# Download and extract zip file if not present.
zipfold = os.path.join(self.root, "geos-{0}".format(self.version))
self.extract(overwrite=True)
version = self.version_tuple

# Define build directory.
# Define build and install directory.
builddir = os.path.join(zipfold, "build")

# Define installation directory.
if installdir is None:
installdir = os.path.expanduser("~/.local/share/libgeos")
installdir = os.path.abspath(installdir)

# Define configure options.
# Define generic configure and build options.
config_opts = [
"-DCMAKE_INSTALL_PREFIX={0}".format(installdir),
"-DGEOS_ENABLE_TESTS=OFF",
"-DCMAKE_BUILD_TYPE=Release",
"-DCMAKE_INSTALL_PREFIX={0}".format(installdir),
"-D{0}=OFF".format("GEOS_ENABLE_TESTS" if version < (3, 8, 0)
else "BUILD_TESTING")
]
if os.name == "nt" and self.version_tuple < (3, 6, 0):
config_opts = ["-G", "NMake Makefiles"] + config_opts

# Define build options.
build_env = os.environ.copy()
build_opts = [
"--config", "Release",
"--target", "install",
]
if os.name != "nt":
build_env["MAKEFLAGS"] = "-j {0:d}".format(njobs)
elif self.version_tuple < (3, 6, 0):
win64 = (8 * struct.calcsize("P") == 64)
build_opts.extend([
"--",
"WIN64={0}".format("YES" if win64 else "NO"),
"BUILD_BATCH={0}".format("YES" if njobs > 1 else "NO"),
])
build_env = os.environ.copy()

# Define custom configure and build options.
if os.name == "nt":
config_opts += ["-DCMAKE_CXX_FLAGS='/wd4251 /wd4458 /wd4530'"]
if version >= (3, 6, 0) and sys.version_info[:2] >= (3, 3):
build_opts = ["-j", "{0:d}".format(njobs)] + build_opts
else:
win64 = (8 * struct.calcsize("P") == 64)
config_opts = ["-G", "NMake Makefiles"] + config_opts
build_opts.extend([
"--",
"WIN64={0}".format("YES" if win64 else "NO"),
"BUILD_BATCH={0}".format("YES" if njobs > 1 else "NO"),
])
if sys.version_info[:2] < (3, 3):
build_opts += ["MSVC_VER=1500"]
else:
build_opts = ["-j", "{0:d}".format(njobs)] + build_opts
build_env["MAKEFLAGS"] = "-j {0:d}".format(njobs)
if version >= (3, 7, 0):
config_opts += ["-DCMAKE_CXX_FLAGS='-fPIC'"]

# Now move to the GEOS source code folder and build with CMake.
cwd = os.getcwd()
# Call cmake configure after ensuring that the build directory exists.
try:
# Ensure that the build directory exists.
try:
os.makedirs(builddir)
except OSError:
pass
os.chdir(builddir)
# Call cmake configure.
subprocess.call(["cmake", ".."] + config_opts)
# Ensure that the install directory exists.
try:
os.makedirs(installdir)
except OSError:
pass
# Call cmake build and install.
subprocess.call(["cmake", "--build", "."] + build_opts,
env=build_env)
finally:
os.chdir(cwd)
os.makedirs(builddir)
except OSError:
pass
subprocess.call(["cmake", ".."] + config_opts, cwd=builddir)

# Call cmake build after ensuring that the install directory exists.
try:
os.makedirs(installdir)
except OSError:
pass
subprocess.call(["cmake", "--build", "."] + build_opts,
cwd=builddir, env=build_env)