Repository: ibis-project/ibis

Issue:
FEAT: Add new geospatial operations into OmniSciDB/MapD backend
The follow operations is already available in OmniSciDB and should be added into ibis.omniscidb backend.

- [x] ST_INTERSECTS
- [x] ST_DWITHIN
- [x] ST_DISJOINT
- [ ] ST_DFULLYWITHIN
- [ ] ST_POINT
- [ ] ST_WITHIN


Discussion:
partial resolved by #1958 

Resolving patch:
diff --git a/ibis/expr/api.py b/ibis/expr/api.py
--- a/ibis/expr/api.py
+++ b/ibis/expr/api.py
@@ -5,6 +5,7 @@
 import functools
 import numbers
 import operator
+from typing import Union
 
 import dateutil.parser
 import pandas as pd
@@ -159,6 +160,7 @@
     'geo_n_points',
     'geo_n_rings',
     'geo_perimeter',
+    'geo_point',
     'geo_point_n',
     'geo_simplify',
     'geo_srid',
@@ -2026,6 +2028,27 @@ def geo_overlaps(left, right):
     return op.to_expr()
 
 
+def geo_point(
+    left: Union[NumericValue, int, float],
+    right: Union[NumericValue, int, float],
+) -> ops.GeoPoint:
+    """
+    Return a point constructed on the fly from the provided coordinate values.
+    Constant coordinates result in construction of a POINT literal.
+
+    Parameters
+    ----------
+    left : NumericValue, integer or float
+    right : NumericValue, integer or float
+
+    Returns
+    -------
+    point
+    """
+    op = ops.GeoPoint(left, right)
+    return op.to_expr()
+
+
 def geo_touches(left, right):
     """
     Check if the geometries have at least one point in common,
diff --git a/ibis/expr/operations.py b/ibis/expr/operations.py
--- a/ibis/expr/operations.py
+++ b/ibis/expr/operations.py
@@ -3269,6 +3269,17 @@ class GeoEndPoint(GeoSpatialUnOp):
     output_type = rlz.shape_like('arg', dt.point)
 
 
+class GeoPoint(GeoSpatialBinOp):
+    """
+    Return a point constructed on the fly from the provided coordinate values.
+    Constant coordinates result in construction of a POINT literal.
+    """
+
+    left = Arg(rlz.numeric)
+    right = Arg(rlz.numeric)
+    output_type = rlz.shape_like('args', dt.point)
+
+
 class GeoPointN(GeoSpatialUnOp):
     """Return the Nth point in a single linestring in the geometry.
     Negative values are counted backwards from the end of the LineString,
diff --git a/ibis/omniscidb/operations.py b/ibis/omniscidb/operations.py
--- a/ibis/omniscidb/operations.py
+++ b/ibis/omniscidb/operations.py
@@ -862,6 +862,7 @@ def formatter(translator, expr):
     ops.GeoContains: fixed_arity('ST_CONTAINS', 2),
     ops.GeoDistance: fixed_arity('ST_DISTANCE', 2),
     ops.GeoDisjoint: fixed_arity('ST_DISJOINT', 2),
+    ops.GeoDFullyWithin: fixed_arity('ST_DFULLYWITHIN', 3),
     ops.GeoDWithin: fixed_arity('ST_DWITHIN', 3),
     ops.GeoEndPoint: unary('ST_ENDPOINT'),
     ops.GeoIntersects: fixed_arity('ST_INTERSECTS', 2),
@@ -870,11 +871,13 @@ def formatter(translator, expr):
     ops.GeoNPoints: unary('ST_NPOINTS'),
     ops.GeoNRings: unary('ST_NRINGS'),
     ops.GeoPerimeter: unary('ST_PERIMETER'),
+    ops.GeoPoint: fixed_arity('ST_POINT', 2),
     ops.GeoPointN: fixed_arity('ST_POINTN', 2),
     ops.GeoSetSRID: fixed_arity('ST_SETSRID', 2),
     ops.GeoSRID: unary('ST_SRID'),
     ops.GeoStartPoint: unary('ST_STARTPOINT'),
     ops.GeoTransform: fixed_arity('ST_TRANSFORM', 2),
+    ops.GeoWithin: fixed_arity('ST_WITHIN', 2),
     ops.GeoX: unary('ST_X'),
     ops.GeoY: unary('ST_Y'),
     ops.GeoXMin: unary('ST_XMIN'),


Test patch:
diff --git a/ibis/tests/all/test_geospatial.py b/ibis/tests/all/test_geospatial.py
--- a/ibis/tests/all/test_geospatial.py
+++ b/ibis/tests/all/test_geospatial.py
@@ -306,6 +306,14 @@ def test_geo_spatial_unops(backend, geo, expr_fn, expected):
             },
             id='d_within',
         ),
+        param(
+            lambda t: t['geo_point'].d_fully_within(t['geo_linestring'], 2.0),
+            {
+                'omniscidb': [True, True, True, True, True],
+                'postgres': [True, True, True, True, True],
+            },
+            id='d_fully_within',
+        ),
         param(
             lambda t: t['geo_linestring'].intersects(point_geom_0_srid0),
             {
@@ -330,6 +338,14 @@ def test_geo_spatial_unops(backend, geo, expr_fn, expected):
             },
             id='max_distance',
         ),
+        param(
+            lambda t: t.geo_polygon.contains(ibis.geo_point(30, 10)),
+            {
+                'omniscidb': [True, False, False, False, False],
+                'postgres': [True, False, False, False, False],
+            },
+            id='point',
+        ),
     ],
 )
 @pytest.mark.only_on_backends(all_db_geo_supported)