This is an automated email from the ASF dual-hosted git repository.

jiayu pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/sedona.git


The following commit(s) were added to refs/heads/master by this push:
     new e6f112c4 [SEDONA-313] Refactor ST_Affine (#875)
e6f112c4 is described below

commit e6f112c48010032dbc4404f0b1239043df0c3253
Author: Nilesh Gajwani <[email protected]>
AuthorDate: Tue Jun 27 22:01:53 2023 -0700

    [SEDONA-313] Refactor ST_Affine (#875)
---
 .../java/org/apache/sedona/common/Functions.java   |  9 +++--
 .../org/apache/sedona/common/utils/GeomUtils.java  |  4 +--
 .../org/apache/sedona/common/FunctionsTest.java    | 19 +++++-----
 docs/api/flink/Function.md                         | 10 +++---
 docs/api/sql/Function.md                           |  8 ++---
 .../apache/sedona/flink/expressions/Functions.java |  6 ++--
 .../java/org/apache/sedona/flink/FunctionTest.java | 14 ++++++++
 python/sedona/sql/st_functions.py                  |  5 ++-
 python/tests/sql/test_dataframe_api.py             |  1 +
 .../sql/sedona_sql/expressions/Functions.scala     |  2 ++
 .../expressions/InferredExpression.scala           | 41 ++++++++++++++++++++++
 .../sql/sedona_sql/expressions/st_functions.scala  |  8 ++---
 .../apache/sedona/sql/dataFrameAPITestScala.scala  |  2 +-
 .../org/apache/sedona/sql/functionTestScala.scala  |  4 +--
 14 files changed, 95 insertions(+), 38 deletions(-)

diff --git a/common/src/main/java/org/apache/sedona/common/Functions.java 
b/common/src/main/java/org/apache/sedona/common/Functions.java
index 78f237fb..be32113f 100644
--- a/common/src/main/java/org/apache/sedona/common/Functions.java
+++ b/common/src/main/java/org/apache/sedona/common/Functions.java
@@ -36,7 +36,6 @@ import org.locationtech.jts.operation.valid.IsSimpleOp;
 import org.locationtech.jts.operation.valid.IsValidOp;
 import org.locationtech.jts.precision.GeometryPrecisionReducer;
 import org.locationtech.jts.simplify.TopologyPreservingSimplifier;
-import org.locationtech.jts.algorithm.distance.DiscreteHausdorffDistance;
 import org.opengis.referencing.FactoryException;
 import org.opengis.referencing.NoSuchAuthorityCodeException;
 import org.opengis.referencing.crs.CoordinateReferenceSystem;
@@ -913,17 +912,17 @@ public class Functions {
         return geometry;
     }
 
-    public static Geometry affine(Geometry geometry, double a, double b, 
double d, double e, double xOff, double yOff, double c,
-                                  double f, double g, double h, double i, 
double zOff) {
+    public static Geometry affine(Geometry geometry, double a, double b, 
double c, double d, double e, double f, double g, double h, double i, double 
xOff, double yOff,
+                                  double zOff) {
         if (!geometry.isEmpty()) {
-            GeomUtils.affineGeom(geometry, a, b, d, e, xOff, yOff, c, f, g, h, 
i, zOff);
+            GeomUtils.affineGeom(geometry, a, b, c, d, e, f, g, h, i, xOff, 
yOff, zOff);
         }
         return geometry;
     }
 
     public static Geometry affine(Geometry geometry, double a, double b, 
double d, double e, double xOff, double yOff) {
         if (!geometry.isEmpty()) {
-            GeomUtils.affineGeom(geometry, a, b, d, e, xOff, yOff, null, null, 
null, null, null, null);
+            GeomUtils.affineGeom(geometry, a, b, null, d, e, null, null, null, 
null, xOff, yOff, null);
         }
         return geometry;
     }
diff --git a/common/src/main/java/org/apache/sedona/common/utils/GeomUtils.java 
b/common/src/main/java/org/apache/sedona/common/utils/GeomUtils.java
index 9c723d91..2960c779 100644
--- a/common/src/main/java/org/apache/sedona/common/utils/GeomUtils.java
+++ b/common/src/main/java/org/apache/sedona/common/utils/GeomUtils.java
@@ -454,8 +454,8 @@ public class GeomUtils {
             geometry.geometryChanged();
         }
     }
-    public static void affineGeom(Geometry geometry, Double a, Double b, 
Double d, Double e, Double xOff, Double yOff, Double c,
-                                  Double f, Double g, Double h, Double i, 
Double zOff) {
+    public static void affineGeom(Geometry geometry, Double a, Double b, 
Double c, Double d, Double e, Double f, Double g, Double h, Double i, Double 
xOff, Double yOff,
+                                  Double zOff) {
         Coordinate[] coordinates = geometry.getCoordinates();
         for (Coordinate currCoordinate : coordinates) {
             double x = currCoordinate.getX(), y = currCoordinate.getY(), z = 
Double.isNaN(currCoordinate.getZ()) ? 0 : currCoordinate.getZ();
diff --git a/common/src/test/java/org/apache/sedona/common/FunctionsTest.java 
b/common/src/test/java/org/apache/sedona/common/FunctionsTest.java
index 7e72e808..5f656523 100644
--- a/common/src/test/java/org/apache/sedona/common/FunctionsTest.java
+++ b/common/src/test/java/org/apache/sedona/common/FunctionsTest.java
@@ -15,7 +15,6 @@ package org.apache.sedona.common;
 
 import com.google.common.geometry.S2CellId;
 import com.google.common.math.DoubleMath;
-import com.sun.org.apache.xpath.internal.operations.Mult;
 import org.apache.sedona.common.sphere.Haversine;
 import org.apache.sedona.common.sphere.Spheroid;
 import org.apache.sedona.common.utils.GeomUtils;
@@ -1037,7 +1036,7 @@ public class FunctionsTest {
     public void affineEmpty3D() {
         LineString emptyLineString = GEOMETRY_FACTORY.createLineString();
         String expected = emptyLineString.toText();
-        String actual = Functions.affine(emptyLineString, 1.0, 1.0, 2.0, 3.0, 
5.0, 6.0, 2.0, 3.0, 4.0, 4.0, 5.0, 6.0).toText();
+        String actual = Functions.affine(emptyLineString, 1.0, 1.0, 4.0, 2.0, 
2.0, 4.0, 5.0, 5.0, 6.0, 3.0, 3.0, 6.0).toText();
         assertEquals(expected, actual);
     }
 
@@ -1052,8 +1051,8 @@ public class FunctionsTest {
    @Test
     public void affine3DGeom2D() {
         LineString lineString = 
GEOMETRY_FACTORY.createLineString(coordArray(1, 0, 1, 1, 1, 2));
-        String expected = GEOMETRY_FACTORY.createLineString(coordArray(6, 8, 
7, 11, 8, 14)).toText();
-        String actual = Functions.affine(lineString, 1.0, 1.0, 2.0, 3.0, 5.0, 
6.0, 2.0, 3.0, 4.0, 4.0, 5.0, 6.0).toText();
+        String expected = GEOMETRY_FACTORY.createLineString(coordArray(4, 5, 
5, 7, 6, 9)).toText();
+        String actual = Functions.affine(lineString, 1.0, 1.0, 4.0, 2.0, 2.0, 
4.0, 5.0, 5.0, 6.0, 3.0, 3.0, 6.0).toText();
         assertEquals(expected, actual);
     }
 
@@ -1061,8 +1060,8 @@ public class FunctionsTest {
     public void affine3DGeom3D() {
         WKTWriter wktWriter = new WKTWriter(3);
         LineString lineString = 
GEOMETRY_FACTORY.createLineString(coordArray3d(1, 0, 1, 1, 1, 2, 1, 2, 2));
-        String expected = 
wktWriter.write(GEOMETRY_FACTORY.createLineString(coordArray3d(8, 11, 15, 11, 
17, 24, 12, 20, 28)));
-        String actual = wktWriter.write(Functions.affine(lineString, 1.0, 1.0, 
2.0, 3.0, 5.0, 6.0, 2.0, 3.0, 4.0, 4.0, 5.0, 6.0));
+        String expected = 
wktWriter.write(GEOMETRY_FACTORY.createLineString(coordArray3d(8, 9, 17, 13, 
15, 28, 14, 17, 33)));
+        String actual = wktWriter.write(Functions.affine(lineString, 1.0, 1.0, 
4.0, 2.0, 2.0, 4.0, 5.0, 5.0, 6.0, 3.0, 3.0, 6.0));
         assertEquals(expected, actual);
     }
 
@@ -1073,11 +1072,11 @@ public class FunctionsTest {
         Polygon polygon2 = GEOMETRY_FACTORY.createPolygon(coordArray3d(1, 0, 
1, 1, 1, 1, 2, 2, 2, 1, 0, 1));
         MultiPolygon multiPolygon = GEOMETRY_FACTORY.createMultiPolygon(new 
Polygon[] {polygon1, polygon2});
         Geometry geomCollection = 
GEOMETRY_FACTORY.createGeometryCollection(new Geometry[] 
{GEOMETRY_FACTORY.createGeometryCollection(new Geometry[] {point3D, 
multiPolygon})});
-        Geometry actualGeomCollection = Functions.affine(geomCollection, 1.0, 
2.0, 1.0, 2.0, 1.0, 2.0, 3.0, 3.0, 1.0, 2.0, 3.0, 3.0);
+        Geometry actualGeomCollection = Functions.affine(geomCollection, 1.0, 
2.0, 1.0, 3.0, 1.0, 2.0, 3.0, 1.0, 2.0, 2.0, 3.0, 3.0);
         WKTWriter wktWriter3D = new WKTWriter(3);
-        Point expectedPoint3D = GEOMETRY_FACTORY.createPoint(new Coordinate(7, 
8, 9));
-        Polygon expectedPolygon1 = 
GEOMETRY_FACTORY.createPolygon(coordArray3d(8, 9, 10, 10, 11, 12, 11, 12, 13, 
9, 10, 11, 8, 9, 10));
-        Polygon expectedPolygon2 = 
GEOMETRY_FACTORY.createPolygon(coordArray3d(5, 6, 7, 7, 8, 9, 13, 14, 15, 5, 6, 
7));
+        Point expectedPoint3D = GEOMETRY_FACTORY.createPoint(new Coordinate(6, 
9, 9));
+        Polygon expectedPolygon1 = 
GEOMETRY_FACTORY.createPolygon(coordArray3d(5, 10, 10,7, 11, 11, 8, 14, 14, 6, 
13, 13, 5, 10, 10));
+        Polygon expectedPolygon2 = 
GEOMETRY_FACTORY.createPolygon(coordArray3d(4, 8, 8, 6, 9, 9, 10, 15, 15, 4, 8, 
8));
         assertEquals(wktWriter3D.write(expectedPoint3D), 
wktWriter3D.write(actualGeomCollection.getGeometryN(0).getGeometryN(0)));
         assertEquals(wktWriter3D.write(expectedPolygon1), 
wktWriter3D.write(actualGeomCollection.getGeometryN(0).getGeometryN(1).getGeometryN(0)));
         assertEquals(wktWriter3D.write(expectedPolygon2), 
wktWriter3D.write(actualGeomCollection.getGeometryN(0).getGeometryN(1).getGeometryN(1)));
diff --git a/docs/api/flink/Function.md b/docs/api/flink/Function.md
index e953b5ac..fa7f7f14 100644
--- a/docs/api/flink/Function.md
+++ b/docs/api/flink/Function.md
@@ -76,7 +76,7 @@ Introduction: Apply an affine transformation to the given 
geometry.
 
 ST_Affine has 2 overloaded signatures: 
 
-`ST_Affine(geometry, a, b, d, e, xOff, yOff, c, f, g, h, i, zOff)` 
+`ST_Affine(geometry, a, b, c, d, e, f, g, h, i, xOff, yOff, zOff)` 
 
 `ST_Affine(geometry, a, b, d, e, xOff, yOff)`
 
@@ -91,12 +91,12 @@ Based on the invoked function, the following transformation 
is applied:
 
 If the given geometry is empty, the result is also empty. 
 
-Format: `ST_Affine(geometry, a, b, d, e, xOff, yOff, c, f, g, h, i, zOff)`  
+Format: `ST_Affine(geometry, a, b, c, d, e, f, g, h, i, xOff, yOff, zOff)`  
 Format: `ST_Affine(geometry, a, b, d, e, xOff, yOff)`
 
 Since: `1.5.0`
 
-Example:
+Examples:
 
 ```sql
 ST_Affine(geometry, 1, 2, 4, 1, 1, 2, 3, 2, 5, 4, 8, 3)
@@ -108,11 +108,11 @@ Output: `LINESTRING EMPTY`
 
 Input: `POLYGON ((1 0 1, 1 1 1, 2 2 2, 1 0 1))`
 
-Output: `POLYGON Z((5 8 16, 7 9 20, 13 16 37, 5 8 16))`
+Output: `POLYGON Z((9 11 11, 11 12 13, 18 16 23, 9 11 11))`
 
 Input: `POLYGON ((1 0, 1 1, 2 1, 2 0, 1 0), (1 0.5, 1 0.75, 1.5 0.75, 1.5 0.5, 
1 0.5))`
 
-Output: `POLYGON ((2 6, 4 7, 5 11, 3 10, 2 6), (3 6.5, 3.5 6.75, 4 8.75, 3.5 
8.5, 3 6.5))`
+Output: `POLYGON((5 9, 7 10, 8 11, 6 10, 5 9), (6 9.5, 6.5 9.75, 7 10.25, 6.5 
10, 6 9.5))`
 
 
 ```sql
diff --git a/docs/api/sql/Function.md b/docs/api/sql/Function.md
index 3e9f443d..a570500f 100644
--- a/docs/api/sql/Function.md
+++ b/docs/api/sql/Function.md
@@ -75,7 +75,7 @@ Introduction: Apply an affine transformation to the given 
geometry.
 
 ST_Affine has 2 overloaded signatures:
 
-`ST_Affine(geometry, a, b, d, e, xOff, yOff, c, f, g, h, i, zOff)`
+`ST_Affine(geometry, a, b, c, d, e, f, g, h, i, xOff, yOff, zOff)`
 
 `ST_Affine(geometry, a, b, d, e, xOff, yOff)`
 
@@ -90,7 +90,7 @@ Based on the invoked function, the following transformation 
is applied:
 
 If the given geometry is empty, the result is also empty.
 
-Format: `ST_Affine(geometry, a, b, d, e, xOff, yOff, c, f, g, h, i, zOff)`  
+Format: `ST_Affine(geometry, a, b, c, d, e, f, g, h, i, xOff, yOff, zOff)`  
 Format: `ST_Affine(geometry, a, b, d, e, xOff, yOff)`
 
 Since: `1.5.0`
@@ -107,11 +107,11 @@ Output: `LINESTRING EMPTY`
 
 Input: `POLYGON ((1 0 1, 1 1 1, 2 2 2, 1 0 1))`
 
-Output: `POLYGON Z((5 8 16, 7 9 20, 13 16 37, 5 8 16))`
+Output: `POLYGON Z((9 11 11, 11 12 13, 18 16 23, 9 11 11))`
 
 Input: `POLYGON ((1 0, 1 1, 2 1, 2 0, 1 0), (1 0.5, 1 0.75, 1.5 0.75, 1.5 0.5, 
1 0.5))`
 
-Output: `POLYGON ((2 6, 4 7, 5 11, 3 10, 2 6), (3 6.5, 3.5 6.75, 4 8.75, 3.5 
8.5, 3 6.5))`
+Output: `POLYGON((5 9, 7 10, 8 11, 6 10, 5 9), (6 9.5, 6.5 9.75, 7 10.25, 6.5 
10, 6 9.5))`
 
 
 ```sql
diff --git 
a/flink/src/main/java/org/apache/sedona/flink/expressions/Functions.java 
b/flink/src/main/java/org/apache/sedona/flink/expressions/Functions.java
index b8b55b12..576d668b 100644
--- a/flink/src/main/java/org/apache/sedona/flink/expressions/Functions.java
+++ b/flink/src/main/java/org/apache/sedona/flink/expressions/Functions.java
@@ -16,7 +16,6 @@ package org.apache.sedona.flink.expressions;
 import org.apache.flink.table.annotation.DataTypeHint;
 import org.apache.flink.table.functions.ScalarFunction;
 import org.locationtech.jts.geom.Geometry;
-import org.locationtech.jts.geom.GeometryCollection;
 import org.opengis.referencing.FactoryException;
 import org.opengis.referencing.operation.TransformException;
 
@@ -652,11 +651,10 @@ public class Functions {
     public static class ST_Affine extends ScalarFunction {
         @DataTypeHint(value = "RAW", bridgedTo = 
org.locationtech.jts.geom.Geometry.class)
         public Geometry eval(@DataTypeHint(value = "RAW", bridgedTo = 
Geometry.class) Object o, @DataTypeHint("Double") Double a,
-                             @DataTypeHint("Double") Double b, 
@DataTypeHint("Double") Double d, @DataTypeHint("Double") Double e, 
@DataTypeHint("Double") Double xOff, @DataTypeHint("Double") Double yOff, 
@DataTypeHint("Double") Double c,
-                             @DataTypeHint("Double") Double f, 
@DataTypeHint("Double") Double g, @DataTypeHint("Double") Double h, 
@DataTypeHint("Double") Double i,
+                             @DataTypeHint("Double") Double b, 
@DataTypeHint("Double") Double c, @DataTypeHint("Double") Double d, 
@DataTypeHint("Double") Double e, @DataTypeHint("Double") Double f, 
@DataTypeHint("Double") Double g, @DataTypeHint("Double") Double h, 
@DataTypeHint("Double") Double i, @DataTypeHint("Double") Double xOff, 
@DataTypeHint("Double") Double yOff,
                              @DataTypeHint("Double") Double zOff) {
             Geometry geometry = (Geometry) o;
-            return org.apache.sedona.common.Functions.affine(geometry, a, b, 
d, e, xOff, yOff, c, f, g, h, i, zOff);
+            return org.apache.sedona.common.Functions.affine(geometry, a, b, 
c, d, e, f, g, h, i, xOff, yOff, zOff);
         }
 
         @DataTypeHint(value = "RAW", bridgedTo = 
org.locationtech.jts.geom.Geometry.class)
diff --git a/flink/src/test/java/org/apache/sedona/flink/FunctionTest.java 
b/flink/src/test/java/org/apache/sedona/flink/FunctionTest.java
index 983004e4..22bb602b 100644
--- a/flink/src/test/java/org/apache/sedona/flink/FunctionTest.java
+++ b/flink/src/test/java/org/apache/sedona/flink/FunctionTest.java
@@ -766,6 +766,20 @@ public class FunctionTest extends TestBase{
         assertEquals(expected, actual);
     }
 
+    @Test
+    public void testAffine() {
+        Table polyTable = tableEnv.sqlQuery("SELECT ST_GeomFromWKT('POLYGON 
((1 0 1, 1 1 1, 2 2 2, 1 0 1))')" + " AS " + polygonColNames[0]);
+        Table polyTableDefault = 
polyTable.select(call(Functions.ST_Affine.class.getSimpleName(), 
$(polygonColNames[0]), 1, 2, 1, 2, 1, 
2)).as(polygonColNames[0]).select(call(Functions.ST_AsText.class.getSimpleName(),
 $(polygonColNames[0])));
+        polyTable = 
polyTable.select(call(Functions.ST_Affine.class.getSimpleName(), 
$(polygonColNames[0]), 1, 2, 4, 1, 1, 2, 3, 2, 5, 4, 8, 
3)).as(polygonColNames[0]).select(call(Functions.ST_AsText.class.getSimpleName(),
 $(polygonColNames[0])));
+        String expectedDefault = "POLYGON Z((2 3 1, 4 5 1, 7 8 2, 2 3 1))";
+        String actualDefault = (String) first(polyTableDefault).getField(0);
+        String expected = "POLYGON Z((9 11 11, 11 12 13, 18 16 23, 9 11 11))";
+        String actual = (String) first(polyTable).getField(0);
+        assertEquals(expected, actual);
+        assertEquals(expectedDefault, actualDefault);
+    }
+
+    @Test
     public void testBoundingDiagonal() {
         Table polyTable = tableEnv.sqlQuery("SELECT 
ST_BoundingDiagonal(ST_GeomFromWKT('POLYGON ((1 0, 1 1, 2 1, 2 0, 1 0))'))" +" 
AS " + polygonColNames[0]);
         polyTable = 
polyTable.select(call(Functions.ST_AsText.class.getSimpleName(), 
$(polygonColNames[0])));
diff --git a/python/sedona/sql/st_functions.py 
b/python/sedona/sql/st_functions.py
index 417be7cb..47da57ff 100644
--- a/python/sedona/sql/st_functions.py
+++ b/python/sedona/sql/st_functions.py
@@ -1340,7 +1340,9 @@ def ST_Affine(geometry: ColumnOrName, a: 
Union[ColumnOrName, float], b: Union[Co
     :param zOff: Default 0.0
     :return: Geometry with affine transformation applied
     """
-    args = (geometry, a, b, d, e, xOff, yOff, c, f, g, h, i, zOff)
+    args = (geometry, a, b, d, e, xOff, yOff)
+    if not [x for x in (c, f, g, h, i, zOff) if x is None]:
+        args = (geometry, a, b, c, d, e, f, g, h, i, xOff, yOff, zOff)
     return _call_st_function("ST_Affine", args)
 
 
@@ -1366,3 +1368,4 @@ def ST_HausdorffDistance(g1: ColumnOrName, g2: 
ColumnOrName, densityFrac: Option
     """
     args = (g1, g2, densityFrac)
     return _call_st_function("ST_HausdorffDistance", args)
+
diff --git a/python/tests/sql/test_dataframe_api.py 
b/python/tests/sql/test_dataframe_api.py
index f6419bde..4ab13eda 100644
--- a/python/tests/sql/test_dataframe_api.py
+++ b/python/tests/sql/test_dataframe_api.py
@@ -52,6 +52,7 @@ test_configurations = [
     (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_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_Area, ("geom",), "triangle_geom", "", 0.5),
diff --git 
a/sql/common/src/main/scala/org/apache/spark/sql/sedona_sql/expressions/Functions.scala
 
b/sql/common/src/main/scala/org/apache/spark/sql/sedona_sql/expressions/Functions.scala
index 4222b16d..7b79175d 100644
--- 
a/sql/common/src/main/scala/org/apache/spark/sql/sedona_sql/expressions/Functions.scala
+++ 
b/sql/common/src/main/scala/org/apache/spark/sql/sedona_sql/expressions/Functions.scala
@@ -31,6 +31,8 @@ import org.locationtech.jts.algorithm.MinimumBoundingCircle
 import org.locationtech.jts.geom._
 import 
org.apache.spark.sql.sedona_sql.expressions.InferrableFunctionConverter._
 
+import java.lang
+
 /**
   * Return the distance between two geometries.
   *
diff --git 
a/sql/common/src/main/scala/org/apache/spark/sql/sedona_sql/expressions/InferredExpression.scala
 
b/sql/common/src/main/scala/org/apache/spark/sql/sedona_sql/expressions/InferredExpression.scala
index 41f2aede..fd29123d 100644
--- 
a/sql/common/src/main/scala/org/apache/spark/sql/sedona_sql/expressions/InferredExpression.scala
+++ 
b/sql/common/src/main/scala/org/apache/spark/sql/sedona_sql/expressions/InferredExpression.scala
@@ -234,4 +234,45 @@ object InferrableFunction {
       }
     })
   }
+
+  def allowSixRightNull[R, A1, A2, A3, A4, A5, A6, A7, A8, A9, A10, A11, A12, 
A13](f: (A1, A2, A3, A4, A5, A6, A7, A8, A9, A10, A11, A12, A13) => R)
+                                                                               
   (implicit typeTag: TypeTag[(A1, A2, A3, A4, A5, A6, A7, A8, A9, A10, A11, 
A12, A13) => R]): InferrableFunction = {
+    apply(typeTag, extractors => {
+      val func = f.asInstanceOf[(Any, Any, Any, Any, Any, Any, Any, Any, Any, 
Any, Any, Any, Any) => Any]
+      val extractor1 = extractors(0)
+      val extractor2 = extractors(1)
+      val extractor3 = extractors(2)
+      val extractor4 = extractors(3)
+      val extractor5 = extractors(4)
+      val extractor6 = extractors(5)
+      val extractor7 = extractors(6)
+      val extractor8 = extractors(7)
+      val extractor9 = extractors(8)
+      val extractor10 = extractors(9)
+      val extractor11 = extractors(10)
+      val extractor12 = extractors(11)
+      val extractor13 = extractors(12)
+      input => {
+        val arg1 = extractor1(input)
+        val arg2 = extractor2(input)
+        val arg3 = extractor3(input)
+        val arg4 = extractor4(input)
+        val arg5 = extractor5(input)
+        val arg6 = extractor6(input)
+        val arg7 = extractor7(input)
+        val arg8 = extractor8(input)
+        val arg9 = extractor9(input)
+        val arg10 = extractor10(input)
+        val arg11 = extractor11(input)
+        val arg12 = extractor12(input)
+        val arg13 = extractor13(input)
+        if (arg1 != null && arg2 != null && arg3 != null && arg4 != null && 
arg5 != null && arg6 != null && arg7 != null) {
+          func(arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9, arg10, 
arg11, arg12, arg13)
+        } else {
+          null
+        }
+      }
+    })
+  }
+
 }
diff --git 
a/sql/common/src/main/scala/org/apache/spark/sql/sedona_sql/expressions/st_functions.scala
 
b/sql/common/src/main/scala/org/apache/spark/sql/sedona_sql/expressions/st_functions.scala
index b22fd84b..f74e2413 100644
--- 
a/sql/common/src/main/scala/org/apache/spark/sql/sedona_sql/expressions/st_functions.scala
+++ 
b/sql/common/src/main/scala/org/apache/spark/sql/sedona_sql/expressions/st_functions.scala
@@ -335,11 +335,11 @@ object st_functions extends DataFrameAPI {
   def ST_FrechetDistance(g1: Column, g2: Column): Column = 
wrapExpression[ST_FrechetDistance](g1, g2)
 
   def ST_FrechetDistance(g1: String, g2: String): Column = 
wrapExpression[ST_FrechetDistance](g1, g2)
-  def ST_Affine(geometry: Column, a: Column, b: Column, d: Column, e: Column, 
xOff: Column, yOff: Column, c: Column, f: Column, g: Column, h: Column, i: 
Column, zOff: Column): Column =
-    wrapExpression[ST_Affine](geometry, a, b, d, e, xOff, yOff, c, f, g, h, i, 
zOff)
+  def ST_Affine(geometry: Column, a: Column, b: Column, c: Column, d: Column, 
e: Column, f: Column, g: Column, h: Column, i: Column, xOff: Column, yOff: 
Column, zOff: Column): Column =
+    wrapExpression[ST_Affine](geometry, a, b, c, d, e, f, g, h, i, xOff, yOff, 
zOff)
 
-  def ST_Affine(geometry: String, a: Double, b: Double, d: Double, e: Double, 
xOff: Double, yOff: Double, c: Double, f: Double, g: Double, h: Double, i: 
Double, zOff: Double): Column =
-    wrapExpression[ST_Affine](geometry, a, b, d, e, xOff, yOff, c, f, g, h, i, 
zOff)
+  def ST_Affine(geometry: String, a: Double, b: Double, c: Double, d: Double, 
e: Double, f: Double, g: Double, h: Double, i: Double, xOff: Double, yOff: 
Double, zOff: Double): Column =
+    wrapExpression[ST_Affine](geometry, a, b, c, d, e, f, g, h, i, xOff, yOff, 
zOff)
 
   def ST_Affine(geometry: Column, a: Column, b: Column, d: Column, e: Column, 
xOff: Column, yOff: Column) =
     wrapExpression[ST_Affine](geometry, a, b, d, e, xOff, yOff)
diff --git 
a/sql/common/src/test/scala/org/apache/sedona/sql/dataFrameAPITestScala.scala 
b/sql/common/src/test/scala/org/apache/sedona/sql/dataFrameAPITestScala.scala
index a78a0e35..db850598 100644
--- 
a/sql/common/src/test/scala/org/apache/sedona/sql/dataFrameAPITestScala.scala
+++ 
b/sql/common/src/test/scala/org/apache/sedona/sql/dataFrameAPITestScala.scala
@@ -1013,7 +1013,7 @@ class dataFrameAPITestScala extends TestBaseScala {
 
     it("Passed ST_Affine") {
       val polyDf = sparkSession.sql("SELECT ST_GeomFromWKT('POLYGON ((2 3 1, 4 
5 1, 7 8 2, 2 3 1))') AS geom")
-      val df = polyDf.select(ST_Affine("geom", 1, 2, 3, 4, 1, 2, 3, 4, 1, 4, 
2, 1));
+      val df = polyDf.select(ST_Affine("geom", 1, 2, 3, 3, 4, 4, 1, 4, 2, 1, 
2, 1));
       val dfDefaultValue = polyDf.select(ST_Affine("geom", 1, 2, 1, 2, 1, 2))
       val wKTWriter3D = new WKTWriter(3);
       val actualGeom = df.take(1)(0).get(0).asInstanceOf[Geometry]
diff --git 
a/sql/common/src/test/scala/org/apache/sedona/sql/functionTestScala.scala 
b/sql/common/src/test/scala/org/apache/sedona/sql/functionTestScala.scala
index 762cb7b2..5754de3d 100644
--- a/sql/common/src/test/scala/org/apache/sedona/sql/functionTestScala.scala
+++ b/sql/common/src/test/scala/org/apache/sedona/sql/functionTestScala.scala
@@ -2023,10 +2023,10 @@ class functionTestScala extends TestBaseScala with 
Matchers with GeometrySample
 
   it ("should pass ST_Affine") {
     val geomTestCases = Map (
-      ("'POLYGON ((1 0 1, 1 1 1, 2 2 2, 1 0 1))'")-> ("'POLYGON Z((5 8 16, 7 9 
20, 13 16 37, 5 8 16))'", "'POLYGON Z((2 3 1, 4 5 1, 7 8 2, 2 3 1))'"),
+      ("'POLYGON ((1 0 1, 1 1 1, 2 2 2, 1 0 1))'")-> ("'POLYGON Z((9 11 11, 11 
12 13, 18 16 23, 9 11 11))'", "'POLYGON Z((2 3 1, 4 5 1, 7 8 2, 2 3 1))'"),
       ("'LINESTRING EMPTY'") -> ("'LINESTRING EMPTY'", "'LINESTRING EMPTY'"),
       ("'GEOMETRYCOLLECTION (MULTIPOLYGON (((1 0, 1 1, 2 1, 2 0, 1 0), (1 0.5, 
1 0.75, 1.5 0.75, 1.5 0.5, 1 0.5)), ((5 0, 5 5, 7 5, 7 0, 5 0))), POINT (10 
10))'")->
-                                                    ("'GEOMETRYCOLLECTION 
(MULTIPOLYGON (((2 6, 4 7, 5 11, 3 10, 2 6), (3 6.5, 3.5 6.75, 4 8.75, 3.5 8.5, 
3 6.5)), ((6 22, 16 27, 18 35, 8 30, 6 22))), POINT (31 52))'",
+                                                    ("'GEOMETRYCOLLECTION 
(MULTIPOLYGON (((5 9, 7 10, 8 11, 6 10, 5 9), (6 9.5, 6.5 9.75, 7 10.25, 6.5 
10, 6 9.5)), ((9 13, 19 18, 21 20, 11 15, 9 13))), POINT (34 28))'",
                                                     "'GEOMETRYCOLLECTION 
(MULTIPOLYGON (((2 3, 4 5, 5 6, 3 4, 2 3), (3 4, 3.5 4.5, 4 5, 3.5 4.5, 3 4)), 
((6 7, 16 17, 18 19, 8 9, 6 7))), POINT (31 32))'")
     )
     for (((geom), expectedResult) <- geomTestCases) {

Reply via email to