---------------------------------------------------------------------------
-- Declare Box+Point functions
---------------------------------------------------------------------------
CREATE OR REPLACE FUNCTION leftof(box,point) RETURNS boolean
LANGUAGE C IMMUTABLE STRICT
AS 'contains.so', 'box_point_leftof';

CREATE OR REPLACE FUNCTION notright(box,point) RETURNS boolean
LANGUAGE C IMMUTABLE STRICT
AS 'contains.so', 'box_point_notright';

CREATE OR REPLACE FUNCTION notleft(box,point) RETURNS boolean
LANGUAGE C IMMUTABLE STRICT
AS 'contains.so', 'box_point_notleft';

CREATE OR REPLACE FUNCTION rightof(box,point) RETURNS boolean
LANGUAGE C IMMUTABLE STRICT
AS 'contains.so', 'box_point_rightof';

CREATE OR REPLACE FUNCTION contains(box,point) RETURNS boolean
LANGUAGE C IMMUTABLE STRICT
AS 'contains.so', 'box_point_contains';

CREATE OR REPLACE FUNCTION notabove(box,point) RETURNS boolean
LANGUAGE C IMMUTABLE STRICT
AS 'contains.so', 'box_point_notabove';

CREATE OR REPLACE FUNCTION below(box,point) RETURNS boolean
LANGUAGE C IMMUTABLE STRICT
AS 'contains.so', 'box_point_below';

CREATE OR REPLACE FUNCTION above(box,point) RETURNS boolean
LANGUAGE C IMMUTABLE STRICT
AS 'contains.so', 'box_point_above';

CREATE OR REPLACE FUNCTION notbelow(box,point) RETURNS boolean
LANGUAGE C IMMUTABLE STRICT
AS 'contains.so', 'box_point_notbelow';

---------------------------------------------------------------------------
-- Grant Execute
---------------------------------------------------------------------------
GRANT EXECUTE ON FUNCTION leftof   (box,point) TO PUBLIC;
GRANT EXECUTE ON FUNCTION notright (box,point) TO PUBLIC;
GRANT EXECUTE ON FUNCTION notleft  (box,point) TO PUBLIC;
GRANT EXECUTE ON FUNCTION rightof  (box,point) TO PUBLIC;
GRANT EXECUTE ON FUNCTION contains (box,point) TO PUBLIC;
GRANT EXECUTE ON FUNCTION notabove (box,point) TO PUBLIC;
GRANT EXECUTE ON FUNCTION below    (box,point) TO PUBLIC;
GRANT EXECUTE ON FUNCTION above    (box,point) TO PUBLIC;
GRANT EXECUTE ON FUNCTION notbelow (box,point) TO PUBLIC;

---------------------------------------------------------------------------
-- Create Operators
---------------------------------------------------------------------------
DROP OPERATOR IF EXISTS <<(box,point);
CREATE OPERATOR << (
  LEFTARG    = box,
  RIGHTARG   = point,
  PROCEDURE  = leftof,
  COMMUTATOR = >>,
  RESTRICT   = positionsel,
  JOIN       = positionjoinsel
);

DROP OPERATOR IF EXISTS &<(box,point);
CREATE OPERATOR &< (
  LEFTARG    = box,
  RIGHTARG   = point,
  PROCEDURE  = notright,
  RESTRICT   = positionsel,
  JOIN       = positionjoinsel
);

DROP OPERATOR IF EXISTS &&(box,point);
CREATE OPERATOR && (
  LEFTARG    = box,
  RIGHTARG   = point,
  PROCEDURE  = contains,
  RESTRICT   = areasel,
  JOIN       = areajoinsel
);

DROP OPERATOR IF EXISTS &>(box,point);
CREATE OPERATOR &> (
  LEFTARG    = box,
  RIGHTARG   = point,
  PROCEDURE  = notleft,
  RESTRICT   = positionsel,
  JOIN       = positionjoinsel
);

DROP OPERATOR IF EXISTS >>(box,point);
CREATE OPERATOR >> (
  LEFTARG    = box,
  RIGHTARG   = point,
  PROCEDURE  = rightof,
  COMMUTATOR = <<,
  RESTRICT   = positionsel,
  JOIN       = positionjoinsel
);

DROP OPERATOR IF EXISTS @>(box,point);
CREATE OPERATOR @> (
  LEFTARG    = box,
  RIGHTARG   = point,
  PROCEDURE  = contains,
  COMMUTATOR = <@,
  RESTRICT   = contsel,
  JOIN       = contjoinsel
);

