44import java .nio .ByteBuffer ;
55import java .util .ArrayList ;
66import java .util .Arrays ;
7+ import java .util .LinkedHashMap ;
78import java .util .List ;
9+ import java .util .Map ;
10+
11+ import com .google .uzaygezen .core .CompactHilbertCurve ;
12+ import com .google .uzaygezen .core .MultiDimensionalSpec ;
813
914import mil .nga .giat .geowave .core .index .ByteArrayUtils ;
1015import mil .nga .giat .geowave .core .index .PersistenceUtils ;
1318import mil .nga .giat .geowave .core .index .sfc .SpaceFillingCurve ;
1419import mil .nga .giat .geowave .core .index .sfc .data .MultiDimensionalNumericData ;
1520
16- import com .google .uzaygezen .core .CompactHilbertCurve ;
17- import com .google .uzaygezen .core .MultiDimensionalSpec ;
18-
1921/***
2022 * Implementation of a Compact Hilbert space filling curve
21- *
23+ *
2224 */
2325public class HilbertSFC implements
2426 SpaceFillingCurve
2527{
28+ private static class QueryCacheKey
29+ {
30+ private final double [] minsPerDimension ;
31+ private final double [] maxesPerDimension ;
32+ private final boolean overInclusiveOnEdge ;
33+ private final int maxFilteredIndexedRanges ;
34+
35+ public QueryCacheKey (
36+ final double [] minsPerDimension ,
37+ final double [] maxesPerDimension ,
38+ final boolean overInclusiveOnEdge ,
39+ final int maxFilteredIndexedRanges ) {
40+ this .minsPerDimension = minsPerDimension ;
41+ this .maxesPerDimension = maxesPerDimension ;
42+ this .overInclusiveOnEdge = overInclusiveOnEdge ;
43+ this .maxFilteredIndexedRanges = maxFilteredIndexedRanges ;
44+ }
45+
46+ @ Override
47+ public int hashCode () {
48+ final int prime = 31 ;
49+ int result = 1 ;
50+ result = (prime * result ) + maxFilteredIndexedRanges ;
51+ result = (prime * result ) + Arrays .hashCode (maxesPerDimension );
52+ result = (prime * result ) + Arrays .hashCode (minsPerDimension );
53+ result = (prime * result ) + (overInclusiveOnEdge ? 1231 : 1237 );
54+ return result ;
55+ }
56+
57+ @ Override
58+ public boolean equals (
59+ final Object obj ) {
60+ if (this == obj ) {
61+ return true ;
62+ }
63+ if (obj == null ) {
64+ return false ;
65+ }
66+ if (getClass () != obj .getClass ()) {
67+ return false ;
68+ }
69+ final QueryCacheKey other = (QueryCacheKey ) obj ;
70+ if (maxFilteredIndexedRanges != other .maxFilteredIndexedRanges ) {
71+ return false ;
72+ }
73+ if (!Arrays .equals (
74+ maxesPerDimension ,
75+ other .maxesPerDimension )) {
76+ return false ;
77+ }
78+ if (!Arrays .equals (
79+ minsPerDimension ,
80+ other .minsPerDimension )) {
81+ return false ;
82+ }
83+ if (overInclusiveOnEdge != other .overInclusiveOnEdge ) {
84+ return false ;
85+ }
86+ return true ;
87+ }
88+ }
89+
90+ private static final int MAX_CACHED_QUERIES = 500 ;
91+ private final Map <QueryCacheKey , RangeDecomposition > queryDecompositionCache = new LinkedHashMap <QueryCacheKey , RangeDecomposition >(
92+ MAX_CACHED_QUERIES + 1 ,
93+ .75F ,
94+ true ) {
95+ private static final long serialVersionUID = 1L ;
96+
97+ @ Override
98+ public boolean removeEldestEntry (
99+ final Map .Entry <QueryCacheKey , RangeDecomposition > eldest ) {
100+ return size () > MAX_CACHED_QUERIES ;
101+ }
102+ };
26103 protected CompactHilbertCurve compactHilbertCurve ;
27104 protected SFCDimensionDefinition [] dimensionDefinitions ;
28105 protected int totalPrecision ;
@@ -37,7 +114,7 @@ protected HilbertSFC() {}
37114 /***
38115 * Use the SFCFactory.createSpaceFillingCurve method - don't call this
39116 * constructor directly
40- *
117+ *
41118 */
42119 public HilbertSFC (
43120 final SFCDimensionDefinition [] dimensionDefs ) {
@@ -143,14 +220,26 @@ public RangeDecomposition decomposeRange(
143220 if (maxFilteredIndexedRanges == -1 ) {
144221 maxFilteredIndexedRanges = Integer .MAX_VALUE ;
145222 }
146- return decomposeQueryOperations .decomposeRange (
147- query .getDataPerDimension (),
148- compactHilbertCurve ,
149- dimensionDefinitions ,
150- totalPrecision ,
151- maxFilteredIndexedRanges ,
152- REMOVE_VACUUM ,
153- overInclusiveOnEdge );
223+ final QueryCacheKey key = new QueryCacheKey (
224+ query .getMinValuesPerDimension (),
225+ query .getMaxValuesPerDimension (),
226+ overInclusiveOnEdge ,
227+ maxFilteredIndexedRanges );
228+ RangeDecomposition rangeDecomp = queryDecompositionCache .get (key );
229+ if (rangeDecomp == null ) {
230+ rangeDecomp = decomposeQueryOperations .decomposeRange (
231+ query .getDataPerDimension (),
232+ compactHilbertCurve ,
233+ dimensionDefinitions ,
234+ totalPrecision ,
235+ maxFilteredIndexedRanges ,
236+ REMOVE_VACUUM ,
237+ overInclusiveOnEdge );
238+ queryDecompositionCache .put (
239+ key ,
240+ rangeDecomp );
241+ }
242+ return rangeDecomp ;
154243 }
155244
156245 protected static byte [] fitExpectedByteCount (
0 commit comments