Skip to content

Commit d73c826

Browse files
committed
Merge branch 'dev'
2 parents 665aa64 + f6ac6ed commit d73c826

File tree

7 files changed

+107
-27
lines changed

7 files changed

+107
-27
lines changed

README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -76,7 +76,7 @@ The actual measurement performance of BigShape is up to 100 times faster than th
7676

7777

7878
## install
79-
The latest version is `1.4.0`
79+
The latest version is `1.4.2`
8080

8181
maven import in your project
8282
```

README_zh.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -76,7 +76,7 @@ System.out.println(bigShape.intersects(tx, s1));//利用BigShape来做空间关
7676

7777

7878
## install
79-
The latest version is `1.4.0`
79+
The latest version is `1.4.2`
8080

8181
maven import in your project
8282
```

pom.xml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@
1212
</properties>
1313
<groupId>org.wowtools</groupId>
1414
<artifactId>neo4j-rtree</artifactId>
15-
<version>1.4.0</version>
15+
<version>1.4.2</version>
1616
<name>neo4j-rtree</name>
1717

1818
<description>a spatial index for neo4j 4.x.</description>

src/main/java/org/wowtools/neo4j/rtree/bigshape/BigShapeManager.java

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -51,16 +51,16 @@ public class BigShapeManager {
5151
public static BigShape get(GraphDatabaseService database, String id) {
5252
String indexName = indexNamePrefix + id;
5353
int maxNodeReferences;
54-
int geometryCacheSize = 256;//TODO 改为传入或动态获取
54+
int nodeValueCacheSize = 256;//TODO 改为动态获取或传入
5555
try (Transaction tx = database.beginTx()) {
5656
Node rootNode = tx.findNode(Constant.RtreeLabel.ReferenceNode, Constant.RtreeProperty.indexName, indexName);
5757
if (null == rootNode) {
5858
throw new RuntimeException("index (" + indexName + ") is nonexistent");
5959
}
6060
maxNodeReferences = (int) rootNode.getProperty(Constant.RtreeProperty.maxNodeReferences);
6161
}
62-
RTreeIndex rTreeIndex = new RTreeIndex(indexName, keyFieldName, database, new BigShapeReadEnvelopeDecoder(), maxNodeReferences, geometryCacheSize, false);
63-
BigShape bigShape = new BigShape(rTreeIndex);
62+
RTreeIndex rTreeIndex = new RTreeIndex(indexName, keyFieldName, database, new BigShapeReadEnvelopeDecoder(), maxNodeReferences, 0, false);
63+
BigShape bigShape = new BigShape(rTreeIndex, nodeValueCacheSize);
6464
return bigShape;
6565
}
6666

src/main/java/org/wowtools/neo4j/rtree/bigshape/pojo/BigShape.java

Lines changed: 35 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -4,19 +4,21 @@
44
import org.locationtech.jts.geom.GeometryFactory;
55
import org.locationtech.jts.geom.Point;
66
import org.locationtech.jts.io.ParseException;
7-
import org.locationtech.jts.io.WKBReader;
87
import org.neo4j.graphdb.Direction;
98
import org.neo4j.graphdb.Node;
109
import org.neo4j.graphdb.Relationship;
1110
import org.neo4j.graphdb.Transaction;
11+
import org.wowtools.common.utils.LruCache;
1212
import org.wowtools.neo4j.rtree.Constant;
1313
import org.wowtools.neo4j.rtree.bigshape.BigShapeManager;
1414
import org.wowtools.neo4j.rtree.spatial.RTreeIndex;
1515
import org.wowtools.neo4j.rtree.util.BboxIntersectUtil;
1616
import org.wowtools.neo4j.rtree.util.GeometryBbox;
17+
import org.wowtools.neo4j.rtree.util.WkbReaderManager;
1718

1819
import java.util.ArrayDeque;
1920
import java.util.Deque;
21+
import java.util.Map;
2022

2123
import static org.wowtools.neo4j.rtree.util.BboxIntersectUtil.bboxIntersect;
2224

@@ -28,9 +30,11 @@
2830
*/
2931
public class BigShape {
3032
private final RTreeIndex rTreeIndex;
33+
private final int nodeValueCacheSize;
3134

32-
public BigShape(RTreeIndex rTreeIndex) {
35+
public BigShape(RTreeIndex rTreeIndex, int nodeValueCacheSize) {
3336
this.rTreeIndex = rTreeIndex;
37+
this.nodeValueCacheSize = nodeValueCacheSize;
3438
}
3539

3640
// /**
@@ -54,9 +58,9 @@ public BigShape(RTreeIndex rTreeIndex) {
5458
public boolean intersects(Transaction tx, Geometry g) {
5559
final IntersectsJudge intersectsJudge;
5660
if (g instanceof Point) {
57-
intersectsJudge = new PointIntersectsJudge(g);
61+
intersectsJudge = new PointIntersectsJudge(g, nodeValueCacheSize);
5862
} else {
59-
intersectsJudge = new OtherIntersectsJudge(g);
63+
intersectsJudge = new OtherIntersectsJudge(g, nodeValueCacheSize);
6064
}
6165
//FIXME 这里由于找到一个相交对象即可return,所以未复用RtreeTraverser的方法,后续有相同场景的话抽取公共代码
6266
Node rtreeNode = rTreeIndex.getIndexRoot(tx);
@@ -80,8 +84,7 @@ public boolean intersects(Transaction tx, Geometry g) {
8084
//若有下级对象节点,返回结果
8185
for (Relationship relationship : rtreeNode.getRelationships(Direction.OUTGOING, Constant.Relationship.RTREE_REFERENCE)) {
8286
Node objNode = relationship.getEndNode();
83-
Object value = objNode.getProperty(BigShapeManager.keyFieldName);
84-
if (intersectsJudge.judge(value)) {
87+
if (intersectsJudge.judge(objNode)) {
8588
return true;//有一个相交即可直接返回
8689
}
8790
}
@@ -96,31 +99,42 @@ public boolean intersects(Transaction tx, Geometry g) {
9699
private static abstract class IntersectsJudge {
97100

98101
protected final Geometry geometry;
99-
protected final WKBReader wkbReader = new WKBReader();
100102
protected final double[] geoBbox;
103+
protected final Map<Long, Object> cache;
101104

102-
public IntersectsJudge(Geometry geometry) {
105+
public IntersectsJudge(Geometry geometry, int cacheSize) {
103106
this.geometry = geometry;
104107
geoBbox = GeometryBbox.getBbox(geometry).toDoubleArray();
108+
cache = LruCache.buildCache(cacheSize, 32);
105109
}
106110

107-
public boolean judge(Object value) {
111+
public boolean judge(Node node) {
112+
Object value = cache.get(node.getId());
113+
if (null == value) {
114+
value = node.getProperty(BigShapeManager.keyFieldName);
115+
if (value instanceof byte[]) {
116+
try {
117+
value = WkbReaderManager.get().read((byte[]) value);
118+
} catch (ParseException e) {
119+
throw new RuntimeException(e);
120+
}
121+
}
122+
cache.put(node.getId(), value);
123+
}
124+
return judgeValue(value);
125+
}
126+
127+
protected boolean judgeValue(Object value) {
108128
if (value instanceof double[]) {//bbox
109129
return judgeBbox((double[]) value);
110130
} else {//wkb
111-
return judgeWkb((byte[]) value);
131+
return judgeGeometry((Geometry) value);
112132
}
113133
}
114134

115135
abstract boolean judgeBbox(double[] bbox);
116136

117-
boolean judgeWkb(byte[] wkb) {
118-
Geometry geometry;
119-
try {
120-
geometry = wkbReader.read(wkb);
121-
} catch (ParseException e) {
122-
throw new RuntimeException(e);
123-
}
137+
protected boolean judgeGeometry(Geometry geometry) {
124138
// double[] gb = GeometryBbox.getBbox(geometry).toDoubleArray();
125139
// if(!BboxIntersectUtil.bboxIntersect(gb,geoBbox)){
126140
// return false;
@@ -137,8 +151,8 @@ private static class PointIntersectsJudge extends IntersectsJudge {
137151
private final double x;
138152
private final double y;
139153

140-
public PointIntersectsJudge(Geometry geometry) {
141-
super(geometry);
154+
public PointIntersectsJudge(Geometry geometry, int cacheSize) {
155+
super(geometry, cacheSize);
142156
Point point = (Point) geometry;
143157
x = point.getX();
144158
y = point.getY();
@@ -157,8 +171,8 @@ boolean judgeBbox(double[] bbox) {
157171
private static class OtherIntersectsJudge extends IntersectsJudge {
158172
private final GeometryFactory geometryFactory = new GeometryFactory();
159173

160-
public OtherIntersectsJudge(Geometry geometry) {
161-
super(geometry);
174+
public OtherIntersectsJudge(Geometry geometry, int cacheSize) {
175+
super(geometry, cacheSize);
162176
}
163177

164178
@Override
Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
package org.wowtools.neo4j.rtree.util;
2+
3+
import org.locationtech.jts.io.WKBReader;
4+
5+
/**
6+
* WkbReader的ThreadLocal获取器
7+
*
8+
* @author liuyu
9+
* @date 2020/11/27
10+
*/
11+
public class WkbReaderManager {
12+
private static final ThreadLocal<WKBReader> wkbReaderThreadLocal = new ThreadLocal<>();
13+
14+
public static WKBReader get() {
15+
WKBReader wkbReader = wkbReaderThreadLocal.get();
16+
if (null == wkbReader) {
17+
wkbReader = new WKBReader();
18+
wkbReaderThreadLocal.set(wkbReader);
19+
}
20+
return wkbReader;
21+
}
22+
}
Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
package org.wowtools.neo4j.rtree.util;
2+
3+
import junit.framework.TestCase;
4+
import org.junit.Test;
5+
import org.locationtech.jts.geom.Coordinate;
6+
import org.locationtech.jts.geom.GeometryFactory;
7+
import org.locationtech.jts.io.ParseException;
8+
import org.locationtech.jts.io.WKBReader;
9+
import org.locationtech.jts.io.WKBWriter;
10+
11+
public class WkbReaderManagerTest extends TestCase {
12+
13+
private volatile boolean flag;
14+
@Test
15+
public void test() {
16+
test1();
17+
}
18+
19+
public void test1(){
20+
//1、测试单个wkbreader多线程环境,应该会抛异常
21+
WKBReader wkbReader = new WKBReader();
22+
for (int i = 0; i < 500; i++) {
23+
final double d = i;
24+
new Thread(()->{
25+
byte[] wkb = new WKBWriter().write(new GeometryFactory().createPoint(new Coordinate(d, d)));
26+
try {
27+
wkbReader.read(wkb);
28+
} catch (Exception e) {
29+
// e.printStackTrace();
30+
flag = true;
31+
}
32+
}).start();
33+
34+
}
35+
try {
36+
Thread.sleep(2000);
37+
} catch (InterruptedException e) {
38+
e.printStackTrace();
39+
}
40+
if(!flag){
41+
throw new RuntimeException("wkbreader未产生多线程异常,请多次运行确认,或检查是否jts官方已优化");
42+
}
43+
}
44+
}

0 commit comments

Comments
 (0)