Skip to content

Commit

Permalink
空间查询支持表达式嵌套
Browse files Browse the repository at this point in the history
  • Loading branch information
codingmiao committed Jul 29, 2022
1 parent 3dee8c5 commit 17d0519
Show file tree
Hide file tree
Showing 8 changed files with 100 additions and 31 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -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) {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
package org.wowtools.giscat.vector.mbexpression;

import org.locationtech.jts.geom.GeometryFactory;

import java.util.HashMap;
import java.util.Map;

Expand All @@ -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<String, Object> params;

//取值缓存,供表达式解析用,减少重复的解析
private final Map<Object, Object> cache = new HashMap<>();

public static final Object empty = new Object();
private GeometryFactory geometryFactory = defaultGeometryFactory;

/**
* @param params 绑定参数 例如 {"$a":"hello","$b":"world"}
Expand Down Expand Up @@ -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;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -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]]
*
Expand All @@ -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;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,6 @@

/**
* 判断输入的bbox是否与要素的geometry相交(envIntersects)
* 注意,参数不支持表达式嵌套
* Syntax
* ["bboxIntersects", [xmin,ymin,xmax,ymax] or Bbox]: boolean
* 示例
Expand All @@ -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;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,6 @@

/**
* 输入geometry,若geometry与要素相交则裁剪要素的geometry并返回裁剪后的要素,若不相交则返回null
* 注意,参数不支持表达式嵌套
* Syntax
* ["geoIntersection", wkt_string or geometry]: Feature
* 示例
Expand All @@ -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;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,6 @@

/**
* 判断输入的wkt geometry是否与要素的geometry相交
* 注意,参数不支持表达式嵌套
* Syntax
* ["geoIntersects", wkt_string or geometry]: boolean
* 示例
Expand All @@ -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;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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;

Expand All @@ -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;
Expand All @@ -39,30 +42,46 @@ 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;
}
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);
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -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();
Expand All @@ -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);
Expand All @@ -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<Double> 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)\"]");
Expand All @@ -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);
Expand Down

0 comments on commit 17d0519

Please sign in to comment.