From 581cec5d87cb6369d8682567b5e19e77977d1f4a Mon Sep 17 00:00:00 2001 From: Joris Van den Bossche Date: Tue, 26 Nov 2024 08:42:11 +0100 Subject: [PATCH] simplify, use s2geography::s2_x/y --- CMakeLists.txt | 1 - src/accessors-geog.cpp | 42 +++++++++++++++++++++++++++ src/coords.cpp | 64 ----------------------------------------- src/spherely.cpp | 2 -- tests/test_accessors.py | 25 ++++++++++++++++ tests/test_coords.py | 25 ---------------- 6 files changed, 67 insertions(+), 92 deletions(-) delete mode 100644 src/coords.cpp diff --git a/CMakeLists.txt b/CMakeLists.txt index b584649..a9e0bb1 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -73,7 +73,6 @@ endif() set(CPP_SOURCES src/accessors-geog.cpp - src/coords.cpp src/creation.cpp src/geography.cpp src/io.cpp diff --git a/src/accessors-geog.cpp b/src/accessors-geog.cpp index 4d413df..0a03b17 100644 --- a/src/accessors-geog.cpp +++ b/src/accessors-geog.cpp @@ -26,6 +26,22 @@ PyObjectGeography convex_hull(PyObjectGeography a) { return make_py_geography(s2geog::s2_convex_hull(a_ptr)); } +double get_x(PyObjectGeography a) { + auto geog = a.as_geog_ptr(); + if (geog->geog_type() != GeographyType::Point) { + throw py::value_error("Only Point geometries supported"); + } + return s2geog::s2_x(geog->geog()); +} + +double get_y(PyObjectGeography a) { + auto geog = a.as_geog_ptr(); + if (geog->geog_type() != GeographyType::Point) { + throw py::value_error("Only Point geometries supported"); + } + return s2geog::s2_y(geog->geog()); +} + double distance(PyObjectGeography a, PyObjectGeography b, double radius = EARTH_RADIUS_METERS) { const auto& a_index = a.as_geog_ptr()->geog_index(); const auto& b_index = b.as_geog_ptr()->geog_index(); @@ -78,6 +94,32 @@ void init_accessors(py::module& m) { )pbdoc"); + m.def("get_x", + py::vectorize(&get_x), + py::arg("a"), + R"pbdoc( + Returns the longitude value of the Point (in degrees). + + Parameters + ---------- + a: :py:class:`Geography` or array_like + Geography object(s). + + )pbdoc"); + + m.def("get_y", + py::vectorize(&get_y), + py::arg("a"), + R"pbdoc( + Returns the latitude value of the Point (in degrees). + + Parameters + ---------- + a: :py:class:`Geography` or array_like + Geography object(s). + + )pbdoc"); + m.def("distance", py::vectorize(&distance), py::arg("a"), diff --git a/src/coords.cpp b/src/coords.cpp deleted file mode 100644 index 3d8d0c4..0000000 --- a/src/coords.cpp +++ /dev/null @@ -1,64 +0,0 @@ -#include -#include - -#include -#include - -#include "geography.hpp" -#include "pybind11.hpp" - -namespace py = pybind11; -namespace s2geog = s2geography; -using namespace spherely; - -double get_y(PyObjectGeography a) { - auto geog = a.as_geog_ptr(); - if (geog->geog_type() != GeographyType::Point) { - throw py::value_error("Only Point geometries supported"); - } - const auto *point = geog->downcast_geog(); - auto s2point = point->Points()[0]; - auto latlng = S2LatLng(std::move(s2point)); - double lat = latlng.lat().degrees(); - return lat; -} - -double get_x(PyObjectGeography a) { - auto geog = a.as_geog_ptr(); - if (geog->geog_type() != GeographyType::Point) { - throw py::value_error("Only Point geometries supported"); - } - const auto *point = geog->downcast_geog(); - auto s2point = point->Points()[0]; - auto latlng = S2LatLng(std::move(s2point)); - double lng = latlng.lng().degrees(); - return lng; -} - -void init_coords(py::module &m) { - m.def("get_y", - py::vectorize(&get_y), - py::arg("a"), - R"pbdoc( - Returns the latitude value of the Point (in degrees). - - Parameters - ---------- - a: :py:class:`Geography` or array_like - Geography object(s). - - )pbdoc"); - - m.def("get_x", - py::vectorize(&get_x), - py::arg("a"), - R"pbdoc( - Returns the longitude value of the Point (in degrees). - - Parameters - ---------- - a: :py:class:`Geography` or array_like - Geography object(s). - - )pbdoc"); -} diff --git a/src/spherely.cpp b/src/spherely.cpp index bc2f2e8..bd0bb66 100644 --- a/src/spherely.cpp +++ b/src/spherely.cpp @@ -8,7 +8,6 @@ namespace py = pybind11; void init_geography(py::module&); void init_creation(py::module&); void init_predicates(py::module&); -void init_coords(py::module&); void init_accessors(py::module&); void init_io(py::module&); #if defined(S2GEOGRAPHY_VERSION_MAJOR) && \ @@ -29,7 +28,6 @@ PYBIND11_MODULE(spherely, m) { init_geography(m); init_creation(m); init_predicates(m); - init_coords(m); init_accessors(m); init_io(m); #if defined(S2GEOGRAPHY_VERSION_MAJOR) && \ diff --git a/tests/test_accessors.py b/tests/test_accessors.py index a203db3..8d323e1 100644 --- a/tests/test_accessors.py +++ b/tests/test_accessors.py @@ -84,6 +84,31 @@ def test_convex_hull(geog, expected) -> None: assert spherely.equals(actual, expected) +def test_get_x_y() -> None: + # scalar + a = spherely.point(1.5, 2.6) + assert spherely.get_x(a) == pytest.approx(1.5, abs=1e-14) + assert spherely.get_y(a) == pytest.approx(2.6, abs=1e-14) + + # array + arr = np.array([spherely.point(0, 1), spherely.point(1, 2), spherely.point(2, 3)]) + + actual = spherely.get_x(arr) + expected = np.array([0, 1, 2], dtype="float64") + np.testing.assert_allclose(actual, expected) + + actual = spherely.get_y(arr) + expected = np.array([1, 2, 3], dtype="float64") + np.testing.assert_allclose(actual, expected) + + # only points are supported + with pytest.raises(ValueError): + spherely.get_x(spherely.linestring([(0, 1), (1, 2)])) + + with pytest.raises(ValueError): + spherely.get_y(spherely.linestring([(0, 1), (1, 2)])) + + @pytest.mark.parametrize( "geog_a, geog_b, expected", [ diff --git a/tests/test_coords.py b/tests/test_coords.py index e6859c7..79ccfe8 100644 --- a/tests/test_coords.py +++ b/tests/test_coords.py @@ -2,28 +2,3 @@ import pytest import spherely - - -def test_get_x_y() -> None: - # scalar - a = spherely.point(1.5, 2.6) - assert spherely.get_x(a) == pytest.approx(1.5, abs=1e-14) - assert spherely.get_y(a) == pytest.approx(2.6, abs=1e-14) - - # array - arr = np.array([spherely.point(0, 1), spherely.point(1, 2), spherely.point(2, 3)]) - - actual = spherely.get_x(arr) - expected = np.array([0, 1, 2], dtype="float64") - np.testing.assert_allclose(actual, expected) - - actual = spherely.get_y(arr) - expected = np.array([1, 2, 3], dtype="float64") - np.testing.assert_allclose(actual, expected) - - # only points are supported - with pytest.raises(ValueError): - spherely.get_x(spherely.linestring([(0, 1), (1, 2)])) - - with pytest.raises(ValueError): - spherely.get_y(spherely.linestring([(0, 1), (1, 2)]))