blob: 522534eb8343e0f20d59442fa3e293169fcc3a2a [file]
# Licensed to the Apache Software Foundation (ASF) under one
# or more contributor license agreements. See the NOTICE file
# distributed with this work for additional information
# regarding copyright ownership. The ASF licenses this file
# to you under the Apache License, Version 2.0 (the
# "License"); you may not use this file except in compliance
# with the License. You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing,
# software distributed under the License is distributed on an
# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
# KIND, either express or implied. See the License for the
# specific language governing permissions and limitations
# under the License.
from math import radians
import os
import concurrent.futures
from typing import Callable, Tuple
import pyspark
import pytest
from pyspark.sql import Row
from pyspark.sql import functions as f
from shapely.geometry.base import BaseGeometry
from tests.test_base import TestBase
from sedona.spark.core.geom.box2d import Box2D
from sedona.spark.core.geom.box3d import Box3D
from sedona.spark.core.geom.geography import Geography
from sedona.spark.sql import st_aggregates as sta
from sedona.spark.sql import st_constructors as stc
from sedona.spark.sql import st_functions as stf
from sedona.spark.sql import st_predicates as stp
from sedona.spark.sql.st_functions import *
test_configurations = [
# constructors
(
stc.ST_GeomFromGeoHash,
("geohash", 4),
"constructor",
"ST_ReducePrecision(geom, 2)",
"POLYGON ((0.7 1.05, 1.05 1.05, 1.05 0.88, 0.7 0.88, 0.7 1.05))",
),
(stc.ST_GeomFromGeoJSON, ("geojson",), "constructor", "", "POINT (0 1)"),
(
stc.ST_GeomFromGML,
("gml",),
"constructor",
"",
"LINESTRING (-71.16 42.25, -71.17 42.25, -71.18 42.25)",
),
(
stc.ST_GeomFromKML,
("kml",),
"constructor",
"",
"LINESTRING (-71.16 42.26, -71.17 42.26)",
),
(stc.ST_GeomFromText, ("wkt",), "linestring_wkt", "", "LINESTRING (1 2, 3 4)"),
(stc.ST_GeomFromText, ("wkt", 4326), "linestring_wkt", "", "LINESTRING (1 2, 3 4)"),
(
stc.ST_GeometryFromText,
("wkt", 4326),
"linestring_wkt",
"",
"LINESTRING (1 2, 3 4)",
),
(
stc.ST_GeomFromWKB,
("wkbLine",),
"constructor",
"ST_ReducePrecision(geom, 2)",
"LINESTRING (-2.1 -0.35, -1.5 -0.67)",
),
(
stc.ST_GeomFromEWKB,
("wkbLine",),
"constructor",
"ST_ReducePrecision(geom, 2)",
"LINESTRING (-2.1 -0.35, -1.5 -0.67)",
),
(stc.ST_GeomFromWKT, ("wkt",), "linestring_wkt", "", "LINESTRING (1 2, 3 4)"),
(stc.ST_GeomFromWKT, ("wkt", 4326), "linestring_wkt", "", "LINESTRING (1 2, 3 4)"),
(stc.ST_GeomFromEWKT, ("ewkt",), "linestring_ewkt", "", "LINESTRING (1 2, 3 4)"),
# (stc.ST_GeogFromWKT, ("wkt",), "linestring_wkt", "", "LINESTRING (1 2, 3 4)"),
# (stc.ST_GeogFromWKT, ("wkt", 4326), "linestring_wkt", "", "LINESTRING (1 2, 3 4)"),
(stc.ST_LineFromText, ("wkt",), "linestring_wkt", "", "LINESTRING (1 2, 3 4)"),
(
stc.ST_LineFromWKB,
("wkbLine",),
"constructor",
"ST_ReducePrecision(geom, 2)",
"LINESTRING (-2.1 -0.35, -1.5 -0.67)",
),
(
stc.ST_LinestringFromWKB,
("wkbLine",),
"constructor",
"ST_ReducePrecision(geom, 2)",
"LINESTRING (-2.1 -0.35, -1.5 -0.67)",
),
(
stc.ST_LineStringFromText,
("multiple_point", lambda: f.lit(",")),
"constructor",
"",
"LINESTRING (0 0, 1 0, 1 1, 0 0)",
),
(stc.ST_Point, ("x", "y"), "constructor", "", "POINT (0 1)"),
(stc.ST_PointZ, ("x", "y", "z", 4326), "constructor", "", "POINT Z (0 1 2)"),
(stc.ST_PointZ, ("x", "y", "z"), "constructor", "", "POINT Z (0 1 2)"),
(
stc.ST_MPolyFromText,
("mpoly",),
"constructor",
"",
"MULTIPOLYGON (((0 0, 20 0, 20 20, 0 20, 0 0), (5 5, 5 7, 7 7, 7 5, 5 5)))",
),
(
stc.ST_MPolyFromText,
("mpoly", 4326),
"constructor",
"",
"MULTIPOLYGON (((0 0, 20 0, 20 20, 0 20, 0 0), (5 5, 5 7, 7 7, 7 5, 5 5)))",
),
(
stc.ST_MLineFromText,
("mline",),
"constructor",
"",
"MULTILINESTRING ((1 2, 3 4), (4 5, 6 7))",
),
(
stc.ST_MLineFromText,
("mline", 4326),
"constructor",
"",
"MULTILINESTRING ((1 2, 3 4), (4 5, 6 7))",
),
(
stc.ST_MPointFromText,
("mpoint",),
"constructor",
"",
"MULTIPOINT (10 10, 20 20, 30 30)",
),
(
stc.ST_MPointFromText,
("mpoint", 4326),
"constructor",
"",
"MULTIPOINT (10 10, 20 20, 30 30)",
),
(
stc.ST_PointFromText,
("single_point", lambda: f.lit(",")),
"constructor",
"",
"POINT (0 1)",
),
(stc.ST_PointFromWKB, ("wkbPoint",), "constructor", "", "POINT (10 15)"),
(stc.ST_MakePoint, ("x", "y", "z"), "constructor", "", "POINT Z (0 1 2)"),
(
stc.ST_MakePointM,
("x", "y", "z"),
"constructor",
"ST_AsText(geom)",
"POINT M(0 1 2)",
),
(
stc.ST_MakeBox2D,
("a", "b"),
"two_points",
"",
# two_points has a=(0,0,0), b=(3,0,4); ST_MakeBox2D drops Z, so y is 0 for both.
Box2D(0.0, 0.0, 3.0, 0.0),
),
(
stc.ST_3DMakeBox,
("a", "b"),
"two_points",
"",
# two_points has a=(0,0,0), b=(3,0,4).
Box3D(0.0, 0.0, 0.0, 3.0, 0.0, 4.0),
),
(
stc.ST_GeomFromBox2D,
(
lambda: stc.ST_MakeBox2D(
f.expr("ST_Point(1.0, 2.0)"), f.expr("ST_Point(4.0, 5.0)")
),
),
"min_max_x_y",
"ST_AsText(geom)",
"POLYGON ((1 2, 1 5, 4 5, 4 2, 1 2))",
),
(
stc.ST_MakeEnvelope,
("minx", "miny", "maxx", "maxy"),
"min_max_x_y",
"",
"POLYGON ((0 1, 0 3, 2 3, 2 1, 0 1))",
),
(
stc.ST_MakeEnvelope,
("minx", "miny", "maxx", "maxy", lambda: f.lit(1111)),
"min_max_x_y",
"",
"POLYGON ((0 1, 0 3, 2 3, 2 1, 0 1))",
),
(
stc.ST_MakeEnvelope,
("minx", "miny", "maxx", "maxy", lambda: f.lit(1111)),
"min_max_x_y",
"ST_SRID(geom)",
1111,
),
(
stc.ST_PolygonFromEnvelope,
("minx", "miny", "maxx", "maxy"),
"min_max_x_y",
"",
"POLYGON ((0 1, 0 3, 2 3, 2 1, 0 1))",
),
(
stc.ST_PolygonFromEnvelope,
(0.0, 1.0, 2.0, 3.0),
"null",
"",
"POLYGON ((0 1, 0 3, 2 3, 2 1, 0 1))",
),
(
stc.ST_PolygonFromText,
("multiple_point", lambda: f.lit(",")),
"constructor",
"",
"POLYGON ((0 0, 1 0, 1 1, 0 0))",
),
(
stc.ST_GeomCollFromText,
("collection",),
"constructor",
"",
"GEOMETRYCOLLECTION (POINT (1 1), LINESTRING (0 0, 1 1))",
),
(
stc.ST_GeomCollFromText,
("collection", 4326),
"constructor",
"ST_SRID(geom)",
4326,
),
# functions
(stf.GeometryType, ("line",), "linestring_geom", "", "LINESTRING"),
(stf.ST_3DDistance, ("a", "b"), "two_points", "", 5.0),
(
stf.ST_Affine,
("geom", 1.0, 2.0, 1.0, 2.0, 1.0, 2.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0),
"square_geom",
"",
"POLYGON ((2 3, 4 5, 5 6, 3 4, 2 3))",
),
(
stf.ST_Affine,
(
"geom",
1.0,
2.0,
1.0,
2.0,
1.0,
2.0,
),
"square_geom",
"",
"POLYGON ((2 3, 4 5, 5 6, 3 4, 2 3))",
),
(
stf.ST_AddMeasure,
("line", 10.0, 40.0),
"linestring_geom",
"ST_AsText(geom)",
"LINESTRING M(0 0 10, 1 0 16, 2 0 22, 3 0 28, 4 0 34, 5 0 40)",
),
(
stf.ST_AddPoint,
("line", lambda: f.expr("ST_Point(1.0, 1.0)")),
"linestring_geom",
"",
"LINESTRING (0 0, 1 0, 2 0, 3 0, 4 0, 5 0, 1 1)",
),
(
stf.ST_AddPoint,
("line", lambda: f.expr("ST_Point(1.0, 1.0)"), 1),
"linestring_geom",
"",
"LINESTRING (0 0, 1 1, 1 0, 2 0, 3 0, 4 0, 5 0)",
),
(
stf.ST_LabelPoint,
("geom",),
"triangle_geom",
"",
"POINT (0.6666666666666666 0.3333333333333333)",
),
(
stf.ST_LabelPoint,
("geom", 1),
"triangle_geom",
"",
"POINT (0.6666666666666666 0.3333333333333333)",
),
(
stf.ST_LabelPoint,
("geom", 1, 0.5),
"triangle_geom",
"",
"POINT (0.6666666666666666 0.3333333333333333)",
),
(
stf.ST_Angle,
(
"p1",
"p2",
"p3",
"p4",
),
"four_points",
"",
0.4048917862850834,
),
(
stf.ST_Angle,
(
"p1",
"p2",
"p3",
),
"three_points",
"",
0.19739555984988078,
),
(stf.ST_Angle, ("line1", "line2"), "two_lines", "", 0.19739555984988078),
(stf.ST_Degrees, ("angleRad",), "two_lines_angle_rad", "", 11.309932474020213),
(stf.ST_Area, ("geom",), "triangle_geom", "", 0.5),
(stf.ST_AreaSpheroid, ("point",), "point_geom", "", 0.0),
(
stf.ST_AsBinary,
("point",),
"point_geom",
"",
"01010000000000000000000000000000000000f03f",
),
(
stf.ST_AsEWKB,
(lambda: f.expr("ST_SetSRID(point, 3021)"),),
"point_geom",
"",
"0101000020cd0b00000000000000000000000000000000f03f",
),
(
stf.ST_AsHEXEWKB,
("point",),
"point_geom",
"",
"01010000000000000000000000000000000000F03F",
),
(
stf.ST_AsEWKT,
(lambda: f.expr("ST_SetSRID(point, 4326)"),),
"point_geom",
"",
"SRID=4326;POINT (0 1)",
),
(
stf.ST_AsGeoJSON,
("point",),
"point_geom",
"",
'{"type":"Point","coordinates":[0.0,1.0]}',
),
(
stf.ST_AsGeoJSON,
("point", lambda: f.lit("feature")),
"point_geom",
"",
'{"type":"Feature","geometry":{"type":"Point","coordinates":[0.0,1.0]},"properties":{}}',
),
(
stf.ST_AsGeoJSON,
("point", lambda: f.lit("featurecollection")),
"point_geom",
"",
'{"type":"FeatureCollection","features":[{"type":"Feature","geometry":{"type":"Point","coordinates":[0.0,1.0]},"properties":{}}]}',
),
(
stf.ST_AsGML,
("point",),
"point_geom",
"",
"<gml:Point>\n <gml:coordinates>\n 0.0,1.0 \n </gml:coordinates>\n</gml:Point>\n",
),
(
stf.ST_AsKML,
("point",),
"point_geom",
"",
"<Point>\n <coordinates>0.0,1.0</coordinates>\n</Point>\n",
),
(stf.ST_AsText, ("point",), "point_geom", "", "POINT (0 1)"),
(stf.ST_Azimuth, ("a", "b"), "two_points", "geom * 180.0 / pi()", 90.0),
(stf.ST_BestSRID, ("geom",), "triangle_geom", "", 32631),
(
stf.ST_Boundary,
("geom",),
"triangle_geom",
"",
"LINESTRING (0 0, 1 0, 1 1, 0 0)",
),
(
stf.ST_Buffer,
("point", 1.0),
"point_geom",
"ST_ReducePrecision(geom, 2)",
"POLYGON ((0.98 0.8, 0.92 0.62, 0.83 0.44, 0.71 0.29, 0.56 0.17, 0.38 0.08, 0.2 0.02, 0 0, -0.2 0.02, -0.38 0.08, -0.56 0.17, -0.71 0.29, -0.83 0.44, -0.92 0.62, -0.98 0.8, -1 1, -0.98 1.2, -0.92 1.38, -0.83 1.56, -0.71 1.71, -0.56 1.83, -0.38 1.92, -0.2 1.98, 0 2, 0.2 1.98, 0.38 1.92, 0.56 1.83, 0.71 1.71, 0.83 1.56, 0.92 1.38, 0.98 1.2, 1 1, 0.98 0.8))",
),
(
stf.ST_Buffer,
("point", 1.0, True),
"point_geom",
"",
"POLYGON ((0.0000089758113634 1.0000000082631704, 0.0000088049473096 0.9999982455016537, 0.0000082957180969 0.9999965501645043, 0.0000074676931201 0.9999949874025787, 0.0000063526929175 0.9999936172719434, 0.0000049935663218 0.9999924924259491, 0.000003442543808 0.9999916560917964, 0.0000017592303026 0.9999911404093366, 0.0000000083146005 0.999990965195956, -0.0000017429165916 0.9999911371850047, -0.0000034271644398 0.9999916497670388, -0.0000049797042467 0.9999924832438165, -0.0000063408727792 0.9999936055852924, -0.0000074583610959 0.9999949736605123, -0.0000082892247492 0.9999965348951139, -0.0000088015341156 0.999998229291728, -0.0000089756014341 0.9999999917356441, -0.0000088047373942 1.0000017544971334, -0.0000082955082053 1.000003449834261, -0.0000074674832591 1.000005012596174, -0.000006352483086 1.0000063827268086, -0.0000049933565169 1.000007507572813, -0.0000034423340222 1.0000083439069856, -0.0000017590205255 1.0000088595894723, -0.0000000081048183 1.0000090348028825, 0.0000017431263877 1.0000088628138615, 0.0000034273742602 1.0000083502318489, 0.000004979914097 1.0000075167550835, 0.0000063410826597 1.000006394413609, 0.000007458571003 1.0000050263383786, 0.000008289434675 1.000003465103757, 0.0000088017440489 1.0000017707071163, 0.0000089758113634 1.0000000082631704))",
),
(
stf.ST_BuildArea,
("geom",),
"multiline_geom",
"ST_Normalize(geom)",
"POLYGON ((0 0, 1 1, 1 0, 0 0))",
),
(
stf.ST_BoundingDiagonal,
("geom",),
"square_geom",
"ST_BoundingDiagonal(geom)",
"LINESTRING (1 0, 2 1)",
),
(
stf.ST_Centroid,
("geom",),
"triangle_geom",
"ST_ReducePrecision(geom, 2)",
"POINT (0.67 0.33)",
),
(
stf.ST_Collect,
(lambda: f.expr("array(a, b)"),),
"two_points",
"",
"MULTIPOINT Z (0 0 0, 3 0 4)",
),
(stf.ST_Collect, ("a", "b"), "two_points", "", "MULTIPOINT Z (0 0 0, 3 0 4)"),
(
stf.ST_ClosestPoint,
(
"point",
"line",
),
"point_and_line",
"",
"POINT (0 1)",
),
(
stf.ST_ShortestLine,
(
"point",
"line",
),
"point_and_line",
"",
"LINESTRING (0 1, 0 0)",
),
(
stf.ST_CollectionExtract,
("geom",),
"geom_collection",
"",
"MULTILINESTRING ((0 0, 1 0))",
),
(stf.ST_CollectionExtract, ("geom", 1), "geom_collection", "", "MULTIPOINT (0 0)"),
(
stf.ST_ConcaveHull,
("geom", 1.0),
"triangle_geom",
"",
"POLYGON ((0 0, 1 1, 1 0, 0 0))",
),
(
stf.ST_ConcaveHull,
("geom", 1.0, True),
"triangle_geom",
"",
"POLYGON ((1 1, 1 0, 0 0, 1 1))",
),
(
stf.ST_ConvexHull,
("geom",),
"triangle_geom",
"",
"POLYGON ((0 0, 1 1, 1 0, 0 0))",
),
(stf.ST_CoordDim, ("point",), "point_geom", "", 2),
(stf.ST_CrossesDateLine, ("line",), "line_crossing_dateline", "", True),
(
stf.ST_Difference,
("a", "b"),
"overlapping_polys",
"",
"POLYGON ((1 0, 0 0, 0 1, 1 1, 1 0))",
),
(stf.ST_Dimension, ("geom",), "geometry_geom_collection", "", 1),
(stf.ST_Distance, ("a", "b"), "two_points", "", 3.0),
(stf.ST_DistanceSpheroid, ("point", "point"), "point_geom", "", 0.0),
(stf.ST_DistanceSphere, ("point", "point"), "point_geom", "", 0.0),
(stf.ST_DistanceSphere, ("point", "point", 6378137.0), "point_geom", "", 0.0),
(
stf.ST_DelaunayTriangles,
("multipoint",),
"multipoint_geom",
"",
"GEOMETRYCOLLECTION (POLYGON ((10 40, 20 20, 40 30, 10 40)), POLYGON ((40 30, 20 20, 30 10, 40 30)))",
),
(stf.ST_Dump, ("geom",), "multipoint", "", ["POINT (0 0)", "POINT (1 1)"]),
(
stf.ST_DumpPoints,
("line",),
"linestring_geom",
"",
[
"POINT (0 0)",
"POINT (1 0)",
"POINT (2 0)",
"POINT (3 0)",
"POINT (4 0)",
"POINT (5 0)",
],
),
(stf.ST_EndPoint, ("line",), "linestring_geom", "", "POINT (5 0)"),
(
stf.ST_Box2D,
("line",),
"linestring_geom",
"",
Box2D(0.0, 0.0, 5.0, 0.0),
),
(
stf.ST_Box3D,
("line",),
"linestring_geom",
"",
# linestring_geom is 2D so Z folds to 0 per PostGIS semantics.
Box3D(0.0, 0.0, 0.0, 5.0, 0.0, 0.0),
),
(
stf.ST_Envelope,
("geom",),
"triangle_geom",
"",
"POLYGON ((0 0, 0 1, 1 1, 1 0, 0 0))",
),
(
stf.ST_Expand,
("geom", 2.0),
"triangle_geom",
"",
"POLYGON ((-2 -2, -2 3, 3 3, 3 -2, -2 -2))",
),
(
stf.ST_Expand,
("geom", 2.0, 2.0),
"triangle_geom",
"",
"POLYGON ((-2 -2, -2 3, 3 3, 3 -2, -2 -2))",
),
(
stf.ST_ExteriorRing,
("geom",),
"triangle_geom",
"",
"LINESTRING (0 0, 1 0, 1 1, 0 0)",
),
(stf.ST_FlipCoordinates, ("point",), "point_geom", "", "POINT (1 0)"),
(stf.ST_Force_2D, ("point",), "point_geom", "", "POINT (0 1)"),
(stf.ST_Force2D, ("point",), "point_geom", "", "POINT (0 1)"),
(stf.ST_Force3D, ("point", 1.0), "point_geom", "", "POINT Z (0 1 1)"),
(
stf.ST_Force3DM,
("point", 1.0),
"point_geom",
"ST_AsText(geom)",
"POINT M(0 1 1)",
),
(stf.ST_Force3DZ, ("point", 1.0), "point_geom", "", "POINT Z (0 1 1)"),
(
stf.ST_Force4D,
("point", 1.0, 1.0),
"point_geom",
"ST_AsText(geom)",
"POINT ZM(0 1 1 1)",
),
(
stf.ST_ForceCollection,
("multipoint",),
"multipoint_geom",
"ST_NumGeometries(geom)",
4,
),
(
stf.ST_ForcePolygonCW,
("geom",),
"geom_with_hole",
"",
"POLYGON ((0 0, 3 3, 3 0, 0 0), (1 1, 2 1, 2 2, 1 1))",
),
(
stf.ST_ForcePolygonCCW,
("geom",),
"geom_with_hole",
"",
"POLYGON ((0 0, 3 0, 3 3, 0 0), (1 1, 2 2, 2 1, 1 1))",
),
(
stf.ST_ForceRHR,
("geom",),
"geom_with_hole",
"",
"POLYGON ((0 0, 3 3, 3 0, 0 0), (1 1, 2 1, 2 2, 1 1))",
),
(
stf.ST_FrechetDistance,
(
"point",
"line",
),
"point_and_line",
"",
5.0990195135927845,
),
(
stf.ST_GeometricMedian,
("multipoint",),
"multipoint_geom",
"",
"POINT (22.500002656424286 21.250001168173426)",
),
(stf.ST_GeneratePoints, ("geom", 15), "square_geom", "ST_NumGeometries(geom)", 15),
(
stf.ST_GeneratePoints,
("geom", 15, 100),
"square_geom",
"ST_NumGeometries(geom)",
15,
),
(stf.ST_GeometryN, ("geom", 0), "multipoint", "", "POINT (0 0)"),
(stf.ST_GeometryType, ("point",), "point_geom", "", "ST_Point"),
(
stf.ST_GeoHashNeighbors,
("geohash",),
"constructor",
"",
[
"s00twy01mk",
"s00twy01mm",
"s00twy01mq",
"s00twy01ms",
"s00twy01mu",
"s00twy01mv",
"s00twy01mw",
"s00twy01my",
],
),
(
stf.ST_GeoHashNeighbor,
("geohash", lambda: f.lit("n")),
"constructor",
"",
"s00twy01mw",
),
(
stf.ST_HausdorffDistance,
(
"point",
"line",
),
"point_and_line",
"",
5.0990195135927845,
),
(
stf.ST_InteriorRingN,
("geom", 0),
"geom_with_hole",
"",
"LINESTRING (1 1, 2 2, 2 1, 1 1)",
),
(
stf.ST_Intersection,
("a", "b"),
"overlapping_polys",
"",
"POLYGON ((2 0, 1 0, 1 1, 2 1, 2 0))",
),
(stf.ST_InterpolatePoint, ("linem", "point"), "linestringm_and_point", "", 1.0),
(stf.ST_IsCollection, ("geom",), "geom_collection", "", True),
(stf.ST_IsClosed, ("geom",), "closed_linestring_geom", "", True),
(stf.ST_IsEmpty, ("geom",), "empty_geom", "", True),
(stf.ST_IsLineStringCCW, ("geom",), "closed_linestring_geom", "", True),
(stf.ST_IsPolygonCW, ("geom",), "geom_with_hole", "", False),
(stf.ST_IsPolygonCCW, ("geom",), "geom_with_hole", "", True),
(stf.ST_IsRing, ("line",), "linestring_geom", "", False),
(stf.ST_IsSimple, ("geom",), "triangle_geom", "", True),
(stf.ST_IsValidTrajectory, ("line",), "4D_line", "", False),
(stf.ST_IsValid, ("geom",), "triangle_geom", "", True),
(stf.ST_IsValid, ("geom", 1), "triangle_geom", "", True),
(stf.ST_IsValid, ("geom", 0), "triangle_geom", "", True),
(
stf.ST_IsValidDetail,
("geom",),
"triangle_geom",
"",
Row(valid=True, reason=None, location=None).asDict(),
),
(
stf.ST_IsValidDetail,
("geom", 1),
"triangle_geom",
"",
Row(valid=True, reason=None, location=None).asDict(),
),
(stf.ST_Length, ("line",), "linestring_geom", "", 5.0),
(stf.ST_Length2D, ("line",), "linestring_geom", "", 5.0),
(stf.ST_LengthSpheroid, ("point",), "point_geom", "", 0.0),
(
stf.ST_LineFromMultiPoint,
("multipoint",),
"multipoint_geom",
"",
"LINESTRING (10 40, 40 30, 20 20, 30 10)",
),
(
stf.ST_LineInterpolatePoint,
("line", 0.5),
"linestring_geom",
"",
"POINT (2.5 0)",
),
(stf.ST_LineLocatePoint, ("line", "point"), "line_and_point", "", 0.5),
(
stf.ST_LineMerge,
("geom",),
"multiline_geom",
"",
"LINESTRING (0 0, 1 0, 1 1, 0 0)",
),
(stf.ST_LineSegments, ("line",), "linestring_geom", "array_size(geom)", 5),
(
stf.ST_LineSegments,
("geom", True),
"polygon_unsimplified",
"array_size(geom)",
0,
),
(
stf.ST_LineSubstring,
("line", 0.5, 1.0),
"linestring_geom",
"",
"LINESTRING (2.5 0, 3 0, 4 0, 5 0)",
),
(
stf.ST_LongestLine,
("geom", "geom"),
"geom_collection",
"",
"LINESTRING (0 0, 1 0)",
),
(
stf.ST_LocateAlong,
("line", 1.0),
"4D_line",
"ST_AsText(geom)",
"MULTIPOINT ZM((1 1 1 1))",
),
(
stf.ST_LocateAlong,
("line", 1.0, 2.0),
"4D_line",
"ST_AsText(geom)",
"MULTIPOINT ZM((-0.4142135623730949 2.414213562373095 1 1), (2.414213562373095 -0.4142135623730949 1 1))",
),
(stf.ST_HasZ, ("a",), "two_points", "", True),
(stf.ST_HasM, ("point",), "4D_point", "", True),
(stf.ST_M, ("point",), "4D_point", "", 4.0),
(stf.ST_MMin, ("line",), "4D_line", "", -1.0),
(stf.ST_MMax, ("line",), "4D_line", "", 3.0),
(
stf.ST_MakeValid,
("geom",),
"invalid_geom",
"",
"MULTIPOLYGON (((1 5, 3 3, 1 1, 1 5)), ((5 3, 7 5, 7 1, 5 3)))",
),
(
stf.ST_MakeLine,
("line1", "line2"),
"two_lines",
"",
"LINESTRING (0 0, 1 1, 0 0, 3 2)",
),
(
stf.ST_MaximumInscribedCircle,
("geom",),
"triangle_geom",
"ST_AsText(geom.center)",
"POINT (0.70703125 0.29296875)",
),
(
stf.ST_MaximumInscribedCircle,
("geom",),
"triangle_geom",
"ST_AsText(geom.nearest)",
"POINT (0.5 0.5)",
),
(
stf.ST_MaximumInscribedCircle,
("geom",),
"triangle_geom",
"geom.radius",
0.2927864015850548,
),
(
stf.ST_MaximumInscribedCircle,
("geom", 2.0),
"triangle_geom",
"ST_AsText(geom.center)",
"POINT (0.75 0.5)",
),
(stf.ST_MaxDistance, ("a", "b"), "overlapping_polys", "", 3.1622776601683795),
(stf.ST_Perimeter, ("geom",), "triangle_geom", "", 3.414213562373095),
(stf.ST_Perimeter, ("geom", True), "triangle_geom", "ceil(geom)", 378794),
(
stf.ST_Perimeter,
(lambda: stf.ST_SetSRID("geom", 4326), True),
"triangle_geom",
"ceil(geom)",
378794,
),
(stf.ST_Perimeter2D, ("geom",), "triangle_geom", "", 3.414213562373095),
(stf.ST_Perimeter2D, ("geom", True), "triangle_geom", "ceil(geom)", 378794),
(
stf.ST_Perimeter2D,
(lambda: stf.ST_SetSRID("geom", 4326), True),
"triangle_geom",
"ceil(geom)",
378794,
),
(
stf.ST_Points,
("line",),
"linestring_geom",
"ST_Normalize(geom)",
"MULTIPOINT (0 0, 1 0, 2 0, 3 0, 4 0, 5 0)",
),
(
stf.ST_Polygon,
("geom", 4236),
"closed_linestring_geom",
"",
"POLYGON ((0 0, 1 0, 1 1, 0 0))",
),
(
stf.ST_Polygonize,
("geom",),
"noded_linework",
"ST_Normalize(geom)",
"GEOMETRYCOLLECTION (POLYGON ((0 2, 1 3, 2 4, 2 3, 2 2, 1 2, 0 2)), POLYGON ((2 2, 2 3, 2 4, 3 3, 4 2, 3 2, 2 2)))",
),
(
stf.ST_Project,
("point", 10.0, radians(10)),
"point_geom",
"",
"POINT (1.7364817766693021 10.848077530122081)",
),
(
stf.ST_Project,
("geom", 10.0, radians(10), True),
"triangle_geom",
"",
"POINT EMPTY",
),
(
stf.ST_MakePolygon,
("geom",),
"closed_linestring_geom",
"",
"POLYGON ((0 0, 1 0, 1 1, 0 0))",
),
(stf.ST_MinimumClearance, ("geom",), "invalid_geom", "", 2.0),
(
stf.ST_MinimumClearanceLine,
("geom",),
"invalid_geom",
"",
"LINESTRING (5 3, 3 3)",
),
(
stf.ST_MinimumBoundingCircle,
("line", 8),
"linestring_geom",
"ST_ReducePrecision(geom, 2)",
"POLYGON ((4.95 -0.49, 4.81 -0.96, 4.58 -1.39, 4.27 -1.77, 3.89 -2.08, 3.46 -2.31, 2.99 -2.45, 2.5 -2.5, 2.01 -2.45, 1.54 -2.31, 1.11 -2.08, 0.73 -1.77, 0.42 -1.39, 0.19 -0.96, 0.05 -0.49, 0 0, 0.05 0.49, 0.19 0.96, 0.42 1.39, 0.73 1.77, 1.11 2.08, 1.54 2.31, 2.01 2.45, 2.5 2.5, 2.99 2.45, 3.46 2.31, 3.89 2.08, 4.27 1.77, 4.58 1.39, 4.81 0.96, 4.95 0.49, 5 0, 4.95 -0.49))",
),
(
stf.ST_MinimumBoundingCircle,
("line", 2),
"linestring_geom",
"ST_ReducePrecision(geom, 2)",
"POLYGON ((4.27 -1.77, 2.5 -2.5, 0.73 -1.77, 0 0, 0.73 1.77, 2.5 2.5, 4.27 1.77, 5 0, 4.27 -1.77))",
),
(
stf.ST_MinimumBoundingRadius,
("line",),
"linestring_geom",
"",
{"center": "POINT (2.5 0)", "radius": 2.5},
),
(stf.ST_Multi, ("point",), "point_geom", "", "MULTIPOINT (0 1)"),
(
stf.ST_Normalize,
("geom",),
"triangle_geom",
"",
"POLYGON ((0 0, 1 1, 1 0, 0 0))",
),
(stf.ST_NPoints, ("line",), "linestring_geom", "", 6),
(stf.ST_NRings, ("geom",), "square_geom", "", 1),
(stf.ST_NumGeometries, ("geom",), "multipoint", "", 2),
(stf.ST_NumInteriorRings, ("geom",), "geom_with_hole", "", 1),
(stf.ST_NumInteriorRing, ("geom",), "geom_with_hole", "", 1),
(stf.ST_NumPoints, ("line",), "linestring_geom", "", 6),
(
stf.ST_OrientedEnvelope,
("geom",),
"diagonal_geom",
"",
"POLYGON ((0 0, 4.5 4.5, 5 4, 0.5 -0.5, 0 0))",
),
(
stf.ST_OffsetCurve,
("line", 1.0),
"linestring_geom",
"ST_AsText(geom)",
"LINESTRING (0 1, 5 1)",
),
(
stf.ST_OffsetCurve,
("line", 1.0, 4),
"linestring_geom",
"ST_AsText(geom)",
"LINESTRING (0 1, 5 1)",
),
(stf.ST_PointN, ("line", 2), "linestring_geom", "", "POINT (1 0)"),
(stf.ST_PointOnSurface, ("line",), "linestring_geom", "", "POINT (2 0)"),
(
stf.ST_ReducePrecision,
("geom", 1),
"precision_reduce_point",
"",
"POINT (0.1 0.2)",
),
(
stf.ST_RemovePoint,
("line", 1),
"linestring_geom",
"",
"LINESTRING (0 0, 2 0, 3 0, 4 0, 5 0)",
),
(
stf.ST_RemoveRepeatedPoints,
("geom",),
"repeated_multipoint",
"",
"MULTIPOINT (1 1, 2 2, 3 3, 4 4)",
),
(
stf.ST_Reverse,
("line",),
"linestring_geom",
"",
"LINESTRING (5 0, 4 0, 3 0, 2 0, 1 0, 0 0)",
),
(
stf.ST_Scale,
("poly", 3, 2),
"poly_and_point",
"",
"POLYGON ((0 0, 0 2, 3 2, 3 0, 0 0))",
),
(
stf.ST_ScaleGeom,
("poly", "point"),
"poly_and_point",
"",
"POLYGON ((0 0, 0 2, 3 2, 3 0, 0 0))",
),
(
stf.ST_RotateX,
("line", 10.0),
"4D_line",
"ST_ReducePrecision(geom, 2)",
"LINESTRING ZM (1 -0.3 -1.383092639965822 1, 2 -0.59 -2.766185279931644 2, 3 -0.89 -4.149277919897466 3, -1 0.3 1.383092639965822 -1)",
),
(
stf.ST_RotateY,
("line", 10.0),
"4D_line",
"ST_AsText(ST_ReducePrecision(geom, 2))",
"LINESTRING ZM(-1.38 1 -0.2950504181870827 1, -2.77 2 -0.5901008363741653 2, -4.15 3 -0.8851512545612479 3, 1.38 -1 0.2950504181870827 -1)",
),
(
stf.ST_Rotate,
("line", 10.0),
"linestring_geom",
"ST_ReducePrecision(geom, 2)",
"LINESTRING (0 0, -0.84 -0.54, -1.68 -1.09, -2.52 -1.63, -3.36 -2.18, -4.2 -2.72)",
),
(
stf.ST_Rotate,
("line", 10.0, 0.0, 0.0),
"linestring_geom",
"ST_ReducePrecision(geom, 2)",
"LINESTRING (0 0, -0.84 -0.54, -1.68 -1.09, -2.52 -1.63, -3.36 -2.18, -4.2 -2.72)",
),
(stf.ST_S2CellIDs, ("point", 30), "point_geom", "", [1153451514845492609]),
(
stf.ST_S2ToGeom,
(lambda: f.expr("array(1154047404513689600)"),),
"null",
"ST_ReducePrecision(geom[0], 5)",
"POLYGON ((0 2.46041, 2.46041 2.46041, 2.46041 0, 0 0, 0 2.46041))",
),
(
stf.ST_SetPoint,
("line", 1, lambda: f.expr("ST_Point(1.0, 1.0)")),
"linestring_geom",
"",
"LINESTRING (0 0, 1 1, 2 0, 3 0, 4 0, 5 0)",
),
(stf.ST_SetSRID, ("point", 3021), "point_geom", "ST_SRID(geom)", 3021),
(
stf.ST_ShiftLongitude,
("geom",),
"triangle_geom",
"",
"POLYGON ((0 0, 1 0, 1 1, 0 0))",
),
(
stf.ST_Simplify,
("geom", 0.1),
"0.9_poly",
"",
"POLYGON ((0 0, 1 0, 1 1, 0 0))",
),
(
stf.ST_SimplifyPreserveTopology,
("geom", 0.2),
"0.9_poly",
"",
"POLYGON ((0 0, 1 0, 1 1, 0 0))",
),
(
stf.ST_SimplifyVW,
("geom", 0.1),
"0.9_poly",
"",
"POLYGON ((0 0, 1 0, 1 1, 0 0))",
),
(
stf.ST_SimplifyPolygonHull,
("geom", 0.3, False),
"polygon_unsimplified",
"",
"POLYGON ((30 10, 40 40, 10 20, 30 10))",
),
(
stf.ST_SimplifyPolygonHull,
("geom", 0.3),
"polygon_unsimplified",
"",
"POLYGON ((30 10, 15 15, 10 20, 20 40, 45 45, 30 10))",
),
(
stf.ST_Snap,
("poly", "line", 2.525),
"poly_and_line",
"",
"POLYGON ((2.6 12.5, 2.6 20, 12.6 20, 12.6 12.5, 10.1 10, 2.6 12.5))",
),
(
stf.ST_Split,
("line", "points"),
"multipoint_splitting_line",
"",
"MULTILINESTRING ((0 0, 0.5 0.5), (0.5 0.5, 1 1), (1 1, 1.5 1.5, 2 2))",
),
(stf.ST_SRID, ("point",), "point_geom", "", 0),
(stf.ST_StartPoint, ("line",), "linestring_geom", "", "POINT (0 0)"),
(
stf.ST_SubDivide,
("line", 5),
"linestring_geom",
"",
["LINESTRING (0 0, 2.5 0)", "LINESTRING (2.5 0, 5 0)"],
),
(
stf.ST_SubDivideExplode,
("line", 5),
"linestring_geom",
"collect_list(geom)",
["LINESTRING (0 0, 2.5 0)", "LINESTRING (2.5 0, 5 0)"],
),
(
stf.ST_Segmentize,
("line", 0.5),
"linestring_geom",
"",
"LINESTRING (0 0, 0.5 0, 1 0, 1.5 0, 2 0, 2.5 0, 3 0, 3.5 0, 4 0, 4.5 0, 5 0)",
),
(
stf.ST_SymDifference,
("a", "b"),
"overlapping_polys",
"",
"MULTIPOLYGON (((1 0, 0 0, 0 1, 1 1, 1 0)), ((2 0, 2 1, 3 1, 3 0, 2 0)))",
),
(
stf.ST_Transform,
("point", lambda: f.lit("EPSG:4326"), lambda: f.lit("EPSG:32649")),
"point_geom",
"ST_ReducePrecision(geom, 2)",
"POINT (-10300622.99 19680322.66)",
),
(
stf.ST_Translate,
(
"geom",
1.0,
1.0,
),
"square_geom",
"",
"POLYGON ((2 1, 2 2, 3 2, 3 1, 2 1))",
),
(
stf.ST_TriangulatePolygon,
("geom",),
"square_geom",
"",
"GEOMETRYCOLLECTION (POLYGON ((1 0, 1 1, 2 1, 1 0)), POLYGON ((2 1, 2 0, 1 0, 2 1)))",
),
(
stf.ST_Union,
("a", "b"),
"overlapping_polys",
"",
"POLYGON ((1 0, 0 0, 0 1, 1 1, 2 1, 3 1, 3 0, 2 0, 1 0))",
),
(
stf.ST_Union,
("polys",),
"array_polygons",
"",
"POLYGON ((2 3, 3 3, 3 -3, -3 -3, -3 3, -2 3, -2 4, 2 4, 2 3))",
),
(
stf.ST_UnaryUnion,
("geom",),
"overlapping_mPolys",
"",
"POLYGON ((10 0, 10 10, 0 10, 0 30, 20 30, 20 20, 30 20, 30 0, 10 0))",
),
(
stf.ST_VoronoiPolygons,
("geom",),
"multipoint",
"",
"GEOMETRYCOLLECTION (POLYGON ((-1 -1, -1 2, 2 -1, -1 -1)), POLYGON ((-1 2, 2 2, 2 -1, -1 2)))",
),
(stf.ST_X, ("b",), "two_points", "", 3.0),
(stf.ST_XMax, ("line",), "linestring_geom", "", 5.0),
(stf.ST_XMin, ("line",), "linestring_geom", "", 0.0),
(stf.ST_Y, ("b",), "two_points", "", 0.0),
(stf.ST_YMax, ("geom",), "triangle_geom", "", 1.0),
(stf.ST_YMin, ("geom",), "triangle_geom", "", 0.0),
(stf.ST_Z, ("b",), "two_points", "", 4.0),
(stf.ST_Zmflag, ("b",), "two_points", "", 2),
(stf.ST_IsValidReason, ("geom",), "triangle_geom", "", "Valid Geometry"),
(stf.ST_IsValidReason, ("geom", 1), "triangle_geom", "", "Valid Geometry"),
# predicates
(
stp.ST_Contains,
("geom", lambda: f.expr("ST_Point(0.5, 0.25)")),
"triangle_geom",
"",
True,
),
(
stp.ST_Intersects,
(
lambda: f.expr("ST_3DMakeBox(ST_PointZ(0, 0, 0), ST_PointZ(5, 5, 5))"),
lambda: f.expr("ST_3DMakeBox(ST_PointZ(1, 1, 1), ST_PointZ(2, 2, 2))"),
),
"triangle_geom",
"",
True,
),
(
stp.ST_Contains,
(
lambda: f.expr("ST_3DMakeBox(ST_PointZ(0, 0, 0), ST_PointZ(5, 5, 5))"),
lambda: f.expr("ST_3DMakeBox(ST_PointZ(1, 1, 1), ST_PointZ(2, 2, 2))"),
),
"triangle_geom",
"",
True,
),
(
stp.ST_3DDWithin,
(
lambda: f.expr("ST_PointZ(0.0, 0.0, 0.0)"),
lambda: f.expr("ST_PointZ(1.0, 1.0, 1.0)"),
# 3D distance is sqrt(3) ≈ 1.732; 2.0 includes it.
2.0,
),
"triangle_geom",
"",
True,
),
(stp.ST_Crosses, ("line", "poly"), "line_crossing_poly", "", True),
(stp.ST_Disjoint, ("a", "b"), "two_points", "", True),
(
stp.ST_Equals,
("line", lambda: f.expr("ST_Reverse(line)")),
"linestring_geom",
"",
True,
),
(
stp.ST_EqualsExact,
(
lambda: f.expr("ST_Point(0.0, 0.0)"),
lambda: f.expr("ST_Point(0.03, 0.04)"),
0.051,
),
"triangle_geom",
"",
True,
),
(stp.ST_Intersects, ("a", "b"), "overlapping_polys", "", True),
(
stp.ST_OrderingEquals,
("line", lambda: f.expr("ST_Reverse(line)")),
"linestring_geom",
"",
False,
),
(stp.ST_Overlaps, ("a", "b"), "overlapping_polys", "", True),
(stp.ST_Touches, ("a", "b"), "touching_polys", "", True),
(stp.ST_Relate, ("a", "b"), "touching_polys", "", "FF2F11212"),
(stp.ST_Relate, ("a", "b", lambda: f.lit("FF2F11212")), "touching_polys", "", True),
(
stp.ST_RelateMatch,
(lambda: f.lit("101202FFF"), lambda: f.lit("TTTTTTFFF")),
"touching_polys",
"",
True,
),
(
stp.ST_Within,
(lambda: f.expr("ST_Point(0.5, 0.25)"), "geom"),
"triangle_geom",
"",
True,
),
(
stp.ST_Covers,
("geom", lambda: f.expr("ST_Point(0.5, 0.25)")),
"triangle_geom",
"",
True,
),
(
stp.ST_CoveredBy,
(lambda: f.expr("ST_Point(0.5, 0.25)"), "geom"),
"triangle_geom",
"",
True,
),
(
stp.ST_Contains,
("geom", lambda: f.expr("ST_Point(0.0, 0.0)")),
"triangle_geom",
"",
False,
),
(
stp.ST_Within,
(lambda: f.expr("ST_Point(0.0, 0.0)"), "geom"),
"triangle_geom",
"",
False,
),
(
stp.ST_Covers,
("geom", lambda: f.expr("ST_Point(0.0, 0.0)")),
"triangle_geom",
"",
True,
),
(
stp.ST_CoveredBy,
(lambda: f.expr("ST_Point(0.0, 0.0)"), "geom"),
"triangle_geom",
"",
True,
),
(
stp.ST_DWithin,
(
"origin",
"point",
5.0,
),
"origin_and_point",
"",
True,
),
(stp.ST_DWithin, ("ny", "seattle", 4000000.0, True), "ny_seattle", "", True),
# aggregates
(
sta.ST_Envelope_Aggr,
("geom",),
"exploded_points",
"",
"POLYGON ((0 0, 0 1, 1 1, 1 0, 0 0))",
),
(
sta.ST_Intersection_Aggr,
("geom",),
"exploded_polys",
"",
"LINESTRING (1 0, 1 1)",
),
(
sta.ST_Union_Aggr,
("geom",),
"exploded_polys",
"",
"POLYGON ((0 0, 0 1, 1 1, 2 1, 2 0, 1 0, 0 0))",
),
(
sta.ST_Collect_Agg,
("geom",),
"exploded_points",
"",
"MULTIPOINT ((0 0), (1 1))",
),
(
sta.ST_Extent,
("geom",),
"exploded_points",
"",
Box2D(0.0, 0.0, 1.0, 1.0),
),
(
sta.ST_3DExtent,
("geom",),
"exploded_points",
"",
# 2D inputs fold Z=0 per PostGIS semantics.
Box3D(0.0, 0.0, 0.0, 1.0, 1.0, 0.0),
),
# Test aliases for *_Aggr functions with *_Agg suffix
(
sta.ST_Envelope_Agg,
("geom",),
"exploded_points",
"",
"POLYGON ((0 0, 0 1, 1 1, 1 0, 0 0))",
),
(
sta.ST_Intersection_Agg,
("geom",),
"exploded_polys",
"",
"LINESTRING (1 0, 1 1)",
),
(
sta.ST_Union_Agg,
("geom",),
"exploded_polys",
"",
"POLYGON ((0 0, 0 1, 1 1, 2 1, 2 0, 1 0, 0 0))",
),
]
wrong_type_configurations = [
# constructors
(stc.ST_GeomFromGeoHash, (None, 4)),
(stc.ST_GeomFromGeoHash, ("", None)),
(stc.ST_GeomFromGeoHash, ("", 4.0)),
(stc.ST_GeomFromGeoJSON, (None,)),
(stc.ST_GeomFromGML, (None,)),
(stc.ST_GeomFromKML, (None,)),
(stc.ST_GeomFromText, (None,)),
(stc.ST_GeomFromWKB, (None,)),
(stc.ST_LinestringFromWKB, (None,)),
(stc.ST_GeomFromEWKB, (None,)),
(stc.ST_GeomFromWKT, (None,)),
# (stc.ST_GeogFromWKT, (None,)),
(stc.ST_GeometryFromText, (None,)),
(stc.ST_LineFromText, (None,)),
(stc.ST_LineStringFromText, (None, "")),
(stc.ST_LineStringFromText, ("", None)),
(stc.ST_Point, (None, "")),
(stc.ST_Point, ("", None)),
(stc.ST_PointFromGeoHash, (None, 4)),
(stc.ST_PointFromGeoHash, (None,)),
(stc.ST_PointFromText, (None, "")),
(stc.ST_PointFromText, ("", None)),
(stc.ST_PointFromWKB, (None,)),
(stc.ST_MPointFromText, (None,)),
(stc.ST_MakeEnvelope, (None, "", "", "", "")),
(stc.ST_MakeEnvelope, ("", None, "", "", "")),
(stc.ST_MakeEnvelope, ("", "", None, "", None)),
(stc.ST_MakeEnvelope, ("", "", "", None, None)),
(stc.ST_PolygonFromEnvelope, (None, "", "", "")),
(stc.ST_PolygonFromEnvelope, ("", None, "", "")),
(stc.ST_PolygonFromEnvelope, ("", "", None, "")),
(stc.ST_PolygonFromEnvelope, ("", "", "", None)),
(stc.ST_PolygonFromText, (None, "")),
(stc.ST_PolygonFromText, ("", None)),
(stc.ST_PolygonFromText, (None, None)),
(stc.ST_PolygonFromText, ("", None)),
(stc.ST_MakePointM, (None, None, None)),
(stc.ST_MakePointM, (None, "", "")),
# functions
(stf.ST_3DDistance, (None, "")),
(stf.ST_3DDistance, ("", None)),
(stf.ST_AddMeasure, (None, None, None)),
(stf.ST_AddMeasure, ("", None, "")),
(stf.ST_AddPoint, (None, "")),
(stf.ST_AddPoint, ("", None)),
(stf.ST_Area, (None,)),
(stf.ST_AsBinary, (None,)),
(stf.ST_AsEWKB, (None,)),
(stf.ST_AsHEXEWKB, (None,)),
(stf.ST_AsEWKT, (None,)),
(stf.ST_AsGeoJSON, (None,)),
(stf.ST_AsGML, (None,)),
(stf.ST_AsKML, (None,)),
(stf.ST_AsText, (None,)),
(stf.ST_Azimuth, (None, "")),
(stf.ST_Azimuth, ("", None)),
(stf.ST_BestSRID, (None,)),
(stf.ST_Boundary, (None,)),
(stf.ST_Buffer, (None, 1.0)),
(stf.ST_Buffer, ("", None)),
(stf.ST_BuildArea, (None,)),
(stf.ST_Centroid, (None,)),
(stf.ST_Collect, (None,)),
(stf.ST_CollectionExtract, (None,)),
(stf.ST_ConcaveHull, (None, 1.0)),
(stf.ST_ConvexHull, (None,)),
(stf.ST_CrossesDateLine, (None,)),
(stf.ST_Difference, (None, "b")),
(stf.ST_Difference, ("", None)),
(stf.ST_Distance, (None, "")),
(stf.ST_Distance, ("", None)),
(stf.ST_Dump, (None,)),
(stf.ST_DumpPoints, (None,)),
(stf.ST_DelaunayTriangles, (None,)),
(stf.ST_EndPoint, (None,)),
(stf.ST_Envelope, (None,)),
(stf.ST_Expand, (None, "")),
(stf.ST_Expand, (None, None)),
(stf.ST_Expand, ("", None)),
(stf.ST_ExteriorRing, (None,)),
(stf.ST_FlipCoordinates, (None,)),
(stf.ST_Force_2D, (None,)),
(stf.ST_Force2D, (None,)),
(stf.ST_Force3DM, (None,)),
(stf.ST_Force3DZ, (None,)),
(stf.ST_Force4D, (None,)),
(stf.ST_ForceCollection, (None,)),
(stf.ST_ForcePolygonCW, (None,)),
(stf.ST_ForcePolygonCCW, (None,)),
(stf.ST_ForceRHR, (None,)),
(stf.ST_GeometryN, (None, 0)),
(stf.ST_GeometryN, ("", None)),
(stf.ST_GeometryN, ("", 0.0)),
(stf.ST_GeometryType, (None,)),
(stf.ST_GeoHashNeighbors, (None,)),
(stf.ST_GeoHashNeighbor, (None, "n")),
(stf.ST_GeoHashNeighbor, ("", None)),
(stf.ST_GeneratePoints, (None, 0.0)),
(stf.ST_GeneratePoints, ("", None)),
(stf.ST_InteriorRingN, (None, 0)),
(stf.ST_InteriorRingN, ("", None)),
(stf.ST_InteriorRingN, ("", 0.0)),
(stf.ST_Intersection, (None, "")),
(stf.ST_Intersection, ("", None)),
(stf.ST_IsClosed, (None,)),
(stf.ST_IsEmpty, (None,)),
(stf.ST_IsLineStringCCW, (None,)),
(stf.ST_IsPolygonCW, (None,)),
(stf.ST_IsPolygonCCW, (None,)),
(stf.ST_IsRing, (None,)),
(stf.ST_IsSimple, (None,)),
(stf.ST_IsValidTrajectory, (None,)),
(stf.ST_IsValidDetail, (None,)),
(stf.ST_IsValid, (None,)),
(stf.ST_IsValidReason, (None,)),
(stf.ST_LabelPoint, (None,)),
(stf.ST_Length, (None,)),
(stf.ST_Length2D, (None,)),
(stf.ST_LineFromMultiPoint, (None,)),
(stf.ST_LineInterpolatePoint, (None, 0.5)),
(stf.ST_LineInterpolatePoint, ("", None)),
(stf.ST_LineLocatePoint, (None, "")),
(stf.ST_LineLocatePoint, ("", None)),
(stf.ST_LineMerge, (None,)),
(stf.ST_LineSubstring, (None, 0.5, 1.0)),
(stf.ST_LineSubstring, ("", None, 1.0)),
(stf.ST_LineSubstring, ("", 0.5, None)),
(stf.ST_LongestLine, (None, "")),
(stf.ST_LongestLine, (None, None)),
(stf.ST_LongestLine, ("", None)),
(stf.ST_LocateAlong, (None, "")),
(stf.ST_LocateAlong, (None, None)),
(stf.ST_LocateAlong, ("", None)),
(stf.ST_HasZ, (None,)),
(stf.ST_HasM, (None,)),
(stf.ST_M, (None,)),
(stf.ST_MMin, (None,)),
(stf.ST_MMax, (None,)),
(stf.ST_MakeValid, (None,)),
(stf.ST_MakePolygon, (None,)),
(stf.ST_MaximumInscribedCircle, (None,)),
(stf.ST_MaximumInscribedCircle, ("", [])),
(stf.ST_MaxDistance, (None, None)),
(stf.ST_MaxDistance, (None, "")),
(stf.ST_MaxDistance, ("", None)),
(stf.ST_MinimumClearance, (None,)),
(stf.ST_MinimumClearanceLine, (None,)),
(stf.ST_MinimumBoundingCircle, (None,)),
(stf.ST_MinimumBoundingRadius, (None,)),
(stf.ST_OrientedEnvelope, (None,)),
(stf.ST_OffsetCurve, (None, 1.0)),
(stf.ST_Multi, (None,)),
(stf.ST_Normalize, (None,)),
(stf.ST_NPoints, (None,)),
(stf.ST_NumGeometries, (None,)),
(stf.ST_NumInteriorRings, (None,)),
(stf.ST_NumInteriorRing, (None,)),
(stf.ST_PointN, (None, 2)),
(stf.ST_PointN, ("", None)),
(stf.ST_PointN, ("", 2.0)),
(stf.ST_PointOnSurface, (None,)),
(stf.ST_Project, (None, "", "", None)),
(stf.ST_Project, ("", None, "", None)),
(stf.ST_Project, ("", "", None, None)),
(stf.ST_ReducePrecision, (None, 1)),
(stf.ST_ReducePrecision, ("", None)),
(stf.ST_ReducePrecision, ("", 1.0)),
(stf.ST_RemovePoint, (None, 1)),
(stf.ST_RemovePoint, ("", None)),
(stf.ST_RemovePoint, ("", 1.0)),
(stf.ST_RemoveRepeatedPoints, (None, None)),
(stf.ST_Reverse, (None,)),
(stf.ST_Scale, (None, None, None)),
(stf.ST_ScaleGeom, (None, None, None)),
(
stf.ST_Rotate,
(
None,
None,
),
),
(stf.ST_Rotate, (None, None)),
(stf.ST_S2CellIDs, (None, 2)),
(stf.ST_S2ToGeom, (None,)),
(stf.ST_SetPoint, (None, 1, "")),
(stf.ST_SetPoint, ("", None, "")),
(stf.ST_SetPoint, ("", 1, None)),
(stf.ST_SetSRID, (None, 3021)),
(stf.ST_SetSRID, ("", None)),
(stf.ST_SetSRID, ("", 3021.0)),
(stf.ST_ShiftLongitude, (None,)),
(stf.ST_Simplify, (None, 2)),
(stf.ST_Simplify, ("", None)),
(stf.ST_SimplifyPreserveTopology, (None, 0.2)),
(stf.ST_SimplifyPreserveTopology, ("", None)),
(stf.ST_SimplifyVW, (None, 2)),
(stf.ST_SimplifyVW, ("", None)),
(stf.ST_SimplifyPolygonHull, ("", None)),
(stf.ST_SimplifyPolygonHull, (None, None)),
(stf.ST_Snap, (None, None, 12)),
(stf.ST_SRID, (None,)),
(stf.ST_StartPoint, (None,)),
(stf.ST_SubDivide, (None, 5)),
(stf.ST_SubDivide, ("", None)),
(stf.ST_SubDivide, ("", 5.0)),
(stf.ST_SubDivideExplode, (None, 5)),
(stf.ST_SubDivideExplode, ("", None)),
(stf.ST_SubDivideExplode, ("", 5.0)),
(stf.ST_SymDifference, (None, "")),
(stf.ST_SymDifference, ("", None)),
(stf.ST_Transform, (None, "", "")),
(stf.ST_Transform, ("", None, "")),
(stf.ST_TriangulatePolygon, (None,)),
(stf.ST_Union, (None, "")),
(stf.ST_Union, (None,)),
(stf.ST_UnaryUnion, (None,)),
(stf.ST_X, (None,)),
(stf.ST_XMax, (None,)),
(stf.ST_XMin, (None,)),
(stf.ST_Y, (None,)),
(stf.ST_YMax, (None,)),
(stf.ST_YMin, (None,)),
(stf.ST_Z, (None,)),
(stf.ST_Zmflag, (None,)),
# predicates
(stp.ST_Contains, (None, "")),
(stp.ST_Contains, ("", None)),
(stp.ST_Crosses, (None, "")),
(stp.ST_Crosses, ("", None)),
(stp.ST_Disjoint, (None, "")),
(stp.ST_Disjoint, ("", None)),
(stp.ST_Equals, (None, "")),
(stp.ST_Equals, ("", None)),
(stp.ST_Intersects, (None, "")),
(stp.ST_Intersects, ("", None)),
(stp.ST_OrderingEquals, (None, "")),
(stp.ST_OrderingEquals, ("", None)),
(stp.ST_EqualsExact, (None, "", 0.0)),
(stp.ST_EqualsExact, ("", None, 0.0)),
(stp.ST_EqualsExact, ("", "", None)),
(stp.ST_Overlaps, (None, "")),
(stp.ST_Overlaps, ("", None)),
(stp.ST_Touches, (None, "")),
(stp.ST_Touches, ("", None)),
(stp.ST_Relate, (None, "")),
(stp.ST_Relate, ("", None)),
(stp.ST_RelateMatch, (None, "")),
(stp.ST_RelateMatch, ("", None)),
(stp.ST_Within, (None, "")),
(stp.ST_Within, ("", None)),
# aggregates
(sta.ST_Envelope_Aggr, (None,)),
(sta.ST_Intersection_Aggr, (None,)),
(sta.ST_Union_Aggr, (None,)),
]
class TestDataFrameAPI(TestBase):
@pytest.fixture
def base_df(self, request):
wkbLine = "0102000000020000000000000084d600c00000000080b5d6bf00000060e1eff7bf00000080075de5bf"
wkbPoint = "010100000000000000000024400000000000002e40"
wkb = "0102000000020000000000000084d600c00000000080b5d6bf00000060e1eff7bf00000080075de5bf"
mpoly = (
"MULTIPOLYGON(((0 0 ,20 0 ,20 20 ,0 20 ,0 0 ),(5 5 ,5 7 ,7 7 ,7 5 ,5 5)))"
)
mline = "MULTILINESTRING((1 2, 3 4), (4 5, 6 7))"
mpoint = "MULTIPOINT ((10 10), (20 20), (30 30))"
geojson = '{ "type": "Feature", "properties": { "prop": "01" }, "geometry": { "type": "Point", "coordinates": [ 0.0, 1.0 ] }},'
gml_string = '<gml:LineString srsName="EPSG:4269"><gml:coordinates>-71.16,42.25 -71.17,42.25 -71.18,42.25</gml:coordinates></gml:LineString>'
kml_string = "<LineString><coordinates>-71.16,42.26 -71.17,42.26</coordinates></LineString>"
wktCollection = "GEOMETRYCOLLECTION(POINT(1 1), LINESTRING(0 0, 1 1)))"
if request.param == "constructor":
return TestDataFrameAPI.spark.sql("SELECT null").selectExpr(
"0.0 AS x",
"1.0 AS y",
"2.0 AS z",
"'0.0,1.0' AS single_point",
"'0.0,0.0,1.0,0.0,1.0,1.0,0.0,0.0' AS multiple_point",
f"X'{wkbLine}' AS wkbLine",
f"X'{wkbPoint}' AS wkbPoint",
f"X'{wkb}' AS wkb",
f"'{mpoly}' AS mpoly",
f"'{mline}' AS mline",
f"'{mpoint}' AS mpoint",
f"'{geojson}' AS geojson",
"'s00twy01mt' AS geohash",
f"'{gml_string}' AS gml",
f"'{kml_string}' AS kml",
f"'{wktCollection}' AS collection",
)
elif request.param == "point_geom":
return TestDataFrameAPI.spark.sql("SELECT ST_Point(0.0, 1.0) AS point")
elif request.param == "linestring_geom":
return TestDataFrameAPI.spark.sql(
"SELECT ST_GeomFromWKT('LINESTRING (0 0, 1 0, 2 0, 3 0, 4 0, 5 0)') AS line"
)
elif request.param == "linestring_wkt":
return TestDataFrameAPI.spark.sql("SELECT 'LINESTRING (1 2, 3 4)' AS wkt")
elif request.param == "linestring_ewkt":
return TestDataFrameAPI.spark.sql(
"SELECT 'SRID=4269;LINESTRING (1 2, 3 4)' AS ewkt"
)
elif request.param == "min_max_x_y":
return TestDataFrameAPI.spark.sql(
"SELECT 0.0 AS minx, 1.0 AS miny, 2.0 AS maxx, 3.0 AS maxy"
)
elif request.param == "x_y_z_m_srid":
return TestDataFrameAPI.spark.sql(
"SELECT 1.0 AS x, 2.0 AS y, 3.0 AS z, 100.9 AS m, 4326 AS srid"
)
elif request.param == "multipoint_geom":
return TestDataFrameAPI.spark.sql(
"SELECT ST_GeomFromWKT('MULTIPOINT((10 40), (40 30), (20 20), (30 10))') AS multipoint"
)
elif request.param == "null":
return TestDataFrameAPI.spark.sql("SELECT null")
elif request.param == "triangle_geom":
return TestDataFrameAPI.spark.sql(
"SELECT ST_GeomFromWKT('POLYGON ((0 0, 1 0, 1 1, 0 0))') AS geom"
)
elif request.param == "two_points":
return TestDataFrameAPI.spark.sql(
"SELECT ST_PointZ(0.0, 0.0, 0.0) AS a, ST_PointZ(3.0, 0.0, 4.0) AS b"
)
elif request.param == "4D_point":
return TestDataFrameAPI.spark.sql(
"SELECT ST_GeomFromWKT('POINT ZM(1 2 3 4)') AS point"
)
elif request.param == "4D_line":
return TestDataFrameAPI.spark.sql(
"SELECT ST_GeomFromWKT('LINESTRING ZM(1 1 1 1, 2 2 2 2, 3 3 3 3, -1 -1 -1 -1)') AS line"
)
elif request.param == "invalid_geom":
return TestDataFrameAPI.spark.sql(
"SELECT ST_GeomFromWKT('POLYGON ((1 5, 1 1, 3 3, 5 3, 7 1, 7 5, 5 3, 3 3, 1 5))') AS geom"
)
elif request.param == "overlapping_polys":
return TestDataFrameAPI.spark.sql(
"SELECT ST_GeomFromWKT('POLYGON((0 0, 2 0, 2 1, 0 1, 0 0))') AS a, ST_GeomFromWKT('POLYGON((1 0, 3 0, 3 1, 1 1, 1 0))') AS b"
)
elif request.param == "overlapping_mPolys":
return TestDataFrameAPI.spark.sql(
"SELECT ST_GeomFromWKT('MULTIPOLYGON(((0 10,0 30,20 30,20 10,0 10)),((10 0,10 20,30 20,30 0,10 0)))') AS geom"
)
elif request.param == "multipoint":
return TestDataFrameAPI.spark.sql(
"SELECT ST_GeomFromWKT('MULTIPOINT ((0 0), (1 1))') AS geom"
)
elif request.param == "geom_with_hole":
return TestDataFrameAPI.spark.sql(
"SELECT ST_GeomFromWKT('POLYGON ((0 0, 3 0, 3 3, 0 0), (1 1, 2 2, 2 1, 1 1))') AS geom"
)
elif request.param == "0.9_poly":
return TestDataFrameAPI.spark.sql(
"SELECT ST_GeomFromWKT('POLYGON ((0 0, 1 0, 1 0.9, 1 1, 0 0))') AS geom"
)
elif request.param == "polygon_unsimplified":
return TestDataFrameAPI.spark.sql(
"SELECT ST_GeomFromWKT('POLYGON ((30 10, 40 40, 45 45, 20 40, 25 35, 10 20, 15 15, 30 10))') AS geom"
)
elif request.param == "precision_reduce_point":
return TestDataFrameAPI.spark.sql("SELECT ST_Point(0.12, 0.23) AS geom")
elif request.param == "closed_linestring_geom":
return TestDataFrameAPI.spark.sql(
"SELECT ST_GeomFromWKT('LINESTRING (0 0, 1 0, 1 1, 0 0)') AS geom"
)
elif request.param == "empty_geom":
return TestDataFrameAPI.spark.sql(
"SELECT ST_Difference(ST_Point(0.0, 0.0), ST_Point(0.0, 0.0)) AS geom"
)
elif request.param == "repeated_multipoint":
return TestDataFrameAPI.spark.sql(
"SELECT ST_GeomFromWKT('MULTIPOINT (1 1, 1 1, 2 2, 3 3, 3 3, 4 4)') AS geom"
)
elif request.param == "multiline_geom":
return TestDataFrameAPI.spark.sql(
"SELECT ST_GeomFromWKT('MULTILINESTRING ((0 0, 1 0), (1 0, 1 1), (1 1, 0 0))') AS geom"
)
elif request.param == "geom_collection":
return TestDataFrameAPI.spark.sql(
"SELECT ST_GeomFromWKT('GEOMETRYCOLLECTION(POINT(0 0), LINESTRING(0 0, 1 0))') AS geom"
)
elif request.param == "exploded_points":
return TestDataFrameAPI.spark.sql(
"SELECT explode(array(ST_Point(0.0, 0.0), ST_Point(1.0, 1.0))) AS geom"
)
elif request.param == "exploded_polys":
return TestDataFrameAPI.spark.sql(
"SELECT explode(array(ST_GeomFromWKT('POLYGON ((0 0, 1 0, 1 1, 0 1, 0 0))'), ST_GeomFromWKT('POLYGON ((1 0, 2 0, 2 1, 1 1, 1 0))'))) AS geom"
)
elif request.param == "touching_polys":
return TestDataFrameAPI.spark.sql(
"SELECT ST_GeomFromWKT('POLYGON ((0 0, 1 0, 1 1, 0 1, 0 0))') AS a, ST_GeomFromWKT('POLYGON ((1 0, 2 0, 2 1, 1 1, 1 0))') AS b"
)
elif request.param == "line_crossing_poly":
return TestDataFrameAPI.spark.sql(
"SELECT ST_GeomFromWKT('LINESTRING (0 0, 2 1)') AS line, ST_GeomFromWKT('POLYGON ((1 0, 2 0, 2 2, 1 2, 1 0))') AS poly"
)
elif request.param == "square_geom":
return TestDataFrameAPI.spark.sql(
"SELECT ST_GeomFromWKT('POLYGON ((1 0, 1 1, 2 1, 2 0, 1 0))') AS geom"
)
elif request.param == "diagonal_geom":
return TestDataFrameAPI.spark.sql(
"SELECT ST_GeomFromWKT('POLYGON ((0 0, 1 0, 5 4, 4 4, 0 0))') AS geom"
)
elif request.param == "four_points":
return TestDataFrameAPI.spark.sql(
"SELECT ST_GeomFromWKT('POINT (0 0)') AS p1, ST_GeomFromWKT('POINT (1 1)') AS p2, ST_GeomFromWKT('POINT (1 0)') AS p3, ST_GeomFromWKT('POINT (6 2)') AS p4"
)
elif request.param == "three_points":
return TestDataFrameAPI.spark.sql(
"SELECT ST_GeomFromWKT('POINT (1 1)') AS p1, ST_GeomFromWKT('POINT (0 0)') AS p2, ST_GeomFromWKT('POINT (3 2)') AS p3"
)
elif request.param == "two_lines":
return TestDataFrameAPI.spark.sql(
"SELECT ST_GeomFromWKT('LINESTRING (0 0, 1 1)') AS line1, ST_GeomFromWKT('LINESTRING (0 0, 3 2)') AS line2"
)
elif request.param == "two_lines_angle_rad":
return TestDataFrameAPI.spark.sql(
"SELECT ST_Angle(ST_GeomFromWKT('LINESTRING (0 0, 1 1)'), ST_GeomFromWKT('LINESTRING (0 0, 3 2)')) AS angleRad"
)
elif request.param == "geometry_geom_collection":
return TestDataFrameAPI.spark.sql(
"SELECT ST_GeomFromWKT('GEOMETRYCOLLECTION(POINT(1 1), LINESTRING(0 0, 1 1, 2 2))') AS geom"
)
elif request.param == "point_and_line":
return TestDataFrameAPI.spark.sql(
"SELECT ST_GeomFromWKT('POINT (0.0 1.0)') AS point, ST_GeomFromWKT('LINESTRING (0 0, 1 0, 2 0, 3 0, 4 0, 5 0)') AS line"
)
elif request.param == "line_and_point":
return TestDataFrameAPI.spark.sql(
"SELECT ST_GeomFromWKT('LINESTRING (0 2, 1 1, 2 0)') AS line, ST_GeomFromWKT('POINT (0 0)') AS point"
)
elif request.param == "multipoint_splitting_line":
return TestDataFrameAPI.spark.sql(
"SELECT ST_GeomFromWKT('LINESTRING (0 0, 1.5 1.5, 2 2)') AS line, ST_GeomFromWKT('MULTIPOINT (0.5 0.5, 1 1)') AS points"
)
elif request.param == "origin_and_point":
return TestDataFrameAPI.spark.sql(
"SELECT ST_GeomFromWKT('POINT (0 0)') AS origin, ST_GeomFromWKT('POINT (1 0)') as point"
)
elif request.param == "ny_seattle":
return TestDataFrameAPI.spark.sql(
"SELECT ST_GeomFromWKT('POINT (-122.335167 47.608013)') AS seattle, ST_GeomFromWKT('POINT (-73.935242 40.730610)') as ny"
)
elif request.param == "line_crossing_dateline":
return TestDataFrameAPI.spark.sql(
"SELECT ST_GeomFromWKT('LINESTRING (179.95 30, -179.95 30)') AS line"
)
elif request.param == "array_polygons":
return TestDataFrameAPI.spark.sql(
"SELECT array(ST_GeomFromWKT('POLYGON ((-3 -3, 3 -3, 3 3, -3 3, -3 -3))'), ST_GeomFromWKT('POLYGON ((-2 1, 2 1, 2 4, -2 4, -2 1))')) as polys"
)
elif request.param == "poly_and_point":
return TestDataFrameAPI.spark.sql(
"SELECT ST_GeomFromWKT('POLYGON ((0 0, 0 1, 1 1, 1 0, 0 0))') AS poly, ST_GeomFromWKT('POINT (3 2)') AS point"
)
elif request.param == "poly_and_line":
return TestDataFrameAPI.spark.sql(
"SELECT ST_GeomFromWKT('POLYGON((2.6 12.5, 2.6 20.0, 12.6 20.0, 12.6 12.5, 2.6 12.5 ))') as poly, ST_GeomFromWKT('LINESTRING (0.5 10.7, 5.4 8.4, 10.1 10.0)') as line"
)
elif request.param == "noded_linework":
return TestDataFrameAPI.spark.sql(
"SELECT ST_GeomFromWKT('GEOMETRYCOLLECTION (LINESTRING (2 0, 2 1, 2 2), LINESTRING (2 2, 2 3, 2 4), LINESTRING (0 2, 1 2, 2 2), LINESTRING (2 2, 3 2, 4 2), LINESTRING (0 2, 1 3, 2 4), LINESTRING (2 4, 3 3, 4 2))') as geom"
)
elif request.param == "linestringm_and_point":
return TestDataFrameAPI.spark.sql(
"SELECT ST_GeomFromWKT('LINESTRING M (0 0 0, 2 0 2, 4 0 4)') as linem, ST_GeomFromWKT('POINT (1 1)') as point"
)
raise ValueError(f"Invalid base_df name passed: {request.param}")
def _id_test_configuration(val):
if isinstance(val, Callable):
return val.__name__
elif isinstance(val, Tuple):
return f"{val}"
elif isinstance(val, dict):
return f"{val}"
return val
@pytest.mark.parametrize(
"func,args,base_df,post_process,expected_result",
test_configurations,
ids=_id_test_configuration,
indirect=["base_df"],
)
def test_dataframe_function(
self, func, args, base_df, post_process, expected_result
):
args = [arg() if isinstance(arg, Callable) else arg for arg in args]
if len(args) == 1:
df = base_df.select(func(args[0]).alias("geom"))
else:
df = base_df.select(func(*args).alias("geom"))
if post_process:
df = df.selectExpr(f"{post_process} AS geom")
actual_result = df.collect()[0][0]
if isinstance(actual_result, BaseGeometry):
self.assert_geometry_almost_equal(expected_result, actual_result)
return
elif isinstance(actual_result, Geography):
# self.assert_geometry_almost_equal(expected_result, actual_result.geometry)
return
elif isinstance(actual_result, (bytes, bytearray)):
actual_result = actual_result.hex()
elif isinstance(actual_result, Row):
actual_result = {
k: v.wkt if isinstance(v, BaseGeometry) else v
for k, v in actual_result.asDict().items()
}
elif isinstance(actual_result, list):
actual_result = sorted(
[x.wkt if isinstance(x, BaseGeometry) else x for x in actual_result]
)
assert actual_result == expected_result
@pytest.mark.parametrize(
"func,args", wrong_type_configurations, ids=_id_test_configuration
)
def test_call_function_with_wrong_type(self, func, args):
with pytest.raises(
ValueError,
match=f"Incorrect argument type: [A-Za-z_0-9]+ for {func.__name__} should be [A-Za-z0-9\\[\\]_, ]+ but received [A-Za-z0-9_]+.",
):
func(*args)
def test_multi_thread(self):
df = self.spark.range(0, 100)
def run_spatial_query():
result = df.select(
stf.ST_Buffer(stc.ST_Point("id", f.col("id") + 1), 1.0).alias("geom")
).collect()
assert len(result) == 100
# Create and run 4 threads
with concurrent.futures.ThreadPoolExecutor(max_workers=4) as executor:
futures = [executor.submit(run_spatial_query) for _ in range(4)]
concurrent.futures.wait(futures)
for future in futures:
future.result()
@pytest.mark.skipif(
os.getenv("SPARK_REMOTE") is not None and pyspark.__version__ < "4.0.0",
reason="DBSCAN requires checkpoint directory which is not available in Spark Connect mode before Spark 4.0.0",
)
def test_dbscan(self):
df = self.spark.createDataFrame([{"id": 1, "x": 2, "y": 3}]).withColumn(
"geometry", f.expr("ST_Point(x, y)")
)
df.withColumn("dbscan", ST_DBSCAN("geometry", 1.0, 2, False)).collect()
@pytest.mark.skipif(
os.getenv("SPARK_REMOTE") is not None and pyspark.__version__ < "4.0.0",
reason="LOF requires checkpoint directory which is not available in Spark Connect mode before Spark 4.0.0",
)
def test_lof(self):
df = self.spark.createDataFrame([{"id": 1, "x": 2, "y": 3}]).withColumn(
"geometry", f.expr("ST_Point(x, y)")
)
df.withColumn(
"localOutlierFactor", ST_LocalOutlierFactor("geometry", 2, False)
).collect()
def test_expand_address_df_api(self):
input_df = (
self.spark.range(1)
.selectExpr(
"'781 Franklin Ave Crown Heights Brooklyn NY 11216 USA' as address"
)
.cache()
) # cache to avoid Constant Folding Optimization
# Actually running downloads the model and is very expensive, so we just check the plan
# Checking the plan should allow us to verify that the function is correctly registered
assert input_df.select(
ExpandAddress("address").alias("normalized")
).sameSemantics(
input_df.select(f.expr("ExpandAddress(address)").alias("normalized"))
)
input_df.unpersist()
def test_parse_address_df_api(self):
input_df = (
self.spark.range(1)
.selectExpr(
"'781 Franklin Ave Crown Heights Brooklyn NY 11216 USA' as address"
)
.cache()
) # cache to avoid Constant Folding Optimization
# Actually running downloads the model and is very expensive, so we just check the plan
# Checking the plan should allow us to verify that the function is correctly registered
assert input_df.select(
ParseAddress(f.col("address")).alias("parsed")
).sameSemantics(
input_df.select(f.expr("ParseAddress(address)").alias("parsed"))
)
input_df.unpersist()