18
18
*/
19
19
package org .elasticsearch .common .geo ;
20
20
21
- import org .apache .lucene .util .BytesRef ;
22
21
import org .elasticsearch .common .io .stream .ByteBufferStreamInput ;
23
22
import org .elasticsearch .common .io .stream .StreamInput ;
24
23
25
24
import java .io .IOException ;
26
- import java .nio . ByteBuffer ;
25
+ import java .util . Optional ;
27
26
28
27
import static org .apache .lucene .geo .GeoUtils .lineCrossesLineWithBoundary ;
29
28
30
29
public class EdgeTreeReader {
31
- final BytesRef bytesRef ;
30
+ final ByteBufferStreamInput input ;
31
+ final int startPosition ;
32
32
33
- public EdgeTreeReader (StreamInput input ) throws IOException {
34
- int treeBytesSize = input .readVInt ();
35
- this .bytesRef = input .readBytesRef (treeBytesSize );
33
+ public EdgeTreeReader (ByteBufferStreamInput input ) throws IOException {
34
+ this .startPosition = input .position ();
35
+ this .input = input ;
36
+ }
37
+
38
+ public Extent getExtent () throws IOException {
39
+ resetInputPosition ();
40
+ return new Extent (input );
36
41
}
37
42
38
43
/**
39
44
* Returns true if the rectangle query and the edge tree's shape overlap
40
45
*/
41
46
public boolean containedInOrCrosses (int minX , int minY , int maxX , int maxY ) throws IOException {
42
- return this .containsBottomLeft (minX , minY , maxX , maxY ) || this .crosses (minX , minY , maxX , maxY );
47
+ Extent extent = new Extent (minX , minY , maxX , maxY );
48
+ return this .containsBottomLeft (extent ) || this .crosses (extent );
43
49
}
44
50
45
- boolean containsBottomLeft (int minX , int minY , int maxX , int maxY ) throws IOException {
46
- ByteBufferStreamInput input = new ByteBufferStreamInput (ByteBuffer .wrap (bytesRef .bytes , bytesRef .offset , bytesRef .length ));
47
- int thisMinX = input .readInt ();
48
- int thisMinY = input .readInt ();
49
- int thisMaxX = input .readInt ();
50
- int thisMaxY = input .readInt ();
51
+ static Optional <Boolean > checkExtent (StreamInput input , Extent extent ) throws IOException {
52
+ Extent edgeExtent = new Extent (input );
51
53
52
- if (thisMinY > maxY || thisMaxX < minX || thisMaxY < minY || thisMinX > maxX ) {
53
- return false ; // tree and bbox-query are disjoint
54
+ if (edgeExtent .minY > extent .maxY || edgeExtent .maxX < extent .minX
55
+ || edgeExtent .maxY < extent .minY || edgeExtent .minX > extent .maxX ) {
56
+ return Optional .of (false ); // tree and bbox-query are disjoint
54
57
}
55
58
56
- if (minX <= thisMinX && minY <= thisMinY && maxX >= thisMaxX && maxY >= thisMaxY ) {
57
- return true ; // bbox-query fully contains tree's extent.
59
+ if (extent .minX <= edgeExtent .minX && extent .minY <= edgeExtent .minY
60
+ && extent .maxX >= edgeExtent .maxX && extent .maxY >= edgeExtent .maxY ) {
61
+ return Optional .of (true ); // bbox-query fully contains tree's extent.
58
62
}
59
-
60
- return containsBottomLeft (input , readRoot (input , input .position ()), minX , minY , maxX , maxY );
63
+ return Optional .empty ();
61
64
}
62
65
63
- public boolean crosses (int minX , int minY , int maxX , int maxY ) throws IOException {
64
- ByteBufferStreamInput input = new ByteBufferStreamInput (ByteBuffer .wrap (bytesRef .bytes , bytesRef .offset , bytesRef .length ));
65
- int thisMinX = input .readInt ();
66
- int thisMinY = input .readInt ();
67
- int thisMaxX = input .readInt ();
68
- int thisMaxY = input .readInt ();
66
+ boolean containsBottomLeft (Extent extent ) throws IOException {
67
+ resetInputPosition ();
69
68
70
- if (thisMinY > maxY || thisMaxX < minX || thisMaxY < minY || thisMinX > maxX ) {
71
- return false ; // tree and bbox-query are disjoint
69
+ Optional <Boolean > extentCheck = checkExtent (input , extent );
70
+ if (extentCheck .isPresent ()) {
71
+ return extentCheck .get ();
72
72
}
73
73
74
- if (minX <= thisMinX && minY <= thisMinY && maxX >= thisMaxX && maxY >= thisMaxY ) {
75
- return true ; // bbox-query fully contains tree's extent.
74
+ return containsBottomLeft (readRoot (input .position ()), extent );
75
+ }
76
+
77
+ public boolean crosses (Extent extent ) throws IOException {
78
+ resetInputPosition ();
79
+
80
+ Optional <Boolean > extentCheck = checkExtent (input , extent );
81
+ if (extentCheck .isPresent ()) {
82
+ return extentCheck .get ();
76
83
}
77
84
78
- return crosses (input , readRoot (input , input .position ()), minX , minY , maxX , maxY );
85
+ return crosses (readRoot (input .position ()), extent );
79
86
}
80
87
81
- public Edge readRoot (ByteBufferStreamInput input , int position ) throws IOException {
82
- return readEdge (input , position );
88
+ public Edge readRoot (int position ) throws IOException {
89
+ return readEdge (position );
83
90
}
84
91
85
- private static Edge readEdge (ByteBufferStreamInput input , int position ) throws IOException {
92
+ private Edge readEdge (int position ) throws IOException {
86
93
input .position (position );
87
94
int minY = input .readInt ();
88
95
int maxY = input .readInt ();
@@ -95,33 +102,33 @@ private static Edge readEdge(ByteBufferStreamInput input, int position) throws I
95
102
}
96
103
97
104
98
- Edge readLeft (ByteBufferStreamInput input , Edge root ) throws IOException {
99
- return readEdge (input , root .streamOffset );
105
+ Edge readLeft (Edge root ) throws IOException {
106
+ return readEdge (root .streamOffset );
100
107
}
101
108
102
- Edge readRight (ByteBufferStreamInput input , Edge root ) throws IOException {
103
- return readEdge (input , root .streamOffset + root .rightOffset );
109
+ Edge readRight (Edge root ) throws IOException {
110
+ return readEdge (root .streamOffset + root .rightOffset );
104
111
}
105
112
106
113
/**
107
114
* Returns true if the bottom-left point of the rectangle query is contained within the
108
115
* tree's edges.
109
116
*/
110
- private boolean containsBottomLeft (ByteBufferStreamInput input , Edge root , int minX , int minY , int maxX , int maxY ) throws IOException {
117
+ private boolean containsBottomLeft (Edge root , Extent extent ) throws IOException {
111
118
boolean res = false ;
112
- if (root .maxY >= minY ) {
119
+ if (root .maxY >= extent . minY ) {
113
120
// is bbox-query contained within linearRing
114
121
// cast infinite ray to the right from bottom-left of bbox-query to see if it intersects edge
115
- if (lineCrossesLineWithBoundary (root .x1 , root .y1 , root .x2 , root .y2 ,minX , minY , Integer .MAX_VALUE , minY )) {
122
+ if (lineCrossesLineWithBoundary (root .x1 , root .y1 , root .x2 , root .y2 , extent . minX , extent . minY , Integer .MAX_VALUE , extent . minY )) {
116
123
res = true ;
117
124
}
118
125
119
126
if (root .rightOffset > 0 ) { /* has left node */
120
- res ^= containsBottomLeft (input , readLeft (input , root ), minX , minY , maxX , maxY );
127
+ res ^= containsBottomLeft (readLeft (root ), extent );
121
128
}
122
129
123
- if (root .rightOffset > 0 && maxY >= root .minY ) { /* no right node if rightOffset == -1 */
124
- res ^= containsBottomLeft (input , readRight (input , root ), minX , minY , maxX , maxY );
130
+ if (root .rightOffset > 0 && extent . maxY >= root .minY ) { /* no right node if rightOffset == -1 */
131
+ res ^= containsBottomLeft (readRight (root ), extent );
125
132
}
126
133
}
127
134
return res ;
@@ -130,44 +137,47 @@ private boolean containsBottomLeft(ByteBufferStreamInput input, Edge root, int m
130
137
/**
131
138
* Returns true if the box crosses any edge in this edge subtree
132
139
* */
133
- private boolean crosses (ByteBufferStreamInput input , Edge root , int minX , int minY , int maxX , int maxY ) throws IOException {
134
- boolean res = false ;
140
+ private boolean crosses (Edge root , Extent extent ) throws IOException {
135
141
// we just have to cross one edge to answer the question, so we descend the tree and return when we do.
136
- if (root .maxY >= minY ) {
142
+ if (root .maxY >= extent . minY ) {
137
143
138
144
// does rectangle's edges intersect or reside inside polygon's edge
139
- if (lineCrossesLineWithBoundary (root .x1 , root .y1 , root .x2 , root .y2 , minX , minY , maxX , minY ) ||
140
- lineCrossesLineWithBoundary (root .x1 , root .y1 , root .x2 , root .y2 , maxX , minY , maxX , maxY ) ||
141
- lineCrossesLineWithBoundary (root .x1 , root .y1 , root .x2 , root .y2 , maxX , maxY , minX , maxY ) ||
142
- lineCrossesLineWithBoundary (root .x1 , root .y1 , root .x2 , root .y2 , minX , maxY , minX , minY )) {
145
+ if (lineCrossesLineWithBoundary (root .x1 , root .y1 , root .x2 , root .y2 ,
146
+ extent .minX , extent .minY , extent .maxX , extent .minY ) ||
147
+ lineCrossesLineWithBoundary (root .x1 , root .y1 , root .x2 , root .y2 ,
148
+ extent .maxX , extent .minY , extent .maxX , extent .maxY ) ||
149
+ lineCrossesLineWithBoundary (root .x1 , root .y1 , root .x2 , root .y2 ,
150
+ extent .maxX , extent .maxY , extent .minX , extent .maxY ) ||
151
+ lineCrossesLineWithBoundary (root .x1 , root .y1 , root .x2 , root .y2 ,
152
+ extent .minX , extent .maxY , extent .minX , extent .minY )) {
143
153
return true ;
144
154
}
145
-
146
- if (root .rightOffset > 0 ) { /* has left node */
147
- if (crosses (input , readLeft (input , root ), minX , minY , maxX , maxY )) {
148
- return true ;
149
- }
155
+ /* has left node */
156
+ if (root .rightOffset > 0 && crosses (readLeft (root ), extent )) {
157
+ return true ;
150
158
}
151
159
152
- if (root .rightOffset > 0 && maxY >= root .minY ) { /* no right node if rightOffset == -1 */
153
- if (crosses (input , readRight (input , root ), minX , minY , maxX , maxY )) {
154
- return true ;
155
- }
160
+ /* no right node if rightOffset == -1 */
161
+ if (root .rightOffset > 0 && extent .maxY >= root .minY && crosses (readRight (root ), extent )) {
162
+ return true ;
156
163
}
157
164
}
158
165
return false ;
159
166
}
160
167
168
+ private void resetInputPosition () throws IOException {
169
+ input .position (startPosition );
170
+ }
161
171
162
- private static class Edge {
163
- int streamOffset ;
164
- int x1 ;
165
- int y1 ;
166
- int x2 ;
167
- int y2 ;
168
- int minY ;
169
- int maxY ;
170
- int rightOffset ;
172
+ private static final class Edge {
173
+ final int streamOffset ;
174
+ final int x1 ;
175
+ final int y1 ;
176
+ final int x2 ;
177
+ final int y2 ;
178
+ final int minY ;
179
+ final int maxY ;
180
+ final int rightOffset ;
171
181
172
182
/**
173
183
* Object representing an edge node read from bytes
0 commit comments