Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[SEDONA-666] add ST_Scale and ST_ScaleGeom #1650

Merged
merged 8 commits into from
Oct 24, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
39 changes: 39 additions & 0 deletions common/src/main/java/org/apache/sedona/common/Functions.java
Original file line number Diff line number Diff line change
Expand Up @@ -2266,6 +2266,45 @@ public static Geometry points(Geometry geometry) {
return geometry.getFactory().createMultiPointFromCoords(coordinates);
}

public static Geometry scale(Geometry geometry, double scaleX, double scaleY) {
return scaleGeom(geometry, Constructors.point(scaleX, scaleY));
}

public static Geometry scaleGeom(Geometry geometry, Geometry factor) {
return scaleGeom(geometry, factor, null);
}

public static Geometry scaleGeom(Geometry geometry, Geometry factor, Geometry origin) {
if (geometry == null || factor == null || geometry.isEmpty() || factor.isEmpty()) {
return geometry;
}

if (!factor.getGeometryType().equalsIgnoreCase(Geometry.TYPENAME_POINT)) {
throw new IllegalArgumentException("Scale factor geometry should be a Point type.");
}

Geometry resultGeom = null;
AffineTransformation scaleInstance = null;
Coordinate factorCoordinate = factor.getCoordinate();

if (origin == null || origin.isEmpty()) {
scaleInstance =
AffineTransformation.scaleInstance(factorCoordinate.getX(), factorCoordinate.getY());
resultGeom = scaleInstance.transform(geometry);
} else {
Coordinate falseOrigin = origin.getCoordinate();
scaleInstance =
AffineTransformation.scaleInstance(
factorCoordinate.getX(),
factorCoordinate.getY(),
falseOrigin.getX(),
falseOrigin.getY());
resultGeom = scaleInstance.transform(geometry);
}

return resultGeom;
}

