Skip to content

Commit

Permalink
clean-up + add tessellate_tolerance
Browse files Browse the repository at this point in the history
  • Loading branch information
jorisvandenbossche committed Oct 25, 2024
1 parent 37cb4ef commit 4784c18
Show file tree
Hide file tree
Showing 4 changed files with 39 additions and 17 deletions.
1 change: 1 addition & 0 deletions docs/api.rst
Original file line number Diff line number Diff line change
Expand Up @@ -71,3 +71,4 @@ Input/Output

from_wkt
to_wkt
from_geoarrow
19 changes: 12 additions & 7 deletions src/geoarrow.cpp
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
// include this before s2geography to avoid ArrowArray compile issues
#include <s2geography.h>

#include "arrow_abi.h"
#include "constants.hpp"
#include "geography.hpp"
#include "pybind11.hpp"

Expand All @@ -12,6 +12,7 @@ using namespace spherely;
py::array_t<PyObjectGeography> from_geoarrow(py::object input,
bool oriented,
bool planar,
float tessellate_tolerance,
py::object geometry_encoding) {
py::tuple capsules = input.attr("__arrow_c_array__")();
py::capsule schema_capsule = capsules[0];
Expand All @@ -26,8 +27,7 @@ py::array_t<PyObjectGeography> from_geoarrow(py::object input,
s2geog::geoarrow::ImportOptions options;
options.set_oriented(oriented);
if (planar) {
// TODO replace with constant
auto tol = S1Angle::Radians(100.0 / (6371.01 * 1000));
auto tol = S1Angle::Radians(tessellate_tolerance / EARTH_RADIUS_METERS);
options.set_tessellate_tolerance(tol);
}
if (geometry_encoding.is(py::none())) {
Expand Down Expand Up @@ -64,6 +64,7 @@ void init_geoarrow(py::module& m) {
py::kw_only(),
py::arg("oriented") = false,
py::arg("planar") = false,
py::arg("tessellate_tolerance") = 100.0,
py::arg("geometry_encoding") = py::none(),
R"pbdoc(
Create an array of geographies from an Arrow array object with a GeoArrow
Expand All @@ -90,12 +91,16 @@ void init_geoarrow(py::module& m) {
By default (False), it will return the polygon with the smaller
area.
planar : bool, default False
If set to True, the edges linestrings and polygons are assumed to
be planar. In that case, additional points will be added to the line
while creating the geography objects, to ensure every point is
within 100m of the original line.
If set to True, the edges of linestrings and polygons are assumed
to be linear on the plane. In that case, additional points will
be added to the line while creating the geography objects, to
ensure every point is within 100m of the original line.
By default (False), it is assumed that the edges are spherical
(i.e. represent the shortest path on the sphere between two points).
tessellate_tolerance : float, default 100.0
The maximum distance in meters that a point must be moved to
satisfy the planar edge constraint. This is only used if `planar`
is set to True.
geometry_encoding : str, default None
By default, the encoding is inferred from the GeoArrow extension
type of the input array.
Expand Down
17 changes: 17 additions & 0 deletions src/spherely.pyi
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,9 @@ from typing import (
Generic,
Iterable,
Literal,
Protocol,
Sequence,
Tuple,
TypeVar,
overload,
)
Expand Down Expand Up @@ -196,3 +198,18 @@ def from_wkt(
planar: bool = False,
tessellate_tolerance: float = 100.0,
) -> npt.NDArray[Any]: ...

class ArrowArrayExportable(Protocol):
def __arrow_c_array__(
self, requested_schema: object | None = None
) -> Tuple[object, object]: ...

def from_geoarrow(
input: ArrowArrayExportable,
/,
*,
oriented: bool = False,
planar: bool = False,
tessellate_tolerance: float = 100.0,
geometry_encoding: str | None = None,
) -> npt.NDArray[Any]: ...
19 changes: 9 additions & 10 deletions tests/test_geoarrow.py
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ def test_from_geoarrow_wkt():
arr = ga.as_wkt(["POINT (1 1)", "POINT(2 2)", "POINT(3 3)"])

result = spherely.from_geoarrow(arr)
expected = spherely.create([1, 2, 3], [1, 2, 3])
expected = spherely.points([1, 2, 3], [1, 2, 3])
# object equality does not yet work
# np.testing.assert_array_equal(result, expected)
assert spherely.equals(result, expected).all()
Expand All @@ -36,7 +36,7 @@ def test_from_geoarrow_wkb():
arr_wkb = ga.as_wkb(arr)

result = spherely.from_geoarrow(arr_wkb)
expected = spherely.create([1, 2, 3], [1, 2, 3])
expected = spherely.points([1, 2, 3], [1, 2, 3])
assert spherely.equals(result, expected).all()

# without extension type
Expand All @@ -52,7 +52,7 @@ def test_from_geoarrow_native():
arr_point = ga.as_geoarrow(arr)

result = spherely.from_geoarrow(arr_point)
expected = spherely.create([1, 2, 3], [1, 2, 3])
expected = spherely.points([1, 2, 3], [1, 2, 3])
assert spherely.equals(result, expected).all()


Expand All @@ -63,10 +63,6 @@ def test_from_geoarrow_native():
)


# @pytest.mark.skipif(
# Version(spherely.__s2geography_version__) < Version("0.2.0"),
# reason="Needs s2geography >= 0.2.0",
# )
def test_from_geoarrow_oriented():
# by default re-orients the inner ring
arr = ga.as_geoarrow([polygon_with_bad_hole_wkt])
Expand All @@ -82,13 +78,16 @@ def test_from_geoarrow_oriented():
spherely.from_geoarrow(arr, oriented=True)


def test_from_geoarrow_planar():
def test_from_wkt_planar():
arr = ga.as_geoarrow(["LINESTRING (-64 45, 0 45)"])
result = spherely.from_geoarrow(arr)
assert spherely.distance(result[0], spherely.Point(45, -30)) > 10000
assert spherely.distance(result, spherely.point(-30.1, 45)) > 10000

result = spherely.from_geoarrow(arr, planar=True)
assert spherely.distance(result[0], spherely.Point(45, -30)) < 100
assert spherely.distance(result, spherely.point(-30.1, 45)) < 100

result = spherely.from_geoarrow(arr, planar=True, tessellate_tolerance=10)
assert spherely.distance(result, spherely.point(-30.1, 45)) < 10


def test_from_geoarrow_no_extension_type():
Expand Down

0 comments on commit 4784c18

Please sign in to comment.