Only Polygon and MultiPolygon need `orientation` property

Removing the `orientation` field from ShapeBuilder, only leaving it in
PolygonBuilder and MultiPolygonBuilder which are the only places where
it is actually used and parsed at the moment.
This commit is contained in:
Christoph Büscher 2015-12-04 15:59:28 +01:00
parent 081e0e9d61
commit 7d2509cd63
12 changed files with 109 additions and 123 deletions

View File

@ -26,7 +26,6 @@ import org.elasticsearch.common.io.stream.StreamInput;
import org.elasticsearch.common.io.stream.StreamOutput;
import org.elasticsearch.common.xcontent.XContentBuilder;
import java.io.IOException;
import java.util.Locale;
import java.util.Objects;
public class EnvelopeBuilder extends ShapeBuilder {
@ -35,16 +34,8 @@ public class EnvelopeBuilder extends ShapeBuilder {
public static final EnvelopeBuilder PROTOTYPE = new EnvelopeBuilder();
protected Coordinate topLeft;
protected Coordinate bottomRight;
public EnvelopeBuilder() {
this(Orientation.RIGHT);
}
public EnvelopeBuilder(Orientation orientation) {
super(orientation);
}
private Coordinate topLeft;
private Coordinate bottomRight;
public EnvelopeBuilder topLeft(Coordinate topLeft) {
this.topLeft = topLeft;
@ -55,6 +46,10 @@ public class EnvelopeBuilder extends ShapeBuilder {
return topLeft(coordinate(longitude, latitude));
}
public Coordinate topLeft() {
return this.topLeft;
}
public EnvelopeBuilder bottomRight(Coordinate bottomRight) {
this.bottomRight = bottomRight;
return this;
@ -64,11 +59,14 @@ public class EnvelopeBuilder extends ShapeBuilder {
return bottomRight(coordinate(longitude, latitude));
}
public Coordinate bottomRight() {
return this.bottomRight;
}
@Override
public XContentBuilder toXContent(XContentBuilder builder, Params params) throws IOException {
builder.startObject();
builder.field(FIELD_TYPE, TYPE.shapeName());
builder.field(FIELD_ORIENTATION, orientation.name().toLowerCase(Locale.ROOT));
builder.startArray(FIELD_COORDINATES);
toXContent(builder, topLeft);
toXContent(builder, bottomRight);
@ -88,7 +86,7 @@ public class EnvelopeBuilder extends ShapeBuilder {
@Override
public int hashCode() {
return Objects.hash(orientation, topLeft, bottomRight);
return Objects.hash(topLeft, bottomRight);
}
@Override
@ -100,21 +98,19 @@ public class EnvelopeBuilder extends ShapeBuilder {
return false;
}
EnvelopeBuilder other = (EnvelopeBuilder) obj;
return Objects.equals(orientation, other.orientation) &&
Objects.equals(topLeft, other.topLeft) &&
return Objects.equals(topLeft, other.topLeft) &&
Objects.equals(bottomRight, other.bottomRight);
}
@Override
public void writeTo(StreamOutput out) throws IOException {
orientation.writeTo(out);
writeCoordinateTo(topLeft, out);
writeCoordinateTo(bottomRight, out);
}
@Override
public EnvelopeBuilder readFrom(StreamInput in) throws IOException {
return new EnvelopeBuilder(Orientation.readFrom(in))
return new EnvelopeBuilder()
.topLeft(readCoordinateFrom(in))
.bottomRight(readCoordinateFrom(in));
}

View File

@ -30,7 +30,6 @@ import org.elasticsearch.common.xcontent.XContentBuilder;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import java.util.Locale;
import java.util.Objects;
public class GeometryCollectionBuilder extends ShapeBuilder {
@ -41,14 +40,6 @@ public class GeometryCollectionBuilder extends ShapeBuilder {
protected final ArrayList<ShapeBuilder> shapes = new ArrayList<>();
public GeometryCollectionBuilder() {
this(Orientation.RIGHT);
}
public GeometryCollectionBuilder(Orientation orientation) {
super(orientation);
}
public GeometryCollectionBuilder shape(ShapeBuilder shape) {
this.shapes.add(shape);
return this;
@ -110,7 +101,6 @@ public class GeometryCollectionBuilder extends ShapeBuilder {
public XContentBuilder toXContent(XContentBuilder builder, Params params) throws IOException {
builder.startObject();
builder.field(FIELD_TYPE, TYPE.shapeName());
builder.field(FIELD_ORIENTATION, orientation.name().toLowerCase(Locale.ROOT));
builder.startArray(FIELD_GEOMETRIES);
for (ShapeBuilder shape : shapes) {
shape.toXContent(builder, params);
@ -142,7 +132,7 @@ public class GeometryCollectionBuilder extends ShapeBuilder {
@Override
public int hashCode() {
return Objects.hash(orientation, shapes);
return Objects.hash(shapes);
}
@Override
@ -154,12 +144,11 @@ public class GeometryCollectionBuilder extends ShapeBuilder {
return false;
}
GeometryCollectionBuilder other = (GeometryCollectionBuilder) obj;
return Objects.equals(orientation, other.orientation) && Objects.equals(shapes, other.shapes);
return Objects.equals(shapes, other.shapes);
}
@Override
public void writeTo(StreamOutput out) throws IOException {
orientation.writeTo(out);
out.writeVInt(shapes.size());
for (ShapeBuilder shape : shapes) {
out.writeShape(shape);
@ -168,7 +157,7 @@ public class GeometryCollectionBuilder extends ShapeBuilder {
@Override
public GeometryCollectionBuilder readFrom(StreamInput in) throws IOException {
GeometryCollectionBuilder geometryCollectionBuilder = new GeometryCollectionBuilder(Orientation.readFrom(in));
GeometryCollectionBuilder geometryCollectionBuilder = new GeometryCollectionBuilder();
int shapes = in.readVInt();
for (int i = 0; i < shapes; i++) {
geometryCollectionBuilder.shape(in.readShape());

View File

@ -40,16 +40,31 @@ public class MultiPolygonBuilder extends ShapeBuilder {
private final ArrayList<PolygonBuilder> polygons = new ArrayList<>();
private Orientation orientation = Orientation.RIGHT;
public MultiPolygonBuilder() {
this(Orientation.RIGHT);
}
public MultiPolygonBuilder(Orientation orientation) {
super(orientation);
this.orientation = orientation;
}
public Orientation orientation() {
return this.orientation;
}
/**
* Add a shallow copy of the polygon to the multipolygon. This will apply the orientation of the
* {@link MultiPolygonBuilder} to the polygon if polygon has different orientation.
*/
public MultiPolygonBuilder polygon(PolygonBuilder polygon) {
this.polygons.add(polygon);
PolygonBuilder pb = new PolygonBuilder(this.orientation);
pb.points(polygon.shell().coordinates(false));
for (LineStringBuilder hole : polygon.holes()) {
pb.hole(hole);
}
this.polygons.add(pb);
return this;
}

View File

@ -57,6 +57,8 @@ public class PolygonBuilder extends ShapeBuilder {
private static final Coordinate[][] EMPTY = new Coordinate[0][];
private Orientation orientation = Orientation.RIGHT;
// line string defining the shell of the polygon
private LineStringBuilder shell;
@ -64,7 +66,7 @@ public class PolygonBuilder extends ShapeBuilder {
private final ArrayList<LineStringBuilder> holes = new ArrayList<>();
public PolygonBuilder() {
this(new ArrayList<Coordinate>(), Orientation.RIGHT);
this(Orientation.RIGHT);
}
public PolygonBuilder(Orientation orientation) {
@ -72,10 +74,14 @@ public class PolygonBuilder extends ShapeBuilder {
}
public PolygonBuilder(ArrayList<Coordinate> points, Orientation orientation) {
super(orientation);
this.orientation = orientation;
this.shell = new LineStringBuilder().points(points);
}
public Orientation orientation() {
return this.orientation;
}
public PolygonBuilder point(double longitude, double latitude) {
shell.point(longitude, latitude);
return this;

View File

@ -77,16 +77,10 @@ public abstract class ShapeBuilder extends ToXContentToBytes implements NamedWri
/** @see com.spatial4j.core.shape.jts.JtsGeometry#index() */
protected final boolean autoIndexJtsGeometry = true;//may want to turn off once SpatialStrategy impls do it.
protected Orientation orientation = Orientation.RIGHT;
protected ShapeBuilder() {
}
protected ShapeBuilder(Orientation orientation) {
this.orientation = orientation;
}
protected static Coordinate coordinate(double longitude, double latitude) {
return new Coordinate(longitude, latitude);
}
@ -186,22 +180,6 @@ public abstract class ShapeBuilder extends ToXContentToBytes implements NamedWri
return new Coordinate(in.readDouble(), in.readDouble());
}
public static Orientation orientationFromString(String orientation) {
orientation = orientation.toLowerCase(Locale.ROOT);
switch (orientation) {
case "right":
case "counterclockwise":
case "ccw":
return Orientation.RIGHT;
case "left":
case "clockwise":
case "cw":
return Orientation.LEFT;
default:
throw new IllegalArgumentException("Unknown orientation [" + orientation + "]");
}
}
protected static Coordinate shift(Coordinate coordinate, double dateline) {
if (dateline == 0) {
return coordinate;
@ -416,6 +394,22 @@ public abstract class ShapeBuilder extends ToXContentToBytes implements NamedWri
public static Orientation readFrom (StreamInput in) throws IOException {
return in.readBoolean() ? Orientation.RIGHT : Orientation.LEFT;
}
public static Orientation fromString(String orientation) {
orientation = orientation.toLowerCase(Locale.ROOT);
switch (orientation) {
case "right":
case "counterclockwise":
case "ccw":
return Orientation.RIGHT;
case "left":
case "clockwise":
case "cw":
return Orientation.LEFT;
default:
throw new IllegalArgumentException("Unknown orientation [" + orientation + "]");
}
}
}
public static final String FIELD_TYPE = "type";
@ -506,7 +500,7 @@ public abstract class ShapeBuilder extends ToXContentToBytes implements NamedWri
radius = Distance.parseDistance(parser.text());
} else if (FIELD_ORIENTATION.equals(fieldName)) {
parser.nextToken();
requestedOrientation = orientationFromString(parser.text());
requestedOrientation = Orientation.fromString(parser.text());
} else {
parser.nextToken();
parser.skipChildren();
@ -532,7 +526,7 @@ public abstract class ShapeBuilder extends ToXContentToBytes implements NamedWri
case POLYGON: return parsePolygon(node, requestedOrientation, coerce);
case MULTIPOLYGON: return parseMultiPolygon(node, requestedOrientation, coerce);
case CIRCLE: return parseCircle(node, radius);
case ENVELOPE: return parseEnvelope(node, requestedOrientation);
case ENVELOPE: return parseEnvelope(node);
case GEOMETRYCOLLECTION: return geometryCollections;
default:
throw new ElasticsearchParseException("shape type [{}] not included", shapeType);
@ -558,7 +552,7 @@ public abstract class ShapeBuilder extends ToXContentToBytes implements NamedWri
return ShapeBuilders.newCircleBuilder().center(coordinates.coordinate).radius(radius);
}
protected static EnvelopeBuilder parseEnvelope(CoordinateNode coordinates, final Orientation orientation) {
protected static EnvelopeBuilder parseEnvelope(CoordinateNode coordinates) {
// validate the coordinate array for envelope type
if (coordinates.children.size() != 2) {
throw new ElasticsearchParseException("invalid number of points [{}] provided for " +
@ -572,7 +566,7 @@ public abstract class ShapeBuilder extends ToXContentToBytes implements NamedWri
uL = new Coordinate(Math.min(uL.x, lR.x), Math.max(uL.y, lR.y));
lR = new Coordinate(Math.max(uLtmp.x, lR.x), Math.min(uLtmp.y, lR.y));
}
return ShapeBuilders.newEnvelope(orientation).topLeft(uL).bottomRight(lR);
return ShapeBuilders.newEnvelope().topLeft(uL).bottomRight(lR);
}
protected static void validateMultiPointNode(CoordinateNode coordinates) {
@ -692,8 +686,7 @@ public abstract class ShapeBuilder extends ToXContentToBytes implements NamedWri
}
XContentParser.Token token = parser.nextToken();
GeometryCollectionBuilder geometryCollection = ShapeBuilders.newGeometryCollection( (mapper == null) ? Orientation.RIGHT : mapper
.fieldType().orientation());
GeometryCollectionBuilder geometryCollection = ShapeBuilders.newGeometryCollection();
while (token != XContentParser.Token.END_ARRAY) {
ShapeBuilder shapeBuilder = GeoShapeType.parse(parser);
geometryCollection.shape(shapeBuilder);

View File

@ -110,15 +110,6 @@ public class ShapeBuilders {
return new GeometryCollectionBuilder();
}
/**
* Create a new GeometryCollection
*
* @return a new {@link GeometryCollectionBuilder}
*/
public static GeometryCollectionBuilder newGeometryCollection(ShapeBuilder.Orientation orientation) {
return new GeometryCollectionBuilder(orientation);
}
/**
* create a new Circle
*
@ -136,13 +127,4 @@ public class ShapeBuilders {
public static EnvelopeBuilder newEnvelope() {
return new EnvelopeBuilder();
}
/**
* create a new rectangle
*
* @return a new {@link EnvelopeBuilder}
*/
public static EnvelopeBuilder newEnvelope(ShapeBuilder.Orientation orientation) {
return new EnvelopeBuilder(orientation);
}
}

View File

@ -184,7 +184,7 @@ public class GeoShapeFieldMapper extends FieldMapper {
builder.fieldType().setDistanceErrorPct(Double.parseDouble(fieldNode.toString()));
iterator.remove();
} else if (Names.ORIENTATION.equals(fieldName)) {
builder.fieldType().setOrientation(ShapeBuilder.orientationFromString(fieldNode.toString()));
builder.fieldType().setOrientation(ShapeBuilder.Orientation.fromString(fieldNode.toString()));
iterator.remove();
} else if (Names.STRATEGY.equals(fieldName)) {
builder.fieldType().setStrategyName(fieldNode.toString());

View File

@ -22,7 +22,6 @@ package org.elasticsearch.common.geo.builders;
import com.spatial4j.core.shape.Rectangle;
import com.vividsolutions.jts.geom.Coordinate;
import org.elasticsearch.common.geo.builders.ShapeBuilder.Orientation;
import org.elasticsearch.test.geo.RandomShapeGenerator;
import java.io.IOException;
@ -41,31 +40,26 @@ public class EnvelopeBuilderTests extends AbstractShapeBuilderTestCase<EnvelopeB
static EnvelopeBuilder mutate(EnvelopeBuilder original) throws IOException {
EnvelopeBuilder mutation = (EnvelopeBuilder) copyShape(original);
if (randomBoolean()) {
// toggle orientation
mutation.orientation = (original.orientation == Orientation.LEFT ? Orientation.RIGHT : Orientation.LEFT);
} else {
// move one corner to the middle of original
switch (randomIntBetween(0, 3)) {
case 0:
mutation.topLeft(new Coordinate(randomDoubleBetween(-180.0, original.bottomRight.x, true), original.topLeft.y));
mutation.topLeft(new Coordinate(randomDoubleBetween(-180.0, original.bottomRight().x, true), original.topLeft().y));
break;
case 1:
mutation.topLeft(new Coordinate(original.topLeft.x, randomDoubleBetween(original.bottomRight.y, 90.0, true)));
mutation.topLeft(new Coordinate(original.topLeft().x, randomDoubleBetween(original.bottomRight().y, 90.0, true)));
break;
case 2:
mutation.bottomRight(new Coordinate(randomDoubleBetween(original.topLeft.x, 180.0, true), original.bottomRight.y));
mutation.bottomRight(new Coordinate(randomDoubleBetween(original.topLeft().x, 180.0, true), original.bottomRight().y));
break;
case 3:
mutation.bottomRight(new Coordinate(original.bottomRight.x, randomDoubleBetween(-90.0, original.topLeft.y, true)));
mutation.bottomRight(new Coordinate(original.bottomRight().x, randomDoubleBetween(-90.0, original.topLeft().y, true)));
break;
}
}
return mutation;
}
static EnvelopeBuilder createRandomShape() {
EnvelopeBuilder envelope = new EnvelopeBuilder(randomFrom(Orientation.values()));
EnvelopeBuilder envelope = new EnvelopeBuilder();
Rectangle box = RandomShapeGenerator.xRandomRectangle(getRandom(), RandomShapeGenerator.xRandomPoint(getRandom()));
envelope.topLeft(box.getMinX(), box.getMaxY())
.bottomRight(box.getMaxX(), box.getMinY());

View File

@ -27,7 +27,6 @@ public class GeometryCollectionBuilderTests extends AbstractShapeBuilderTestCase
@Override
protected GeometryCollectionBuilder createTestShapeBuilder() {
// NORELEASE check of GeometryCollectionBuilder should parse maintain orientation
GeometryCollectionBuilder geometryCollection = new GeometryCollectionBuilder();
int shapes = randomIntBetween(0, 8);
for (int i = 0; i < shapes; i++) {
@ -68,12 +67,6 @@ public class GeometryCollectionBuilderTests extends AbstractShapeBuilderTestCase
static GeometryCollectionBuilder mutate(GeometryCollectionBuilder original) throws IOException {
GeometryCollectionBuilder mutation = (GeometryCollectionBuilder) copyShape(original);
// NORELEASE check of GeometryCollectionBuilder should parse maintain orientation
// if (randomBoolean()) {
// // toggle orientation
// mutation.orientation = (mutation.orientation == Orientation.LEFT ? Orientation.RIGHT : Orientation.LEFT);
// } else {
// change one shape
if (mutation.shapes.size() > 0) {
int shapePosition = randomIntBetween(0, mutation.shapes.size() - 1);
ShapeBuilder shapeToChange = mutation.shapes.get(shapePosition);
@ -109,7 +102,6 @@ public class GeometryCollectionBuilderTests extends AbstractShapeBuilderTestCase
} else {
mutation.shape(RandomShapeGenerator.createShape(getRandom()));
}
// }
return mutation;
}
}

View File

@ -38,23 +38,29 @@ public class MultiPolygonBuilderTests extends AbstractShapeBuilderTestCase<Multi
}
static MultiPolygonBuilder mutate(MultiPolygonBuilder original) throws IOException {
MultiPolygonBuilder mutation = (MultiPolygonBuilder) copyShape(original);
MultiPolygonBuilder mutation;
if (randomBoolean()) {
// toggle orientation
mutation.orientation = (original.orientation == Orientation.LEFT ? Orientation.RIGHT : Orientation.LEFT);
mutation = new MultiPolygonBuilder(original.orientation() == Orientation.LEFT ? Orientation.RIGHT : Orientation.LEFT);
for (PolygonBuilder pb : original.polygons()) {
mutation.polygon((PolygonBuilder) copyShape(pb));
}
} else {
mutation = (MultiPolygonBuilder) copyShape(original);
if (mutation.polygons().size() > 0) {
int polyToChange = randomInt(mutation.polygons().size() - 1);
PolygonBuilderTests.mutatePolygonBuilder(mutation.polygons().get(polyToChange));
mutation.polygons().set(polyToChange, PolygonBuilderTests.mutatePolygonBuilder(mutation.polygons().get(polyToChange)));
} else {
mutation.polygon((PolygonBuilder) RandomShapeGenerator.createShape(getRandom(), ShapeType.POLYGON));
}
}
return mutation;
}
static MultiPolygonBuilder createRandomShape() {
MultiPolygonBuilder mpb = new MultiPolygonBuilder(randomFrom(Orientation.values()));
int polys = randomIntBetween(1, 10);
int polys = randomIntBetween(0, 10);
for (int i = 0; i < polys; i++) {
PolygonBuilder pgb = (PolygonBuilder) RandomShapeGenerator.createShape(getRandom(), ShapeType.POLYGON);
pgb.orientation = mpb.orientation;
mpb.polygon(pgb);
}
return mpb;

View File

@ -46,8 +46,7 @@ public class PolygonBuilderTests extends AbstractShapeBuilderTestCase<PolygonBui
static PolygonBuilder mutatePolygonBuilder(PolygonBuilder pb) {
if (randomBoolean()) {
// toggle orientation
pb.orientation = (pb.orientation == Orientation.LEFT ? Orientation.RIGHT : Orientation.LEFT);
pb = polyWithOposingOrientation(pb);
} else {
// change either point in shell or in random hole
LineStringBuilder lineToChange;
@ -74,9 +73,24 @@ public class PolygonBuilderTests extends AbstractShapeBuilderTestCase<PolygonBui
return pb;
}
/**
* Takes an input polygon and returns an identical one, only with opposing orientation setting.
* This is done so we don't have to expose a setter for orientation in the actual class
*/
private static PolygonBuilder polyWithOposingOrientation(PolygonBuilder pb) {
PolygonBuilder mutation = new PolygonBuilder(pb.orientation() == Orientation.LEFT ? Orientation.RIGHT : Orientation.LEFT);
mutation.points(pb.shell().coordinates(false));
for (LineStringBuilder hole : pb.holes()) {
mutation.hole(hole);
}
return mutation;
}
static PolygonBuilder createRandomShape() {
PolygonBuilder pgb = (PolygonBuilder) RandomShapeGenerator.createShape(getRandom(), ShapeType.POLYGON);
pgb.orientation = randomFrom(Orientation.values());
if (randomBoolean()) {
pgb = polyWithOposingOrientation(pgb);
}
return pgb;
}
}

View File

@ -227,7 +227,6 @@ public class GeoShapeQueryBuilderTests extends AbstractQueryTestCase<GeoShapeQue
" \"location\" : {\n" +
" \"shape\" : {\n" +
" \"type\" : \"envelope\",\n" +
" \"orientation\" : \"right\",\n" +
" \"coordinates\" : [ [ 13.0, 53.0 ], [ 14.0, 52.0 ] ]\n" +
" },\n" +
" \"relation\" : \"intersects\"\n" +