Making MultiPolygonBuilder writable and adding equals/hashCode

This commit is contained in:
Christoph Büscher 2015-11-19 18:35:35 +01:00
parent ae7e8bbaf0
commit 1f5ee642fd
5 changed files with 122 additions and 7 deletions

View File

@ -22,8 +22,12 @@ package org.elasticsearch.common.geo.builders;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import java.util.Locale;
import java.util.Objects;
import org.elasticsearch.common.geo.XShapeCollection;
import org.elasticsearch.common.io.stream.StreamInput;
import org.elasticsearch.common.io.stream.StreamOutput;
import org.elasticsearch.common.xcontent.XContentBuilder;
import com.spatial4j.core.shape.Shape;
@ -32,8 +36,9 @@ import com.vividsolutions.jts.geom.Coordinate;
public class MultiPolygonBuilder extends ShapeBuilder {
public static final GeoShapeType TYPE = GeoShapeType.MULTIPOLYGON;
static final MultiPolygonBuilder PROTOTYPE = new MultiPolygonBuilder();
protected final ArrayList<PolygonBuilder> polygons = new ArrayList<>();
private final ArrayList<PolygonBuilder> polygons = new ArrayList<>();
public MultiPolygonBuilder() {
this(Orientation.RIGHT);
@ -48,10 +53,18 @@ public class MultiPolygonBuilder extends ShapeBuilder {
return this;
}
/**
* get the list of polygons
*/
public ArrayList<PolygonBuilder> polygons() {
return polygons;
}
@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);
for(PolygonBuilder polygon : polygons) {
builder.startArray();
@ -89,4 +102,42 @@ public class MultiPolygonBuilder extends ShapeBuilder {
return new XShapeCollection<>(shapes, SPATIAL_CONTEXT);
//note: ShapeCollection is probably faster than a Multi* geom.
}
@Override
public int hashCode() {
return Objects.hash(polygons, orientation);
}
@Override
public boolean equals(Object obj) {
if (this == obj) {
return true;
}
if (obj == null || getClass() != obj.getClass()) {
return false;
}
MultiPolygonBuilder other = (MultiPolygonBuilder) obj;
return Objects.equals(polygons, other.polygons) &&
Objects.equals(orientation, other.orientation);
}
@Override
public void writeTo(StreamOutput out) throws IOException {
out.writeBoolean(orientation == Orientation.RIGHT);
out.writeVInt(polygons.size());
for (PolygonBuilder polygon : polygons) {
polygon.writeTo(out);
}
}
@Override
public MultiPolygonBuilder readFrom(StreamInput in) throws IOException {
Orientation orientation = in.readBoolean() ? Orientation.RIGHT : Orientation.LEFT;
MultiPolygonBuilder polyBuilder = new MultiPolygonBuilder(orientation);
int holes = in.readVInt();
for (int i = 0; i < holes; i++) {
polyBuilder.polygon(PolygonBuilder.PROTOTYPE.readFrom(in));
}
return polyBuilder;
}
}

View File

@ -42,6 +42,7 @@ import java.util.HashSet;
import java.util.Iterator;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.List;
import java.util.Locale;
import java.util.Objects;
/**
@ -196,6 +197,7 @@ public class PolygonBuilder 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_COORDINATES);
coordinatesArray(builder, params);
builder.endArray();

View File

@ -34,7 +34,7 @@ import static org.hamcrest.Matchers.*;
public abstract class AbstractShapeBuilderTestCase<SB extends ShapeBuilder> extends ESTestCase {
private static final int NUMBER_OF_TESTBUILDERS = 1;
private static final int NUMBER_OF_TESTBUILDERS = 20;
private static NamedWriteableRegistry namedWriteableRegistry;
/**
@ -51,6 +51,7 @@ public abstract class AbstractShapeBuilderTestCase<SB extends ShapeBuilder> exte
namedWriteableRegistry.registerPrototype(ShapeBuilder.class, LineStringBuilder.PROTOTYPE);
namedWriteableRegistry.registerPrototype(ShapeBuilder.class, MultiLineStringBuilder.PROTOTYPE);
namedWriteableRegistry.registerPrototype(ShapeBuilder.class, PolygonBuilder.PROTOTYPE);
namedWriteableRegistry.registerPrototype(ShapeBuilder.class, MultiPolygonBuilder.PROTOTYPE);
}
}

View File

@ -0,0 +1,56 @@
/*
* Licensed to Elasticsearch under one or more contributor
* license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright
* ownership. Elasticsearch licenses this file to you under
* the Apache License, Version 2.0 (the "License"); you may
* not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
package org.elasticsearch.common.geo.builders;
import org.elasticsearch.common.geo.builders.ShapeBuilder.Orientation;
import org.elasticsearch.test.geo.RandomShapeGenerator;
import org.elasticsearch.test.geo.RandomShapeGenerator.ShapeType;
import java.io.IOException;
public class MultiPolygonBuilderTests extends AbstractShapeBuilderTestCase<MultiPolygonBuilder> {
@Override
protected MultiPolygonBuilder createTestShapeBuilder() {
MultiPolygonBuilder mpb = new MultiPolygonBuilder(randomFrom(Orientation.values()));
int polys = randomIntBetween(1, 10);
for (int i = 0; i < polys; i++) {
PolygonBuilder pgb = (PolygonBuilder) RandomShapeGenerator.createShape(getRandom(), ShapeType.POLYGON);
pgb.orientation = mpb.orientation;
// NORELEASE translated might have been changed by createShape, but won't survive xContent->Parse roundtrip
pgb.shell().translated = false;
mpb.polygon(pgb);
}
return mpb;
}
@Override
protected MultiPolygonBuilder mutate(MultiPolygonBuilder original) throws IOException {
MultiPolygonBuilder mutation = copyShape(original);
if (randomBoolean()) {
// toggle orientation
mutation.orientation = (original.orientation == Orientation.LEFT ? Orientation.RIGHT : Orientation.LEFT);
} else {
int polyToChange = randomInt(mutation.polygons().size() - 1);
PolygonBuilderTests.mutatePolygonBuilder(mutation.polygons().get(polyToChange));
}
return mutation;
}
}

View File

@ -32,6 +32,7 @@ public class PolygonBuilderTests extends AbstractShapeBuilderTestCase<PolygonBui
@Override
protected PolygonBuilder createTestShapeBuilder() {
PolygonBuilder pgb = (PolygonBuilder) RandomShapeGenerator.createShape(getRandom(), ShapeType.POLYGON);
pgb.orientation = randomFrom(Orientation.values());
// NORELEASE translated might have been changed by createShape, but won't survive xContent->Parse roundtrip
pgb.shell().translated = false;
return pgb;
@ -40,16 +41,20 @@ public class PolygonBuilderTests extends AbstractShapeBuilderTestCase<PolygonBui
@Override
protected PolygonBuilder mutate(PolygonBuilder original) throws IOException {
PolygonBuilder mutation = copyShape(original);
return mutatePolygonBuilder(mutation);
}
static PolygonBuilder mutatePolygonBuilder(PolygonBuilder pb) {
if (randomBoolean()) {
// toggle orientation
mutation.orientation = (original.orientation == Orientation.LEFT ? Orientation.RIGHT : Orientation.LEFT);
pb.orientation = (pb.orientation == Orientation.LEFT ? Orientation.RIGHT : Orientation.LEFT);
} else {
// change either point in shell or in random hole
LineStringBuilder lineToChange;
if (randomBoolean() || mutation.holes().size() == 0) {
lineToChange = mutation.shell();
if (randomBoolean() || pb.holes().size() == 0) {
lineToChange = pb.shell();
} else {
lineToChange = randomFrom(mutation.holes());
lineToChange = randomFrom(pb.holes());
}
Coordinate coordinate = randomFrom(lineToChange.coordinates(false));
if (randomBoolean()) {
@ -66,6 +71,6 @@ public class PolygonBuilderTests extends AbstractShapeBuilderTestCase<PolygonBui
}
}
}
return mutation;
return pb;
}
}