DROP OPERATOR IF EXISTS &<|(box,point);
CREATE OPERATOR &<| (
  LEFTARG    = box,
  RIGHTARG   = point,
  PROCEDURE  = notabove,
  RESTRICT   = positionsel,
  JOIN       = positionjoinsel
);

DROP OPERATOR IF EXISTS <<|(box,point);
CREATE OPERATOR <<| (
  LEFTARG    = box,
  RIGHTARG   = point,
  PROCEDURE  = below,
  COMMUTATOR = |>>,  
  RESTRICT   = positionsel,
  JOIN       = positionjoinsel
);

DROP OPERATOR IF EXISTS |>>(box,point);
CREATE OPERATOR |>> (
  LEFTARG    = box,
  RIGHTARG   = point,
  PROCEDURE  = above,
  COMMUTATOR = <<|,  
  RESTRICT   = positionsel,
  JOIN       = positionjoinsel
);

DROP OPERATOR IF EXISTS |&>(box,point);
CREATE OPERATOR |&> (
  LEFTARG    = box,
  RIGHTARG   = point,
  PROCEDURE  = notbelow,
  RESTRICT   = positionsel,
  JOIN       = positionjoinsel
);



---------------------------------------------------------------------------
-- Declare Point+Box Functions
---------------------------------------------------------------------------
CREATE OR REPLACE FUNCTION leftof(point,box) RETURNS boolean
LANGUAGE C IMMUTABLE STRICT
AS 'contains.so', 'point_box_leftof';

CREATE OR REPLACE FUNCTION notright(point,box) RETURNS boolean
LANGUAGE C IMMUTABLE STRICT
AS 'contains.so', 'point_box_notright';

CREATE OR REPLACE FUNCTION overlaps(point,box) RETURNS boolean
LANGUAGE C IMMUTABLE STRICT
AS 'contains.so', 'point_box_overlaps';

CREATE OR REPLACE FUNCTION notleft(point,box) RETURNS boolean
LANGUAGE C IMMUTABLE STRICT
AS 'contains.so', 'point_box_notleft';

CREATE OR REPLACE FUNCTION rightof(point,box) RETURNS boolean
LANGUAGE C IMMUTABLE STRICT
AS 'contains.so', 'point_box_rightof';

--CREATE OR REPLACE FUNCTION contained(point,box) RETURNS boolean
--LANGUAGE C IMMUTABLE STRICT
--AS 'contains.so', 'point_box_contained';

CREATE OR REPLACE FUNCTION notabove(point,box) RETURNS boolean
LANGUAGE C IMMUTABLE STRICT
AS 'contains.so', 'point_box_notabove';

CREATE OR REPLACE FUNCTION below(point,box) RETURNS boolean
LANGUAGE C IMMUTABLE STRICT
AS 'contains.so', 'point_box_below';

CREATE OR REPLACE FUNCTION above(point,box) RETURNS boolean
LANGUAGE C IMMUTABLE STRICT
AS 'contains.so', 'point_box_above';

CREATE OR REPLACE FUNCTION notbelow(point,box) RETURNS boolean
LANGUAGE C IMMUTABLE STRICT
AS 'contains.so', 'point_box_notbelow';

---------------------------------------------------------------------------
-- Grant Execute
---------------------------------------------------------------------------
GRANT EXECUTE ON FUNCTION leftof   (point,box) TO PUBLIC;
GRANT EXECUTE ON FUNCTION notright (point,box) TO PUBLIC;
GRANT EXECUTE ON FUNCTION overlaps (point,box) TO PUBLIC;
GRANT EXECUTE ON FUNCTION notleft  (point,box) TO PUBLIC;
GRANT EXECUTE ON FUNCTION rightof  (point,box) TO PUBLIC;
--GRANT EXECUTE ON FUNCTION contained(point,box) TO PUBLIC;
GRANT EXECUTE ON FUNCTION notabove (point,box) TO PUBLIC;
GRANT EXECUTE ON FUNCTION below    (point,box) TO PUBLIC;
GRANT EXECUTE ON FUNCTION above    (point,box) TO PUBLIC;
GRANT EXECUTE ON FUNCTION notbelow (point,box) TO PUBLIC;

---------------------------------------------------------------------------
-- Create Point+Box operators
---------------------------------------------------------------------------
DROP OPERATOR IF EXISTS <<(point,box);
CREATE OPERATOR << (
  LEFTARG    = point,
  RIGHTARG   = box,
  PROCEDURE  = leftof,
  COMMUTATOR = >>,  
  RESTRICT   = positionsel,
  JOIN       = positionjoinsel
);

