diff --git a/.travis.yml b/.travis.yml index dfb1bcb96f1e4050fcbdd24f3f90db48f7d69cd8..7a2c932425b8773be588b5134c4369b3f1b2bd05 100644 --- a/.travis.yml +++ b/.travis.yml @@ -45,9 +45,8 @@ install: - conda config --add channels jlaura - conda install python=$PYTHON_VERSION - conda install -c conda-forge gdal h5py - - conda install pandas sqlalchemy pyyaml networkx + - conda install pandas sqlalchemy pyyaml networkx affine - conda install -c jlaura pvl protobuf - - pip install affine libpysal # Development installation - conda install nose coverage sh anaconda-client diff --git a/appveyor.yml b/appveyor.yml index e4347ef9757defea5db2b91aa07790e976154eab..0c05cf4895f44d0deae194e9c1f64740d3f892d8 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -40,7 +40,7 @@ install: - cmd: set PYTHONUNBUFFERED=1 - cmd: conda config --set show_channel_urls true - - cmd: conda install --yes python=3.5 + - cmd: conda install --yes python=3.5 - cmd: conda install -c pelson/channel/development --yes --quiet obvious-ci - cmd: conda config --add channels conda-forge - cmd: conda info @@ -56,10 +56,9 @@ install: - cmd: conda install --yes -c conda-forge gdal h5py - cmd: conda install --yes pandas sqlalchemy pyyaml networkx affine - cmd: conda install --yes -c jlaura protobuf pvl - - cmd: pip install libpysal # Development installation - - cmd: conda install --yes nose coverage + - cmd: conda install --yes nose coverage pytest - cmd: pip install coveralls # Skip .NET project specific build phase. diff --git a/plio/geofuncs/geofuncs.py b/plio/geofuncs/geofuncs.py index 83b2d49e2bd354dd9920a2b79be96541cd1cc13c..9db0f00da7fe4c683d3d420ed72f3d2a794a30b5 100644 --- a/plio/geofuncs/geofuncs.py +++ b/plio/geofuncs/geofuncs.py @@ -133,3 +133,31 @@ def find_four_corners(coords, threshold=120): ll = min(lower, key=key) return ul, ur, lr, ll + +def is_clockwise(vertices): + """ + Returns whether a list of points describing a polygon are clockwise or counterclockwise. + is_clockwise(Point list) -> bool + Parameters + ---------- + vertices : a list of points that form a single ring + Examples + -------- + >>> is_clockwise([Point((0, 0)), Point((10, 0)), Point((0, 10))]) + False + >>> is_clockwise([Point((0, 0)), Point((0, 10)), Point((10, 0))]) + True + >>> v = [(-106.57798, 35.174143999999998), (-106.583412, 35.174141999999996), (-106.58417999999999, 35.174143000000001), (-106.58377999999999, 35.175542999999998), (-106.58287999999999, 35.180543), (-106.58263099999999, 35.181455), (-106.58257999999999, 35.181643000000001), (-106.58198299999999, 35.184615000000001), (-106.58148, 35.187242999999995), (-106.58127999999999, 35.188243), (-106.58138, 35.188243), (-106.58108, 35.189442999999997), (-106.58104, 35.189644000000001), (-106.58028, 35.193442999999995), (-106.580029, 35.194541000000001), (-106.57974399999999, 35.195785999999998), (-106.579475, 35.196961999999999), (-106.57922699999999, 35.198042999999998), (-106.578397, 35.201665999999996), (-106.57827999999999, 35.201642999999997), (-106.57737999999999, 35.201642999999997), (-106.57697999999999, 35.201543000000001), (-106.56436599999999, 35.200311999999997), (-106.56058, 35.199942999999998), (-106.56048, 35.197342999999996), (-106.56048, 35.195842999999996), (-106.56048, 35.194342999999996), (-106.56048, 35.193142999999999), (-106.56048, 35.191873999999999), (-106.56048, 35.191742999999995), (-106.56048, 35.190242999999995), (-106.56037999999999, 35.188642999999999), (-106.56037999999999, 35.187242999999995), (-106.56037999999999, 35.186842999999996), (-106.56037999999999, 35.186552999999996), (-106.56037999999999, 35.185842999999998), (-106.56037999999999, 35.184443000000002), (-106.56037999999999, 35.182943000000002), (-106.56037999999999, 35.181342999999998), (-106.56037999999999, 35.180433000000001), (-106.56037999999999, 35.179943000000002), (-106.56037999999999, 35.178542999999998), (-106.56037999999999, 35.177790999999999), (-106.56037999999999, 35.177143999999998), (-106.56037999999999, 35.175643999999998), (-106.56037999999999, 35.174444000000001), (-106.56037999999999, 35.174043999999995), (-106.560526, 35.174043999999995), (-106.56478, 35.174043999999995), (-106.56627999999999, 35.174143999999998), (-106.566541, 35.174144999999996), (-106.569023, 35.174157000000001), (-106.56917199999999, 35.174157999999998), (-106.56938, 35.174143999999998), (-106.57061499999999, 35.174143999999998), (-106.57097999999999, 35.174143999999998), (-106.57679999999999, 35.174143999999998), (-106.57798, 35.174143999999998)] + >>> is_clockwise(v) + True + """ + if len(vertices) < 3: + return True + area = 0.0 + ax, ay = vertices[0] + for bx, by in vertices[1:]: + area += ax * by - ay * bx + ax, ay = bx, by + bx, by = vertices[0] + area += ax * by - ay * bx + return area < 0.0 diff --git a/plio/io/io_gdal.py b/plio/io/io_gdal.py index 0b4f9ad3db663e4dec662ae2f7f7f54247f7f34a..44a54913251eb6b41579d4ae0c63ed1221cc9584 100644 --- a/plio/io/io_gdal.py +++ b/plio/io/io_gdal.py @@ -14,8 +14,6 @@ from plio.io import extract_metadata from plio.geofuncs import geofuncs from plio.utils.utils import find_in_dict -from libpysal.cg import is_clockwise - gdal.UseExceptions() NP2GDAL_CONVERSION = { @@ -220,7 +218,7 @@ class GeoDataset(object): @property def north_up(self): if self.footprint: - return is_clockwise(json.loads(self.footprint.ExportToJson())['coordinates'][0][0]) + return geofuncs.is_clockwise(json.loads(self.footprint.ExportToJson())['coordinates'][0][0]) else: return True