public static Geometry rotateX(Geometry geometry, double angle) {
if (GeomUtils.isAnyGeomEmpty(geometry)) {
return geometry;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3994,6 +3994,44 @@ public void points() throws ParseException {
assertEquals("MULTIPOINT Z((0 0 1), (1 1 2), (2 2 3), (0 0 1))", result1);
}

@Test
public void scale() throws ParseException {
Geometry geom = Constructors.geomFromWKT("POLYGON ((0 0, 0 1, 1 1, 1 0, 0 0))", 0);
Geometry actual = Functions.scale(geom, 3, 2);
String expected = "POLYGON ((0 0, 0 2, 3 2, 3 0, 0 0))";
assertEquals(expected, actual.toString());

geom = Constructors.geomFromWKT("LINESTRING(0 1, 1 0)", 0);
actual = Functions.scale(geom, 10, 5);
expected = "LINESTRING (0 5, 10 0)";
assertEquals(expected, actual.toString());

geom = Constructors.geomFromWKT("POLYGON ((0 0, 0 1.5, 1.5 1.5, 1.5 0, 0 0))", 1111);
actual = Functions.scaleGeom(geom, Constructors.point(1.8, 2.1));
expected = "POLYGON ((0 0, 0 3.1500000000000004, 2.7 3.1500000000000004, 2.7 0, 0 0))";
assertEquals(expected, actual.toString());
assertEquals(1111, actual.getSRID());

actual =
Functions.scaleGeom(geom, Constructors.point(3, 2), Constructors.point(0.32959, 0.796483));
expected =
"POLYGON ((-0.6591799999999999 -0.796483, -0.6591799999999999 2.2035169999999997, 3.84082 2.2035169999999997, 3.84082 -0.796483, -0.6591799999999999 -0.796483))";
assertEquals(expected, actual.toString());

// test to check Z and M ordinate preservation
geom = Constructors.geomFromWKT("POLYGON ((0 0 1, 0 1.5 2, 1.5 1.5 2, 1.5 0 3, 0 0 1))", 0);
String actualWKT = Functions.asWKT(Functions.scale(geom, 3, 2));
expected = "POLYGON Z((0 0 1, 0 3 2, 4.5 3 2, 4.5 0 3, 0 0 1))";
assertEquals(expected, actualWKT);

geom =
Constructors.geomFromWKT(
"POLYGON ZM((0 0 1 2, 0 1.5 2 2, 1.5 1.5 2 2, 1.5 0 3 2, 0 0 1 2))", 0);
actualWKT = Functions.asWKT(Functions.scale(geom, 3, 2));
expected = "POLYGON ZM((0 0 1 2, 0 3 2 2, 4.5 3 2 2, 4.5 0 3 2, 0 0 1 2))";
assertEquals(expected, actualWKT);
}

@Test
public void rotateX() throws ParseException {
Geometry lineString = Constructors.geomFromEWKT("LINESTRING (50 160, 50 50, 100 50)");
Expand Down
73 changes: 73 additions & 0 deletions docs/api/flink/Function.md
Original file line number Diff line number Diff line change
Expand Up @@ -3430,6 +3430,79 @@ Output:
[POLYGON ((-36.609392788630245 -38.169532607255846, -36.609392706252954 -38.169532607255846, -36.609392706252954 -38.169532507473015, -36.609392788630245 -38.169532507473015, -36.609392788630245 -38.169532607255846))]
```

## ST_Scale

Introduction: This function scales the geometry to a new size by multiplying the ordinates with the corresponding scaling factors provided as parameters `scaleX` and `scaleY`.

!!!Note
This function is designed for scaling 2D geometries. While it currently doesn't support scaling the Z and M coordinates, it preserves these values during the scaling operation.

Format: `ST_Scale(geometry: Geometry, scaleX: Double, scaleY: Double)`

Since: `v1.7.0`

SQL Example:

```sql
SELECT ST_Scale(
ST_GeomFromWKT('POLYGON ((0 0, 0 1.5, 1.5 1.5, 1.5 0, 0 0))'),
3, 2
)
```

Output:

```
POLYGON ((0 0, 0 3, 4.5 3, 4.5 0, 0 0))
```

## ST_ScaleGeom

Introduction: This function scales the input geometry (`geometry`) to a new size. It does this by multiplying the coordinates of the input geometry with corresponding values from another geometry (`factor`) representing the scaling factors.

To scale the geometry relative to a point other than the true origin (e.g., scaling a polygon in place using its centroid), you can use the three-geometry variant of this function. This variant requires an additional geometry (`origin`) representing the "false origin" for the scaling operation. If no `origin` is provided, the scaling occurs relative to the true origin, with all coordinates of the input geometry simply multiplied by the corresponding scale factors.

!!!Note
This function is designed for scaling 2D geometries. While it currently doesn't support scaling the Z and M coordinates, it preserves these values during the scaling operation.

Format:

`ST_ScaleGeom(geometry: Geometry, factor: Geometry, origin: Geometry)`

`ST_ScaleGeom(geometry: Geometry, factor: Geometry)`

Since: `v1.7.0`

SQL Example:

```sql
SELECT ST_Scale(
ST_GeomFromWKT('POLYGON ((0 0, 0 1.5, 1.5 1.5, 1.5 0, 0 0))'),
ST_Point(3, 2)
)
```

Output:

```
POLYGON ((0 0, 0 3, 4.5 3, 4.5 0, 0 0))
```

SQL Example:

```sql
SELECT ST_Scale(
ST_GeomFromWKT('POLYGON ((0 0, 0 1.5, 1.5 1.5, 1.5 0, 0 0))'),
ST_Point(3, 2), ST_Point(1, 2)
)
```

Output:

```
POLYGON ((-2 -2, -2 1, 2.5 1, 2.5 -2, -2 -2))
```

## ST_SetPoint

Introduction: Replace Nth point of linestring with given point. Index is 0-based. Negative index are counted backwards, e.g., -1 is last point.
Expand Down
69 changes: 69 additions & 0 deletions docs/api/snowflake/vector-data/Function.md
Original file line number Diff line number Diff line change
Expand Up @@ -2640,6 +2640,75 @@ Output:
+------------------------------------------------------------------------------------------------------------------------------+
```

## ST_Scale

Introduction: This function scales the geometry to a new size by multiplying the ordinates with the corresponding scaling factors provided as parameters `scaleX` and `scaleY`.

!!!Note
This function is designed for scaling 2D geometries. While it currently doesn't support scaling the Z and M coordinates, it preserves these values during the scaling operation.

Format: `ST_Scale(geometry: Geometry, scaleX: Double, scaleY: Double)`

SQL Example:

```sql
SELECT ST_Scale(
ST_GeomFromWKT('POLYGON ((0 0, 0 1.5, 1.5 1.5, 1.5 0, 0 0))'),
3, 2
)
```

Output:

```
POLYGON ((0 0, 0 3, 4.5 3, 4.5 0, 0 0))
```

## ST_ScaleGeom

Introduction: This function scales the input geometry (`geometry`) to a new size. It does this by multiplying the coordinates of the input geometry with corresponding values from another geometry (`factor`) representing the scaling factors.

To scale the geometry relative to a point other than the true origin (e.g., scaling a polygon in place using its centroid), you can use the three-geometry variant of this function. This variant requires an additional geometry (`origin`) representing the "false origin" for the scaling operation. If no `origin` is provided, the scaling occurs relative to the true origin, with all coordinates of the input geometry simply multiplied by the corresponding scale factors.

!!!Note
This function is designed for scaling 2D geometries. While it currently doesn't support scaling the Z and M coordinates, it preserves these values during the scaling operation.

Format:

`ST_ScaleGeom(geometry: Geometry, factor: Geometry, origin: Geometry)`

`ST_ScaleGeom(geometry: Geometry, factor: Geometry)`

SQL Example:

```sql
SELECT ST_Scale(
ST_GeomFromWKT('POLYGON ((0 0, 0 1.5, 1.5 1.5, 1.5 0, 0 0))'),
ST_Point(3, 2)
)
```

Output:

```
POLYGON ((0 0, 0 3, 4.5 3, 4.5 0, 0 0))
```

SQL Example:

```sql
SELECT ST_Scale(
ST_GeomFromWKT('POLYGON ((0 0, 0 1.5, 1.5 1.5, 1.5 0, 0 0))'),
ST_Point(3, 2), ST_Point(1, 2)
)
```

Output:

```
POLYGON ((-2 -2, -2 1, 2.5 1, 2.5 -2, -2 -2))
```

## ST_SetPoint

Introduction: Replace Nth point of linestring with given point. Index is 0-based. Negative index are counted backwards, e.g., -1 is last point.
Expand Down
73 changes: 73 additions & 0 deletions docs/api/sql/Function.md
Original file line number Diff line number Diff line change
Expand Up @@ -3510,6 +3510,79 @@ Output:
[POLYGON ((-36.609392788630245 -38.169532607255846, -36.609392706252954 -38.169532607255846, -36.609392706252954 -38.169532507473015, -36.609392788630245 -38.169532507473015, -36.609392788630245 -38.169532607255846))]
```

## ST_Scale

Introduction: This function scales the geometry to a new size by multiplying the ordinates with the corresponding scaling factors provided as parameters `scaleX` and `scaleY`.

!!!Note
This function is designed for scaling 2D geometries. While it currently doesn't support scaling the Z and M coordinates, it preserves these values during the scaling operation.

Format: `ST_Scale(geometry: Geometry, scaleX: Double, scaleY: Double)`

Since: `v1.7.0`

SQL Example:

```sql
SELECT ST_Scale(
ST_GeomFromWKT('POLYGON ((0 0, 0 1.5, 1.5 1.5, 1.5 0, 0 0))'),
3, 2
)
```

Output:

```
POLYGON ((0 0, 0 3, 4.5 3, 4.5 0, 0 0))
```

## ST_ScaleGeom

Introduction: This function scales the input geometry (`geometry`) to a new size. It does this by multiplying the coordinates of the input geometry with corresponding values from another geometry (`factor`) representing the scaling factors.

To scale the geometry relative to a point other than the true origin (e.g., scaling a polygon in place using its centroid), you can use the three-geometry variant of this function. This variant requires an additional geometry (`origin`) representing the "false origin" for the scaling operation. If no `origin` is provided, the scaling occurs relative to the true origin, with all coordinates of the input geometry simply multiplied by the corresponding scale factors.

!!!Note
This function is designed for scaling 2D geometries. While it currently doesn't support scaling the Z and M coordinates, it preserves these values during the scaling operation.

Format:

`ST_ScaleGeom(geometry: Geometry, factor: Geometry, origin: Geometry)`

`ST_ScaleGeom(geometry: Geometry, factor: Geometry)`

Since: `v1.7.0`

SQL Example:

```sql
SELECT ST_Scale(
ST_GeomFromWKT('POLYGON ((0 0, 0 1.5, 1.5 1.5, 1.5 0, 0 0))'),
ST_Point(3, 2)
)
```

Output:

```
POLYGON ((0 0, 0 3, 4.5 3, 4.5 0, 0 0))
```

SQL Example:

```sql
SELECT ST_Scale(
ST_GeomFromWKT('POLYGON ((0 0, 0 1.5, 1.5 1.5, 1.5 0, 0 0))'),
ST_Point(3, 2), ST_Point(1, 2)
)
```

Output:

```
POLYGON ((-2 -2, -2 1, 2.5 1, 2.5 -2, -2 -2))
```

## ST_SetPoint

Introduction: Replace Nth point of linestring with given point. Index is 0-based. Negative index are counted backwards, e.g., -1 is last point.
Expand Down
2 changes: 2 additions & 0 deletions flink/src/main/java/org/apache/sedona/flink/Catalog.java
Original file line number Diff line number Diff line change
Expand Up @@ -100,6 +100,8 @@ public static UserDefinedFunction[] getFuncs() {
new Functions.ST_FlipCoordinates(),
new Functions.ST_GeoHash(),
new Functions.ST_PointOnSurface(),
new Functions.ST_Scale(),
new Functions.ST_ScaleGeom(),
new Functions.ST_ReducePrecision(),
new Functions.ST_Reverse(),
new Functions.ST_Rotate(),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1977,6 +1977,44 @@ public String eval(
}
}

public static class ST_Scale extends ScalarFunction {
@DataTypeHint(value = "RAW", bridgedTo = org.locationtech.jts.geom.Geometry.class)
public Geometry eval(
@DataTypeHint(value = "RAW", bridgedTo = org.locationtech.jts.geom.Geometry.class) Object o,
@DataTypeHint(value = "Double") Double scaleX,
@DataTypeHint(value = "Double") Double scaleY) {
Geometry geometry = (Geometry) o;
return org.apache.sedona.common.Functions.scale(geometry, scaleX, scaleY);
}
}

public static class ST_ScaleGeom extends ScalarFunction {
@DataTypeHint(value = "RAW", bridgedTo = org.locationtech.jts.geom.Geometry.class)
public Geometry eval(
@DataTypeHint(value = "RAW", bridgedTo = org.locationtech.jts.geom.Geometry.class)
Object o1,
@DataTypeHint(value = "RAW", bridgedTo = org.locationtech.jts.geom.Geometry.class)
Object o2,
@DataTypeHint(value = "RAW", bridgedTo = org.locationtech.jts.geom.Geometry.class)
Object o3) {
Geometry geometry = (Geometry) o1;
Geometry factor = (Geometry) o2;
Geometry origin = (Geometry) o3;
return org.apache.sedona.common.Functions.scaleGeom(geometry, factor, origin);
}

@DataTypeHint(value = "RAW", bridgedTo = org.locationtech.jts.geom.Geometry.class)
public Geometry eval(
@DataTypeHint(value = "RAW", bridgedTo = org.locationtech.jts.geom.Geometry.class)
Object o1,
@DataTypeHint(value = "RAW", bridgedTo = org.locationtech.jts.geom.Geometry.class)
Object o2) {
Geometry geometry = (Geometry) o1;
Geometry factor = (Geometry) o2;
return org.apache.sedona.common.Functions.scaleGeom(geometry, factor);
}
}

public static class ST_RotateX extends ScalarFunction {
@DataTypeHint(value = "RAW", bridgedTo = org.locationtech.jts.geom.Geometry.class)
public Geometry eval(
Expand Down
Loading
Loading