lucene-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From kwri...@apache.org
Subject [1/2] lucene-solr:master: LUCENE-7212: Add geo3d doc values field
Date Mon, 16 May 2016 10:53:17 GMT
Repository: lucene-solr
Updated Branches:
  refs/heads/master c0d23a741 -> 05178b3e5


LUCENE-7212: Add geo3d doc values field


Project: http://git-wip-us.apache.org/repos/asf/lucene-solr/repo
Commit: http://git-wip-us.apache.org/repos/asf/lucene-solr/commit/35187822
Tree: http://git-wip-us.apache.org/repos/asf/lucene-solr/tree/35187822
Diff: http://git-wip-us.apache.org/repos/asf/lucene-solr/diff/35187822

Branch: refs/heads/master
Commit: 351878223ddbb31722ee00882a214bf252378c65
Parents: 0a150bb
Author: Karl Wright <DaddyWri@gmail.com>
Authored: Thu May 12 09:39:10 2016 -0400
Committer: Karl Wright <DaddyWri@gmail.com>
Committed: Thu May 12 09:39:10 2016 -0400

----------------------------------------------------------------------
 .../lucene/spatial3d/Geo3DDocValuesField.java   | 206 +++++++++++++++++++
 1 file changed, 206 insertions(+)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/35187822/lucene/spatial3d/src/java/org/apache/lucene/spatial3d/Geo3DDocValuesField.java
