Created
December 5, 2018 22:34
-
-
Save nknize/68a7b0e15686a7c7570ecc8258fad441 to your computer and use it in GitHub Desktop.
Encodes LatLonShape.Triangle w/ shortcut implementations for points and lines
This file contains 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
/* | |
* Licensed to Elasticsearch under one or more contributor | |
* license agreements. See the NOTICE file distributed with | |
* this work for additional information regarding copyright | |
* ownership. Elasticsearch licenses this file to you under | |
* the Apache License, Version 2.0 (the "License"); you may | |
* not use this file except in compliance with the License. | |
* You may obtain a copy of the License at | |
* | |
* http://www.apache.org/licenses/LICENSE-2.0 | |
* | |
* Unless required by applicable law or agreed to in writing, | |
* software distributed under the License is distributed on an | |
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY | |
* KIND, either express or implied. See the License for the | |
* specific language governing permissions and limitations | |
* under the License. | |
*/ | |
package org.apache.lucene.document; | |
import org.apache.lucene.geo.GeoEncodingUtils; | |
import org.apache.lucene.util.NumericUtils; | |
public class TriangleEncoder { | |
public static int BYTES = LatLonShape.BYTES; | |
//////////////////// | |
// encode methods // | |
//////////////////// | |
/** encodes as minLat, minLon, maxLat, maxLon, bits, lat, lon */ | |
public static void encode(int minX, int minY, int maxX, int maxY, | |
int[] x, int[] y, byte[] bytes) { | |
// encode bbox | |
NumericUtils.intToSortableBytes(minY, bytes, 0 * BYTES); | |
NumericUtils.intToSortableBytes(minX, bytes, 1 * BYTES); | |
NumericUtils.intToSortableBytes(maxY, bytes, 2 * BYTES); | |
NumericUtils.intToSortableBytes(maxX, bytes, 3 * BYTES); | |
if (isPoint(minX, minY, maxX, maxY)) { | |
// its a point; no need to continue | |
return; | |
} | |
int[] boxX = new int[] {minX, maxX, minX, maxX}; | |
int[] boxY = new int[] {minY, minY, maxY, maxY}; | |
if (x[0] == x[2] && y[0] == y[2]) { | |
// its a line; encode line value | |
encodeLine(boxX, boxY, x, y, bytes); | |
} else { | |
encodePolygon(boxX, boxY, x, y, bytes); | |
} | |
} | |
private static void encodeLine(int[] boxX, int[] boxY, int[] x, int[] y, byte[] bytes) { | |
int shared = Integer.MIN_VALUE; | |
outer: for (int i = 0; i < 4; ++i) { | |
if (boxX[i] == x[0] && boxY[i] == y[0]) { | |
shared = i; | |
break; | |
} | |
} | |
assert shared != Integer.MIN_VALUE : "no triangle vertex is shared with bounding box - impossible"; | |
// encode the shared vertex | |
NumericUtils.intToSortableBytes(shared << 1, bytes, 4 * BYTES); | |
// encode explicit vertex index 1 | |
NumericUtils.intToSortableBytes(y[1], bytes, 5 * BYTES); | |
NumericUtils.intToSortableBytes(x[1], bytes, 6 * BYTES); | |
} | |
private static void encodePolygon(int[] boxX, int[] boxY, int[] x, int[] y, byte[] bytes) { | |
// 1. its a polygon; encode polygon value as LSB | |
int flags = 1; | |
int numSharedVertices = 0; | |
int commonTriangleVertex = Integer.MIN_VALUE; | |
int commonBoxVertex = Integer.MIN_VALUE; | |
// 2. encode shared vertices (4 bits in Z curve order) | |
for (int t = 0; t < 3; ++t) { | |
for (int i = 0; i < 4; ++i) { | |
if (boxX[i] == x[t] && boxY[i] == y[t]) { | |
// set the vertex bit | |
flags = flags | (1 << (t + 1)); | |
++numSharedVertices; | |
// for the single vertex case; keep track of triangle and box vertex | |
commonTriangleVertex = t; | |
commonBoxVertex = i; | |
break; | |
} | |
} | |
} | |
NumericUtils.intToSortableBytes(flags, bytes, 4 * BYTES); | |
// 3. | |
if (numSharedVertices == 3) { | |
return; | |
} else if (numSharedVertices == 2) { | |
// set last two dimensions as the third point: | |
NumericUtils.intToSortableBytes(y[2], bytes, 5 * BYTES); | |
NumericUtils.intToSortableBytes(x[2], bytes, 6 * BYTES); | |
return; | |
} | |
// complex case: encode remaining two points | |
// separate remaining two points: | |
int[][] triPts = new int[2][2]; | |
int[] boxPt = new int[] {boxY[commonBoxVertex], boxX[commonBoxVertex]}; | |
int i = 0; | |
for (int t = 0; t < 3; ++t) { | |
if (t != commonTriangleVertex) { | |
if (y[t] == ) | |
triPts[i++] = new int[]{y[t], x[t]}; | |
} | |
} | |
int y, x; | |
for () | |
NumericUtils.intToSortableBytes(); | |
} | |
private static boolean isPoint(int minX, int minY, int maxX, int maxY) { | |
return minX == maxX && minY == maxY; | |
} | |
private static boolean isLine(int minX, int minY, int maxX, int maxY, byte[] encoded) { | |
// if horizontal or vertical line; return true: | |
if ((minX == maxX && minY != maxY) || (minY == maxY && minX != maxX)) { | |
return true; | |
} | |
// otherwise check the type bit: (0 == line, 1 == polygon) | |
return (NumericUtils.sortableBytesToInt(encoded, 4 * BYTES) & 0x1) == 0; | |
} | |
//////////////////// | |
// decode methods // | |
//////////////////// | |
public static int decodeX(int minX, int minY, int maxX, int maxY, byte[] encoded, int vertex) { | |
if (isPoint(minX, minY, maxX, maxY)) { | |
return minX; | |
} else if (isLine(minX, minY, maxX, maxY, encoded)) { | |
return decodeLineX(minX, maxX, encoded, vertex); | |
} | |
return decodePolygonX(minX, minY, encoded, vertex); | |
} | |
public static int decodeY(int minX, int minY, int maxX, int maxY, byte[] encoded, int vertex) { | |
if (isPoint(minX, minY, maxX, maxY)) { | |
return minY; | |
} else if (isLine(minX, minY, maxX, maxY, encoded)) { | |
return decodeLineY(minY, maxY, encoded, vertex); | |
} | |
return decodePolygonX(minX, minY, encoded, vertex); | |
} | |
public static double decodeLon(int minX, int minY, int maxX, int maxY, byte[] encoded, int vertex) { | |
return GeoEncodingUtils.decodeLongitude(decodeX(minX, minY, maxX, maxY, encoded, vertex)); | |
} | |
public static double decodeLat(int minX, int minY, int maxX, int maxY, byte[] encoded, int vertex) { | |
return GeoEncodingUtils.decodeLatitude(decodeY(minX, minY, maxX, maxY, encoded, vertex)); | |
} | |
/** decodes x value of line vertex; 0 and 2 map to same vertex, 1 maps to explicit point at offset 6 * BYTES */ | |
private static int decodeLineX(int minX, int maxX, byte[] encoded, int vertex) { | |
// decode the shared vertex index | |
int sharedVrtxIdx = NumericUtils.sortableBytesToInt(encoded, 4 * BYTES) >>> 1; | |
if (vertex == 0 || vertex == 2) { | |
return decodeSharedVertexX(minX, maxX, sharedVrtxIdx); | |
} | |
return NumericUtils.sortableBytesToInt(encoded, 6 * BYTES); | |
} | |
/** decodes y value of line vertex; 0 and 2 map to same vertex, 1 maps to explicit point at offset 5 * BYTES */ | |
private static int decodeLineY(int minY, int maxY, byte[] encoded, int vertex) { | |
// decode the shared vertex index | |
int sharedVrtxIdx = NumericUtils.sortableBytesToInt(encoded, 4 * BYTES) >>> 1; | |
if (vertex == 0 || vertex == 2) { | |
return decodeSharedVertexY(minY, maxY, sharedVrtxIdx); | |
} | |
return NumericUtils.sortableBytesToInt(encoded, 5 * BYTES); | |
} | |
private static int decodePolygonX(int minX, int maxX, byte[] encoded, int vertex) { | |
return 0; | |
} | |
private static int decodePolygonY(int minY, int maxY, byte[] encoded, int vertex) { | |
return 0; | |
} | |
/** decodes the x value of the shared vertex */ | |
private static int decodeSharedVertexX(int minX, int maxX, int sharedVertex) { | |
return ((sharedVertex & 0x1) == 0) ? minX : maxX; | |
} | |
/** decodes the y value of the shared vertex identified by the sharedVertex parameter */ | |
private static int decodeSharedVertexY(int minY, int maxY, int sharedVertex) { | |
return ((sharedVertex & 0x10) == 0) ? minY : maxY; | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment