-
Notifications
You must be signed in to change notification settings - Fork 25.2k
Clean up Extent logic in Geo Tree readers #42968
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Merged
Merged
Changes from 1 commit
Commits
Show all changes
6 commits
Select commit
Hold shift + click to select a range
191eda0
Clean up Extent logic in Geo Tree readers
talevy 3b7806c
Merge remote-tracking branch 'upstream/geoshape-doc-values' into exte…
talevy 1e4e88a
respond to review
talevy f826c4f
Merge remote-tracking branch 'upstream/geoshape-doc-values' into exte…
talevy 94ee089
add tests for getExtent
talevy f6cb267
re-use Extent stream input constructor
talevy File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -20,67 +20,87 @@ | |
|
||
import org.apache.lucene.util.BytesRef; | ||
import org.elasticsearch.common.io.stream.ByteBufferStreamInput; | ||
import org.elasticsearch.common.io.stream.StreamInput; | ||
|
||
import java.io.IOException; | ||
import java.nio.ByteBuffer; | ||
import java.util.Optional; | ||
|
||
import static org.apache.lucene.geo.GeoUtils.lineCrossesLineWithBoundary; | ||
|
||
public class EdgeTreeReader { | ||
final BytesRef bytesRef; | ||
final ByteBufferStreamInput input; | ||
|
||
public EdgeTreeReader(BytesRef bytesRef) { | ||
this.bytesRef = bytesRef; | ||
this.input = new ByteBufferStreamInput(ByteBuffer.wrap(bytesRef.bytes, bytesRef.offset, bytesRef.length)); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Now that you merged #42910 that just doesn't look right. Perhaps we can brainstorm a bit on how to improve that. |
||
} | ||
|
||
public Extent getExtent() throws IOException { | ||
input.position(0); | ||
int thisMinX = input.readInt(); | ||
int thisMinY = input.readInt(); | ||
int thisMaxX = input.readInt(); | ||
int thisMaxY = input.readInt(); | ||
return new Extent(thisMinX, thisMinY, thisMaxX, thisMaxY); | ||
} | ||
|
||
/** | ||
* Returns true if the rectangle query and the edge tree's shape overlap | ||
*/ | ||
public boolean containedInOrCrosses(int minX, int minY, int maxX, int maxY) throws IOException { | ||
return this.containsBottomLeft(minX, minY, maxX, maxY) || this.crosses(minX, minY, maxX, maxY); | ||
Extent extent = new Extent(minX, minY, maxX, maxY); | ||
return this.containsBottomLeft(extent, true) || this.crosses(extent, true); | ||
} | ||
|
||
boolean containsBottomLeft(int minX, int minY, int maxX, int maxY) throws IOException { | ||
ByteBufferStreamInput input = new ByteBufferStreamInput(ByteBuffer.wrap(bytesRef.bytes, bytesRef.offset, bytesRef.length)); | ||
static Optional<Boolean> checkExtent(StreamInput input, Extent extent) throws IOException { | ||
int thisMinX = input.readInt(); | ||
int thisMinY = input.readInt(); | ||
int thisMaxX = input.readInt(); | ||
int thisMaxY = input.readInt(); | ||
|
||
if (thisMinY > maxY || thisMaxX < minX || thisMaxY < minY || thisMinX > maxX) { | ||
return false; // tree and bbox-query are disjoint | ||
if (thisMinY > extent.maxY || thisMaxX < extent.minX || thisMaxY < extent.minY || thisMinX > extent.maxX) { | ||
return Optional.of(false); // tree and bbox-query are disjoint | ||
} | ||
|
||
if (minX <= thisMinX && minY <= thisMinY && maxX >= thisMaxX && maxY >= thisMaxY) { | ||
return true; // bbox-query fully contains tree's extent. | ||
if (extent.minX <= thisMinX && extent.minY <= thisMinY && extent.maxX >= thisMaxX && extent.maxY >= thisMaxY) { | ||
return Optional.of(true); // bbox-query fully contains tree's extent. | ||
} | ||
|
||
return containsBottomLeft(input, readRoot(input, input.position()), minX, minY, maxX, maxY); | ||
return Optional.empty(); | ||
} | ||
|
||
public boolean crosses(int minX, int minY, int maxX, int maxY) throws IOException { | ||
ByteBufferStreamInput input = new ByteBufferStreamInput(ByteBuffer.wrap(bytesRef.bytes, bytesRef.offset, bytesRef.length)); | ||
int thisMinX = input.readInt(); | ||
int thisMinY = input.readInt(); | ||
int thisMaxX = input.readInt(); | ||
int thisMaxY = input.readInt(); | ||
boolean containsBottomLeft(Extent extent, boolean resetInput) throws IOException { | ||
if (resetInput) { | ||
talevy marked this conversation as resolved.
Show resolved
Hide resolved
|
||
input.position(0); | ||
} | ||
|
||
Optional<Boolean> extentCheck = checkExtent(input, extent); | ||
if (extentCheck.isPresent()) { | ||
return extentCheck.get(); | ||
} | ||
|
||
return containsBottomLeft(readRoot(input.position()), extent); | ||
} | ||
|
||
if (thisMinY > maxY || thisMaxX < minX || thisMaxY < minY || thisMinX > maxX) { | ||
return false; // tree and bbox-query are disjoint | ||
public boolean crosses(Extent extent, boolean resetInput) throws IOException { | ||
if (resetInput) { | ||
input.position(0); | ||
} | ||
|
||
if (minX <= thisMinX && minY <= thisMinY && maxX >= thisMaxX && maxY >= thisMaxY) { | ||
return true; // bbox-query fully contains tree's extent. | ||
Optional<Boolean> extentCheck = checkExtent(input, extent); | ||
if (extentCheck.isPresent()) { | ||
return extentCheck.get(); | ||
} | ||
|
||
return crosses(input, readRoot(input, input.position()), minX, minY, maxX, maxY); | ||
return crosses(readRoot(input.position()), extent); | ||
} | ||
|
||
public Edge readRoot(ByteBufferStreamInput input, int position) throws IOException { | ||
return readEdge(input, position); | ||
public Edge readRoot(int position) throws IOException { | ||
return readEdge(position); | ||
} | ||
|
||
private static Edge readEdge(ByteBufferStreamInput input, int position) throws IOException { | ||
private Edge readEdge(int position) throws IOException { | ||
input.position(position); | ||
int minY = input.readInt(); | ||
int maxY = input.readInt(); | ||
|
@@ -93,33 +113,33 @@ private static Edge readEdge(ByteBufferStreamInput input, int position) throws I | |
} | ||
|
||
|
||
Edge readLeft(ByteBufferStreamInput input, Edge root) throws IOException { | ||
return readEdge(input, root.streamOffset); | ||
Edge readLeft(Edge root) throws IOException { | ||
return readEdge(root.streamOffset); | ||
} | ||
|
||
Edge readRight(ByteBufferStreamInput input, Edge root) throws IOException { | ||
return readEdge(input, root.streamOffset + root.rightOffset); | ||
Edge readRight(Edge root) throws IOException { | ||
return readEdge(root.streamOffset + root.rightOffset); | ||
} | ||
|
||
/** | ||
* Returns true if the bottom-left point of the rectangle query is contained within the | ||
* tree's edges. | ||
*/ | ||
private boolean containsBottomLeft(ByteBufferStreamInput input, Edge root, int minX, int minY, int maxX, int maxY) throws IOException { | ||
private boolean containsBottomLeft(Edge root, Extent extent) throws IOException { | ||
boolean res = false; | ||
if (root.maxY >= minY) { | ||
if (root.maxY >= extent.minY) { | ||
// is bbox-query contained within linearRing | ||
// cast infinite ray to the right from bottom-left of bbox-query to see if it intersects edge | ||
if (lineCrossesLineWithBoundary(root.x1, root.y1, root.x2, root.y2,minX, minY, Integer.MAX_VALUE, minY)) { | ||
if (lineCrossesLineWithBoundary(root.x1, root.y1, root.x2, root.y2, extent.minX, extent.minY, Integer.MAX_VALUE, extent.minY)) { | ||
res = true; | ||
} | ||
|
||
if (root.rightOffset > 0) { /* has left node */ | ||
res ^= containsBottomLeft(input, readLeft(input, root), minX, minY, maxX, maxY); | ||
res ^= containsBottomLeft(readLeft(root), extent); | ||
} | ||
|
||
if (root.rightOffset > 0 && maxY >= root.minY) { /* no right node if rightOffset == -1 */ | ||
res ^= containsBottomLeft(input, readRight(input, root), minX, minY, maxX, maxY); | ||
if (root.rightOffset > 0 && extent.maxY >= root.minY) { /* no right node if rightOffset == -1 */ | ||
res ^= containsBottomLeft(readRight(root), extent); | ||
} | ||
} | ||
return res; | ||
|
@@ -128,34 +148,47 @@ private boolean containsBottomLeft(ByteBufferStreamInput input, Edge root, int m | |
/** | ||
* Returns true if the box crosses any edge in this edge subtree | ||
* */ | ||
private boolean crosses(ByteBufferStreamInput input, Edge root, int minX, int minY, int maxX, int maxY) throws IOException { | ||
boolean res = false; | ||
private boolean crosses(Edge root, Extent extent) throws IOException { | ||
// we just have to cross one edge to answer the question, so we descend the tree and return when we do. | ||
if (root.maxY >= minY) { | ||
if (root.maxY >= extent.minY) { | ||
|
||
// does rectangle's edges intersect or reside inside polygon's edge | ||
if (lineCrossesLineWithBoundary(root.x1, root.y1, root.x2, root.y2, minX, minY, maxX, minY) || | ||
lineCrossesLineWithBoundary(root.x1, root.y1, root.x2, root.y2, maxX, minY, maxX, maxY) || | ||
lineCrossesLineWithBoundary(root.x1, root.y1, root.x2, root.y2, maxX, maxY, minX, maxY) || | ||
lineCrossesLineWithBoundary(root.x1, root.y1, root.x2, root.y2, minX, maxY, minX, minY)) { | ||
if (lineCrossesLineWithBoundary(root.x1, root.y1, root.x2, root.y2, | ||
extent.minX, extent.minY, extent.maxX, extent.minY) || | ||
lineCrossesLineWithBoundary(root.x1, root.y1, root.x2, root.y2, | ||
extent.maxX, extent.minY, extent.maxX, extent.maxY) || | ||
lineCrossesLineWithBoundary(root.x1, root.y1, root.x2, root.y2, | ||
extent.maxX, extent.maxY, extent.minX, extent.maxY) || | ||
lineCrossesLineWithBoundary(root.x1, root.y1, root.x2, root.y2, | ||
extent.minX, extent.maxY, extent.minX, extent.minY)) { | ||
return true; | ||
} | ||
|
||
if (root.rightOffset > 0) { /* has left node */ | ||
if (crosses(input, readLeft(input, root), minX, minY, maxX, maxY)) { | ||
return true; | ||
} | ||
/* has left node */ | ||
if (root.rightOffset > 0 && crosses(readLeft(root), extent)) { | ||
return true; | ||
} | ||
|
||
if (root.rightOffset > 0 && maxY >= root.minY) { /* no right node if rightOffset == -1 */ | ||
if (crosses(input, readRight(input, root), minX, minY, maxX, maxY)) { | ||
return true; | ||
} | ||
/* no right node if rightOffset == -1 */ | ||
if (root.rightOffset > 0 && extent.maxY >= root.minY && crosses(readRight(root), extent)) { | ||
return true; | ||
} | ||
} | ||
return false; | ||
} | ||
|
||
static final class Extent { | ||
talevy marked this conversation as resolved.
Show resolved
Hide resolved
|
||
final int minX; | ||
final int minY; | ||
final int maxX; | ||
final int maxY; | ||
|
||
Extent(int minX, int minY, int maxX, int maxY) { | ||
this.minX = minX; | ||
this.minY = minY; | ||
this.maxX = maxX; | ||
this.maxY = maxY; | ||
} | ||
} | ||
|
||
private static class Edge { | ||
int streamOffset; | ||
|
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.