diff --git a/giscat-vector/giscat-vector-mbexpression/src/main/java/org/wowtools/giscat/vector/mbexpression/Expression.java b/giscat-vector/giscat-vector-mbexpression/src/main/java/org/wowtools/giscat/vector/mbexpression/Expression.java index e8be5dd..d4eb574 100644 --- a/giscat-vector/giscat-vector-mbexpression/src/main/java/org/wowtools/giscat/vector/mbexpression/Expression.java +++ b/giscat-vector/giscat-vector-mbexpression/src/main/java/org/wowtools/giscat/vector/mbexpression/Expression.java @@ -152,7 +152,7 @@ public ArrayList getExpressionArray() { } - protected static Object getRealValue(Feature feature, Object o, ExpressionParams expressionParams) { + public static Object getRealValue(Feature feature, Object o, ExpressionParams expressionParams) { //若结果不是表达式,即结果是具体值,检查是不是绑定变量,绑定变量返回绑定值,否则返回原值 if (!(o instanceof Expression)) { if (o instanceof String) { diff --git a/giscat-vector/giscat-vector-mbexpression/src/main/java/org/wowtools/giscat/vector/mbexpression/ExpressionParams.java b/giscat-vector/giscat-vector-mbexpression/src/main/java/org/wowtools/giscat/vector/mbexpression/ExpressionParams.java index 5372268..412da72 100644 --- a/giscat-vector/giscat-vector-mbexpression/src/main/java/org/wowtools/giscat/vector/mbexpression/ExpressionParams.java +++ b/giscat-vector/giscat-vector-mbexpression/src/main/java/org/wowtools/giscat/vector/mbexpression/ExpressionParams.java @@ -1,5 +1,7 @@ package org.wowtools.giscat.vector.mbexpression; +import org.locationtech.jts.geom.GeometryFactory; + import java.util.HashMap; import java.util.Map; @@ -10,16 +12,27 @@ * 例如,希望表达式["concat", "$a","sss"]输出结果为"$asss",则可通过传入参数{"$a":"$a"}来解决。 * 使用参数绑定可减少解析时的性能消耗。 * + * 包含一个geometryFactory对象,用于geometry对象变换相关的表达式,可根据需要通过setGeometryFactory设置自定义的geometryFactory + * * @author liuyu * @date 2022/7/28 */ public class ExpressionParams { + private static final GeometryFactory defaultGeometryFactory = new GeometryFactory(); + /** + * 空对象 用以避免实际值为null时缓存重复查询的问题 + */ + public static final Object empty = new Object(); + + /** + * 参数 + */ private final Map params; //取值缓存,供表达式解析用,减少重复的解析 private final Map cache = new HashMap<>(); - public static final Object empty = new Object(); + private GeometryFactory geometryFactory = defaultGeometryFactory; /** * @param params 绑定参数 例如 {"$a":"hello","$b":"world"} @@ -49,4 +62,12 @@ public void putCache(Object key, Object value) { public Object getCache(Object key) { return cache.get(key); } + + public GeometryFactory getGeometryFactory() { + return geometryFactory; + } + + public void setGeometryFactory(GeometryFactory geometryFactory) { + this.geometryFactory = geometryFactory; + } } diff --git a/giscat-vector/giscat-vector-mbexpression/src/main/java/org/wowtools/giscat/vector/mbexpression/spatial/BboxIntersection.java b/giscat-vector/giscat-vector-mbexpression/src/main/java/org/wowtools/giscat/vector/mbexpression/spatial/BboxIntersection.java index c422042..3af40f6 100644 --- a/giscat-vector/giscat-vector-mbexpression/src/main/java/org/wowtools/giscat/vector/mbexpression/spatial/BboxIntersection.java +++ b/giscat-vector/giscat-vector-mbexpression/src/main/java/org/wowtools/giscat/vector/mbexpression/spatial/BboxIntersection.java @@ -32,9 +32,8 @@ /** * 输入bbox,若geometry与要素相交则裁剪要素的geometry并返回裁剪后的要素,若不相交则返回null - * 注意,参数不支持表达式嵌套 * Syntax - * ["bboxIntersection", [xmin,ymin,xmax,ymax] or Bbox]: boolean + * ["bboxIntersection", [xmin,ymin,xmax,ymax] or TileClip]: boolean * 示例 * ["bboxIntersection", [90,20,92.5,21.3]] * @@ -61,12 +60,7 @@ public Feature getValue(Feature feature, ExpressionParams expressionParams) { tileClip = null; } else if (null == cache) { Object value = expressionArray.get(1); - Bbox bbox = Read.readBbox(value, expressionParams); - if (null == bbox) { - tileClip = null; - } else { - tileClip = new TileClip(bbox.xmin, bbox.ymin, bbox.xmax, bbox.ymax, gf); - } + tileClip = Read.readTileClip(feature, value, expressionParams); expressionParams.putCache(this, tileClip); } else { tileClip = (TileClip) cache; diff --git a/giscat-vector/giscat-vector-mbexpression/src/main/java/org/wowtools/giscat/vector/mbexpression/spatial/BboxIntersects.java b/giscat-vector/giscat-vector-mbexpression/src/main/java/org/wowtools/giscat/vector/mbexpression/spatial/BboxIntersects.java index a882cd8..98c241d 100644 --- a/giscat-vector/giscat-vector-mbexpression/src/main/java/org/wowtools/giscat/vector/mbexpression/spatial/BboxIntersects.java +++ b/giscat-vector/giscat-vector-mbexpression/src/main/java/org/wowtools/giscat/vector/mbexpression/spatial/BboxIntersects.java @@ -30,7 +30,6 @@ /** * 判断输入的bbox是否与要素的geometry相交(envIntersects) - * 注意,参数不支持表达式嵌套 * Syntax * ["bboxIntersects", [xmin,ymin,xmax,ymax] or Bbox]: boolean * 示例 @@ -55,7 +54,7 @@ public Boolean getValue(Feature feature, ExpressionParams expressionParams) { bbox = null; } else if (null == cache) { Object value = expressionArray.get(1); - bbox = Read.readBbox(value, expressionParams); + bbox = Read.readBbox(feature, value, expressionParams); expressionParams.putCache(this, bbox); } else { bbox = (Bbox) cache; diff --git a/giscat-vector/giscat-vector-mbexpression/src/main/java/org/wowtools/giscat/vector/mbexpression/spatial/GeoIntersection.java b/giscat-vector/giscat-vector-mbexpression/src/main/java/org/wowtools/giscat/vector/mbexpression/spatial/GeoIntersection.java index 8a10e27..510e276 100644 --- a/giscat-vector/giscat-vector-mbexpression/src/main/java/org/wowtools/giscat/vector/mbexpression/spatial/GeoIntersection.java +++ b/giscat-vector/giscat-vector-mbexpression/src/main/java/org/wowtools/giscat/vector/mbexpression/spatial/GeoIntersection.java @@ -29,7 +29,6 @@ /** * 输入geometry,若geometry与要素相交则裁剪要素的geometry并返回裁剪后的要素,若不相交则返回null - * 注意,参数不支持表达式嵌套 * Syntax * ["geoIntersection", wkt_string or geometry]: Feature * 示例 @@ -55,7 +54,7 @@ public Feature getValue(Feature feature, ExpressionParams expressionParams) { inputGeometry = null; } else if (null == cache) { Object value = expressionArray.get(1); - inputGeometry = Read.readGeometry(value, expressionParams); + inputGeometry = Read.readGeometry(feature, value, expressionParams); expressionParams.putCache(this, inputGeometry); } else { inputGeometry = (Geometry) cache; diff --git a/giscat-vector/giscat-vector-mbexpression/src/main/java/org/wowtools/giscat/vector/mbexpression/spatial/GeoIntersects.java b/giscat-vector/giscat-vector-mbexpression/src/main/java/org/wowtools/giscat/vector/mbexpression/spatial/GeoIntersects.java index 7e0cb93..cc7cde4 100644 --- a/giscat-vector/giscat-vector-mbexpression/src/main/java/org/wowtools/giscat/vector/mbexpression/spatial/GeoIntersects.java +++ b/giscat-vector/giscat-vector-mbexpression/src/main/java/org/wowtools/giscat/vector/mbexpression/spatial/GeoIntersects.java @@ -29,7 +29,6 @@ /** * 判断输入的wkt geometry是否与要素的geometry相交 - * 注意,参数不支持表达式嵌套 * Syntax * ["geoIntersects", wkt_string or geometry]: boolean * 示例 @@ -55,7 +54,7 @@ public Boolean getValue(Feature feature, ExpressionParams expressionParams) { inputGeometry = null; } else if (null == cache) { Object value = expressionArray.get(1); - inputGeometry = Read.readGeometry(value, expressionParams); + inputGeometry = Read.readGeometry(feature, value, expressionParams); expressionParams.putCache(this, inputGeometry); } else { inputGeometry = (Geometry) cache; diff --git a/giscat-vector/giscat-vector-mbexpression/src/main/java/org/wowtools/giscat/vector/mbexpression/spatial/Read.java b/giscat-vector/giscat-vector-mbexpression/src/main/java/org/wowtools/giscat/vector/mbexpression/spatial/Read.java index 51dac0d..81412df 100644 --- a/giscat-vector/giscat-vector-mbexpression/src/main/java/org/wowtools/giscat/vector/mbexpression/spatial/Read.java +++ b/giscat-vector/giscat-vector-mbexpression/src/main/java/org/wowtools/giscat/vector/mbexpression/spatial/Read.java @@ -4,7 +4,10 @@ import org.locationtech.jts.io.ParseException; import org.locationtech.jts.io.WKTReader; import org.wowtools.giscat.util.analyse.Bbox; +import org.wowtools.giscat.util.analyse.TileClip; +import org.wowtools.giscat.vector.mbexpression.Expression; import org.wowtools.giscat.vector.mbexpression.ExpressionParams; +import org.wowtools.giscat.vector.pojo.Feature; import java.util.ArrayList; @@ -18,11 +21,11 @@ class Read { private static final WKTReader wktReader = new WKTReader(); - public static Geometry readGeometry(Object value, ExpressionParams expressionParams) { + public static Geometry readGeometry(Feature feature,Object value, ExpressionParams expressionParams) { if (null == value) { return null; } - value = getValue(value, expressionParams); + value = Expression.getRealValue(feature, value, expressionParams); Geometry inputGeometry; if (value instanceof String) { String wkt = (String) value; @@ -39,16 +42,17 @@ public static Geometry readGeometry(Object value, ExpressionParams expressionPar return inputGeometry; } - public static Bbox readBbox(Object value, ExpressionParams expressionParams) { + public static Bbox readBbox(Feature feature, Object value, ExpressionParams expressionParams) { if (null == value) { return null; } + value = Expression.getRealValue(feature, value, expressionParams); if (value instanceof ArrayList) { ArrayList list = (ArrayList) value; - return new Bbox(((Number) getValue(list.get(0), expressionParams)).doubleValue(), - ((Number) getValue(list.get(1), expressionParams)).doubleValue(), - ((Number) getValue(list.get(2), expressionParams)).doubleValue(), - ((Number) getValue(list.get(3), expressionParams)).doubleValue()); + return new Bbox(((Number) Expression.getRealValue(feature, list.get(0), expressionParams)).doubleValue(), + ((Number) Expression.getRealValue(feature, list.get(1), expressionParams)).doubleValue(), + ((Number) Expression.getRealValue(feature, list.get(2), expressionParams)).doubleValue(), + ((Number) Expression.getRealValue(feature, list.get(3), expressionParams)).doubleValue()); } if (value instanceof Bbox) { return (Bbox) value; @@ -56,13 +60,28 @@ public static Bbox readBbox(Object value, ExpressionParams expressionParams) { throw new RuntimeException("未知的Bbox数据类型 " + value); } - private static Object getValue(Object o, ExpressionParams expressionParams) { - if (o instanceof String) { - String s = (String) o; - if (s.charAt(0) == '$') { - return expressionParams.getValue(s); - } + public static TileClip readTileClip(Feature feature, Object value, ExpressionParams expressionParams) { + if (null == value) { + return null; + } + value = Expression.getRealValue(feature, value, expressionParams); + if (value instanceof ArrayList) { + ArrayList list = (ArrayList) value; + return new TileClip(((Number) Expression.getRealValue(feature, list.get(0), expressionParams)).doubleValue(), + ((Number) Expression.getRealValue(feature, list.get(1), expressionParams)).doubleValue(), + ((Number) Expression.getRealValue(feature, list.get(2), expressionParams)).doubleValue(), + ((Number) Expression.getRealValue(feature, list.get(3), expressionParams)).doubleValue(), + expressionParams.getGeometryFactory() + ); + } + if (value instanceof TileClip) { + return (TileClip) value; } - return o; + if (value instanceof Bbox) { + Bbox bbox = (Bbox) value; + return new TileClip(bbox.xmin, bbox.ymin, bbox.xmax, bbox.ymax, expressionParams.getGeometryFactory()); + } + throw new RuntimeException("未知的TileClip数据类型 " + value); } + } diff --git a/giscat-vector/giscat-vector-mbexpression/src/test/java/org/wowtools/giscat/vector/mbexpression/ExpressionTest.java b/giscat-vector/giscat-vector-mbexpression/src/test/java/org/wowtools/giscat/vector/mbexpression/ExpressionTest.java index 7589356..f8c3246 100644 --- a/giscat-vector/giscat-vector-mbexpression/src/test/java/org/wowtools/giscat/vector/mbexpression/ExpressionTest.java +++ b/giscat-vector/giscat-vector-mbexpression/src/test/java/org/wowtools/giscat/vector/mbexpression/ExpressionTest.java @@ -4,6 +4,9 @@ import org.locationtech.jts.geom.Coordinate; import org.locationtech.jts.geom.GeometryFactory; import org.locationtech.jts.geom.LineString; +import org.locationtech.jts.io.WKTReader; +import org.wowtools.giscat.util.analyse.Bbox; +import org.wowtools.giscat.util.analyse.TileClip; import org.wowtools.giscat.vector.pojo.Feature; import java.util.ArrayList; @@ -237,7 +240,8 @@ public void math() { } @org.junit.Test - public void spatial() { + public void spatial() throws Exception { + WKTReader wktReader = new WKTReader(); Feature feature; //bboxIntersection feature = buildTestFeature(); @@ -249,6 +253,11 @@ public void spatial() { , new ExpressionParams(Map.of("$1", 15, "$2", 15, "$3", 16, "$4", 16))); Assert.assertEquals("LINESTRING (15 15, 16 16)", feature.getGeometry().toText()); + feature = buildTestFeature(); + feature = (Feature) getValue(feature, "[\"bboxIntersection\",\"$1\"]" + ,new ExpressionParams(Map.of("$1",new TileClip(15,15,16,16,new GeometryFactory())))); + Assert.assertEquals("LINESTRING (15 15, 16 16)", feature.getGeometry().toText()); + feature = buildTestFeature(); feature = (Feature) getValue(feature, "[\"bboxIntersection\",[0,0,5,5]]"); Assert.assertEquals(null, feature); @@ -260,6 +269,30 @@ public void spatial() { Assert.assertEquals(false, getValue(feature, "[\"bboxIntersects\",[0,0,5,5]]") ); + + Assert.assertEquals(true, + getValue(feature, "[\"bboxIntersects\",[\"$1\",\"$2\",\"$3\",\"$4\"]]", + new ExpressionParams(Map.of("$1",0,"$2",0,"$3",50,"$4",50)) + ) + ); + + ArrayList list = new ArrayList<>(); + list.add(0d); + list.add(0d); + list.add(50d); + list.add(50d); + Assert.assertEquals(true, + getValue(feature, "[\"bboxIntersects\",\"$1\"]", + new ExpressionParams(Map.of("$1",list)) + ) + ); + + Assert.assertEquals(true, + getValue(feature, "[\"bboxIntersects\",\"$1\"]", + new ExpressionParams(Map.of("$1",new Bbox(0,0,50,50))) + ) + ); + //geoIntersection feature = buildTestFeature(); feature = (Feature) getValue(feature, "[\"geoIntersection\",\"LINESTRING(0 0,16 16)\"]"); @@ -270,6 +303,11 @@ public void spatial() { new ExpressionParams(Map.of("$1", "LINESTRING(0 0,16 16)"))); Assert.assertEquals("LINESTRING (10 10, 16 16)", feature.getGeometry().toText()); + feature = buildTestFeature(); + feature = (Feature) getValue(feature, "[\"geoIntersection\",\"$1\"]", + new ExpressionParams(Map.of("$1", wktReader.read("LINESTRING(0 0,16 16)")))); + Assert.assertEquals("LINESTRING (10 10, 16 16)", feature.getGeometry().toText()); + feature = buildTestFeature(); feature = (Feature) getValue(feature, "[\"geoIntersection\",\"LINESTRING(0 0,1 1)\"]"); Assert.assertEquals(null, feature);