----------------------------------------------------------------------
diff --git a/lucene/spatial3d/src/java/org/apache/lucene/spatial3d/Geo3DDocValuesField.java
b/lucene/spatial3d/src/java/org/apache/lucene/spatial3d/Geo3DDocValuesField.java
new file mode 100644
index 0000000..703cc67
--- /dev/null
+++ b/lucene/spatial3d/src/java/org/apache/lucene/spatial3d/Geo3DDocValuesField.java
@@ -0,0 +1,206 @@
+/*
+ * 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.index.DocValuesType;
+import org.apache.lucene.index.FieldInfo;
+import org.apache.lucene.search.FieldDoc;
+import org.apache.lucene.search.SortField;
+import org.apache.lucene.document.Field;
+import org.apache.lucene.document.FieldType;
+
+import org.apache.lucene.spatial3d.geom.PlanetModel;
+import org.apache.lucene.spatial3d.geom.GeoPoint;
+
+/** 
+ * An per-document 3D location field.
+ * <p>
+ * Sorting by distance is efficient. Multiple values for the same field in one document
+ * is allowed. 
+ * <p>
+ * This field defines static factory methods for common operations:
+ * <ul>
+ *   <li>TBD
+ * </ul>
+ * <p>
+ * If you also need query operations, you should add a separate {@link Geo3DPoint} instance.
+ * <p>
+ * <b>WARNING</b>: Values are indexed with some loss of precision from the
+ * original {@code double} values (4.190951585769653E-8 for the latitude component
+ * and 8.381903171539307E-8 for longitude).
+ * @see Geo3DPoint
+ */
+public class Geo3DDocValuesField extends Field {
+
+  // These are the multiplicative constants we need to use to arrive at values that fit in
21 bits.
+  // The formula we use to go from double to encoded value is:  Math.floor((value - minimum)
* factor + 0.5)
+  // 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)
+
+  private final double inverseMaximumValue = 1.0 / (double)(0x200000);
+  
+  private final double inverseXFactor = (PlanetModel.WGS84.getMaximumXValue() - PlanetModel.WGS84.getMinimumXValue())
* inverseMaximumValue;
+  private final double inverseYFactor = (PlanetModel.WGS84.getMaximumYValue() - PlanetModel.WGS84.getMinimumYValue())
* inverseMaximumValue;
+  private final double inverseZFactor = (PlanetModel.WGS84.getMaximumZValue() - PlanetModel.WGS84.getMinimumZValue())
* inverseMaximumValue;
+  
+  private final double xFactor = 1.0 / inverseXFactor;
+  private final double yFactor = 1.0 / inverseYFactor;
+  private final double zFactor = 1.0 / inverseZFactor;
+  
+  /**
+   * Type for a Geo3DDocValuesField
+   * <p>
+   * Each value stores a 64-bit long where the three values (x, y, and z) are given
+   * 21 bits each.  Each 21-bit value represents the maximum extent in that dimension
+   * for the WGS84 planet model.
+   */
+  public static final FieldType TYPE = new FieldType();
+  static {
+    TYPE.setDocValuesType(DocValuesType.SORTED_NUMERIC);
+    TYPE.freeze();
+  }
+  
+  /** 
+   * Creates a new Geo3DDocValuesField with the specified x, y, and z
+   * @param name field name
+   * @param point is the point.
+   * @throws IllegalArgumentException if the field name is null or the point is out of bounds
+   */
+  public Geo3DDocValuesField(final String name, final GeoPoint point) {
+    super(name, TYPE);
+    setLocationValue(point);
+  }
+
+  /** 
+   * Creates a new Geo3DDocValuesField with the specified x, y, and z
+   * @param name field name
+   * @param x is the x value for the point.
+   * @param y is the y value for the point.
+   * @param z is the z value for the point.
+   * @throws IllegalArgumentException if the field name is null or x, y, or z are out of
bounds
+   */
+  public Geo3DDocValuesField(final String name, final double x, final double y, final double
z) {
+    super(name, TYPE);
+    setLocationValue(x, y, z);
+  }
+  
+  /**
+   * Change the values of this field
+   * @param point is the point.
+   * @throws IllegalArgumentException if the point is out of bounds
+   */
+  public void setLocationValue(final GeoPoint point) {
+    setLocationValue(point.x, point.y, point.z);
+  }
+
+  /**
+   * Change the values of this field
+   * @param x is the x value for the point.
+   * @param y is the y value for the point.
+   * @param z is the z value for the point.
+   * @throws IllegalArgumentException if x, y, or z are out of bounds
+   */
+  public void setLocationValue(final double x, final double y, final double z) {
+    int XEncoded = encodeX(x);
+    int YEncoded = encodeY(y);
+    int ZEncoded = encodeZ(z);
+    fieldsData = Long.valueOf(
+      (((long)(XEncoded & 0x1FFFFF)) << 42) |
+      (((long)(YEncoded & 0x1FFFFF)) << 21) |
+      ((long)(ZEncoded & 0x1FFFFF))
+      );
+  }
+
+  // For encoding/decoding, we generally want the following behavior:
+  // (1) If you encode the maximum value or the minimum value, the resulting int fits in
21 bits.
+  // (2) If you decode an encoded value, you get back the original value for both the minimum
and maximum planet model values.
+  // (3) Rounding occurs such that a small delta from the minimum and maximum planet model
values still returns the same
+  // values -- that is, these are in the center of the range of input values that should
return the minimum or maximum when decoded
+  
+  private int encodeX(final double x) {
+    if (x > PlanetModel.WGS84.getMaximumXValue()) {
+      throw new IllegalArgumentException("x value exceeds WGS84 maximum");
+    } else if (x < PlanetModel.WGS84.getMinimumXValue()) {
+      throw new IllegalArgumentException("x value less than WGS84 minimum");
+    }
+    return (int)Math.floor((x - PlanetModel.WGS84.getMinimumXValue()) * xFactor + 0.5);
+  }
+  
+  private double decodeX(final int x) {
+    return x * inverseXFactor + PlanetModel.WGS84.getMinimumXValue();
+  }
+
+  private int encodeY(final double y) {
+    if (y > PlanetModel.WGS84.getMaximumYValue()) {
+      throw new IllegalArgumentException("y value exceeds WGS84 maximum");
+    } else if (y < PlanetModel.WGS84.getMinimumYValue()) {
+      throw new IllegalArgumentException("y value less than WGS84 minimum");
+    }
+    return (int)Math.floor((y - PlanetModel.WGS84.getMinimumYValue()) * yFactor + 0.5);
+  }
+
+  private double decodeY(final int y) {
+    return y * inverseYFactor + PlanetModel.WGS84.getMinimumYValue();
+  }
+
+  private int encodeZ(final double z) {
+    if (z > PlanetModel.WGS84.getMaximumZValue()) {
+      throw new IllegalArgumentException("z value exceeds WGS84 maximum");
+    } else if (z < PlanetModel.WGS84.getMinimumZValue()) {
+      throw new IllegalArgumentException("z value less than WGS84 minimum");
+    }
+    return (int)Math.floor((z - PlanetModel.WGS84.getMinimumZValue()) * zFactor + 0.5);
+  }
+
+  private double decodeZ(final int z) {
+    return z * inverseZFactor + PlanetModel.WGS84.getMinimumZValue();
+  }
+
+  /** helper: checks a fieldinfo and throws exception if its definitely not a Geo3DDocValuesField
*/
+  static void checkCompatible(FieldInfo fieldInfo) {
+    // dv properties could be "unset", if you e.g. used only StoredField with this same name
in the segment.
+    if (fieldInfo.getDocValuesType() != DocValuesType.NONE && fieldInfo.getDocValuesType()
!= TYPE.docValuesType()) {
+      throw new IllegalArgumentException("field=\"" + fieldInfo.name + "\" was indexed with
docValuesType=" + fieldInfo.getDocValuesType() + 
+                                         " but this type has docValuesType=" + TYPE.docValuesType()
+ 
+                                         ", is the field really a Geo3DDocValuesField?");
+    }
+  }
+  
+  @Override
+  public String toString() {
+    StringBuilder result = new StringBuilder();
+    result.append(getClass().getSimpleName());
+    result.append(" <");
+    result.append(name);
+    result.append(':');
+
+    long currentValue = Long.valueOf((Long)fieldsData);
+    
+    result.append(decodeX(((int)(currentValue >> 42)) & 0x1FFFFF));
+    result.append(',');
+    result.append(decodeY(((int)(currentValue >> 21)) & 0x1FFFFF));
+    result.append(',');
+    result.append(decodeZ(((int)(currentValue)) & 0x1FFFFF));
+
+    result.append('>');
+    return result.toString();
+  }
+
+}


Mime
View raw message