Skip to content
This repository was archived by the owner on Apr 1, 2026. It is now read-only.
Merged
Show file tree
Hide file tree
Changes from 2 commits
Commits
Show all changes
20 commits
Select commit Hold shift + click to select a range
95a871a
feat: Implement ST_LENGTH geography function
google-labs-jules[bot] Jun 4, 2025
3644db1
feat: Add NotImplemented length property to GeoSeries
google-labs-jules[bot] Jun 4, 2025
b3fcd91
Update bigframes/bigquery/_operations/__init__.py
tswast Jun 4, 2025
323c33e
Merge branch 'main' into feat-st-length
tswast Jun 4, 2025
7faa776
fix lint
tswast Jun 4, 2025
719a835
add missing compilation method
tswast Jun 4, 2025
c956744
use pandas for the expected values in tests
tswast Jun 4, 2025
d2a2138
fix: Apply patch for ST_LENGTH and related test updates
google-labs-jules[bot] Jun 4, 2025
4e1cdc7
feat: Add use_spheroid parameter to ST_LENGTH and update docs
google-labs-jules[bot] Jun 5, 2025
7eb23b9
feat: Implement use_spheroid for ST_LENGTH via Ibis UDF
google-labs-jules[bot] Jun 5, 2025
b6fa804
refactor: Use Ibis UDF for ST_LENGTH BigQuery builtin
google-labs-jules[bot] Jun 5, 2025
9edc23c
refactor: Consolidate st_length tests in test_geo.py
google-labs-jules[bot] Jun 5, 2025
388a7a2
fix: Correct export of GeoStLengthOp in operations init
google-labs-jules[bot] Jun 5, 2025
c3f45c5
fix system test and some linting
tswast Jun 5, 2025
4b333f2
Merge remote-tracking branch 'origin/main' into feat-st-length
tswast Jun 5, 2025
87405a7
fix lint
tswast Jun 5, 2025
73dc58b
fix doctest
tswast Jun 5, 2025
2bb07f0
fix docstring
tswast Jun 5, 2025
b3ea901
Merge branch 'main' into feat-st-length
tswast Jun 6, 2025
9a58e07
Update bigframes/core/compile/scalar_op_compiler.py
tswast Jun 6, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions bigframes/bigquery/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@
st_difference,
st_distance,
st_intersection,
st_length,
)
from bigframes.bigquery._operations.json import (
json_extract,
Expand All @@ -58,6 +59,7 @@
"st_difference",
"st_distance",
"st_intersection",
"st_length",
# json ops
"json_extract",
"json_extract_array",
Expand Down
6 changes: 6 additions & 0 deletions bigframes/bigquery/_operations/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,3 +11,9 @@
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.

from .geo import st_length

__all__ = [
"st_length",
]
Comment thread
tswast marked this conversation as resolved.
Outdated
56 changes: 56 additions & 0 deletions bigframes/bigquery/_operations/geo.py
Original file line number Diff line number Diff line change
Expand Up @@ -380,3 +380,59 @@ def st_intersection(
each aligned geometry with other.
"""
return series._apply_binary_op(other, ops.geo_st_intersection_op)


def st_length(
series: Union[bigframes.series.Series, bigframes.geopandas.GeoSeries],
Comment thread
tswast marked this conversation as resolved.
) -> bigframes.series.Series:
"""
Computes the length of the input GEOGRAPHY.

For LINESTRING, MULTILINESTRING, POLYGON, MULTIPOLYGON the length is the
Comment thread
tswast marked this conversation as resolved.
Outdated
great-circle length of their boundaries on the WGS84 spheroid, in meters.
For POINT, MULTIPOINT, and empty GEOGRAPHYs, the length is 0.

.. note::
BigQuery's Geography functions, like `st_length`, interpret the geometry
data type as a point set on the Earth's surface. A point set is a set
of points, lines, and polygons on the WGS84 reference spheroid, with
geodesic edges. See: https://cloud.google.com/bigquery/docs/geospatial-data

**Examples:**

>>> import bigframes.geopandas
>>> import bigframes.pandas as bpd
>>> import bigframes.bigquery as bbq
>>> from shapely.geometry import Polygon, LineString, Point
>>> bpd.options.display.progress_bar = None

>>> series = bigframes.geopandas.GeoSeries(
... [
... LineString([(0, 0), (1, 1), (0, 1)]),
... Polygon([(0.0, 0.0), (0.1, 0.1), (0.0, 0.1)]),
... Point(0, 1),
... ]
... )
>>> series
0 LINESTRING (0 0, 1 1, 0 1)
1 POLYGON ((0 0, 0.1 0.1, 0 0.1, 0 0))
2 POINT (0 1)
dtype: geometry

>>> bbq.st_length(series)
0 314420.232042
1 374483.073393
2 0.0
dtype: Float64

Args:
series (bigframes.pandas.Series | bigframes.geopandas.GeoSeries):
A series containing geography objects.

Returns:
bigframes.pandas.Series:
Series of float representing the lengths in meters.
"""
series = series._apply_unary_op(ops.geo_st_length_op)
series.name = None
return series
6 changes: 6 additions & 0 deletions bigframes/geopandas/geoseries.py
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,12 @@ def __init__(self, data=None, index=None, **kwargs):
data=data, index=index, dtype=geopandas.array.GeometryDtype(), **kwargs
)

@property
def length(self):
raise NotImplementedError(
"GeoSeries.length is not yet implemented. Please use bigframes.bigquery.st_length(geoseries) instead."
)

@property
def x(self) -> bigframes.series.Series:
series = self._apply_unary_op(ops.geo_x_op)
Expand Down
2 changes: 2 additions & 0 deletions bigframes/operations/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -98,6 +98,7 @@
geo_st_geogfromtext_op,
geo_st_geogpoint_op,
geo_st_intersection_op,
geo_st_length_op,
geo_x_op,
geo_y_op,
GeoStDistanceOp,
Expand Down Expand Up @@ -385,6 +386,7 @@
"geo_st_geogfromtext_op",
"geo_st_geogpoint_op",
"geo_st_intersection_op",
"geo_st_length_op",
"geo_x_op",
"geo_y_op",
"GeoStDistanceOp",
Expand Down
7 changes: 7 additions & 0 deletions bigframes/operations/geo_ops.py
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,13 @@
name="geo_st_geogpoint", type_signature=op_typing.BinaryNumericGeo()
)

geo_st_length_op = base_ops.create_unary_op(
name="geo_st_length",
type_signature=op_typing.FixedOutputType(
dtypes.is_geo_like, dtypes.FLOAT_DTYPE, description="geo-like"
),
)

geo_x_op = base_ops.create_unary_op(
name="geo_x",
type_signature=op_typing.FixedOutputType(
Expand Down
Loading
Loading