Browse Source

Simplify creation of CentroidCalculator objects (#64619)

Creation of those objects is responsibility now of BinaryGeoShapeDocValuesField.
Ignacio Vera 5 years ago
parent
commit
47da916dd1
13 changed files with 222 additions and 213 deletions
  1. 55 76
      x-pack/plugin/spatial/src/main/java/org/elasticsearch/xpack/spatial/index/fielddata/CentroidCalculator.java
  2. 6 0
      x-pack/plugin/spatial/src/main/java/org/elasticsearch/xpack/spatial/index/fielddata/CoordinateEncoder.java
  3. 11 0
      x-pack/plugin/spatial/src/main/java/org/elasticsearch/xpack/spatial/index/fielddata/GeoShapeCoordinateEncoder.java
  4. 2 2
      x-pack/plugin/spatial/src/main/java/org/elasticsearch/xpack/spatial/index/fielddata/GeoShapeValues.java
  5. 3 2
      x-pack/plugin/spatial/src/main/java/org/elasticsearch/xpack/spatial/index/fielddata/GeometryDocValueWriter.java
  6. 6 6
      x-pack/plugin/spatial/src/main/java/org/elasticsearch/xpack/spatial/index/mapper/BinaryGeoShapeDocValuesField.java
  7. 3 8
      x-pack/plugin/spatial/src/main/java/org/elasticsearch/xpack/spatial/index/mapper/GeoShapeWithDocValuesFieldMapper.java
  8. 4 2
      x-pack/plugin/spatial/src/test/java/org/elasticsearch/xpack/spatial/aggregations/metrics/GeoShapeCentroidAggregatorTests.java
  9. 100 85
      x-pack/plugin/spatial/src/test/java/org/elasticsearch/xpack/spatial/index/fielddata/CentroidCalculatorTests.java
  10. 10 0
      x-pack/plugin/spatial/src/test/java/org/elasticsearch/xpack/spatial/index/fielddata/TestCoordinateEncoder.java
  11. 9 21
      x-pack/plugin/spatial/src/test/java/org/elasticsearch/xpack/spatial/search/aggregations/bucket/geogrid/GeoGridTilerTests.java
  12. 2 7
      x-pack/plugin/spatial/src/test/java/org/elasticsearch/xpack/spatial/search/aggregations/bucket/geogrid/GeoShapeGeoGridTestCase.java
  13. 11 4
      x-pack/plugin/spatial/src/test/java/org/elasticsearch/xpack/spatial/util/GeoTestUtils.java

+ 55 - 76
x-pack/plugin/spatial/src/main/java/org/elasticsearch/xpack/spatial/index/fielddata/CentroidCalculator.java

@@ -6,7 +6,6 @@
 
 
 package org.elasticsearch.xpack.spatial.index.fielddata;
 package org.elasticsearch.xpack.spatial.index.fielddata;
 
 
-import org.elasticsearch.common.geo.GeoUtils;
 import org.elasticsearch.geometry.Circle;
 import org.elasticsearch.geometry.Circle;
 import org.elasticsearch.geometry.Geometry;
 import org.elasticsearch.geometry.Geometry;
 import org.elasticsearch.geometry.GeometryCollection;
 import org.elasticsearch.geometry.GeometryCollection;
@@ -27,106 +26,62 @@ import org.elasticsearch.search.aggregations.metrics.CompensatedSum;
  * as the centroid of a shape.
  * as the centroid of a shape.
  */
  */
 public class CentroidCalculator {
 public class CentroidCalculator {
-    CompensatedSum compSumX;
-    CompensatedSum compSumY;
-    CompensatedSum compSumWeight;
-    private CentroidCalculatorVisitor visitor;
-    private DimensionalShapeType dimensionalShapeType;
-
-    public CentroidCalculator(Geometry geometry) {
-        this.compSumX = new CompensatedSum(0, 0);
-        this.compSumY = new CompensatedSum(0, 0);
-        this.compSumWeight = new CompensatedSum(0, 0);
-        this.dimensionalShapeType = null;
-        this.visitor = new CentroidCalculatorVisitor(this);
-        geometry.visit(visitor);
-        this.dimensionalShapeType = visitor.calculator.dimensionalShapeType;
-    }
 
 
-    /**
-     * adds a single coordinate to the running sum and count of coordinates
-     * for centroid calculation
-     *  @param x the x-coordinate of the point
-     * @param y the y-coordinate of the point
-     * @param weight the associated weight of the coordinate
-     */
-    private void addCoordinate(double x, double y, double weight, DimensionalShapeType dimensionalShapeType) {
-        // x and y can be infinite due to really small areas and rounding problems
-        if (Double.isFinite(x) && Double.isFinite(y)) {
-            if (this.dimensionalShapeType == null || this.dimensionalShapeType == dimensionalShapeType) {
-                compSumX.add(x * weight);
-                compSumY.add(y * weight);
-                compSumWeight.add(weight);
-                this.dimensionalShapeType = dimensionalShapeType;
-            } else if (dimensionalShapeType.compareTo(this.dimensionalShapeType) > 0) {
-                // reset counters
-                compSumX.reset(x * weight, 0);
-                compSumY.reset(y * weight, 0);
-                compSumWeight.reset(weight, 0);
-                this.dimensionalShapeType = dimensionalShapeType;
-            }
-        }
+    private final CentroidCalculatorVisitor visitor;
+
+    public CentroidCalculator() {
+        this.visitor = new CentroidCalculatorVisitor();
     }
     }
 
 
     /**
     /**
-     * Adjusts the existing calculator to add the running sum and count
-     * from another {@link CentroidCalculator}. This is used to keep
-     * a running count of points from different sub-shapes of a single
-     * geo-shape field
+     * Add a geometry to the calculator
      *
      *
-     * @param otherCalculator the other centroid calculator to add from
+     * @param geometry the geometry to add
      */
      */
-    public void addFrom(CentroidCalculator otherCalculator) {
-        int compared = dimensionalShapeType.compareTo(otherCalculator.dimensionalShapeType);
-        if (compared < 0) {
-            dimensionalShapeType = otherCalculator.dimensionalShapeType;
-            this.compSumX = otherCalculator.compSumX;
-            this.compSumY = otherCalculator.compSumY;
-            this.compSumWeight = otherCalculator.compSumWeight;
-
-        } else if (compared == 0) {
-            this.compSumX.add(otherCalculator.compSumX.value());
-            this.compSumY.add(otherCalculator.compSumY.value());
-            this.compSumWeight.add(otherCalculator.compSumWeight.value());
-        } // else (compared > 0) do not modify centroid calculation since otherCalculator is of lower dimension than this calculator
+    public void add(Geometry geometry) {
+        geometry.visit(visitor);
     }
     }
 
 
     /**
     /**
      * @return the x-coordinate centroid
      * @return the x-coordinate centroid
      */
      */
     public double getX() {
     public double getX() {
-        // normalization required due to floating point precision errors
-        return GeoUtils.normalizeLon(compSumX.value() / compSumWeight.value());
+        return visitor.compSumX.value() / visitor.compSumWeight.value();
     }
     }
 
 
     /**
     /**
      * @return the y-coordinate centroid
      * @return the y-coordinate centroid
      */
      */
     public double getY() {
     public double getY() {
-        // normalization required due to floating point precision errors
-        return GeoUtils.normalizeLat(compSumY.value() / compSumWeight.value());
+        return visitor.compSumY.value() / visitor.compSumWeight.value();
     }
     }
 
 
     /**
     /**
      * @return the sum of all the weighted coordinates summed in the calculator
      * @return the sum of all the weighted coordinates summed in the calculator
      */
      */
     public double sumWeight() {
     public double sumWeight() {
-        return compSumWeight.value();
+        return visitor.compSumWeight.value();
     }
     }
 
 
     /**
     /**
      * @return the highest dimensional shape type summed in the calculator
      * @return the highest dimensional shape type summed in the calculator
      */
      */
     public DimensionalShapeType getDimensionalShapeType() {
     public DimensionalShapeType getDimensionalShapeType() {
-        return dimensionalShapeType;
+        return visitor.dimensionalShapeType;
     }
     }
 
 
     private static class CentroidCalculatorVisitor implements GeometryVisitor<Void, IllegalArgumentException> {
     private static class CentroidCalculatorVisitor implements GeometryVisitor<Void, IllegalArgumentException> {
 
 
-        private final CentroidCalculator calculator;
+        final CompensatedSum compSumX;
+        final CompensatedSum compSumY;
+        final CompensatedSum compSumWeight;
+        DimensionalShapeType dimensionalShapeType;
 
 
-        private CentroidCalculatorVisitor(CentroidCalculator calculator) {
-            this.calculator = calculator;
+        private CentroidCalculatorVisitor() {
+            this.compSumX = new CompensatedSum(0, 0);
+            this.compSumY = new CompensatedSum(0, 0);
+            this.compSumWeight = new CompensatedSum(0, 0);
+            this.dimensionalShapeType = DimensionalShapeType.POINT;
         }
         }
 
 
         @Override
         @Override
@@ -144,7 +99,7 @@ public class CentroidCalculator {
 
 
         @Override
         @Override
         public Void visit(Line line) {
         public Void visit(Line line) {
-            if (calculator.dimensionalShapeType != DimensionalShapeType.POLYGON) {
+            if (dimensionalShapeType != DimensionalShapeType.POLYGON) {
                 visitLine(line.length(), line::getX, line::getY);
                 visitLine(line.length(), line::getX, line::getY);
             }
             }
             return null;
             return null;
@@ -158,7 +113,7 @@ public class CentroidCalculator {
 
 
         @Override
         @Override
         public Void visit(MultiLine multiLine) {
         public Void visit(MultiLine multiLine) {
-            if (calculator.getDimensionalShapeType() != DimensionalShapeType.POLYGON) {
+            if (dimensionalShapeType != DimensionalShapeType.POLYGON) {
                 for (Line line : multiLine) {
                 for (Line line : multiLine) {
                     visit(line);
                     visit(line);
                 }
                 }
@@ -168,7 +123,7 @@ public class CentroidCalculator {
 
 
         @Override
         @Override
         public Void visit(MultiPoint multiPoint) {
         public Void visit(MultiPoint multiPoint) {
-            if (calculator.getDimensionalShapeType() == null || calculator.getDimensionalShapeType() == DimensionalShapeType.POINT) {
+            if (dimensionalShapeType == DimensionalShapeType.POINT) {
                 for (Point point : multiPoint) {
                 for (Point point : multiPoint) {
                     visit(point);
                     visit(point);
                 }
                 }
@@ -186,7 +141,7 @@ public class CentroidCalculator {
 
 
         @Override
         @Override
         public Void visit(Point point) {
         public Void visit(Point point) {
-            if (calculator.getDimensionalShapeType() == null || calculator.getDimensionalShapeType() == DimensionalShapeType.POINT) {
+            if (dimensionalShapeType == DimensionalShapeType.POINT) {
                 visitPoint(point.getX(), point.getY());
                 visitPoint(point.getX(), point.getY());
             }
             }
             return null;
             return null;
@@ -211,11 +166,11 @@ public class CentroidCalculator {
                 sumWeight += w;
                 sumWeight += w;
             }
             }
 
 
-            if (sumWeight == 0 && calculator.dimensionalShapeType != DimensionalShapeType.POLYGON) {
+            if (sumWeight == 0 && dimensionalShapeType != DimensionalShapeType.POLYGON) {
                 visitLine(polygon.getPolygon().length(), polygon.getPolygon()::getX, polygon.getPolygon()::getY);
                 visitLine(polygon.getPolygon().length(), polygon.getPolygon()::getX, polygon.getPolygon()::getY);
             } else {
             } else {
                 for (int i = 0; i < 1 + polygon.getNumberOfHoles(); i++) {
                 for (int i = 0; i < 1 + polygon.getNumberOfHoles(); i++) {
-                    calculator.addCoordinate(centroidX[i], centroidY[i], weight[i], DimensionalShapeType.POLYGON);
+                    addCoordinate(centroidX[i], centroidY[i], weight[i], DimensionalShapeType.POLYGON);
                 }
                 }
             }
             }
 
 
@@ -230,7 +185,7 @@ public class CentroidCalculator {
             if (rectWeight != 0) {
             if (rectWeight != 0) {
                 double sumX = rectangle.getMaxX() + rectangle.getMinX();
                 double sumX = rectangle.getMaxX() + rectangle.getMinX();
                 double sumY = rectangle.getMaxY() + rectangle.getMinY();
                 double sumY = rectangle.getMaxY() + rectangle.getMinY();
-                calculator.addCoordinate(sumX / 2, sumY / 2, rectWeight, DimensionalShapeType.POLYGON);
+                addCoordinate(sumX / 2, sumY / 2, rectWeight, DimensionalShapeType.POLYGON);
             } else {
             } else {
                 // degenerated rectangle, transform to Line
                 // degenerated rectangle, transform to Line
                 Line line = new Line(new double[]{rectangle.getMinX(), rectangle.getMaxX()},
                 Line line = new Line(new double[]{rectangle.getMinX(), rectangle.getMaxX()},
@@ -240,9 +195,8 @@ public class CentroidCalculator {
             return null;
             return null;
         }
         }
 
 
-
         private void visitPoint(double x, double y) {
         private void visitPoint(double x, double y) {
-            calculator.addCoordinate(x, y, 1.0, DimensionalShapeType.POINT);
+            addCoordinate(x, y, 1.0, DimensionalShapeType.POINT);
         }
         }
 
 
         private void visitLine(int length, CoordinateSupplier x, CoordinateSupplier y) {
         private void visitLine(int length, CoordinateSupplier x, CoordinateSupplier y) {
@@ -258,7 +212,7 @@ public class CentroidCalculator {
                     // degenerated line, it can be considered a point
                     // degenerated line, it can be considered a point
                     visitPoint(x.get(i), y.get(i));
                     visitPoint(x.get(i), y.get(i));
                 } else {
                 } else {
-                    calculator.addCoordinate(xAvg, yAvg, weight, DimensionalShapeType.LINE);
+                    addCoordinate(xAvg, yAvg, weight, DimensionalShapeType.LINE);
                 }
                 }
             }
             }
         }
         }
@@ -289,6 +243,31 @@ public class CentroidCalculator {
             centroidY[idx] = sumY / (6 * totalRingArea);
             centroidY[idx] = sumY / (6 * totalRingArea);
             weight[idx] = sign * Math.abs(totalRingArea);
             weight[idx] = sign * Math.abs(totalRingArea);
         }
         }
+
+        /**
+         * adds a single coordinate to the running sum and count of coordinates
+         * for centroid calculation
+         *  @param x the x-coordinate of the point
+         * @param y the y-coordinate of the point
+         * @param weight the associated weight of the coordinate
+         */
+        private void addCoordinate(double x, double y, double weight, DimensionalShapeType dimensionalShapeType) {
+            // x and y can be infinite due to really small areas and rounding problems
+            if (Double.isFinite(x) && Double.isFinite(y)) {
+                if (this.dimensionalShapeType == dimensionalShapeType) {
+                    compSumX.add(x * weight);
+                    compSumY.add(y * weight);
+                    compSumWeight.add(weight);
+                    this.dimensionalShapeType = dimensionalShapeType;
+                } else if (dimensionalShapeType.compareTo(this.dimensionalShapeType) > 0) {
+                    // reset counters
+                    compSumX.reset(x * weight, 0);
+                    compSumY.reset(y * weight, 0);
+                    compSumWeight.reset(weight, 0);
+                    this.dimensionalShapeType = dimensionalShapeType;
+                }
+            }
+        }
     }
     }
 
 
     @FunctionalInterface
     @FunctionalInterface

+ 6 - 0
x-pack/plugin/spatial/src/main/java/org/elasticsearch/xpack/spatial/index/fielddata/CoordinateEncoder.java

@@ -25,4 +25,10 @@ public interface CoordinateEncoder {
 
 
     /** decode Y value */
     /** decode Y value */
     double decodeY(int y);
     double decodeY(int y);
+
+    /** normalize X value */
+    double normalizeX(double x);
+
+    /** normalize Y value */
+    double normalizeY(double y);
 }
 }

+ 11 - 0
x-pack/plugin/spatial/src/main/java/org/elasticsearch/xpack/spatial/index/fielddata/GeoShapeCoordinateEncoder.java

@@ -7,6 +7,7 @@
 package org.elasticsearch.xpack.spatial.index.fielddata;
 package org.elasticsearch.xpack.spatial.index.fielddata;
 
 
 import org.apache.lucene.geo.GeoEncodingUtils;
 import org.apache.lucene.geo.GeoEncodingUtils;
+import org.elasticsearch.common.geo.GeoUtils;
 
 
 final class GeoShapeCoordinateEncoder implements CoordinateEncoder {
 final class GeoShapeCoordinateEncoder implements CoordinateEncoder {
 
 
@@ -41,4 +42,14 @@ final class GeoShapeCoordinateEncoder implements CoordinateEncoder {
     public double decodeY(int y) {
     public double decodeY(int y) {
         return GeoEncodingUtils.decodeLatitude(y);
         return GeoEncodingUtils.decodeLatitude(y);
     }
     }
+
+    @Override
+    public double normalizeX(double x) {
+        return GeoUtils.normalizeLon(x);
+    }
+
+    @Override
+    public double normalizeY(double y) {
+        return GeoUtils.normalizeLat(y);
+    }
 }
 }

+ 2 - 2
x-pack/plugin/spatial/src/main/java/org/elasticsearch/xpack/spatial/index/fielddata/GeoShapeValues.java

@@ -133,8 +133,8 @@ public abstract class GeoShapeValues {
             try {
             try {
                 final GeoShapeIndexer indexer = new GeoShapeIndexer(true, "missing");
                 final GeoShapeIndexer indexer = new GeoShapeIndexer(true, "missing");
                 final Geometry geometry = indexer.prepareForIndexing(MISSING_GEOMETRY_PARSER.fromWKT(missing));
                 final Geometry geometry = indexer.prepareForIndexing(MISSING_GEOMETRY_PARSER.fromWKT(missing));
-                final BinaryGeoShapeDocValuesField field =
-                    new BinaryGeoShapeDocValuesField(missing, indexer.indexShape(null, geometry), new CentroidCalculator(geometry));
+                final BinaryGeoShapeDocValuesField field = new BinaryGeoShapeDocValuesField("missing");
+                field.add(indexer.indexShape(null, geometry), geometry);
                 final GeometryDocValueReader reader = new GeometryDocValueReader();
                 final GeometryDocValueReader reader = new GeometryDocValueReader();
                 reader.reset(field.binaryValue());
                 reader.reset(field.binaryValue());
                 return new GeoShapeValue(reader);
                 return new GeoShapeValue(reader);

+ 3 - 2
x-pack/plugin/spatial/src/main/java/org/elasticsearch/xpack/spatial/index/fielddata/GeometryDocValueWriter.java

@@ -27,8 +27,9 @@ public class GeometryDocValueWriter {
                                  CoordinateEncoder coordinateEncoder,
                                  CoordinateEncoder coordinateEncoder,
                                  CentroidCalculator centroidCalculator) throws IOException {
                                  CentroidCalculator centroidCalculator) throws IOException {
         final ByteBuffersDataOutput out = new ByteBuffersDataOutput();
         final ByteBuffersDataOutput out = new ByteBuffersDataOutput();
-        out.writeInt(coordinateEncoder.encodeX(centroidCalculator.getX()));
-        out.writeInt(coordinateEncoder.encodeY(centroidCalculator.getY()));
+        // normalization may be required due to floating point precision errors
+        out.writeInt(coordinateEncoder.encodeX(coordinateEncoder.normalizeX(centroidCalculator.getX())));
+        out.writeInt(coordinateEncoder.encodeY(coordinateEncoder.normalizeY(centroidCalculator.getY())));
         centroidCalculator.getDimensionalShapeType().writeTo(out);
         centroidCalculator.getDimensionalShapeType().writeTo(out);
         out.writeVLong(Double.doubleToLongBits(centroidCalculator.sumWeight()));
         out.writeVLong(Double.doubleToLongBits(centroidCalculator.sumWeight()));
         TriangleTreeWriter.writeTo(out, fields);
         TriangleTreeWriter.writeTo(out, fields);

+ 6 - 6
x-pack/plugin/spatial/src/main/java/org/elasticsearch/xpack/spatial/index/mapper/BinaryGeoShapeDocValuesField.java

@@ -9,6 +9,7 @@ package org.elasticsearch.xpack.spatial.index.mapper;
 import org.apache.lucene.index.IndexableField;
 import org.apache.lucene.index.IndexableField;
 import org.apache.lucene.util.BytesRef;
 import org.apache.lucene.util.BytesRef;
 import org.elasticsearch.ElasticsearchException;
 import org.elasticsearch.ElasticsearchException;
+import org.elasticsearch.geometry.Geometry;
 import org.elasticsearch.index.mapper.CustomDocValuesField;
 import org.elasticsearch.index.mapper.CustomDocValuesField;
 import org.elasticsearch.xpack.spatial.index.fielddata.CentroidCalculator;
 import org.elasticsearch.xpack.spatial.index.fielddata.CentroidCalculator;
 import org.elasticsearch.xpack.spatial.index.fielddata.CoordinateEncoder;
 import org.elasticsearch.xpack.spatial.index.fielddata.CoordinateEncoder;
@@ -23,16 +24,15 @@ public class BinaryGeoShapeDocValuesField extends CustomDocValuesField {
     private final List<IndexableField> fields;
     private final List<IndexableField> fields;
     private final CentroidCalculator centroidCalculator;
     private final CentroidCalculator centroidCalculator;
 
 
-    public BinaryGeoShapeDocValuesField(String name, List<IndexableField> fields, CentroidCalculator centroidCalculator) {
+    public BinaryGeoShapeDocValuesField(String name) {
         super(name);
         super(name);
-        this.fields = new ArrayList<>(fields.size());
-        this.centroidCalculator = centroidCalculator;
-        this.fields.addAll(fields);
+        this.fields = new ArrayList<>();
+        this.centroidCalculator = new CentroidCalculator();
     }
     }
 
 
-    public void add( List<IndexableField> fields, CentroidCalculator centroidCalculator) {
+    public void add(List<IndexableField> fields, Geometry geometry) {
         this.fields.addAll(fields);
         this.fields.addAll(fields);
-        this.centroidCalculator.addFrom(centroidCalculator);
+        this.centroidCalculator.add(geometry);
     }
     }
 
 
     @Override
     @Override

+ 3 - 8
x-pack/plugin/spatial/src/main/java/org/elasticsearch/xpack/spatial/index/mapper/GeoShapeWithDocValuesFieldMapper.java

@@ -30,7 +30,6 @@ import org.elasticsearch.index.query.QueryShardContext;
 import org.elasticsearch.index.query.VectorGeoShapeQueryProcessor;
 import org.elasticsearch.index.query.VectorGeoShapeQueryProcessor;
 import org.elasticsearch.search.lookup.SearchLookup;
 import org.elasticsearch.search.lookup.SearchLookup;
 import org.elasticsearch.xpack.spatial.index.fielddata.AbstractLatLonShapeIndexFieldData;
 import org.elasticsearch.xpack.spatial.index.fielddata.AbstractLatLonShapeIndexFieldData;
-import org.elasticsearch.xpack.spatial.index.fielddata.CentroidCalculator;
 import org.elasticsearch.xpack.spatial.search.aggregations.support.GeoShapeValuesSourceType;
 import org.elasticsearch.xpack.spatial.search.aggregations.support.GeoShapeValuesSourceType;
 
 
 import java.util.Arrays;
 import java.util.Arrays;
@@ -119,16 +118,12 @@ public class GeoShapeWithDocValuesFieldMapper extends AbstractShapeGeometryField
     @Override
     @Override
     @SuppressWarnings({"rawtypes", "unchecked"})
     @SuppressWarnings({"rawtypes", "unchecked"})
     protected void addDocValuesFields(String name, Geometry shape, List<IndexableField> fields, ParseContext context) {
     protected void addDocValuesFields(String name, Geometry shape, List<IndexableField> fields, ParseContext context) {
-        CentroidCalculator calculator = new CentroidCalculator(shape);
-        BinaryGeoShapeDocValuesField docValuesField =
-            (BinaryGeoShapeDocValuesField) context.doc().getByKey(name);
+        BinaryGeoShapeDocValuesField docValuesField = (BinaryGeoShapeDocValuesField) context.doc().getByKey(name);
         if (docValuesField == null) {
         if (docValuesField == null) {
-            docValuesField = new BinaryGeoShapeDocValuesField(name, fields, calculator);
+            docValuesField = new BinaryGeoShapeDocValuesField(name);
             context.doc().addWithKey(name, docValuesField);
             context.doc().addWithKey(name, docValuesField);
-
-        } else {
-            docValuesField.add(fields, calculator);
         }
         }
+        docValuesField.add(fields, shape);
     }
     }
 
 
     public static final class GeoShapeWithDocValuesFieldType extends AbstractShapeGeometryFieldType implements GeoShapeQueryable {
     public static final class GeoShapeWithDocValuesFieldType extends AbstractShapeGeometryFieldType implements GeoShapeQueryable {

+ 4 - 2
x-pack/plugin/spatial/src/test/java/org/elasticsearch/xpack/spatial/aggregations/metrics/GeoShapeCentroidAggregatorTests.java

@@ -145,7 +145,8 @@ public class GeoShapeCentroidAggregatorTests extends AggregatorTestCase {
                 // do not include geometry
                 // do not include geometry
             }
             }
             // find dimensional-shape-type of geometry
             // find dimensional-shape-type of geometry
-            CentroidCalculator centroidCalculator = new CentroidCalculator(geometry);
+            CentroidCalculator centroidCalculator = new CentroidCalculator();
+            centroidCalculator.add(geometry);
             DimensionalShapeType geometryShapeType = centroidCalculator.getDimensionalShapeType();
             DimensionalShapeType geometryShapeType = centroidCalculator.getDimensionalShapeType();
             targetShapeType = targetShapeType.compareTo(geometryShapeType) >= 0 ? targetShapeType : geometryShapeType;
             targetShapeType = targetShapeType.compareTo(geometryShapeType) >= 0 ? targetShapeType : geometryShapeType;
         }
         }
@@ -156,7 +157,8 @@ public class GeoShapeCentroidAggregatorTests extends AggregatorTestCase {
             CompensatedSum compensatedSumWeight = new CompensatedSum(0, 0);
             CompensatedSum compensatedSumWeight = new CompensatedSum(0, 0);
             for (Geometry geometry : geometries) {
             for (Geometry geometry : geometries) {
                 Document document = new Document();
                 Document document = new Document();
-                CentroidCalculator calculator = new CentroidCalculator(geometry);
+                CentroidCalculator calculator = new CentroidCalculator();
+                calculator.add(geometry);
                 document.add(GeoTestUtils.binaryGeoShapeDocValuesField("field", geometry));
                 document.add(GeoTestUtils.binaryGeoShapeDocValuesField("field", geometry));
                 w.addDocument(document);
                 w.addDocument(document);
                 if (targetShapeType.compareTo(calculator.getDimensionalShapeType()) == 0) {
                 if (targetShapeType.compareTo(calculator.getDimensionalShapeType()) == 0) {

+ 100 - 85
x-pack/plugin/spatial/src/test/java/org/elasticsearch/xpack/spatial/index/fielddata/CentroidCalculatorTests.java

@@ -20,7 +20,9 @@ import org.elasticsearch.geometry.ShapeType;
 import org.elasticsearch.geometry.utils.GeographyValidator;
 import org.elasticsearch.geometry.utils.GeographyValidator;
 import org.elasticsearch.geometry.utils.WellKnownText;
 import org.elasticsearch.geometry.utils.WellKnownText;
 import org.elasticsearch.test.ESTestCase;
 import org.elasticsearch.test.ESTestCase;
+import org.elasticsearch.xpack.spatial.util.GeoTestUtils;
 
 
+import java.io.IOException;
 import java.util.ArrayList;
 import java.util.ArrayList;
 import java.util.Collections;
 import java.util.Collections;
 import java.util.List;
 import java.util.List;
@@ -38,9 +40,10 @@ public class CentroidCalculatorTests extends ESTestCase {
 
 
     public void testPoint() {
     public void testPoint() {
         Point point = GeometryTestUtils.randomPoint(false);
         Point point = GeometryTestUtils.randomPoint(false);
-        CentroidCalculator calculator = new CentroidCalculator(point);
-        assertThat(calculator.getX(), equalTo(GeoUtils.normalizeLon(point.getX())));
-        assertThat(calculator.getY(), equalTo(GeoUtils.normalizeLat(point.getY())));
+        CentroidCalculator calculator = new CentroidCalculator();
+        calculator.add(point);
+        assertThat(calculator.getX(), equalTo(point.getX()));
+        assertThat(calculator.getY(), equalTo(point.getY()));
         assertThat(calculator.sumWeight(), equalTo(1.0));
         assertThat(calculator.sumWeight(), equalTo(1.0));
         assertThat(calculator.getDimensionalShapeType(), equalTo(POINT));
         assertThat(calculator.getDimensionalShapeType(), equalTo(POINT));
     }
     }
@@ -67,7 +70,8 @@ public class CentroidCalculatorTests extends ESTestCase {
                 "-4.3847623 55.2260539,-4.3847341 55.2260432,-4.3847046 55.2260279,-4.3846738 55.2260062,-4.3846496 55.2259844," +
                 "-4.3847623 55.2260539,-4.3847341 55.2260432,-4.3847046 55.2260279,-4.3846738 55.2260062,-4.3846496 55.2259844," +
                 "-4.3846429 55.2259737,-4.3846523 55.2259714,-4.384651 55.2259629,-4.3846541 55.2259549)," +
                 "-4.3846429 55.2259737,-4.3846523 55.2259714,-4.384651 55.2259629,-4.3846541 55.2259549)," +
                 "(-4.3846608 55.2259374,-4.3846559 55.2259502,-4.3846541 55.2259549,-4.3846608 55.2259374))");
                 "(-4.3846608 55.2259374,-4.3846559 55.2259502,-4.3846541 55.2259549,-4.3846608 55.2259374))");
-        CentroidCalculator calculator = new CentroidCalculator(geometry);
+        CentroidCalculator calculator = new CentroidCalculator();
+        calculator.add(geometry);
         assertThat(calculator.getX(), closeTo( -4.3848, 1e-4));
         assertThat(calculator.getX(), closeTo( -4.3848, 1e-4));
         assertThat(calculator.getY(), closeTo(55.22595, 1e-4));
         assertThat(calculator.getY(), closeTo(55.22595, 1e-4));
         assertThat(calculator.sumWeight(), closeTo(0, 1e-5));
         assertThat(calculator.sumWeight(), closeTo(0, 1e-5));
@@ -82,7 +86,8 @@ public class CentroidCalculatorTests extends ESTestCase {
         double[] xRunningAvg = new double[] { 10, 15, 20, 25, 30, 35, 40, 45, 50, 55 };
         double[] xRunningAvg = new double[] { 10, 15, 20, 25, 30, 35, 40, 45, 50, 55 };
 
 
         Point point = new Point(x[0], y[0]);
         Point point = new Point(x[0], y[0]);
-        CentroidCalculator calculator = new CentroidCalculator(point);
+        CentroidCalculator calculator = new CentroidCalculator();
+        calculator.add(point);
         assertThat(calculator.getX(), equalTo(xRunningAvg[0]));
         assertThat(calculator.getX(), equalTo(xRunningAvg[0]));
         assertThat(calculator.getY(), equalTo(yRunningAvg[0]));
         assertThat(calculator.getY(), equalTo(yRunningAvg[0]));
         for (int i = 1; i < 10; i++) {
         for (int i = 1; i < 10; i++) {
@@ -91,79 +96,74 @@ public class CentroidCalculatorTests extends ESTestCase {
             System.arraycopy(x, 0, subX, 0, i + 1);
             System.arraycopy(x, 0, subX, 0, i + 1);
             System.arraycopy(y, 0, subY, 0, i + 1);
             System.arraycopy(y, 0, subY, 0, i + 1);
             Geometry geometry  = new Line(subX, subY);
             Geometry geometry  = new Line(subX, subY);
-            calculator = new CentroidCalculator(geometry);
+            calculator = new CentroidCalculator();
+            calculator.add(geometry);
             assertEquals(xRunningAvg[i], calculator.getX(), DELTA);
             assertEquals(xRunningAvg[i], calculator.getX(), DELTA);
             assertEquals(yRunningAvg[i], calculator.getY(), DELTA);
             assertEquals(yRunningAvg[i], calculator.getY(), DELTA);
         }
         }
-        CentroidCalculator otherCalculator = new CentroidCalculator(new Point(0, 0));
-        calculator.addFrom(otherCalculator);
+        calculator.add(new Point(0, 0));
         assertEquals(55.0, calculator.getX(), DELTA);
         assertEquals(55.0, calculator.getX(), DELTA);
         assertEquals(5.5, calculator.getY(), DELTA);
         assertEquals(5.5, calculator.getY(), DELTA);
     }
     }
 
 
     public void testMultiLine() {
     public void testMultiLine() {
         MultiLine multiLine = GeometryTestUtils.randomMultiLine(false);
         MultiLine multiLine = GeometryTestUtils.randomMultiLine(false);
-        double sumLineX = 0;
-        double sumLineY = 0;
-        double sumLineWeight = 0;
+        CentroidCalculator lineCalculator = new CentroidCalculator();
         for (Line line : multiLine) {
         for (Line line : multiLine) {
-            CentroidCalculator calculator = new CentroidCalculator(line);
-            sumLineX += calculator.compSumX.value();
-            sumLineY += calculator.compSumY.value();
-            sumLineWeight += calculator.compSumWeight.value();
+            lineCalculator.add(line);
         }
         }
-        CentroidCalculator calculator = new CentroidCalculator(multiLine);
+        CentroidCalculator calculator = new CentroidCalculator();
+        calculator.add(multiLine);
 
 
-        assertEquals(sumLineX / sumLineWeight, calculator.getX(), DELTA);
-        assertEquals(sumLineY / sumLineWeight, calculator.getY(), DELTA);
-        assertEquals(sumLineWeight, calculator.sumWeight(), DELTA);
+        assertEquals(lineCalculator.getX(), calculator.getX(), DELTA);
+        assertEquals(lineCalculator.getY(), calculator.getY(), DELTA);
+        assertEquals(lineCalculator.sumWeight(), calculator.sumWeight(), DELTA);
+        assertThat(lineCalculator.getDimensionalShapeType(), equalTo(calculator.getDimensionalShapeType()));
         assertThat(calculator.getDimensionalShapeType(), equalTo(LINE));
         assertThat(calculator.getDimensionalShapeType(), equalTo(LINE));
     }
     }
 
 
     public void testMultiPoint() {
     public void testMultiPoint() {
         MultiPoint multiPoint = GeometryTestUtils.randomMultiPoint(false);
         MultiPoint multiPoint = GeometryTestUtils.randomMultiPoint(false);
-        double sumPointX = 0;
-        double sumPointY = 0;
-        double sumPointWeight = 0;
+        CentroidCalculator pointCalculator = new CentroidCalculator();
         for (Point point : multiPoint) {
         for (Point point : multiPoint) {
-            sumPointX += point.getX();
-            sumPointY += point.getY();
-            sumPointWeight += 1;
+            pointCalculator.add(point);
         }
         }
-
-        CentroidCalculator calculator = new CentroidCalculator(multiPoint);
-        assertEquals(sumPointX / sumPointWeight, calculator.getX(), DELTA);
-        assertEquals(sumPointY / sumPointWeight, calculator.getY(), DELTA);
-        assertEquals(sumPointWeight, calculator.sumWeight(), DELTA);
+        CentroidCalculator calculator = new CentroidCalculator();
+        calculator.add(multiPoint);
+        assertEquals(pointCalculator.getX(), calculator.getX(), DELTA);
+        assertEquals(pointCalculator.getY(), calculator.getY(), DELTA);
+        assertEquals(pointCalculator.sumWeight(), calculator.sumWeight(), DELTA);
         assertThat(calculator.getDimensionalShapeType(), equalTo(POINT));
         assertThat(calculator.getDimensionalShapeType(), equalTo(POINT));
 
 
     }
     }
 
 
-    public void testRoundingErrorAndNormalization() {
+    public void testRoundingErrorAndNormalization() throws IOException {
         double lonA = GeometryTestUtils.randomLon();
         double lonA = GeometryTestUtils.randomLon();
         double latA = GeometryTestUtils.randomLat();
         double latA = GeometryTestUtils.randomLat();
         double lonB = randomValueOtherThanMany((l) -> Math.abs(l - lonA) <= GeoUtils.TOLERANCE, GeometryTestUtils::randomLon);
         double lonB = randomValueOtherThanMany((l) -> Math.abs(l - lonA) <= GeoUtils.TOLERANCE, GeometryTestUtils::randomLon);
         double latB = randomValueOtherThanMany((l) -> Math.abs(l - latA) <= GeoUtils.TOLERANCE, GeometryTestUtils::randomLat);
         double latB = randomValueOtherThanMany((l) -> Math.abs(l - latA) <= GeoUtils.TOLERANCE, GeometryTestUtils::randomLat);
         {
         {
             Line line = new Line(new double[]{180.0, 180.0}, new double[]{latA, latB});
             Line line = new Line(new double[]{180.0, 180.0}, new double[]{latA, latB});
-            assertThat(new CentroidCalculator(line).getX(), anyOf(equalTo(179.99999999999997),
-                equalTo(180.0), equalTo(-179.99999999999997)));
+            GeoShapeValues.GeoShapeValue value = GeoTestUtils.geoShapeValue(line);
+            assertThat(value.lon(), anyOf(equalTo(179.99999991618097), equalTo(-180.0)));
         }
         }
 
 
         {
         {
             Line line = new Line(new double[]{-180.0, -180.0}, new double[]{latA, latB});
             Line line = new Line(new double[]{-180.0, -180.0}, new double[]{latA, latB});
-            assertThat(new CentroidCalculator(line).getX(), anyOf(equalTo(179.99999999999997),
-                equalTo(180.0), equalTo(-179.99999999999997)));
+            GeoShapeValues.GeoShapeValue value = GeoTestUtils.geoShapeValue(line);
+            assertThat(value.lon(), anyOf(equalTo(179.99999991618097), equalTo(-180.0)));
         }
         }
 
 
         {
         {
             Line line = new Line(new double[]{lonA, lonB}, new double[] { 90.0, 90.0 });
             Line line = new Line(new double[]{lonA, lonB}, new double[] { 90.0, 90.0 });
-            assertThat(new CentroidCalculator(line).getY(), anyOf(equalTo(90.0), equalTo(89.99999999999999)));
+            GeoShapeValues.GeoShapeValue value = GeoTestUtils.geoShapeValue(line);
+            assertThat(value.lat(), equalTo(89.99999995809048));
         }
         }
 
 
         {
         {
             Line line = new Line(new double[]{lonA, lonB}, new double[] { -90.0, -90.0 });
             Line line = new Line(new double[]{lonA, lonB}, new double[] { -90.0, -90.0 });
-            assertThat(new CentroidCalculator(line).getY(), anyOf(equalTo(-90.0), equalTo(-89.99999999999999)));
+            GeoShapeValues.GeoShapeValue value = GeoTestUtils.geoShapeValue(line);
+            assertThat(value.lat(), equalTo(-90.0));
         }
         }
     }
     }
 
 
@@ -183,7 +183,8 @@ public class CentroidCalculatorTests extends ESTestCase {
                     inner = new LinearRing(new double[]{-40, -40, 30, 30, -40}, new double[]{-40, 30, 30, -40, -40});
                     inner = new LinearRing(new double[]{-40, -40, 30, 30, -40}, new double[]{-40, 30, 30, -40, -40});
                 }
                 }
                 final double POLY_CENTROID = 4.803921568627451;
                 final double POLY_CENTROID = 4.803921568627451;
-                CentroidCalculator calculator = new CentroidCalculator(new Polygon(outer, Collections.singletonList(inner)));
+                CentroidCalculator calculator = new CentroidCalculator();
+                calculator.add(new Polygon(outer, Collections.singletonList(inner)));
                 assertEquals(POLY_CENTROID, calculator.getX(), DELTA);
                 assertEquals(POLY_CENTROID, calculator.getX(), DELTA);
                 assertEquals(POLY_CENTROID, calculator.getY(), DELTA);
                 assertEquals(POLY_CENTROID, calculator.getY(), DELTA);
                 assertThat(calculator.sumWeight(), equalTo(5100.0));
                 assertThat(calculator.sumWeight(), equalTo(5100.0));
@@ -193,7 +194,8 @@ public class CentroidCalculatorTests extends ESTestCase {
 
 
     public void testRectangle() {
     public void testRectangle() {
         for (int i = 0; i < 100; i++) {
         for (int i = 0; i < 100; i++) {
-            CentroidCalculator calculator = new CentroidCalculator(GeometryTestUtils.randomRectangle());
+            CentroidCalculator calculator = new CentroidCalculator();
+            calculator.add(GeometryTestUtils.randomRectangle());
             assertThat(calculator.sumWeight(), greaterThan(0.0));
             assertThat(calculator.sumWeight(), greaterThan(0.0));
         }
         }
     }
     }
@@ -201,9 +203,10 @@ public class CentroidCalculatorTests extends ESTestCase {
     public void testLineAsClosedPoint() {
     public void testLineAsClosedPoint() {
         double lon = GeometryTestUtils.randomLon();
         double lon = GeometryTestUtils.randomLon();
         double lat = GeometryTestUtils.randomLat();
         double lat = GeometryTestUtils.randomLat();
-        CentroidCalculator calculator = new CentroidCalculator(new Line(new double[] {lon, lon}, new double[] { lat, lat}));
-        assertThat(calculator.getX(), equalTo(GeoUtils.normalizeLon(lon)));
-        assertThat(calculator.getY(), equalTo(GeoUtils.normalizeLat(lat)));
+        CentroidCalculator calculator = new CentroidCalculator();
+        calculator.add(new Line(new double[] {lon, lon}, new double[] { lat, lat}));
+        assertThat(calculator.getX(), equalTo(lon));
+        assertThat(calculator.getY(), equalTo(lat));
         assertThat(calculator.sumWeight(), equalTo(1.0));
         assertThat(calculator.sumWeight(), equalTo(1.0));
     }
     }
 
 
@@ -225,10 +228,12 @@ public class CentroidCalculatorTests extends ESTestCase {
         }
         }
 
 
         Line line = new Line(x, y);
         Line line = new Line(x, y);
-        CentroidCalculator lineCalculator = new CentroidCalculator(line);
+        CentroidCalculator lineCalculator = new CentroidCalculator();
+        lineCalculator.add(line);
 
 
         Polygon polygon = new Polygon(new LinearRing(x, y));
         Polygon polygon = new Polygon(new LinearRing(x, y));
-        CentroidCalculator calculator = new CentroidCalculator(polygon);
+        CentroidCalculator calculator = new CentroidCalculator();
+        calculator.add(polygon);
 
 
         // sometimes precision issues yield non-zero areas. must verify that area is close to zero
         // sometimes precision issues yield non-zero areas. must verify that area is close to zero
         if (calculator.getDimensionalShapeType() == POLYGON) {
         if (calculator.getDimensionalShapeType() == POLYGON) {
@@ -237,14 +242,15 @@ public class CentroidCalculatorTests extends ESTestCase {
             assertThat(calculator.getDimensionalShapeType(), equalTo(LINE));
             assertThat(calculator.getDimensionalShapeType(), equalTo(LINE));
             assertThat(calculator.getX(), equalTo(lineCalculator.getX()));
             assertThat(calculator.getX(), equalTo(lineCalculator.getX()));
             assertThat(calculator.getY(), equalTo(lineCalculator.getY()));
             assertThat(calculator.getY(), equalTo(lineCalculator.getY()));
-            assertThat(calculator.sumWeight(), equalTo(lineCalculator.compSumWeight.value()));
+            assertThat(calculator.sumWeight(), equalTo(lineCalculator.sumWeight()));
         }
         }
     }
     }
 
 
     public void testPolygonWithEqualSizedHole() {
     public void testPolygonWithEqualSizedHole() {
         Polygon polyWithHole = new Polygon(new LinearRing(new double[]{-50, 50, 50, -50, -50}, new double[]{-50, -50, 50, 50, -50}),
         Polygon polyWithHole = new Polygon(new LinearRing(new double[]{-50, 50, 50, -50, -50}, new double[]{-50, -50, 50, 50, -50}),
             Collections.singletonList(new LinearRing(new double[]{-50, -50, 50, 50, -50}, new double[]{-50, 50, 50, -50, -50})));
             Collections.singletonList(new LinearRing(new double[]{-50, -50, 50, 50, -50}, new double[]{-50, 50, 50, -50, -50})));
-        CentroidCalculator calculator = new CentroidCalculator(polyWithHole);
+        CentroidCalculator calculator = new CentroidCalculator();
+        calculator.add(polyWithHole);
         assertThat(calculator.getX(), equalTo(0.0));
         assertThat(calculator.getX(), equalTo(0.0));
         assertThat(calculator.getY(), equalTo(0.0));
         assertThat(calculator.getY(), equalTo(0.0));
         assertThat(calculator.sumWeight(), equalTo(400.0));
         assertThat(calculator.sumWeight(), equalTo(400.0));
@@ -255,12 +261,11 @@ public class CentroidCalculatorTests extends ESTestCase {
         Point point = GeometryTestUtils.randomPoint(false);
         Point point = GeometryTestUtils.randomPoint(false);
         Polygon polygon = new Polygon(new LinearRing(new double[] { point.getX(), point.getX(), point.getX(), point.getX() },
         Polygon polygon = new Polygon(new LinearRing(new double[] { point.getX(), point.getX(), point.getX(), point.getX() },
             new double[] { point.getY(), point.getY(), point.getY(), point.getY() }));
             new double[] { point.getY(), point.getY(), point.getY(), point.getY() }));
-        CentroidCalculator calculator = new CentroidCalculator(polygon);
-        double normLon = GeoUtils.normalizeLon(point.getX());
-        double normLat = GeoUtils.normalizeLat(point.getY());
+        CentroidCalculator calculator = new CentroidCalculator();
+        calculator.add(polygon);
         // make calculation to account for floating-point arithmetic
         // make calculation to account for floating-point arithmetic
-        assertThat(calculator.getX(), equalTo((3 * normLon) / 3));
-        assertThat(calculator.getY(), equalTo((3 * normLat) / 3));
+        assertThat(calculator.getX(), equalTo((3 * point.getX()) / 3));
+        assertThat(calculator.getY(), equalTo((3 * point.getY()) / 3));
         assertThat(calculator.sumWeight(), equalTo(3.0));
         assertThat(calculator.sumWeight(), equalTo(3.0));
         assertThat(calculator.getDimensionalShapeType(), equalTo(POINT));
         assertThat(calculator.getDimensionalShapeType(), equalTo(POINT));
     }
     }
@@ -301,16 +306,12 @@ public class CentroidCalculatorTests extends ESTestCase {
         DimensionalShapeType dimensionalShapeType = numPolygons > 0 ? POLYGON : numLines > 0 ? LINE : POINT;
         DimensionalShapeType dimensionalShapeType = numPolygons > 0 ? POLYGON : numLines > 0 ? LINE : POINT;
 
 
         // addFromCalculator is only adding from shapes with the highest dimensionalShapeType
         // addFromCalculator is only adding from shapes with the highest dimensionalShapeType
-        CentroidCalculator addFromCalculator = null;
+        CentroidCalculator addFromCalculator = new CentroidCalculator();
         for (Geometry shape : shapes) {
         for (Geometry shape : shapes) {
             if ((shape.type() == ShapeType.MULTIPOLYGON || shape.type() == ShapeType.POLYGON) ||
             if ((shape.type() == ShapeType.MULTIPOLYGON || shape.type() == ShapeType.POLYGON) ||
                 (dimensionalShapeType == LINE && (shape.type() == ShapeType.LINESTRING || shape.type() == ShapeType.MULTILINESTRING)) ||
                 (dimensionalShapeType == LINE && (shape.type() == ShapeType.LINESTRING || shape.type() == ShapeType.MULTILINESTRING)) ||
                 (dimensionalShapeType == POINT && (shape.type() == ShapeType.POINT || shape.type() == ShapeType.MULTIPOINT))) {
                 (dimensionalShapeType == POINT && (shape.type() == ShapeType.POINT || shape.type() == ShapeType.MULTIPOINT))) {
-                if (addFromCalculator == null) {
-                    addFromCalculator = new CentroidCalculator(shape);
-                } else {
-                    addFromCalculator.addFrom(new CentroidCalculator(shape));
-                }
+                addFromCalculator.add(shape);
             }
             }
         }
         }
 
 
@@ -322,7 +323,8 @@ public class CentroidCalculatorTests extends ESTestCase {
         }
         }
 
 
         GeometryCollection<Geometry> collection = new GeometryCollection<>(shapes);
         GeometryCollection<Geometry> collection = new GeometryCollection<>(shapes);
-        CentroidCalculator calculator = new CentroidCalculator(collection);
+        CentroidCalculator calculator = new CentroidCalculator();
+        calculator.add(collection);
 
 
         assertNotNull(addFromCalculator.getDimensionalShapeType());
         assertNotNull(addFromCalculator.getDimensionalShapeType());
         assertThat(addFromCalculator.getDimensionalShapeType(), equalTo(dimensionalShapeType));
         assertThat(addFromCalculator.getDimensionalShapeType(), equalTo(dimensionalShapeType));
@@ -332,25 +334,28 @@ public class CentroidCalculatorTests extends ESTestCase {
         assertEquals(calculator.sumWeight(), addFromCalculator.sumWeight(), DELTA);
         assertEquals(calculator.sumWeight(), addFromCalculator.sumWeight(), DELTA);
     }
     }
 
 
-    public void testAddFrom() {
+    public void testAddDifferentDimensionalType() {
         Point point = GeometryTestUtils.randomPoint(false);
         Point point = GeometryTestUtils.randomPoint(false);
         Line line = GeometryTestUtils.randomLine(false);
         Line line = GeometryTestUtils.randomLine(false);
         Polygon polygon = GeometryTestUtils.randomPolygon(false);
         Polygon polygon = GeometryTestUtils.randomPolygon(false);
 
 
         // point add point
         // point add point
         {
         {
-            CentroidCalculator calculator = new CentroidCalculator(point);
-            calculator.addFrom(new CentroidCalculator(point));
-            assertThat(calculator.compSumX.value(), equalTo(2 * point.getX()));
-            assertThat(calculator.compSumY.value(), equalTo(2 * point.getY()));
+            CentroidCalculator calculator = new CentroidCalculator();
+            calculator.add(point);
+            calculator.add(point);
+            assertThat(calculator.getX(), equalTo(point.getX()));
+            assertThat(calculator.getY(), equalTo(point.getY()));
             assertThat(calculator.sumWeight(), equalTo(2.0));
             assertThat(calculator.sumWeight(), equalTo(2.0));
         }
         }
 
 
         // point add line/polygon
         // point add line/polygon
         {
         {
-            CentroidCalculator lineCalculator = new CentroidCalculator(line);
-            CentroidCalculator calculator = new CentroidCalculator(point);
-            calculator.addFrom(lineCalculator);
+            CentroidCalculator lineCalculator = new CentroidCalculator();
+            lineCalculator.add(line);
+            CentroidCalculator calculator = new CentroidCalculator();
+            calculator.add(point);
+            calculator.add(line);
             assertThat(calculator.getX(), equalTo(lineCalculator.getX()));
             assertThat(calculator.getX(), equalTo(lineCalculator.getX()));
             assertThat(calculator.getY(), equalTo(lineCalculator.getY()));
             assertThat(calculator.getY(), equalTo(lineCalculator.getY()));
             assertThat(calculator.sumWeight(), equalTo(lineCalculator.sumWeight()));
             assertThat(calculator.sumWeight(), equalTo(lineCalculator.sumWeight()));
@@ -358,9 +363,11 @@ public class CentroidCalculatorTests extends ESTestCase {
 
 
         // line add point
         // line add point
         {
         {
-            CentroidCalculator lineCalculator = new CentroidCalculator(line);
-            CentroidCalculator calculator = new CentroidCalculator(line);
-            calculator.addFrom(new CentroidCalculator(point));
+            CentroidCalculator lineCalculator = new CentroidCalculator();
+            lineCalculator.add(line);
+            CentroidCalculator calculator = new CentroidCalculator();
+            calculator.add(line);
+            calculator.add(point);
             assertThat(calculator.getX(), equalTo(lineCalculator.getX()));
             assertThat(calculator.getX(), equalTo(lineCalculator.getX()));
             assertThat(calculator.getY(), equalTo(lineCalculator.getY()));
             assertThat(calculator.getY(), equalTo(lineCalculator.getY()));
             assertThat(calculator.sumWeight(), equalTo(lineCalculator.sumWeight()));
             assertThat(calculator.sumWeight(), equalTo(lineCalculator.sumWeight()));
@@ -368,19 +375,23 @@ public class CentroidCalculatorTests extends ESTestCase {
 
 
         // line add line
         // line add line
         {
         {
-            CentroidCalculator lineCalculator = new CentroidCalculator(line);
-            CentroidCalculator calculator = new CentroidCalculator(line);
-            calculator.addFrom(lineCalculator);
-            assertEquals(2 * lineCalculator.compSumX.value(), calculator.compSumX.value(), DELTA);
-            assertEquals(2 * lineCalculator.compSumY.value(), calculator.compSumY.value(), DELTA);
+            CentroidCalculator lineCalculator = new CentroidCalculator();
+            lineCalculator.add(line);
+            CentroidCalculator calculator = new CentroidCalculator();
+            calculator.add(line);
+            calculator.add(line);
+            assertEquals(lineCalculator.getX(), calculator.getX(), DELTA);
+            assertEquals(lineCalculator.getY(), calculator.getY(), DELTA);
             assertEquals(2 * lineCalculator.sumWeight(), calculator.sumWeight(), DELTA);
             assertEquals(2 * lineCalculator.sumWeight(), calculator.sumWeight(), DELTA);
         }
         }
 
 
         // line add polygon
         // line add polygon
         {
         {
-            CentroidCalculator polygonCalculator = new CentroidCalculator(polygon);
-            CentroidCalculator calculator = new CentroidCalculator(line);
-            calculator.addFrom(polygonCalculator);
+            CentroidCalculator polygonCalculator = new CentroidCalculator();
+            polygonCalculator.add(polygon);
+            CentroidCalculator calculator = new CentroidCalculator();
+            calculator.add(line);
+            calculator.add(polygon);
             assertThat(calculator.getX(), equalTo(polygonCalculator.getX()));
             assertThat(calculator.getX(), equalTo(polygonCalculator.getX()));
             assertThat(calculator.getY(), equalTo(polygonCalculator.getY()));
             assertThat(calculator.getY(), equalTo(polygonCalculator.getY()));
             assertThat(calculator.sumWeight(), equalTo(calculator.sumWeight()));
             assertThat(calculator.sumWeight(), equalTo(calculator.sumWeight()));
@@ -388,9 +399,11 @@ public class CentroidCalculatorTests extends ESTestCase {
 
 
         // polygon add point/line
         // polygon add point/line
         {
         {
-            CentroidCalculator polygonCalculator = new CentroidCalculator(polygon);
-            CentroidCalculator calculator = new CentroidCalculator(polygon);
-            calculator.addFrom(new CentroidCalculator(randomBoolean() ? point : line));
+            CentroidCalculator polygonCalculator = new CentroidCalculator();
+            polygonCalculator.add(polygon);
+            CentroidCalculator calculator = new CentroidCalculator();
+            calculator.add(polygon);
+            calculator.add(randomBoolean() ? point : line);
             assertThat(calculator.getX(), equalTo(polygonCalculator.getX()));
             assertThat(calculator.getX(), equalTo(polygonCalculator.getX()));
             assertThat(calculator.getY(), equalTo(polygonCalculator.getY()));
             assertThat(calculator.getY(), equalTo(polygonCalculator.getY()));
             assertThat(calculator.sumWeight(), equalTo(calculator.sumWeight()));
             assertThat(calculator.sumWeight(), equalTo(calculator.sumWeight()));
@@ -398,11 +411,13 @@ public class CentroidCalculatorTests extends ESTestCase {
 
 
         // polygon add polygon
         // polygon add polygon
         {
         {
-            CentroidCalculator polygonCalculator = new CentroidCalculator(polygon);
-            CentroidCalculator calculator = new CentroidCalculator(polygon);
-            calculator.addFrom(polygonCalculator);
-            assertThat(calculator.compSumX.value(), equalTo(2 * polygonCalculator.compSumX.value()));
-            assertThat(calculator.compSumY.value(), equalTo(2 * polygonCalculator.compSumY.value()));
+            CentroidCalculator polygonCalculator = new CentroidCalculator();
+            polygonCalculator.add(polygon);
+            CentroidCalculator calculator = new CentroidCalculator();
+            calculator.add(polygon);
+            calculator.add(polygon);
+            assertEquals(polygonCalculator.getX(), calculator.getX(), DELTA);
+            assertEquals(polygonCalculator.getY(), calculator.getY(), DELTA);
             assertThat(calculator.sumWeight(), equalTo(2 * polygonCalculator.sumWeight()));
             assertThat(calculator.sumWeight(), equalTo(2 * polygonCalculator.sumWeight()));
         }
         }
     }
     }

+ 10 - 0
x-pack/plugin/spatial/src/test/java/org/elasticsearch/xpack/spatial/index/fielddata/TestCoordinateEncoder.java

@@ -32,4 +32,14 @@ public class TestCoordinateEncoder implements CoordinateEncoder {
     public double decodeY(int y) {
     public double decodeY(int y) {
         return y;
         return y;
     }
     }
+
+    @Override
+    public double normalizeX(double x) {
+        return x;
+    }
+
+    @Override
+    public double normalizeY(double y) {
+        return y;
+    }
 }
 }

+ 9 - 21
x-pack/plugin/spatial/src/test/java/org/elasticsearch/xpack/spatial/search/aggregations/bucket/geogrid/GeoGridTilerTests.java

@@ -27,8 +27,6 @@ import org.elasticsearch.indices.breaker.CircuitBreakerService;
 import org.elasticsearch.indices.breaker.HierarchyCircuitBreakerService;
 import org.elasticsearch.indices.breaker.HierarchyCircuitBreakerService;
 import org.elasticsearch.search.aggregations.bucket.geogrid.GeoTileUtils;
 import org.elasticsearch.search.aggregations.bucket.geogrid.GeoTileUtils;
 import org.elasticsearch.test.ESTestCase;
 import org.elasticsearch.test.ESTestCase;
-import org.elasticsearch.xpack.spatial.index.fielddata.CoordinateEncoder;
-import org.elasticsearch.xpack.spatial.index.fielddata.GeometryDocValueReader;
 import org.elasticsearch.xpack.spatial.index.fielddata.GeoRelation;
 import org.elasticsearch.xpack.spatial.index.fielddata.GeoRelation;
 import org.elasticsearch.xpack.spatial.index.fielddata.GeoShapeValues;
 import org.elasticsearch.xpack.spatial.index.fielddata.GeoShapeValues;
 
 
@@ -44,8 +42,8 @@ import static org.elasticsearch.search.aggregations.bucket.geogrid.GeoTileUtils.
 import static org.elasticsearch.search.aggregations.bucket.geogrid.GeoTileUtils.NORMALIZED_NEGATIVE_LATITUDE_MASK;
 import static org.elasticsearch.search.aggregations.bucket.geogrid.GeoTileUtils.NORMALIZED_NEGATIVE_LATITUDE_MASK;
 import static org.elasticsearch.xpack.spatial.util.GeoTestUtils.encodeDecodeLat;
 import static org.elasticsearch.xpack.spatial.util.GeoTestUtils.encodeDecodeLat;
 import static org.elasticsearch.xpack.spatial.util.GeoTestUtils.encodeDecodeLon;
 import static org.elasticsearch.xpack.spatial.util.GeoTestUtils.encodeDecodeLon;
+import static org.elasticsearch.xpack.spatial.util.GeoTestUtils.geoShapeValue;
 import static org.elasticsearch.xpack.spatial.util.GeoTestUtils.randomBBox;
 import static org.elasticsearch.xpack.spatial.util.GeoTestUtils.randomBBox;
-import static org.elasticsearch.xpack.spatial.util.GeoTestUtils.geometryDocValueReader;
 import static org.hamcrest.Matchers.equalTo;
 import static org.hamcrest.Matchers.equalTo;
 
 
 public class GeoGridTilerTests extends ESTestCase {
 public class GeoGridTilerTests extends ESTestCase {
@@ -63,8 +61,7 @@ public class GeoGridTilerTests extends ESTestCase {
         Rectangle tile = GeoTileUtils.toBoundingBox(1309, 3166, 13);
         Rectangle tile = GeoTileUtils.toBoundingBox(1309, 3166, 13);
         Rectangle shapeRectangle = new Rectangle(tile.getMinX() + 0.00001, tile.getMaxX() - 0.00001,
         Rectangle shapeRectangle = new Rectangle(tile.getMinX() + 0.00001, tile.getMaxX() - 0.00001,
             tile.getMaxY() - 0.00001,  tile.getMinY() + 0.00001);
             tile.getMaxY() - 0.00001,  tile.getMinY() + 0.00001);
-        GeometryDocValueReader reader = geometryDocValueReader(shapeRectangle, CoordinateEncoder.GEO);
-        GeoShapeValues.GeoShapeValue value = new GeoShapeValues.GeoShapeValue(reader);
+        GeoShapeValues.GeoShapeValue value = geoShapeValue(shapeRectangle);
         // test shape within tile bounds
         // test shape within tile bounds
         {
         {
             GeoShapeCellValues values = new GeoShapeCellValues(null, precision, GEOTILE, NOOP_BREAKER);
             GeoShapeCellValues values = new GeoShapeCellValues(null, precision, GEOTILE, NOOP_BREAKER);
@@ -115,9 +112,8 @@ public class GeoGridTilerTests extends ESTestCase {
                 }
                 }
             }, () -> boxToGeo(randomBBox())));
             }, () -> boxToGeo(randomBBox())));
 
 
-            GeometryDocValueReader reader = geometryDocValueReader(geometry, CoordinateEncoder.GEO);
             GeoBoundingBox geoBoundingBox = randomBBox();
             GeoBoundingBox geoBoundingBox = randomBBox();
-            GeoShapeValues.GeoShapeValue value = new GeoShapeValues.GeoShapeValue(reader);
+            GeoShapeValues.GeoShapeValue value = geoShapeValue(geometry);
             GeoShapeCellValues cellValues = new GeoShapeCellValues(null, precision, GEOTILE, NOOP_BREAKER);
             GeoShapeCellValues cellValues = new GeoShapeCellValues(null, precision, GEOTILE, NOOP_BREAKER);
 
 
             int numTiles = new BoundedGeoTileGridTiler(geoBoundingBox).setValues(cellValues, value, precision);
             int numTiles = new BoundedGeoTileGridTiler(geoBoundingBox).setValues(cellValues, value, precision);
@@ -142,8 +138,7 @@ public class GeoGridTilerTests extends ESTestCase {
                 }
                 }
             }, () -> boxToGeo(randomBBox())));
             }, () -> boxToGeo(randomBBox())));
 
 
-            GeometryDocValueReader reader = geometryDocValueReader(geometry, CoordinateEncoder.GEO);
-            GeoShapeValues.GeoShapeValue value = new GeoShapeValues.GeoShapeValue(reader);
+            GeoShapeValues.GeoShapeValue value = geoShapeValue(geometry);
             GeoShapeCellValues unboundedCellValues = new GeoShapeCellValues(null, precision, GEOTILE, NOOP_BREAKER);
             GeoShapeCellValues unboundedCellValues = new GeoShapeCellValues(null, precision, GEOTILE, NOOP_BREAKER);
             int numTiles = GEOTILE.setValues(unboundedCellValues, value, precision);
             int numTiles = GEOTILE.setValues(unboundedCellValues, value, precision);
             int expected = numTiles(value, precision);
             int expected = numTiles(value, precision);
@@ -175,8 +170,7 @@ public class GeoGridTilerTests extends ESTestCase {
             if (point.getX() == GeoUtils.MAX_LON || point.getY() == -LATITUDE_MASK) {
             if (point.getX() == GeoUtils.MAX_LON || point.getY() == -LATITUDE_MASK) {
                 continue;
                 continue;
             }
             }
-            GeometryDocValueReader reader = geometryDocValueReader(point, CoordinateEncoder.GEO);
-            GeoShapeValues.GeoShapeValue value = new GeoShapeValues.GeoShapeValue(reader);
+            GeoShapeValues.GeoShapeValue value = geoShapeValue(point);
             GeoShapeCellValues unboundedCellValues = new GeoShapeCellValues(null, precision, GEOTILE, NOOP_BREAKER);
             GeoShapeCellValues unboundedCellValues = new GeoShapeCellValues(null, precision, GEOTILE, NOOP_BREAKER);
             int numTiles = GEOTILE.setValues(unboundedCellValues, value, precision);
             int numTiles = GEOTILE.setValues(unboundedCellValues, value, precision);
             assertThat(numTiles, equalTo(1));
             assertThat(numTiles, equalTo(1));
@@ -196,8 +190,7 @@ public class GeoGridTilerTests extends ESTestCase {
 
 
         Rectangle shapeRectangle = new Rectangle(tile.getMinX() + 0.00001, tile.getMaxX() - 0.00001,
         Rectangle shapeRectangle = new Rectangle(tile.getMinX() + 0.00001, tile.getMaxX() - 0.00001,
             tile.getMaxY() - 0.00001,  tile.getMinY() + 0.00001);
             tile.getMaxY() - 0.00001,  tile.getMinY() + 0.00001);
-        GeometryDocValueReader reader = geometryDocValueReader(shapeRectangle, CoordinateEncoder.GEO);
-        GeoShapeValues.GeoShapeValue value =  new GeoShapeValues.GeoShapeValue(reader);
+        GeoShapeValues.GeoShapeValue value = geoShapeValue(shapeRectangle);
 
 
         // test shape within tile bounds
         // test shape within tile bounds
         {
         {
@@ -315,8 +308,7 @@ public class GeoGridTilerTests extends ESTestCase {
         int precision = randomIntBetween(1, 4);
         int precision = randomIntBetween(1, 4);
         GeoShapeIndexer indexer = new GeoShapeIndexer(true, "test");
         GeoShapeIndexer indexer = new GeoShapeIndexer(true, "test");
         geometry = indexer.prepareForIndexing(geometry);
         geometry = indexer.prepareForIndexing(geometry);
-        GeometryDocValueReader reader = geometryDocValueReader(geometry, CoordinateEncoder.GEO);
-        GeoShapeValues.GeoShapeValue value = new GeoShapeValues.GeoShapeValue(reader);
+        GeoShapeValues.GeoShapeValue value = geoShapeValue(geometry);
         GeoShapeCellValues recursiveValues = new GeoShapeCellValues(null, precision, GEOTILE, NOOP_BREAKER);
         GeoShapeCellValues recursiveValues = new GeoShapeCellValues(null, precision, GEOTILE, NOOP_BREAKER);
         int recursiveCount;
         int recursiveCount;
         {
         {
@@ -343,10 +335,7 @@ public class GeoGridTilerTests extends ESTestCase {
 
 
     private void checkGeoHashSetValuesBruteAndRecursive(Geometry geometry) throws Exception {
     private void checkGeoHashSetValuesBruteAndRecursive(Geometry geometry) throws Exception {
         int precision = randomIntBetween(1, 3);
         int precision = randomIntBetween(1, 3);
-        GeoShapeIndexer indexer = new GeoShapeIndexer(true, "test");
-        geometry = indexer.prepareForIndexing(geometry);
-        GeometryDocValueReader reader = geometryDocValueReader(geometry, CoordinateEncoder.GEO);
-        GeoShapeValues.GeoShapeValue value = new GeoShapeValues.GeoShapeValue(reader);
+        GeoShapeValues.GeoShapeValue value = geoShapeValue(geometry);
         GeoShapeCellValues recursiveValues = new GeoShapeCellValues(null, precision, GEOHASH, NOOP_BREAKER);
         GeoShapeCellValues recursiveValues = new GeoShapeCellValues(null, precision, GEOHASH, NOOP_BREAKER);
         int recursiveCount;
         int recursiveCount;
         {
         {
@@ -466,8 +455,7 @@ public class GeoGridTilerTests extends ESTestCase {
     private void testCircuitBreaker(GeoGridTiler tiler) throws IOException {
     private void testCircuitBreaker(GeoGridTiler tiler) throws IOException {
         Geometry geometry = GeometryTestUtils.randomPolygon(false);
         Geometry geometry = GeometryTestUtils.randomPolygon(false);
         int precision = randomIntBetween(0, 3);
         int precision = randomIntBetween(0, 3);
-        GeometryDocValueReader reader = geometryDocValueReader(geometry, CoordinateEncoder.GEO);
-        GeoShapeValues.GeoShapeValue value =  new GeoShapeValues.GeoShapeValue(reader);
+        GeoShapeValues.GeoShapeValue value = geoShapeValue(geometry);
 
 
         List<Long> byteChangeHistory = new ArrayList<>();
         List<Long> byteChangeHistory = new ArrayList<>();
         if (precision == 0) {
         if (precision == 0) {

+ 2 - 7
x-pack/plugin/spatial/src/test/java/org/elasticsearch/xpack/spatial/search/aggregations/bucket/geogrid/GeoShapeGeoGridTestCase.java

@@ -37,8 +37,6 @@ import org.elasticsearch.search.aggregations.support.AggregationInspectionHelper
 import org.elasticsearch.search.aggregations.support.CoreValuesSourceType;
 import org.elasticsearch.search.aggregations.support.CoreValuesSourceType;
 import org.elasticsearch.search.aggregations.support.ValuesSourceType;
 import org.elasticsearch.search.aggregations.support.ValuesSourceType;
 import org.elasticsearch.xpack.spatial.LocalStateSpatialPlugin;
 import org.elasticsearch.xpack.spatial.LocalStateSpatialPlugin;
-import org.elasticsearch.xpack.spatial.index.fielddata.CoordinateEncoder;
-import org.elasticsearch.xpack.spatial.index.fielddata.GeometryDocValueReader;
 import org.elasticsearch.xpack.spatial.index.fielddata.GeoRelation;
 import org.elasticsearch.xpack.spatial.index.fielddata.GeoRelation;
 import org.elasticsearch.xpack.spatial.index.fielddata.GeoShapeValues;
 import org.elasticsearch.xpack.spatial.index.fielddata.GeoShapeValues;
 import org.elasticsearch.xpack.spatial.index.mapper.BinaryGeoShapeDocValuesField;
 import org.elasticsearch.xpack.spatial.index.mapper.BinaryGeoShapeDocValuesField;
@@ -57,7 +55,7 @@ import java.util.Set;
 import java.util.function.Consumer;
 import java.util.function.Consumer;
 
 
 import static org.elasticsearch.xpack.spatial.util.GeoTestUtils.binaryGeoShapeDocValuesField;
 import static org.elasticsearch.xpack.spatial.util.GeoTestUtils.binaryGeoShapeDocValuesField;
-import static org.elasticsearch.xpack.spatial.util.GeoTestUtils.geometryDocValueReader;
+import static org.elasticsearch.xpack.spatial.util.GeoTestUtils.geoShapeValue;
 import static org.hamcrest.Matchers.equalTo;
 import static org.hamcrest.Matchers.equalTo;
 
 
 public abstract class GeoShapeGeoGridTestCase<T extends InternalGeoGridBucket<T>> extends AggregatorTestCase {
 public abstract class GeoShapeGeoGridTestCase<T extends InternalGeoGridBucket<T>> extends AggregatorTestCase {
@@ -183,7 +181,6 @@ public abstract class GeoShapeGeoGridTestCase<T extends InternalGeoGridBucket<T>
         }
         }
 
 
         List<BinaryGeoShapeDocValuesField> docs = new ArrayList<>();
         List<BinaryGeoShapeDocValuesField> docs = new ArrayList<>();
-        List<Point> points = new ArrayList<>();
         for (int i = 0; i < numDocs; i++) {
         for (int i = 0; i < numDocs; i++) {
             Point p;
             Point p;
             p = randomPoint();
             p = randomPoint();
@@ -191,8 +188,7 @@ public abstract class GeoShapeGeoGridTestCase<T extends InternalGeoGridBucket<T>
             double y = GeoTestUtils.encodeDecodeLat(p.getY());
             double y = GeoTestUtils.encodeDecodeLat(p.getY());
             Rectangle pointTile = getTile(x, y, precision);
             Rectangle pointTile = getTile(x, y, precision);
 
 
-            GeometryDocValueReader reader = geometryDocValueReader(p, CoordinateEncoder.GEO);
-            GeoShapeValues.GeoShapeValue value = new GeoShapeValues.GeoShapeValue(reader);
+            GeoShapeValues.GeoShapeValue value = geoShapeValue(p);
             GeoRelation tileRelation =  value.relate(pointTile);
             GeoRelation tileRelation =  value.relate(pointTile);
             boolean intersectsBounds = boundsTop >= pointTile.getMinY() && boundsBottom <= pointTile.getMaxY()
             boolean intersectsBounds = boundsTop >= pointTile.getMinY() && boundsBottom <= pointTile.getMaxY()
                 && (boundsEastLeft <= pointTile.getMaxX() && boundsEastRight >= pointTile.getMinX()
                 && (boundsEastLeft <= pointTile.getMaxX() && boundsEastRight >= pointTile.getMinX()
@@ -201,7 +197,6 @@ public abstract class GeoShapeGeoGridTestCase<T extends InternalGeoGridBucket<T>
                 numDocsWithin += 1;
                 numDocsWithin += 1;
             }
             }
 
 
-            points.add(p);
             docs.add(binaryGeoShapeDocValuesField(FIELD_NAME, p));
             docs.add(binaryGeoShapeDocValuesField(FIELD_NAME, p));
         }
         }
 
 

+ 11 - 4
x-pack/plugin/spatial/src/test/java/org/elasticsearch/xpack/spatial/util/GeoTestUtils.java

@@ -27,6 +27,7 @@ import org.elasticsearch.geometry.Rectangle;
 import org.elasticsearch.index.mapper.GeoShapeIndexer;
 import org.elasticsearch.index.mapper.GeoShapeIndexer;
 import org.elasticsearch.xpack.spatial.index.fielddata.CentroidCalculator;
 import org.elasticsearch.xpack.spatial.index.fielddata.CentroidCalculator;
 import org.elasticsearch.xpack.spatial.index.fielddata.CoordinateEncoder;
 import org.elasticsearch.xpack.spatial.index.fielddata.CoordinateEncoder;
+import org.elasticsearch.xpack.spatial.index.fielddata.GeoShapeValues;
 import org.elasticsearch.xpack.spatial.index.fielddata.GeometryDocValueReader;
 import org.elasticsearch.xpack.spatial.index.fielddata.GeometryDocValueReader;
 import org.elasticsearch.xpack.spatial.index.fielddata.GeometryDocValueWriter;
 import org.elasticsearch.xpack.spatial.index.fielddata.GeometryDocValueWriter;
 import org.elasticsearch.xpack.spatial.index.mapper.BinaryGeoShapeDocValuesField;
 import org.elasticsearch.xpack.spatial.index.mapper.BinaryGeoShapeDocValuesField;
@@ -38,17 +39,25 @@ public class GeoTestUtils {
     public static GeometryDocValueReader geometryDocValueReader(Geometry geometry, CoordinateEncoder encoder) throws IOException {
     public static GeometryDocValueReader geometryDocValueReader(Geometry geometry, CoordinateEncoder encoder) throws IOException {
         GeoShapeIndexer indexer = new GeoShapeIndexer(true, "test");
         GeoShapeIndexer indexer = new GeoShapeIndexer(true, "test");
         geometry = indexer.prepareForIndexing(geometry);
         geometry = indexer.prepareForIndexing(geometry);
+        CentroidCalculator centroidCalculator = new CentroidCalculator();
+        centroidCalculator.add(geometry);
         GeometryDocValueReader reader = new GeometryDocValueReader();
         GeometryDocValueReader reader = new GeometryDocValueReader();
-        reader.reset(GeometryDocValueWriter.write(indexer.indexShape(null, geometry), encoder, new CentroidCalculator(geometry)));
+        reader.reset(GeometryDocValueWriter.write(indexer.indexShape(null, geometry), encoder, centroidCalculator));
         return reader;
         return reader;
     }
     }
 
 
     public static BinaryGeoShapeDocValuesField binaryGeoShapeDocValuesField(String name, Geometry geometry) {
     public static BinaryGeoShapeDocValuesField binaryGeoShapeDocValuesField(String name, Geometry geometry) {
         GeoShapeIndexer indexer = new GeoShapeIndexer(true, name);
         GeoShapeIndexer indexer = new GeoShapeIndexer(true, name);
         geometry = indexer.prepareForIndexing(geometry);
         geometry = indexer.prepareForIndexing(geometry);
-        return new BinaryGeoShapeDocValuesField(name, indexer.indexShape(null, geometry) , new CentroidCalculator(geometry));
+        BinaryGeoShapeDocValuesField field = new BinaryGeoShapeDocValuesField(name);
+        field.add(indexer.indexShape(null, geometry) , geometry);
+        return field;
     }
     }
 
 
+    public static GeoShapeValues.GeoShapeValue geoShapeValue(Geometry geometry) throws IOException {
+        GeometryDocValueReader reader = geometryDocValueReader(geometry, CoordinateEncoder.GEO);
+        return new GeoShapeValues.GeoShapeValue(reader);
+    }
 
 
     public static GeoBoundingBox randomBBox() {
     public static GeoBoundingBox randomBBox() {
         Rectangle rectangle = GeometryTestUtils.randomRectangle();
         Rectangle rectangle = GeometryTestUtils.randomRectangle();
@@ -77,6 +86,4 @@ public class GeoTestUtils {
         Geometry geometry = new GeometryParser(true, true, true).parse(parser);
         Geometry geometry = new GeometryParser(true, true, true).parse(parser);
         return new GeoShapeIndexer(true, "indexer").prepareForIndexing(geometry);
         return new GeoShapeIndexer(true, "indexer").prepareForIndexing(geometry);
     }
     }
-
-
 }
 }