Skip to content

Commit

Permalink
Add new NTS translations (#851)
Browse files Browse the repository at this point in the history
- Geometry.Buffer(double, int)
- Geometry.InteriorPoint
- Geometry.OgcGeometryType
- Geometry.Union()
  • Loading branch information
EricStG authored and austindrenski committed May 21, 2019
1 parent 301fb4c commit 8575536
Show file tree
Hide file tree
Showing 4 changed files with 89 additions and 6 deletions.
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
using System.Collections.Generic;
using System.Collections.Generic;
using System.Linq.Expressions;
using GeoAPI.Geometries;
using Microsoft.EntityFrameworkCore.Query.Expressions;
Expand All @@ -18,6 +18,24 @@ public class NpgsqlNetTopologySuiteMemberTranslatorPlugin : IMemberTranslatorPlu

public class NpgsqlGeometryMemberTranslator : IMemberTranslator
{
static readonly CaseWhenClause[] _ogcGeometryTypeWhenThenList = new[]
{
new CaseWhenClause(Expression.Constant("ST_CircularString"), Expression.Constant(OgcGeometryType.CircularString)),
new CaseWhenClause(Expression.Constant("ST_CompoundCurve"), Expression.Constant(OgcGeometryType.CompoundCurve)),
new CaseWhenClause(Expression.Constant("ST_CurvePolygon"), Expression.Constant(OgcGeometryType.CurvePolygon)),
new CaseWhenClause(Expression.Constant("ST_GeometryCollection"), Expression.Constant(OgcGeometryType.GeometryCollection)),
new CaseWhenClause(Expression.Constant("ST_LineString"), Expression.Constant(OgcGeometryType.LineString)),
new CaseWhenClause(Expression.Constant("ST_MultiCurve"), Expression.Constant(OgcGeometryType.MultiCurve)),
new CaseWhenClause(Expression.Constant("ST_MultiLineString"), Expression.Constant(OgcGeometryType.MultiLineString)),
new CaseWhenClause(Expression.Constant("ST_MultiPoint"), Expression.Constant(OgcGeometryType.MultiPoint)),
new CaseWhenClause(Expression.Constant("ST_MultiPolygon"), Expression.Constant(OgcGeometryType.MultiPolygon)),
new CaseWhenClause(Expression.Constant("ST_MultiSurface"), Expression.Constant(OgcGeometryType.MultiSurface)),
new CaseWhenClause(Expression.Constant("ST_Point"), Expression.Constant(OgcGeometryType.Point)),
new CaseWhenClause(Expression.Constant("ST_Polygon"), Expression.Constant(OgcGeometryType.Polygon)),
new CaseWhenClause(Expression.Constant("ST_PolyhedralSurface"), Expression.Constant(OgcGeometryType.PolyhedralSurface)),
new CaseWhenClause(Expression.Constant("ST_Tin"), Expression.Constant(OgcGeometryType.TIN))
};

public Expression Translate(MemberExpression e)
{
var declaringType = e.Member.DeclaringType;
Expand Down Expand Up @@ -86,8 +104,13 @@ public Expression Translate(MemberExpression e)
return new SqlFunctionExpression("ST_NumInteriorRings", typeof(int), new[] { e.Expression });
case "NumPoints":
return new SqlFunctionExpression("ST_NumPoints", typeof(int), new[] { e.Expression });
case "OgcGeometryType":
return new CaseExpression(
new SqlFunctionExpression("ST_GeometryType", typeof(string), new[] { e.Expression }),
_ogcGeometryTypeWhenThenList);
case "PointOnSurface":
return new SqlFunctionExpression("ST_PointOnSurface", typeof(IPoint), new[] { e.Expression });
case "InteriorPoint":
return new SqlFunctionExpression("ST_PointOnSurface", typeof(IGeometry), new[] { e.Expression });
case "SRID":
return new SqlFunctionExpression("ST_SRID", typeof(int), new[] { e.Expression });
case "StartPoint":
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Linq.Expressions;
using System.Reflection;
using GeoAPI.Geometries;
Expand Down Expand Up @@ -43,7 +44,7 @@ public virtual Expression Translate(MethodCallExpression e, IDiagnosticsLogger<D
case "AsText":
return new SqlFunctionExpression("ST_AsText", typeof(string), new[] { e.Object });
case "Buffer":
return new SqlFunctionExpression("ST_Buffer", typeof(Geometry), new[] { e.Object, e.Arguments[0] });
return new SqlFunctionExpression("ST_Buffer", typeof(Geometry), new[] { e.Object }.Concat(e.Arguments));
case "Contains":
return new SqlFunctionExpression("ST_Contains", typeof(bool), new[] { e.Object, e.Arguments[0] });
case "ConvexHull":
Expand Down Expand Up @@ -91,7 +92,7 @@ public virtual Expression Translate(MethodCallExpression e, IDiagnosticsLogger<D
case "Touches":
return new SqlFunctionExpression("ST_Touches", typeof(bool), new[] { e.Object, e.Arguments[0] });
case "Union" when e.Arguments.Count == 0:
return null; // ST_Union() with only one parameter is an aggregate function in PostGIS
return new SqlFunctionExpression("ST_UnaryUnion", typeof(Geometry), new[] { e.Object });
case "Union" when e.Arguments.Count == 1:
return new SqlFunctionExpression("ST_Union", typeof(Geometry), new[] { e.Object, e.Arguments[0] });
case "Within":
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,15 @@ public override async Task Buffer(bool isAsync)
FROM ""PolygonEntity"" AS e");
}

public override async Task Buffer_quadrantSegments(bool isAsync)
{
await base.Buffer_quadrantSegments(isAsync);

AssertSql(
@"SELECT e.""Id"", ST_Buffer(e.""Polygon"", 1.0, 8) AS ""Buffer""
FROM ""PolygonEntity"" AS e");
}

public override async Task Centroid(bool isAsync)
{
await base.Centroid(isAsync);
Expand Down Expand Up @@ -184,11 +193,13 @@ public override async Task ToText(bool isAsync)
public override Task IsSimple(bool isAsync) => Task.CompletedTask;
public override Task IsValid(bool isAsync) => Task.CompletedTask;
public override Task Item(bool isAsync) => Task.CompletedTask;
public override Task InteriorPoint(bool isAsync) => Task.CompletedTask;
public override Task LineString_Count(bool isAsync) => Task.CompletedTask;
public override Task M(bool isAsync) => Task.CompletedTask;
public override Task NumGeometries(bool isAsync) => Task.CompletedTask;
public override Task NumInteriorRings(bool isAsync) => Task.CompletedTask;
public override Task NumPoints(bool isAsync) => Task.CompletedTask;
public override Task OgcGeometryType(bool isAsync) => Task.CompletedTask;
public override Task Overlaps(bool isAsync) => Task.CompletedTask;
public override Task PointOnSurface(bool isAsync) => Task.CompletedTask;
public override Task Relate(bool isAsync) => Task.CompletedTask;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,15 @@ public override async Task Buffer(bool isAsync)
FROM ""PolygonEntity"" AS e");
}

public override async Task Buffer_quadrantSegments(bool isAsync)
{
await base.Buffer_quadrantSegments(isAsync);

AssertSql(
@"SELECT e.""Id"", ST_Buffer(e.""Polygon"", 1.0, 8) AS ""Buffer""
FROM ""PolygonEntity"" AS e");
}

public override async Task Centroid(bool isAsync)
{
await base.Centroid(isAsync);
Expand Down Expand Up @@ -248,6 +257,15 @@ public override async Task GetPointN(bool isAsync)
FROM ""LineStringEntity"" AS e");
}

public override async Task InteriorPoint(bool isAsync)
{
await base.InteriorPoint(isAsync);

AssertSql(
@"SELECT e.""Id"", ST_PointOnSurface(e.""Polygon"") AS ""InteriorPoint"", e.""Polygon""
FROM ""PolygonEntity"" AS e");
}

public override async Task Intersection(bool isAsync)
{
await base.Intersection(isAsync);
Expand Down Expand Up @@ -393,6 +411,30 @@ public override async Task NumPoints(bool isAsync)
FROM ""LineStringEntity"" AS e");
}

public override async Task OgcGeometryType(bool isAsync)
{
await base.OgcGeometryType(isAsync);

AssertSql(
@"SELECT e.""Id"", CASE ST_GeometryType(e.""Point"")
WHEN 'ST_CircularString' THEN 8
WHEN 'ST_CompoundCurve' THEN 9
WHEN 'ST_CurvePolygon' THEN 10
WHEN 'ST_GeometryCollection' THEN 7
WHEN 'ST_LineString' THEN 2
WHEN 'ST_MultiCurve' THEN 11
WHEN 'ST_MultiLineString' THEN 5
WHEN 'ST_MultiPoint' THEN 4
WHEN 'ST_MultiPolygon' THEN 6
WHEN 'ST_MultiSurface' THEN 12
WHEN 'ST_Point' THEN 1
WHEN 'ST_Polygon' THEN 3
WHEN 'ST_PolyhedralSurface' THEN 15
WHEN 'ST_Tin' THEN 16
END AS ""OgcGeometryType""
FROM ""PointEntity"" AS e");
}

public override async Task Overlaps(bool isAsync)
{
await base.Overlaps(isAsync);
Expand Down Expand Up @@ -508,8 +550,14 @@ 1 1
FROM ""PolygonEntity"" AS e");
}

[ConditionalTheory(Skip="ST_Union() with only one parameter is an aggregate function in PostGIS")]
public override Task Union_void(bool isAsync) => null;
public override async Task Union_void(bool isAsync)
{
await base.Union_void(isAsync);

AssertSql(
@"SELECT e.""Id"", ST_UnaryUnion(e.""MultiLineString"") AS ""Union""
FROM ""MultiLineStringEntity"" AS e");
}

public override async Task Within(bool isAsync)
{
Expand Down

0 comments on commit 8575536

Please sign in to comment.