DROP OPERATOR IF EXISTS &<(point,box);
CREATE OPERATOR &< (
  LEFTARG    = point,
  RIGHTARG   = box,
  PROCEDURE  = notright,
  RESTRICT   = positionsel,
  JOIN       = positionjoinsel
);

DROP OPERATOR IF EXISTS &&(point,box);
CREATE OPERATOR && (
  LEFTARG    = point,
  RIGHTARG   = box,
  PROCEDURE  = overlaps,
  RESTRICT   = areasel,
  JOIN       = areajoinsel
);

DROP OPERATOR IF EXISTS &>(point,box);
CREATE OPERATOR &> (
  LEFTARG    = point,
  RIGHTARG   = box,
  PROCEDURE  = notleft,
  RESTRICT   = positionsel,
  JOIN       = positionjoinsel
);

DROP OPERATOR IF EXISTS >>(point,box);
CREATE OPERATOR >> (
  LEFTARG    = point,
  RIGHTARG   = box,
  PROCEDURE  = rightof,
  COMMUTATOR = <<,  
  RESTRICT   = positionsel,
  JOIN       = positionjoinsel
);

--DROP OPERATOR IF EXISTS <@(point,box);
--CREATE OPERATOR <@ (
--  LEFTARG    = point,
--  RIGHTARG   = box,
--  PROCEDURE  = contained,
--  RESTRICT   = contsel,
--  JOIN       = contjoinsel
--);

DROP OPERATOR IF EXISTS &<|(point,box);
CREATE OPERATOR &<| (
  LEFTARG    = point,
  RIGHTARG   = box,
  PROCEDURE  = notabove,
  RESTRICT   = positionsel,
  JOIN       = positionjoinsel
);

DROP OPERATOR IF EXISTS <<|(point,box);
CREATE OPERATOR <<| (
  LEFTARG    = point,
  RIGHTARG   = box,
  PROCEDURE  = below,
  COMMUTATOR = |>>,  
  RESTRICT   = positionsel,
  JOIN       = positionjoinsel
);

DROP OPERATOR IF EXISTS |>>(point,box);
CREATE OPERATOR |>> (
  LEFTARG    = point,
  RIGHTARG   = box,
  PROCEDURE  = above,
  COMMUTATOR = <<|,  
  RESTRICT   = positionsel,
  JOIN       = positionjoinsel
);

DROP OPERATOR IF EXISTS |&>(point,box);
CREATE OPERATOR |&> (
  LEFTARG    = point,
  RIGHTARG   = box,
  PROCEDURE  = notbelow,
  RESTRICT   = positionsel,
  JOIN       = positionjoinsel
);


-----------------------------------------------------------------------------
---- Alter the existing box_ops family
-----------------------------------------------------------------------------
ALTER OPERATOR FAMILY box_ops USING GiST ADD
  OPERATOR 1  <<  (box,point),
  OPERATOR 2  &<  (box,point),
  OPERATOR 3  &&  (box,point),
  OPERATOR 4  &>  (box,point),
  OPERATOR 5  >>  (box,point),  
  OPERATOR 7  @>  (box,point), 
  OPERATOR 9  &<| (box,point), 
  OPERATOR 10 <<| (box,point), 
  OPERATOR 11 |>> (box,point),   
  OPERATOR 12 |&> (box,point),
  OPERATOR 1  <<  (point,box),
  OPERATOR 2  &<  (point,box),
  OPERATOR 3  &&  (point,box),
  OPERATOR 4  &>  (point,box),
  OPERATOR 5  >>  (point,box),  
--OPERATOR 8  <@  (point,box),
  OPERATOR 9  &<| (point,box), 
  OPERATOR 10 <<| (point,box), 
  OPERATOR 11 |>> (point,box),   
  OPERATOR 12 |&> (point,box);   


---------------------------------------------------------------------------
-- Polygon Functions
---------------------------------------------------------------------------

-- Polygon contains Point
CREATE OR REPLACE FUNCTION contains(polygon,point) RETURNS boolean
LANGUAGE C IMMUTABLE STRICT
AS 'contains.so', 'contains_polygon_point';

GRANT EXECUTE ON FUNCTION contains(polygon,point) TO PUBLIC;


-- Point contained in Polygon
CREATE OR REPLACE FUNCTION contained(point,polygon) RETURNS boolean
LANGUAGE C IMMUTABLE STRICT
AS 'contains.so', 'contained_point_polygon';

GRANT EXECUTE ON FUNCTION contained(point,polygon) TO PUBLIC;
