2222import static org .apache .sedona .common .Functions .crossesDateLine ;
2323import static org .junit .Assert .*;
2424
25+ import org .apache .sedona .common .geometryObjects .Box2D ;
2526import org .junit .Test ;
2627import org .locationtech .jts .geom .Coordinate ;
2728import org .locationtech .jts .geom .Geometry ;
@@ -32,6 +33,55 @@ public class PredicatesTest extends TestBase {
3233
3334 private static final GeometryFactory GEOMETRY_FACTORY = new GeometryFactory ();
3435
36+ @ Test
37+ public void testBoxIntersects () {
38+ Box2D a = new Box2D (0.0 , 0.0 , 5.0 , 5.0 );
39+
40+ // Full overlap
41+ assertTrue (Predicates .boxIntersects (a , new Box2D (1.0 , 1.0 , 2.0 , 2.0 )));
42+ // Partial overlap
43+ assertTrue (Predicates .boxIntersects (a , new Box2D (3.0 , 3.0 , 7.0 , 7.0 )));
44+ // Edge-touching (closed intervals)
45+ assertTrue (Predicates .boxIntersects (a , new Box2D (5.0 , 0.0 , 10.0 , 5.0 )));
46+ // Corner-touching (closed intervals)
47+ assertTrue (Predicates .boxIntersects (a , new Box2D (5.0 , 5.0 , 10.0 , 10.0 )));
48+ // Disjoint on X
49+ assertFalse (Predicates .boxIntersects (a , new Box2D (6.0 , 0.0 , 10.0 , 5.0 )));
50+ // Disjoint on Y
51+ assertFalse (Predicates .boxIntersects (a , new Box2D (0.0 , 6.0 , 5.0 , 10.0 )));
52+ }
53+
54+ @ Test
55+ public void testBoxContains () {
56+ Box2D outer = new Box2D (0.0 , 0.0 , 10.0 , 10.0 );
57+
58+ assertTrue (Predicates .boxContains (outer , new Box2D (2.0 , 2.0 , 5.0 , 5.0 )));
59+ // Boundaries are inclusive
60+ assertTrue (Predicates .boxContains (outer , new Box2D (0.0 , 0.0 , 10.0 , 10.0 )));
61+ assertTrue (Predicates .boxContains (outer , new Box2D (0.0 , 0.0 , 1.0 , 1.0 )));
62+ // Outside on X
63+ assertFalse (Predicates .boxContains (outer , new Box2D (-1.0 , 0.0 , 5.0 , 5.0 )));
64+ // Crosses boundary on X
65+ assertFalse (Predicates .boxContains (outer , new Box2D (5.0 , 0.0 , 11.0 , 5.0 )));
66+ }
67+
68+ @ Test
69+ public void testBoxPredicatesRejectInvertedBounds () {
70+ // Box2D allows xmin > xmax (reserved for future antimeridian wraparound); planar predicates
71+ // refuse to evaluate them rather than silently returning misleading results.
72+ Box2D normal = new Box2D (0.0 , 0.0 , 5.0 , 5.0 );
73+ Box2D wrapX = new Box2D (170.0 , 10.0 , -170.0 , 20.0 ); // longitude crosses antimeridian
74+ Box2D wrapY = new Box2D (0.0 , 5.0 , 5.0 , 0.0 ); // ymin > ymax
75+
76+ IllegalArgumentException ex1 =
77+ assertThrows (IllegalArgumentException .class , () -> Predicates .boxIntersects (wrapX , normal ));
78+ assertTrue (ex1 .getMessage ().contains ("inverted bounds" ));
79+
80+ IllegalArgumentException ex2 =
81+ assertThrows (IllegalArgumentException .class , () -> Predicates .boxContains (normal , wrapY ));
82+ assertTrue (ex2 .getMessage ().contains ("inverted bounds" ));
83+ }
84+
3585 @ Test
3686 public void testDWithinSuccess () {
3787 Geometry point1 = GEOMETRY_FACTORY .createPoint (new Coordinate (1 , 1 ));
0 commit comments