LUCENE-7936: Complete the work to support serialization and deserialization of individual Geo3D objects. This adds support for GeoComplexPolygon and the composites.

This commit is contained in:
Karl Wright 2017-08-25 02:52:11 -04:00
parent 7f52920352
commit 693db3fe38
7 changed files with 135 additions and 0 deletions

View File

@ -17,6 +17,9 @@
package org.apache.lucene.spatial3d.geom; package org.apache.lucene.spatial3d.geom;
import java.io.InputStream;
import java.io.IOException;
/** /**
* Base class to create a composite of GeoAreaShapes * Base class to create a composite of GeoAreaShapes
* *
@ -39,6 +42,16 @@ abstract class GeoBaseCompositeAreaShape<T extends GeoAreaShape> extends GeoBase
super(planetModel); super(planetModel);
} }
/**
* Constructor for deserialization.
* @param planetModel is the planet model.
* @param inputStream is the input stream.
* @param clazz is the class of the generic.
*/
public GeoBaseCompositeAreaShape(final PlanetModel planetModel, final InputStream inputStream, final Class<T> clazz) throws IOException {
super(planetModel, inputStream, clazz);
}
@Override @Override
public boolean intersects(GeoShape geoShape){ public boolean intersects(GeoShape geoShape){
for(GeoAreaShape geoAreaShape : shapes){ for(GeoAreaShape geoAreaShape : shapes){

View File

@ -17,6 +17,9 @@
package org.apache.lucene.spatial3d.geom; package org.apache.lucene.spatial3d.geom;
import java.io.InputStream;
import java.io.IOException;
/** /**
* Base class to create a composite of GeoMembershipShapes * Base class to create a composite of GeoMembershipShapes
* *
@ -33,6 +36,16 @@ abstract class GeoBaseCompositeMembershipShape<T extends GeoMembershipShape>
super(planetModel); super(planetModel);
} }
/**
* Constructor for deserialization.
* @param planetModel is the planet model.
* @param inputStream is the input stream.
* @param clazz is the class of the generic.
*/
GeoBaseCompositeMembershipShape(final PlanetModel planetModel, final InputStream inputStream, final Class<T> clazz) throws IOException {
super(planetModel, inputStream, clazz);
}
@Override @Override
public double computeOutsideDistance(final DistanceStyle distanceStyle, final GeoPoint point) { public double computeOutsideDistance(final DistanceStyle distanceStyle, final GeoPoint point) {
return computeOutsideDistance(distanceStyle, point.x, point.y, point.z); return computeOutsideDistance(distanceStyle, point.x, point.y, point.z);

View File

@ -20,6 +20,9 @@ package org.apache.lucene.spatial3d.geom;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Arrays; import java.util.Arrays;
import java.util.List; import java.util.List;
import java.io.InputStream;
import java.io.OutputStream;
import java.io.IOException;
/** /**
* Base class to create a composite of GeoShapes. * Base class to create a composite of GeoShapes.
@ -71,6 +74,28 @@ public abstract class GeoBaseCompositeShape<T extends GeoShape> extends BasePlan
return shapes.get(index); return shapes.get(index);
} }
/**
* Constructor for deserialization.
* @param planetModel is the planet model.
* @param inputStream is the input stream.
* @param clazz is the class of the generic.
*/
public GeoBaseCompositeShape(final PlanetModel planetModel, final InputStream inputStream, final Class<T> clazz) throws IOException {
this(planetModel);
final SerializableObject[] array = SerializableObject.readHeterogeneousArray(planetModel, inputStream);
for (final SerializableObject member : array) {
if (!(clazz.isAssignableFrom(member.getClass()))) {
throw new IOException("Can't deserialize composite because member has wrong type: "+member.getClass().getName());
}
addShape(clazz.cast(member));
}
}
@Override
public void write(final OutputStream outputStream) throws IOException {
SerializableObject.writeHeterogeneousArray(outputStream, shapes);
}
@Override @Override
public boolean isWithin(final Vector point) { public boolean isWithin(final Vector point) {
return isWithin(point.x, point.y, point.z); return isWithin(point.x, point.y, point.z);

View File

@ -19,6 +19,9 @@ package org.apache.lucene.spatial3d.geom;
import java.util.Arrays; import java.util.Arrays;
import java.util.List; import java.util.List;
import java.util.ArrayList; import java.util.ArrayList;
import java.io.InputStream;
import java.io.OutputStream;
import java.io.IOException;
/** /**
* GeoComplexPolygon objects are structures designed to handle very large numbers of edges. * GeoComplexPolygon objects are structures designed to handle very large numbers of edges.
@ -37,6 +40,7 @@ class GeoComplexPolygon extends GeoBasePolygon {
private final Tree yTree; private final Tree yTree;
private final Tree zTree; private final Tree zTree;
private final List<List<GeoPoint>> pointsList;
private final boolean testPointInSet; private final boolean testPointInSet;
private final GeoPoint testPoint; private final GeoPoint testPoint;
@ -66,6 +70,7 @@ class GeoComplexPolygon extends GeoBasePolygon {
*/ */
public GeoComplexPolygon(final PlanetModel planetModel, final List<List<GeoPoint>> pointsList, final GeoPoint testPoint, final boolean testPointInSet) { public GeoComplexPolygon(final PlanetModel planetModel, final List<List<GeoPoint>> pointsList, final GeoPoint testPoint, final boolean testPointInSet) {
super(planetModel); super(planetModel);
this.pointsList = pointsList; // For serialization
this.testPointInSet = testPointInSet; this.testPointInSet = testPointInSet;
this.testPoint = testPoint; this.testPoint = testPoint;
@ -115,6 +120,41 @@ class GeoComplexPolygon extends GeoBasePolygon {
zTree = new ZTree(allEdges); zTree = new ZTree(allEdges);
} }
/**
* Constructor for deserialization.
* @param planetModel is the planet model.
* @param inputStream is the input stream.
*/
public GeoComplexPolygon(final PlanetModel planetModel, final InputStream inputStream) throws IOException {
this(planetModel,
readPointsList(planetModel, inputStream),
new GeoPoint(planetModel, inputStream),
SerializableObject.readBoolean(inputStream));
}
private static List<List<GeoPoint>> readPointsList(final PlanetModel planetModel, final InputStream inputStream) throws IOException {
final int count = SerializableObject.readInt(inputStream);
final List<List<GeoPoint>> array = new ArrayList<>(count);
for (int i = 0; i < count; i++) {
array.add(java.util.Arrays.asList(SerializableObject.readPointArray(planetModel, inputStream)));
}
return array;
}
@Override
public void write(final OutputStream outputStream) throws IOException {
writePointsList(outputStream, pointsList);
testPoint.write(outputStream);
SerializableObject.writeBoolean(outputStream, testPointInSet);
}
private static void writePointsList(final OutputStream outputStream, final List<List<GeoPoint>> pointsList) throws IOException {
SerializableObject.writeInt(outputStream, pointsList.size());
for (final List<GeoPoint> points : pointsList) {
SerializableObject.writePointArray(outputStream, points);
}
}
@Override @Override
public boolean isWithin(final double x, final double y, final double z) { public boolean isWithin(final double x, final double y, final double z) {
// If we're right on top of the point, we know the answer. // If we're right on top of the point, we know the answer.

View File

@ -17,6 +17,9 @@
package org.apache.lucene.spatial3d.geom; package org.apache.lucene.spatial3d.geom;
import java.io.InputStream;
import java.io.IOException;
/** /**
* GeoCompositeAreaShape is a set of GeoAreaShape's, treated as a unit. * GeoCompositeAreaShape is a set of GeoAreaShape's, treated as a unit.
* *
@ -31,6 +34,15 @@ public class GeoCompositeAreaShape extends GeoBaseCompositeAreaShape<GeoAreaShap
super(planetModel); super(planetModel);
} }
/**
* Constructor for deserialization.
* @param planetModel is the planet model.
* @param inputStream is the input stream.
*/
public GeoCompositeAreaShape(final PlanetModel planetModel, final InputStream inputStream) throws IOException {
super(planetModel, inputStream, GeoAreaShape.class);
}
@Override @Override
public boolean equals(Object o) { public boolean equals(Object o) {
if (!(o instanceof GeoCompositeAreaShape)) if (!(o instanceof GeoCompositeAreaShape))

View File

@ -16,6 +16,9 @@
*/ */
package org.apache.lucene.spatial3d.geom; package org.apache.lucene.spatial3d.geom;
import java.io.InputStream;
import java.io.IOException;
/** /**
* GeoCompositePolygon is a specific implementation of GeoCompositeAreaShape, which implements GeoPolygon explicitly. * GeoCompositePolygon is a specific implementation of GeoCompositeAreaShape, which implements GeoPolygon explicitly.
* *
@ -29,6 +32,15 @@ public class GeoCompositePolygon extends GeoBaseCompositeAreaShape<GeoPolygon> i
super(planetModel); super(planetModel);
} }
/**
* Constructor for deserialization.
* @param planetModel is the planet model.
* @param inputStream is the input stream.
*/
public GeoCompositePolygon(final PlanetModel planetModel, final InputStream inputStream) throws IOException {
super(planetModel, inputStream, GeoPolygon.class);
}
@Override @Override
public boolean equals(Object o) { public boolean equals(Object o) {
if (!(o instanceof GeoCompositePolygon)) if (!(o instanceof GeoCompositePolygon))

View File

@ -376,4 +376,24 @@ public interface SerializableObject {
return l1 + l2 + l3 + l4; return l1 + l2 + l3 + l4;
} }
/** Write a boolean to a stream.
* @param outputStream is the output stream.
* @param value is the value to write.
*/
static void writeBoolean(final OutputStream outputStream, final boolean value) throws IOException {
outputStream.write(value?0:1);
}
/** Read a boolean from a stream.
* @param inputStream is the input stream.
* @return the boolean value.
*/
static boolean readBoolean(final InputStream inputStream) throws IOException {
final int valueRead = inputStream.read();
if (valueRead == -1) {
throw new IOException("Unexpected end of input stream");
}
return (valueRead == 0)?false:true;
}
} }