[GH-2883] Add ST_MakeBox2D(p1, p2) scalar constructor#2897
Merged
jiayuasu merged 2 commits intoapache:masterfrom May 3, 2026
Merged
[GH-2883] Add ST_MakeBox2D(p1, p2) scalar constructor#2897jiayuasu merged 2 commits intoapache:masterfrom
jiayuasu merged 2 commits intoapache:masterfrom
Conversation
Construct a Box2D from two corner points (lower-left, upper-right). PostGIS-compatible. Coordinates are taken verbatim — no swapping or ordering validation — so xmin > xmax / ymin > ymax are preserved as supplied. This leaves those orderings reserved for a future antimeridian-wraparound semantics on the longitude axis (cf. sedona-db's WraparoundInterval). Null or empty point inputs return NULL. Non-point inputs raise IllegalArgumentException. Closes apache#2883.
Contributor
There was a problem hiding this comment.
Pull request overview
Adds a new PostGIS-compatible scalar constructor ST_MakeBox2D(p1, p2) to build a native Box2D value from two corner points, integrating it into Sedona’s Spark SQL function catalog and validating behavior via Scala tests.
Changes:
- Implement
ST_MakeBox2DSpark SQL expression backed byorg.apache.sedona.common.Constructors.makeBox2D. - Register
ST_MakeBox2Din the Sedona SQL UDF catalog under Geometry-Constructors. - Add Scala tests covering happy path, NULL/empty propagation, swapped-corner preservation, and non-point rejection.
Reviewed changes
Copilot reviewed 4 out of 4 changed files in this pull request and generated 1 comment.
| File | Description |
|---|---|
| spark/common/src/test/scala/org/apache/sedona/sql/constructorTestScala.scala | Adds unit tests for ST_MakeBox2D behavior and error handling. |
| spark/common/src/main/scala/org/apache/spark/sql/sedona_sql/expressions/Constructors.scala | Introduces the ST_MakeBox2D Spark SQL expression wrapper. |
| spark/common/src/main/scala/org/apache/sedona/sql/UDF/Catalog.scala | Registers ST_MakeBox2D in the function catalog. |
| common/src/main/java/org/apache/sedona/common/Constructors.java | Implements makeBox2D helper to construct Box2D from two POINT geometries. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
Comment on lines
+142
to
+167
| it("Passed ST_MakeBox2D") { | ||
| val df = sparkSession.sql(""" | ||
| SELECT | ||
| ST_MakeBox2D(ST_Point(1.0, 2.0), ST_Point(4.0, 5.0)) AS bbox, | ||
| ST_MakeBox2D(ST_Point(10.0, 20.0), ST_GeomFromText(NULL)) AS bbox_null, | ||
| ST_MakeBox2D(ST_GeomFromText('POINT EMPTY'), ST_Point(1.0, 1.0)) AS bbox_empty | ||
| """) | ||
| val row = df.collect()(0) | ||
| val bbox = row.getAs[Box2D]("bbox") | ||
| assert(bbox.getXMin == 1.0) | ||
| assert(bbox.getYMin == 2.0) | ||
| assert(bbox.getXMax == 4.0) | ||
| assert(bbox.getYMax == 5.0) | ||
| assert(row.isNullAt(1)) | ||
| assert(row.isNullAt(2)) | ||
| } | ||
|
|
||
| it("ST_MakeBox2D preserves swapped corners") { | ||
| // No swapping or reordering; lower-left/upper-right are taken verbatim. | ||
| // This leaves xmin > xmax / ymin > ymax available for future antimeridian semantics. | ||
| val df = sparkSession.sql( | ||
| "SELECT ST_MakeBox2D(ST_Point(170.0, 10.0), ST_Point(-170.0, 20.0)) AS bbox") | ||
| val bbox = df.collect()(0).getAs[Box2D]("bbox") | ||
| assert(bbox.getXMin == 170.0) | ||
| assert(bbox.getXMax == -170.0) | ||
| } |
Member
Author
There was a problem hiding this comment.
Added in 16d9137. ST_PointZ inputs round-trip with Z ignored — Box2D gets the supplied X/Y verbatim.
jiayuasu
added a commit
to jiayuasu/sedona
that referenced
this pull request
May 5, 2026
Mirrors the Phase 1 SQL surface added in apache#2890, apache#2895, apache#2897, apache#2898, apache#2899 in PySpark wrappers: - ST_Box2D in st_functions - ST_MakeBox2D and ST_GeomFromBox2D in st_constructors - ST_Extent in st_aggregates Accessor overloads (ST_XMin/XMax/YMin/YMax) and ST_AsText already worked with Box2D inputs through their existing wrappers; SQL overload resolution happens on the JVM side. The Python Box2DType UDT and Box2D value class were merged in apache#2878, so collected results materialize as Box2D Python objects with xmin/ymin/xmax/ymax attributes. Closes apache#2887.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Did you read the Contributor Guide?
Is this PR related to a ticket?
[GH-XXX] my subject. Closes Implement ST_MakeBox2D(p1, p2) scalar constructor #2883What changes were proposed in this PR?
Adds the
ST_MakeBox2D(lower_left: Point, upper_right: Point) -> Box2Dscalar constructor. PostGIS-compatible.Behavior:
xmin > xmax/ymin > ymaxare preserved as supplied. This is deliberate: it leaves those orderings reserved for a future antimeridian-wraparound semantics on the longitude axis (cf.apache/sedona-db'sWraparoundInterval).IllegalArgumentException("ST_MakeBox2D requires two POINT geometries").How was this patch tested?
constructorTestScala:ST_MakeBox2D(ST_Point(170,10), ST_Point(-170,20))round-trips withxmin=170, xmax=-170(no auto-swap).ST_PointZinputs round-trip with Z ignored.Did this PR include necessary documentation updates?
ST_MakeBox2Dlands with the rest of the Phase 1 surface (Add a native Box2D type for bounding boxes #2877) onceST_Extent, the cast/text functions, and bindings exist. Scala DataFrame API wrappers tracked separately in Scala/Python DataFrame API wrappers for Box2D Phase 1 functions #2891.