Skip to content

Commit

Permalink
New cell area functions with h3==3.7 (#171)
Browse files Browse the repository at this point in the history
* move to h3lib 3.8pre

* cython functions done

* have tests running

* linting

* bump core library

* skip building wheels for Python 3.9 for now (buggy)

* try bumping codecov action version

* try testing for 3.9

* ah, no 3.9 up yet

* bump some action versions

* add some docstrings

* changelog

* bump badges
  • Loading branch information
ajfriend authored Oct 2, 2020
1 parent 496dab0 commit 5e0dceb
Show file tree
Hide file tree
Showing 15 changed files with 335 additions and 36 deletions.
4 changes: 2 additions & 2 deletions .github/workflows/coverage-lint.yml
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ jobs:
runs-on: ubuntu-latest

steps:
- uses: actions/checkout@v2.1.1
- uses: actions/checkout@v2.3.3
with:
submodules: recursive

Expand All @@ -32,7 +32,7 @@ jobs:
run: pytest --cov=h3 --full-trace --cov-report=xml

- name: Upload coverage to Codecov
uses: codecov/[email protected].7
uses: codecov/[email protected].13
with:
file: ./coverage.xml
fail_ci_if_error: true
4 changes: 2 additions & 2 deletions .github/workflows/tests.yml
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ jobs:
python-version: 2.7

steps:
- uses: actions/checkout@v2.1.1
- uses: actions/checkout@v2.3.3
with:
submodules: recursive

Expand All @@ -29,7 +29,7 @@ jobs:
python-version: "${{ matrix.python-version }}"

## Start Windows stuff
- uses: ilammy/msvc-dev-cmd@v1.2.0
- uses: ilammy/msvc-dev-cmd@v1.3.0
if: startsWith(matrix.os, 'windows')

- name: Set Windows Compiler
Expand Down
6 changes: 3 additions & 3 deletions .github/workflows/wheels.yml
Original file line number Diff line number Diff line change
Expand Up @@ -23,15 +23,15 @@ jobs:

## Setup Env

- uses: actions/checkout@v2.1.1
- uses: actions/checkout@v2.3.3
with:
submodules: recursive

- uses: actions/setup-python@v2
with:
python-version: 3.8

- uses: ilammy/msvc-dev-cmd@v1.2.0
- uses: ilammy/msvc-dev-cmd@v1.3.0
if: startsWith(matrix.os, 'windows')


Expand All @@ -52,7 +52,7 @@ jobs:
- name: Build Mac
if: startsWith(matrix.os, 'mac')
env:
CIBW_SKIP: pp*
CIBW_SKIP: pp* cp39-*
run: |
python -m cibuildwheel --output-dir wheelhouse
Expand Down
6 changes: 6 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,12 @@ Because H3-Py is versioned in lockstep with the H3 core library, please
avoid adding features or APIs which do not map onto the
[H3 core API](https://uber.github.io/h3/#/documentation/api-reference/).

## Unreleased

- Add functions (#171)
+ `cell_area`
+ `exact_edge_length`
+ `point_dist`

## [3.6.4] - 2020-07-20

Expand Down
2 changes: 1 addition & 1 deletion makefile
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ test:
env/bin/pytest tests/* --cov=h3 --cov-report term-missing --durations=10

lint:
flake8 src/h3 setup.py tests
env/bin/flake8 src/h3 setup.py tests

lab:
env/bin/pip install jupyterlab
Expand Down
2 changes: 1 addition & 1 deletion readme.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
[![PyPI version](https://badge.fury.io/py/h3.svg)](https://badge.fury.io/py/h3)
[![PyPI downloads](https://pypip.in/d/h3/badge.png)](https://pypistats.org/packages/h3)
[![conda](https://img.shields.io/conda/vn/conda-forge/h3-py.svg)](https://anaconda.org/conda-forge/h3-py)
[![version](https://img.shields.io/badge/h3-v3.6.4-blue.svg)](https://github.com/uber/h3/releases/tag/v3.6.4)
[![version](https://img.shields.io/badge/h3-v3.7.0-blue.svg)](https://github.com/uber/h3/releases/tag/v3.7.0)
[![version](https://img.shields.io/badge/License-Apache%202.0-blue.svg)](LICENSE)

[![Tests](https://github.com/uber/h3-py/workflows/tests/badge.svg)](https://github.com/uber/h3-py/actions)
Expand Down
5 changes: 4 additions & 1 deletion src/h3/_cy/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@
uncompact,
num_hexagons,
mean_hex_area,
mean_edge_length,
cell_area,
line,
is_res_class_iii,
get_pentagon_indexes,
Expand All @@ -46,6 +46,8 @@
edge_destination,
edge_cells,
edges_from_cell,
mean_edge_length,
edge_length,
)

from .geo import (
Expand All @@ -56,6 +58,7 @@
polyfill,
cell_boundary,
edge_boundary,
point_dist,
)

from .to_multipoly import (
Expand Down
23 changes: 10 additions & 13 deletions src/h3/_cy/cells.pyx
Original file line number Diff line number Diff line change
Expand Up @@ -250,23 +250,20 @@ cpdef double mean_hex_area(int resolution, unit='km^2') except -1:

return area

cpdef double mean_edge_length(int resolution, unit='km') except -1:
check_res(resolution)

length = h3lib.edgeLengthKm(resolution)

# todo: multiple units
convert = {
'km': 1.0,
'm': 1000.0
}
cpdef double cell_area(H3int h, unit='km^2') except -1:
check_cell(h)

try:
length *= convert[unit]
except:
if unit == 'rads^2':
area = h3lib.cellAreaRads2(h)
elif unit == 'km^2':
area = h3lib.cellAreaKm2(h)
elif unit == 'm^2':
area = h3lib.cellAreaM2(h)
else:
raise H3ValueError('Unknown unit: {}'.format(unit))

return length
return area


cpdef H3int[:] line(H3int start, H3int end):
Expand Down
39 changes: 39 additions & 0 deletions src/h3/_cy/edges.pyx
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ from .h3lib cimport bool, H3int
from .util cimport (
check_cell,
check_edge,
check_res,
create_ptr,
create_mv,
)
Expand Down Expand Up @@ -59,3 +60,41 @@ cpdef H3int[:] edges_from_cell(H3int origin):
mv = create_mv(ptr, 6)

return mv


cpdef double mean_edge_length(int resolution, unit='km') except -1:
check_res(resolution)

length = h3lib.edgeLengthKm(resolution)

# todo: multiple units
convert = {
'km': 1.0,
'm': 1000.0
}

try:
length *= convert[unit]
except:
raise H3ValueError('Unknown unit: {}'.format(unit))

return length


cpdef double edge_length(H3int e, unit='km') except -1:
check_edge(e)

# todo: maybe kick this logic up to the python level
# it might be a little cleaner, because we can do the "switch statement"
# with a dict, but would require exposing more C functions

if unit == 'rads':
length = h3lib.exactEdgeLengthRads(e)
elif unit == 'km':
length = h3lib.exactEdgeLengthKm(e)
elif unit == 'm':
length = h3lib.exactEdgeLengthM(e)
else:
raise H3ValueError('Unknown unit: {}'.format(unit))

return length
21 changes: 21 additions & 0 deletions src/h3/_cy/geo.pyx
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,8 @@ from .util cimport (
)
from libc cimport stdlib

from .util import H3ValueError


cpdef H3int geo_to_h3(double lat, double lng, int res) except 1:
cdef:
Expand Down Expand Up @@ -255,3 +257,22 @@ def edge_boundary(H3int edge, bool geo_json=False):
verts = tuple(v[::-1] for v in verts)

return verts


cpdef double point_dist(
double lat1, double lng1,
double lat2, double lng2, unit='km') except -1:

a = deg2coord(lat1, lng1)
b = deg2coord(lat2, lng2)

if unit == 'rads':
d = h3lib.pointDistRads(&a, &b)
elif unit == 'km':
d = h3lib.pointDistKm(&a, &b)
elif unit == 'm':
d = h3lib.pointDistM(&a, &b)
else:
raise H3ValueError('Unknown unit: {}'.format(unit))

return d
29 changes: 18 additions & 11 deletions src/h3/_cy/h3lib.pxd
Original file line number Diff line number Diff line change
Expand Up @@ -86,14 +86,6 @@ cdef extern from "h3api.h":

double radsToDegs(double radians) nogil

double hexAreaKm2(int res)

double hexAreaM2(int res)

double edgeLengthKm(int res)

double edgeLengthM(int res)

stdint.int64_t numHexagons(int res)

int h3GetResolution(H3Index h)
Expand Down Expand Up @@ -149,13 +141,28 @@ cdef extern from "h3api.h":
void getH3UnidirectionalEdgeBoundary(H3Index edge, GeoBoundary *gb)

int h3LineSize(H3Index start, H3Index end)

int h3Line(H3Index start, H3Index end, H3Index *out)

int maxFaceCount(H3Index h3)

void h3GetFaces(H3Index h3, int *out)

int experimentalH3ToLocalIj(H3Index origin, H3Index h3, CoordIJ *out)

int experimentalLocalIjToH3(H3Index origin, const CoordIJ *ij, H3Index *out)

double hexAreaKm2(int res) nogil
double hexAreaM2(int res) nogil

double cellAreaRads2(H3Index h) nogil
double cellAreaKm2(H3Index h) nogil
double cellAreaM2(H3Index h) nogil

double edgeLengthKm(int res) nogil
double edgeLengthM(int res) nogil

double exactEdgeLengthRads(H3Index edge) nogil
double exactEdgeLengthKm(H3Index edge) nogil
double exactEdgeLengthM(H3Index edge) nogil

double pointDistRads(const GeoCoord *a, const GeoCoord *b) nogil
double pointDistKm(const GeoCoord *a, const GeoCoord *b) nogil
double pointDistM(const GeoCoord *a, const GeoCoord *b) nogil
2 changes: 1 addition & 1 deletion src/h3/_version.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
__version__ = '3.6.4'
__version__ = '3.7.0'
__description__ = 'Hierarchical hexagonal geospatial indexing system'
__url__ = 'https://github.com/uber/h3-py'
__license__ = "Apache 2.0 License"
Expand Down
83 changes: 83 additions & 0 deletions src/h3/api/_api_template.py
Original file line number Diff line number Diff line change
Expand Up @@ -886,4 +886,87 @@ def experimental_local_ij_to_h3(origin, i, j):

return h

def cell_area(h, unit='km^2'):
"""
Compute the spherical surface area of a specific H3 cell.
Parameters
----------
h : H3Cell
unit: str
Unit for area result ('km^2', 'm^2', or 'rads^2')
Returns
-------
The area of the H3 cell in the given units
Implementation Notes
--------------------
This function breaks the cell into spherical triangles, and computes
their spherical area.
The function uses the spherical distance calculation given by
`point_dist`.
"""
h = _in_scalar(h)

return _cy.cell_area(h, unit=unit)

def exact_edge_length(e, unit='km'):
"""
Compute the spherical length of a specific H3 edge.
Parameters
----------
h : H3Cell
unit: str
Unit for length result ('km', 'm', or 'rads')
Returns
-------
The length of the edge in the given units
Implementation Notes
--------------------
This function uses the spherical distance calculation given by
`point_dist`.
"""
e = _in_scalar(e)

return _cy.edge_length(e, unit=unit)

def point_dist(point1, point2, unit='km'):
"""
Compute the spherical distance between two (lat, lng) points.
todo: do we handle lat/lng points consistently in the api? what
about (lat1, lng1, lat2, lng2) as the input? How will this work
for vectorized versions?
Parameters
----------
point1 : tuple
(lat, lng) tuple in degrees
point2 : tuple
(lat, lng) tuple in degrees
unit: str
Unit for distance result ('km', 'm', or 'rads')
Returns
-------
Spherical (or "haversine") distance between the points
"""
lat1, lng1 = point1
lat2, lng2 = point2

return _cy.point_dist(
lat1, lng1,
lat2, lng2,
unit=unit
)

_globals.update(locals())
2 changes: 1 addition & 1 deletion src/h3lib
Submodule h3lib updated 49 files
+118 −0 .github/workflows/test-linux.yml
+42 −0 .github/workflows/test-macos.yml
+32 −0 .github/workflows/test-website.yml
+44 −0 .github/workflows/test-windows.yml
+3 −0 .gitignore
+8 −52 .travis.yml
+0 −92 .ycm_extra_conf.py
+19 −0 CHANGELOG.md
+19 −8 CMakeLists.txt
+52 −9 README.md
+3 −1 RELEASE.md
+1 −1 VERSION
+0 −50 appveyor.yml
+4 −0 dev-docs/RFCs/v4.0.0/names_for_concepts_types_functions.md
+6 −1 dev-docs/build_windows.md
+3 −3 dev-docs/creating_bindings.md
+76 −0 docs/api/misc.md
+1 −0 docs/community/applications.md
+8 −4 docs/community/tutorials.md
+12 −1 docs/core-library/h3indexing.md
+4 −1 src/apps/applib/include/utility.h
+119 −3 src/apps/applib/lib/utility.c
+1 −1 src/apps/benchmarks/benchmarkH3Api.c
+34 −0 src/apps/benchmarks/benchmarkH3UniEdge.c
+67 −0 src/apps/miscapps/generatePentagonDirectionFaces.c
+15 −1 src/apps/testapps/testBaseCells.c
+39 −13 src/apps/testapps/testGeoCoord.c
+47 −0 src/apps/testapps/testH3CellArea.c
+180 −0 src/apps/testapps/testH3CellAreaExhaustive.c
+8 −5 src/apps/testapps/testH3ToLocalIj.c
+29 −16 src/apps/testapps/testH3UniEdge.c
+111 −0 src/apps/testapps/testH3UniEdgeExhaustive.c
+1 −1 src/apps/testapps/testPolyfill.c
+66 −0 src/apps/testapps/testVertex.c
+4 −0 src/h3lib/include/baseCells.h
+3 −2 src/h3lib/include/faceijk.h
+1 −3 src/h3lib/include/geoCoord.h
+9 −3 src/h3lib/include/h3Index.h
+46 −2 src/h3lib/include/h3api.h.in
+44 −0 src/h3lib/include/vertex.h
+5 −5 src/h3lib/lib/algos.c
+25 −4 src/h3lib/lib/baseCells.c
+4 −4 src/h3lib/lib/bbox.c
+30 −21 src/h3lib/lib/faceijk.c
+160 −44 src/h3lib/lib/geoCoord.c
+26 −19 src/h3lib/lib/h3Index.c
+35 −57 src/h3lib/lib/h3UniEdge.c
+134 −0 src/h3lib/lib/vertex.c
+1 −1 website/README.md
Loading

0 comments on commit 5e0dceb

Please sign in to comment.