|
21 | 21 | import static org.apache.flink.table.api.Expressions.$; |
22 | 22 | import static org.apache.flink.table.api.Expressions.call; |
23 | 23 | import static org.junit.Assert.assertEquals; |
| 24 | +import static org.junit.Assert.assertNull; |
24 | 25 |
|
25 | 26 | import org.apache.flink.table.api.Table; |
26 | 27 | import org.apache.sedona.flink.expressions.Predicates; |
@@ -62,6 +63,75 @@ public void testContainsOnBox2D() { |
62 | 63 | assertEquals(false, row.getField(1)); |
63 | 64 | } |
64 | 65 |
|
| 66 | + @Test |
| 67 | + public void testIntersectsOnBox3D() { |
| 68 | + Table t = |
| 69 | + tableEnv.sqlQuery( |
| 70 | + "WITH boxes AS (" |
| 71 | + + " SELECT ST_3DMakeBox(ST_PointZ(0, 0, 0), ST_PointZ(5, 5, 5)) AS a," |
| 72 | + + " ST_3DMakeBox(ST_PointZ(3, 3, 3), ST_PointZ(7, 7, 7)) AS overlap," |
| 73 | + + " ST_3DMakeBox(ST_PointZ(0, 0, 10), ST_PointZ(5, 5, 11)) AS zdisjoint," |
| 74 | + + " ST_3DMakeBox(ST_PointZ(6, 6, 6), ST_PointZ(7, 7, 7)) AS disjoint)" |
| 75 | + + " SELECT ST_Intersects(a, overlap), ST_Intersects(a, zdisjoint)," |
| 76 | + + " ST_Intersects(a, disjoint) FROM boxes"); |
| 77 | + org.apache.flink.types.Row row = first(t); |
| 78 | + assertEquals(true, row.getField(0)); |
| 79 | + // Overlaps in XY but separated in Z — Box3D intersection must reject it. |
| 80 | + assertEquals(false, row.getField(1)); |
| 81 | + assertEquals(false, row.getField(2)); |
| 82 | + } |
| 83 | + |
| 84 | + @Test |
| 85 | + public void testContainsOnBox3D() { |
| 86 | + Table t = |
| 87 | + tableEnv.sqlQuery( |
| 88 | + "WITH boxes AS (" |
| 89 | + + " SELECT ST_3DMakeBox(ST_PointZ(0, 0, 0), ST_PointZ(10, 10, 10)) AS outer_box," |
| 90 | + + " ST_3DMakeBox(ST_PointZ(2, 2, 2), ST_PointZ(5, 5, 5)) AS inner_box," |
| 91 | + + " ST_3DMakeBox(ST_PointZ(2, 2, 2), ST_PointZ(5, 5, 99)) AS zout)" |
| 92 | + + " SELECT ST_Contains(outer_box, inner_box), ST_Contains(outer_box, zout)" |
| 93 | + + " FROM boxes"); |
| 94 | + org.apache.flink.types.Row row = first(t); |
| 95 | + assertEquals(true, row.getField(0)); |
| 96 | + // Contained in XY but pokes out of the Z range — not contained in 3D. |
| 97 | + assertEquals(false, row.getField(1)); |
| 98 | + } |
| 99 | + |
| 100 | + @Test |
| 101 | + public void test3DDWithin() { |
| 102 | + // Two POINT Z 3 units apart in Z only. |
| 103 | + Table within = |
| 104 | + tableEnv.sqlQuery( |
| 105 | + "SELECT ST_3DDWithin(ST_PointZ(0, 0, 0), ST_PointZ(0, 0, 3), 3.0)," |
| 106 | + + " ST_3DDWithin(ST_PointZ(0, 0, 0), ST_PointZ(0, 0, 3), 2.9)"); |
| 107 | + org.apache.flink.types.Row row = first(within); |
| 108 | + assertEquals(true, row.getField(0)); |
| 109 | + assertEquals(false, row.getField(1)); |
| 110 | + |
| 111 | + // Box3D-on-Box3D: faces 4 units apart in Z. |
| 112 | + Table boxes = |
| 113 | + tableEnv.sqlQuery( |
| 114 | + "WITH b AS (" |
| 115 | + + " SELECT ST_3DMakeBox(ST_PointZ(0, 0, 0), ST_PointZ(1, 1, 1)) AS a," |
| 116 | + + " ST_3DMakeBox(ST_PointZ(0, 0, 5), ST_PointZ(1, 1, 6)) AS far)" |
| 117 | + + " SELECT ST_3DDWithin(a, far, 4.0), ST_3DDWithin(a, far, 3.9) FROM b"); |
| 118 | + org.apache.flink.types.Row boxRow = first(boxes); |
| 119 | + assertEquals(true, boxRow.getField(0)); |
| 120 | + assertEquals(false, boxRow.getField(1)); |
| 121 | + |
| 122 | + // NULL distance propagates to NULL rather than throwing on autounbox. |
| 123 | + Table nullDist = |
| 124 | + tableEnv.sqlQuery( |
| 125 | + "SELECT ST_3DDWithin(ST_PointZ(0, 0, 0), ST_PointZ(0, 0, 3)," |
| 126 | + + " CAST(NULL AS DOUBLE)) AS geom_null," |
| 127 | + + " ST_3DDWithin(ST_3DMakeBox(ST_PointZ(0, 0, 0), ST_PointZ(1, 1, 1))," |
| 128 | + + " ST_3DMakeBox(ST_PointZ(0, 0, 5), ST_PointZ(1, 1, 6))," |
| 129 | + + " CAST(NULL AS DOUBLE)) AS box_null"); |
| 130 | + org.apache.flink.types.Row nullRow = first(nullDist); |
| 131 | + assertNull(nullRow.getField(0)); |
| 132 | + assertNull(nullRow.getField(1)); |
| 133 | + } |
| 134 | + |
65 | 135 | @Test |
66 | 136 | public void testIntersects() { |
67 | 137 | Table pointTable = createPointTable(testDataSize); |
|
0 commit comments