diff --git a/lucene/spatial3d/src/java/org/apache/lucene/spatial3d/Geo3DDocValuesField.java b/lucene/spatial3d/src/java/org/apache/lucene/spatial3d/Geo3DDocValuesField.java index 46dd777d8b0..1003a46a7eb 100644 --- a/lucene/spatial3d/src/java/org/apache/lucene/spatial3d/Geo3DDocValuesField.java +++ b/lucene/spatial3d/src/java/org/apache/lucene/spatial3d/Geo3DDocValuesField.java @@ -52,10 +52,10 @@ public class Geo3DDocValuesField extends Field { // If we plug in maximum for value, we should get 0x1FFFFF. // So, 0x1FFFFF = Math.floor((maximum - minimum) * factor + 0.5) // We factor out the 0.5 and Math.floor by stating instead: - // 0x200000 = (maximum - minimum) * factor - // So, factor = 0x200000 / (maximum - minimum) + // 0x1FFFFF = (maximum - minimum) * factor + // So, factor = 0x1FFFFF / (maximum - minimum) - private final static double inverseMaximumValue = 1.0 / (double)(0x200000); + private final static double inverseMaximumValue = 1.0 / (double)(0x1FFFFF); private final static double inverseXFactor = (PlanetModel.WGS84.getMaximumXValue() - PlanetModel.WGS84.getMinimumXValue()) * inverseMaximumValue; private final static double inverseYFactor = (PlanetModel.WGS84.getMaximumYValue() - PlanetModel.WGS84.getMinimumYValue()) * inverseMaximumValue; @@ -108,7 +108,7 @@ public class Geo3DDocValuesField extends Field { * @throws IllegalArgumentException if the point is out of bounds */ public void setLocationValue(final GeoPoint point) { - setLocationValue(point.x, point.y, point.z); + fieldsData = Long.valueOf(encodePoint(point)); } /** @@ -119,14 +119,31 @@ public class Geo3DDocValuesField extends Field { * @throws IllegalArgumentException if x, y, or z are out of bounds */ public void setLocationValue(final double x, final double y, final double z) { + fieldsData = Long.valueOf(encodePoint(x, y, z)); + } + + /** Encode a point. + * @param point is the point + * @return the encoded long + */ + public static long encodePoint(final GeoPoint point) { + return encodePoint(point.x, point.y, point.z); + } + + /** Encode a point. + * @param x is the x value + * @param y is the y value + * @param z is the z value + * @return the encoded long + */ + public static long encodePoint(final double x, final double y, final double z) { int XEncoded = encodeX(x); int YEncoded = encodeY(y); int ZEncoded = encodeZ(z); - fieldsData = Long.valueOf( + return (((long)(XEncoded & 0x1FFFFF)) << 42) | (((long)(YEncoded & 0x1FFFFF)) << 21) | - ((long)(ZEncoded & 0x1FFFFF)) - ); + ((long)(ZEncoded & 0x1FFFFF)); } /** Decode GeoPoint value from long docvalues value. diff --git a/lucene/spatial3d/src/test/org/apache/lucene/spatial3d/TestGeo3DDocValues.java b/lucene/spatial3d/src/test/org/apache/lucene/spatial3d/TestGeo3DDocValues.java new file mode 100644 index 00000000000..a099c540463 --- /dev/null +++ b/lucene/spatial3d/src/test/org/apache/lucene/spatial3d/TestGeo3DDocValues.java @@ -0,0 +1,53 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF 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.spatial3d; + +import org.apache.lucene.spatial3d.geom.GeoPoint; +import org.apache.lucene.spatial3d.geom.PlanetModel; + +import org.apache.lucene.util.LuceneTestCase; +import org.apache.lucene.util.TestUtil; + +public class TestGeo3DDocValues extends LuceneTestCase { + + public void testBasic() throws Exception { + checkPointEncoding(0.0, 0.0); + checkPointEncoding(45.0, 72.0); + checkPointEncoding(-45.0, -100.0); + final int testAmt = TestUtil.nextInt(random(), 1000, 2000); + for (int i = 0; i < testAmt; i++) { + checkPointEncoding(random().nextDouble() * 180.0 - 90.0, random().nextDouble() * 360.0 - 180.0); + } + } + + void checkPointEncoding(final double latitude, final double longitude) { + final GeoPoint point = new GeoPoint(PlanetModel.WGS84, Geo3DUtil.fromDegrees(latitude), Geo3DUtil.fromDegrees(longitude)); + long pointValue = Geo3DDocValuesField.encodePoint(point); + final double x = Geo3DDocValuesField.decodeXValue(pointValue); + final double y = Geo3DDocValuesField.decodeYValue(pointValue); + final double z = Geo3DDocValuesField.decodeZValue(pointValue); + final GeoPoint pointR = new GeoPoint(x,y,z); + // Check whether stable + pointValue = Geo3DDocValuesField.encodePoint(x, y, z); + assertEquals(x, Geo3DDocValuesField.decodeXValue(pointValue), 0.0); + assertEquals(y, Geo3DDocValuesField.decodeYValue(pointValue), 0.0); + assertEquals(z, Geo3DDocValuesField.decodeZValue(pointValue), 0.0); + // Check whether has some relationship with original point + assertEquals(0.0, point.arcDistance(pointR), 0.02); + } + +}