From 9428dbf2d3094e0de324ed518ca3f211e8b2370b Mon Sep 17 00:00:00 2001
From: Emre Hasegeli <emre@hasegeli.com>
Date: Sun, 22 Mar 2015 17:41:26 +0100
Subject: [PATCH 5/7] box vs point operators

---
 src/backend/utils/adt/geo_ops.c   | 115 ++++++++++++++++++++++++++++++++++----
 src/include/catalog/pg_operator.h |  16 ++++++
 src/include/catalog/pg_proc.h     |   8 +++
 src/include/utils/geo_decls.h     |   8 +++
 4 files changed, 137 insertions(+), 10 deletions(-)

diff --git a/src/backend/utils/adt/geo_ops.c b/src/backend/utils/adt/geo_ops.c
index 39a7855..382d925 100644
--- a/src/backend/utils/adt/geo_ops.c
+++ b/src/backend/utils/adt/geo_ops.c
@@ -767,20 +767,125 @@ Datum
 box_ge(PG_FUNCTION_ARGS)
 {
 	BOX		   *box1 = PG_GETARG_BOX_P(0);
 	BOX		   *box2 = PG_GETARG_BOX_P(1);
 
 	PG_RETURN_BOOL(FPge(box_ar(box1), box_ar(box2)));
 }
 
 
 /*----------------------------------------------------------
+ *	Relational operators for BOX vs Point
+ *---------------------------------------------------------*/
+
+/*		box_left_pt		-		is box strictly left of point?
+ */
+Datum
+box_left_pt(PG_FUNCTION_ARGS)
+{
+	BOX		   *box = PG_GETARG_BOX_P(0);
+	Point	   *pt = PG_GETARG_POINT_P(1);
+
+	PG_RETURN_BOOL(box->high.x < pt->x);
+}
+
+/*		box_overleft_pt	-		is the right edge of box at or left of point?
+ */
+Datum
+box_overleft_pt(PG_FUNCTION_ARGS)
+{
+	BOX		   *box = PG_GETARG_BOX_P(0);
+	Point	   *pt = PG_GETARG_POINT_P(1);
+
+	PG_RETURN_BOOL(box->low.x <= pt->x);
+}
+
+/*		box_right_pt	-		is box strictly right of point?
+ */
+Datum
+box_right_pt(PG_FUNCTION_ARGS)
+{
+	BOX		   *box = PG_GETARG_BOX_P(0);
+	Point	   *pt = PG_GETARG_POINT_P(1);
+
+	PG_RETURN_BOOL(box->low.x > pt->x);
+}
+
+/*		box_overright_pt -		is the left edge of box at or right of point?
+ */
+Datum
+box_overright_pt(PG_FUNCTION_ARGS)
+{
+	BOX		   *box = PG_GETARG_BOX_P(0);
+	Point	   *pt = PG_GETARG_POINT_P(1);
+
+	PG_RETURN_BOOL(box->high.x >= pt->x);
+}
+
+/*		box_below_pt	-		is box strictly below point?
+ */
+Datum
+box_below_pt(PG_FUNCTION_ARGS)
+{
+	BOX		   *box = PG_GETARG_BOX_P(0);
+	Point	   *pt = PG_GETARG_POINT_P(1);
+
+	PG_RETURN_BOOL(box->high.y < pt->y);
+}
+
+/*		box_overbelow_pt -		is the upper edge of box at or below point?
+ */
+Datum
+box_overbelow_pt(PG_FUNCTION_ARGS)
+{
+	BOX		   *box = PG_GETARG_BOX_P(0);
+	Point	   *pt = PG_GETARG_POINT_P(1);
+
+	PG_RETURN_BOOL(box->low.y <= pt->y);
+}
+
+/*		box_above_pt	-		is box strictly above point?
+ */
+Datum
+box_above_pt(PG_FUNCTION_ARGS)
+{
+	BOX		   *box = PG_GETARG_BOX_P(0);
+	Point	   *pt = PG_GETARG_POINT_P(1);
+
+	PG_RETURN_BOOL(box->low.y > pt->y);
+}
+
+/*		box_overabove_pt -		is the lower edge of box at or above point?
+ */
+Datum
+box_overabove_pt(PG_FUNCTION_ARGS)
+{
+	BOX		   *box = PG_GETARG_BOX_P(0);
+	Point	   *pt = PG_GETARG_POINT_P(1);
+
+	PG_RETURN_BOOL(box->high.y >= pt->y);
+}
+
+/*		box_contain_pt	-		does box contain point?
+ */
+Datum
+box_contain_pt(PG_FUNCTION_ARGS)
+{
+	BOX		   *box = PG_GETARG_BOX_P(0);
+	Point	   *pt = PG_GETARG_POINT_P(1);
+
+	PG_RETURN_BOOL(pt->x <= box->high.x && pt->x >= box->low.x &&
+				   pt->y <= box->high.y && pt->y >= box->low.y);
+}
+
+
+/*----------------------------------------------------------
  *	"Arithmetic" operators on boxes.
  *---------------------------------------------------------*/
 
 /*		box_area		-		returns the area of the box.
  */
 Datum
 box_area(PG_FUNCTION_ARGS)
 {
 	BOX		   *box = PG_GETARG_BOX_P(0);
 
@@ -3205,30 +3310,20 @@ on_ps_internal(Point *pt, LSEG *lseg)
 Datum
 on_pb(PG_FUNCTION_ARGS)
 {
 	Point	   *pt = PG_GETARG_POINT_P(0);
 	BOX		   *box = PG_GETARG_BOX_P(1);
 
 	PG_RETURN_BOOL(pt->x <= box->high.x && pt->x >= box->low.x &&
 				   pt->y <= box->high.y && pt->y >= box->low.y);
 }
 
-Datum
-box_contain_pt(PG_FUNCTION_ARGS)
-{
-	BOX		   *box = PG_GETARG_BOX_P(0);
-	Point	   *pt = PG_GETARG_POINT_P(1);
-
-	PG_RETURN_BOOL(pt->x <= box->high.x && pt->x >= box->low.x &&
-				   pt->y <= box->high.y && pt->y >= box->low.y);
-}
-
 /* on_ppath -
  *		Whether a point lies within (on) a polyline.
  *		If open, we have to (groan) check each segment.
  * (uses same algorithm as for point intersecting segment - tgl 1997-07-09)
  *		If closed, we use the old O(n) ray method for point-in-polygon.
  *				The ray is horizontal, from pt out to the right.
  *				Each segment that crosses the ray counts as an
  *				intersection; note that an endpoint or edge may touch
  *				but not cross.
  *				(we can do p-in-p in lg(n), but it takes preprocessing)
diff --git a/src/include/catalog/pg_operator.h b/src/include/catalog/pg_operator.h
index e22eb27..a22fc0d 100644
--- a/src/include/catalog/pg_operator.h
+++ b/src/include/catalog/pg_operator.h
@@ -252,20 +252,36 @@ DESCR("is above");
 DATA(insert OID = 507 (  "<<"	   PGNSP PGUID b f f 600 600	16	 0	 0 point_left positionsel positionjoinsel ));
 DESCR("is left of");
 DATA(insert OID = 508 (  ">>"	   PGNSP PGUID b f f 600 600	16	 0	 0 point_right positionsel positionjoinsel ));
 DESCR("is right of");
 DATA(insert OID = 509 (  "<^"	   PGNSP PGUID b f f 600 600	16	 0	 0 point_below positionsel positionjoinsel ));
 DESCR("is below");
 DATA(insert OID = 510 (  "~="	   PGNSP PGUID b f f 600 600	16 510 713 point_eq eqsel eqjoinsel ));
 DESCR("same as");
 DATA(insert OID = 511 (  "<@"	   PGNSP PGUID b f f 600 603	16 433	 0 on_pb contsel contjoinsel ));
 DESCR("point inside box");
+DATA(insert OID = 4092 ( "<<"	   PGNSP PGUID b f f 603 600	16	 0	 0 box_left_pt positionsel positionjoinsel ));
+DESCR("is left of");
+DATA(insert OID = 4093 ( "&<"	   PGNSP PGUID b f f 603 600	16	 0	 0 box_overleft_pt positionsel positionjoinsel ));
+DESCR("overlaps or is left of");
+DATA(insert OID = 4094 ( ">>"	   PGNSP PGUID b f f 603 600	16	 0	 0 box_right_pt positionsel positionjoinsel ));
+DESCR("is right of");
+DATA(insert OID = 4095 ( "&>"	   PGNSP PGUID b f f 603 600	16	 0	 0 box_overright_pt positionsel positionjoinsel ));
+DESCR("overlaps or is right of");
+DATA(insert OID = 4096 ( "<<|"	   PGNSP PGUID b f f 603 600	16	 0	 0 box_below_pt positionsel positionjoinsel ));
+DESCR("is below");
+DATA(insert OID = 4097 ( "&<|"	   PGNSP PGUID b f f 603 600	16	 0	 0 box_overbelow_pt positionsel positionjoinsel ));
+DESCR("overlaps or is below");
+DATA(insert OID = 4098 ( "|>>"	   PGNSP PGUID b f f 603 600	16	 0	 0 box_above_pt positionsel positionjoinsel ));
+DESCR("is above");
+DATA(insert OID = 4099 ( "|&>"	   PGNSP PGUID b f f 603 600	16	 0	 0 box_overabove_pt positionsel positionjoinsel ));
+DESCR("overlaps or is above");
 DATA(insert OID = 433 (  "@>"	   PGNSP PGUID b f f 603 600	16 511	 0 box_contain_pt contsel contjoinsel ));
 DESCR("contains");
 DATA(insert OID = 512 (  "<@"	   PGNSP PGUID b f f 600 602	16 755	 0 on_ppath - - ));
 DESCR("point within closed path, or point on open path");
 DATA(insert OID = 513 (  "@@"	   PGNSP PGUID l f f	 0 603 600	 0	 0 box_center - - ));
 DESCR("center of");
 DATA(insert OID = 514 (  "*"	   PGNSP PGUID b f f	23	23	23 514	 0 int4mul - - ));
 DESCR("multiply");
 DATA(insert OID = 517 (  "<->"	   PGNSP PGUID b f f 600 600 701 517	 0 point_distance - - ));
 DESCR("distance between");
diff --git a/src/include/catalog/pg_proc.h b/src/include/catalog/pg_proc.h
index 5fa65d6..e9d589e 100644
--- a/src/include/catalog/pg_proc.h
+++ b/src/include/catalog/pg_proc.h
@@ -336,20 +336,28 @@ DATA(insert OID = 182 (  int24mi		   PGNSP PGUID 12 1 0 0 0 f f f f t f i 2 0 23
 DATA(insert OID = 183 (  int42mi		   PGNSP PGUID 12 1 0 0 0 f f f f t f i 2 0 23 "23 21" _null_ _null_ _null_ _null_ _null_ int42mi _null_ _null_ _null_ ));
 DATA(insert OID = 184 (  oideq			   PGNSP PGUID 12 1 0 0 0 f f f t t f i 2 0 16 "26 26" _null_ _null_ _null_ _null_ _null_ oideq _null_ _null_ _null_ ));
 DATA(insert OID = 185 (  oidne			   PGNSP PGUID 12 1 0 0 0 f f f t t f i 2 0 16 "26 26" _null_ _null_ _null_ _null_ _null_ oidne _null_ _null_ _null_ ));
 DATA(insert OID = 186 (  box_same		   PGNSP PGUID 12 1 0 0 0 f f f f t f i 2 0 16 "603 603" _null_ _null_ _null_ _null_ _null_ box_same _null_ _null_ _null_ ));
 DATA(insert OID = 187 (  box_contain	   PGNSP PGUID 12 1 0 0 0 f f f f t f i 2 0 16 "603 603" _null_ _null_ _null_ _null_ _null_ box_contain _null_ _null_ _null_ ));
 DATA(insert OID = 188 (  box_left		   PGNSP PGUID 12 1 0 0 0 f f f f t f i 2 0 16 "603 603" _null_ _null_ _null_ _null_ _null_ box_left _null_ _null_ _null_ ));
 DATA(insert OID = 189 (  box_overleft	   PGNSP PGUID 12 1 0 0 0 f f f f t f i 2 0 16 "603 603" _null_ _null_ _null_ _null_ _null_ box_overleft _null_ _null_ _null_ ));
 DATA(insert OID = 190 (  box_overright	   PGNSP PGUID 12 1 0 0 0 f f f f t f i 2 0 16 "603 603" _null_ _null_ _null_ _null_ _null_ box_overright _null_ _null_ _null_ ));
 DATA(insert OID = 191 (  box_right		   PGNSP PGUID 12 1 0 0 0 f f f f t f i 2 0 16 "603 603" _null_ _null_ _null_ _null_ _null_ box_right _null_ _null_ _null_ ));
 DATA(insert OID = 192 (  box_contained	   PGNSP PGUID 12 1 0 0 0 f f f f t f i 2 0 16 "603 603" _null_ _null_ _null_ _null_ _null_ box_contained _null_ _null_ _null_ ));
+DATA(insert OID = 4083 (  box_left_pt	   PGNSP PGUID 12 1 0 0 0 f f f f t f i 2 0 16 "603 600" _null_ _null_ _null_ _null_ _null_ box_left_pt _null_ _null_ _null_ ));
+DATA(insert OID = 4084 (  box_overleft_pt  PGNSP PGUID 12 1 0 0 0 f f f f t f i 2 0 16 "603 600" _null_ _null_ _null_ _null_ _null_ box_overleft_pt _null_ _null_ _null_ ));
+DATA(insert OID = 4085 (  box_right_pt	   PGNSP PGUID 12 1 0 0 0 f f f f t f i 2 0 16 "603 600" _null_ _null_ _null_ _null_ _null_ box_right_pt _null_ _null_ _null_ ));
+DATA(insert OID = 4086 (  box_overright_pt PGNSP PGUID 12 1 0 0 0 f f f f t f i 2 0 16 "603 600" _null_ _null_ _null_ _null_ _null_ box_overright_pt _null_ _null_ _null_ ));
+DATA(insert OID = 4087 (  box_below_pt	   PGNSP PGUID 12 1 0 0 0 f f f f t f i 2 0 16 "603 600" _null_ _null_ _null_ _null_ _null_ box_below_pt _null_ _null_ _null_ ));
+DATA(insert OID = 4088 (  box_overbelow_pt PGNSP PGUID 12 1 0 0 0 f f f f t f i 2 0 16 "603 600" _null_ _null_ _null_ _null_ _null_ box_overbelow_pt _null_ _null_ _null_ ));
+DATA(insert OID = 4089 (  box_above_pt	   PGNSP PGUID 12 1 0 0 0 f f f f t f i 2 0 16 "603 600" _null_ _null_ _null_ _null_ _null_ box_above_pt _null_ _null_ _null_ ));
+DATA(insert OID = 4090 (  box_overabove_pt PGNSP PGUID 12 1 0 0 0 f f f f t f i 2 0 16 "603 600" _null_ _null_ _null_ _null_ _null_ box_overabove_pt _null_ _null_ _null_ ));
 DATA(insert OID = 193 (  box_contain_pt    PGNSP PGUID 12 1 0 0 0 f f f f t f i 2 0 16 "603 600" _null_ _null_ _null_ _null_ _null_ box_contain_pt _null_ _null_ _null_ ));
 
 DATA(insert OID = 195 (  pg_node_tree_in	PGNSP PGUID 12 1 0 0 0 f f f f t f i 1 0 194 "2275" _null_ _null_ _null_ _null_ _null_ pg_node_tree_in _null_ _null_ _null_ ));
 DESCR("I/O");
 DATA(insert OID = 196 (  pg_node_tree_out	PGNSP PGUID 12 1 0 0 0 f f f f t f i 1 0 2275 "194" _null_ _null_ _null_ _null_ _null_ pg_node_tree_out _null_ _null_ _null_ ));
 DESCR("I/O");
 DATA(insert OID = 197 (  pg_node_tree_recv	PGNSP PGUID 12 1 0 0 0 f f f f t f s 1 0 194 "2281" _null_ _null_ _null_ _null_ _null_ pg_node_tree_recv _null_ _null_ _null_ ));
 DESCR("I/O");
 DATA(insert OID = 198 (  pg_node_tree_send	PGNSP PGUID 12 1 0 0 0 f f f f t f s 1 0 17 "194" _null_ _null_ _null_ _null_ _null_	pg_node_tree_send _null_ _null_ _null_ ));
 DESCR("I/O");
diff --git a/src/include/utils/geo_decls.h b/src/include/utils/geo_decls.h
index 4377baa..69a78e8 100644
--- a/src/include/utils/geo_decls.h
+++ b/src/include/utils/geo_decls.h
@@ -275,20 +275,28 @@ extern Datum box_overlap(PG_FUNCTION_ARGS);
 extern Datum box_left(PG_FUNCTION_ARGS);
 extern Datum box_overleft(PG_FUNCTION_ARGS);
 extern Datum box_right(PG_FUNCTION_ARGS);
 extern Datum box_overright(PG_FUNCTION_ARGS);
 extern Datum box_below(PG_FUNCTION_ARGS);
 extern Datum box_overbelow(PG_FUNCTION_ARGS);
 extern Datum box_above(PG_FUNCTION_ARGS);
 extern Datum box_overabove(PG_FUNCTION_ARGS);
 extern Datum box_contained(PG_FUNCTION_ARGS);
 extern Datum box_contain(PG_FUNCTION_ARGS);
+extern Datum box_left_pt(PG_FUNCTION_ARGS);
+extern Datum box_overleft_pt(PG_FUNCTION_ARGS);
+extern Datum box_right_pt(PG_FUNCTION_ARGS);
+extern Datum box_overright_pt(PG_FUNCTION_ARGS);
+extern Datum box_below_pt(PG_FUNCTION_ARGS);
+extern Datum box_overbelow_pt(PG_FUNCTION_ARGS);
+extern Datum box_above_pt(PG_FUNCTION_ARGS);
+extern Datum box_overabove_pt(PG_FUNCTION_ARGS);
 extern Datum box_contain_pt(PG_FUNCTION_ARGS);
 extern Datum box_below_eq(PG_FUNCTION_ARGS);
 extern Datum box_above_eq(PG_FUNCTION_ARGS);
 extern Datum box_lt(PG_FUNCTION_ARGS);
 extern Datum box_gt(PG_FUNCTION_ARGS);
 extern Datum box_eq(PG_FUNCTION_ARGS);
 extern Datum box_le(PG_FUNCTION_ARGS);
 extern Datum box_ge(PG_FUNCTION_ARGS);
 extern Datum box_area(PG_FUNCTION_ARGS);
 extern Datum box_width(PG_FUNCTION_ARGS);
-- 
2.3.2

