Skip to content

Commit 32cddfe

Browse files
authored
feat: add GeoSeries.boundary() (#1435)
* feat: add GeoSeries.boundary() * add test and update notebook * update method return type
1 parent e6392b6 commit 32cddfe

File tree

7 files changed

+269
-106
lines changed

7 files changed

+269
-106
lines changed

bigframes/core/compile/scalar_op_compiler.py

+18-8
Original file line numberDiff line numberDiff line change
@@ -1001,14 +1001,9 @@ def normalize_op_impl(x: ibis_types.Value):
10011001

10021002

10031003
# Geo Ops
1004-
@scalar_op_compiler.register_unary_op(ops.geo_x_op)
1005-
def geo_x_op_impl(x: ibis_types.Value):
1006-
return typing.cast(ibis_types.GeoSpatialValue, x).x()
1007-
1008-
1009-
@scalar_op_compiler.register_unary_op(ops.geo_y_op)
1010-
def geo_y_op_impl(x: ibis_types.Value):
1011-
return typing.cast(ibis_types.GeoSpatialValue, x).y()
1004+
@scalar_op_compiler.register_unary_op(ops.geo_st_boundary_op, pass_op=False)
1005+
def geo_st_boundary_op_impl(x: ibis_types.Value):
1006+
return st_boundary(x)
10121007

10131008

10141009
@scalar_op_compiler.register_unary_op(ops.geo_area_op)
@@ -1035,6 +1030,16 @@ def geo_st_geogpoint_op_impl(x: ibis_types.Value, y: ibis_types.Value):
10351030
)
10361031

10371032

1033+
@scalar_op_compiler.register_unary_op(ops.geo_x_op)
1034+
def geo_x_op_impl(x: ibis_types.Value):
1035+
return typing.cast(ibis_types.GeoSpatialValue, x).x()
1036+
1037+
1038+
@scalar_op_compiler.register_unary_op(ops.geo_y_op)
1039+
def geo_y_op_impl(x: ibis_types.Value):
1040+
return typing.cast(ibis_types.GeoSpatialValue, x).y()
1041+
1042+
10381043
# Parameterized ops
10391044
@scalar_op_compiler.register_unary_op(ops.StructFieldOp, pass_op=True)
10401045
def struct_field_op_impl(x: ibis_types.Value, op: ops.StructFieldOp):
@@ -1965,6 +1970,11 @@ def unix_millis(a: ibis_dtypes.timestamp) -> int: # type: ignore
19651970
"""Convert a timestamp to milliseconds"""
19661971

19671972

1973+
@ibis_udf.scalar.builtin
1974+
def st_boundary(a: ibis_dtypes.geography) -> ibis_dtypes.geography: # type: ignore
1975+
"""Find the boundary of a geography."""
1976+
1977+
19681978
@ibis_udf.scalar.builtin
19691979
def unix_micros(a: ibis_dtypes.timestamp) -> int: # type: ignore
19701980
"""Convert a timestamp to microseconds"""

bigframes/geopandas/geoseries.py

+6
Original file line numberDiff line numberDiff line change
@@ -68,6 +68,12 @@ def area(self, crs=None) -> bigframes.series.Series: # type: ignore
6868
f"GeoSeries.area is not supported. Use bigframes.bigquery.st_area(series), instead. {constants.FEEDBACK_LINK}"
6969
)
7070

71+
@property
72+
def boundary(self) -> bigframes.series.Series: # type: ignore
73+
series = self._apply_unary_op(ops.geo_st_boundary_op)
74+
series.name = None
75+
return series
76+
7177
@classmethod
7278
def from_wkt(cls, data, index=None) -> GeoSeries:
7379
series = bigframes.series.Series(data, index=index)

bigframes/operations/__init__.py

+2
Original file line numberDiff line numberDiff line change
@@ -89,6 +89,7 @@
8989
from bigframes.operations.geo_ops import (
9090
geo_area_op,
9191
geo_st_astext_op,
92+
geo_st_boundary_op,
9293
geo_st_geogfromtext_op,
9394
geo_st_geogpoint_op,
9495
geo_x_op,
@@ -364,6 +365,7 @@
364365
"manhattan_distance_op",
365366
# Geo ops
366367
"geo_area_op",
368+
"geo_st_boundary_op",
367369
"geo_st_astext_op",
368370
"geo_st_geogfromtext_op",
369371
"geo_st_geogpoint_op",

bigframes/operations/geo_ops.py

+21-15
Original file line numberDiff line numberDiff line change
@@ -16,35 +16,26 @@
1616
from bigframes.operations import base_ops
1717
import bigframes.operations.type as op_typing
1818

19-
geo_x_op = base_ops.create_unary_op(
20-
name="geo_x",
21-
type_signature=op_typing.FixedOutputType(
22-
dtypes.is_geo_like, dtypes.FLOAT_DTYPE, description="geo-like"
23-
),
24-
)
25-
26-
geo_y_op = base_ops.create_unary_op(
27-
name="geo_y",
28-
type_signature=op_typing.FixedOutputType(
29-
dtypes.is_geo_like, dtypes.FLOAT_DTYPE, description="geo-like"
30-
),
31-
)
32-
3319
geo_area_op = base_ops.create_unary_op(
3420
name="geo_area",
3521
type_signature=op_typing.FixedOutputType(
3622
dtypes.is_geo_like, dtypes.FLOAT_DTYPE, description="geo-like"
3723
),
3824
)
3925

40-
4126
geo_st_astext_op = base_ops.create_unary_op(
4227
name="geo_st_astext",
4328
type_signature=op_typing.FixedOutputType(
4429
dtypes.is_geo_like, dtypes.STRING_DTYPE, description="geo-like"
4530
),
4631
)
4732

33+
geo_st_boundary_op = base_ops.create_unary_op(
34+
name="geo_st_boundary",
35+
type_signature=op_typing.FixedOutputType(
36+
dtypes.is_geo_like, dtypes.GEO_DTYPE, description="geo-like"
37+
),
38+
)
4839

4940
geo_st_geogfromtext_op = base_ops.create_unary_op(
5041
name="geo_st_geogfromtext",
@@ -53,6 +44,21 @@
5344
),
5445
)
5546

47+
5648
geo_st_geogpoint_op = base_ops.create_binary_op(
5749
name="geo_st_geogpoint", type_signature=op_typing.BinaryNumericGeo()
5850
)
51+
52+
geo_x_op = base_ops.create_unary_op(
53+
name="geo_x",
54+
type_signature=op_typing.FixedOutputType(
55+
dtypes.is_geo_like, dtypes.FLOAT_DTYPE, description="geo-like"
56+
),
57+
)
58+
59+
geo_y_op = base_ops.create_unary_op(
60+
name="geo_y",
61+
type_signature=op_typing.FixedOutputType(
62+
dtypes.is_geo_like, dtypes.FLOAT_DTYPE, description="geo-like"
63+
),
64+
)

0 commit comments

Comments
 (0)