Skip to content

Commit

Permalink
GIS #462: added LineString and LinearRing types with tests for them
Browse files Browse the repository at this point in the history
  • Loading branch information
danylokravchenko committed Nov 2, 2023
1 parent 018e966 commit 127c2c8
Show file tree
Hide file tree
Showing 8 changed files with 470 additions and 60 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -233,7 +233,8 @@ public static Function1<PolyValue, Object> getPolyToJava( AlgDataType type, bool
case VIDEO:
return o -> o.asBlob().asByteArray();
case GEOMETRY:
return o -> o.asGeometry().getJtsGeometry();
// TODO: check how does it work
return o -> o.asGeometry().toString();
default:
throw new org.apache.commons.lang3.NotImplementedException( "meta" );
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -69,37 +69,45 @@ public class PolyGeometry extends PolyValue {
@Getter
protected PolyGeometryType geometryType;


/**
* Constructor creates the {@link Geometry} from the WKT text.
* <p>
* The WKT may contain SRID in the text, e.g. <code>"SRID=4326;POINT (13.4050 52.5200)"</code>.
* In this case SRID from the WKT would be used, otherwise the default one is selected.
* <p>
*
* @param wkt Well Know Text representation of the geometry
* @throws InvalidGeometryException if {@link Geometry} is invalid or provided WKT is invalid.
*/
public PolyGeometry( @JsonProperty("wkt") @Deserialize("wkt") String wkt ) throws InvalidGeometryException {
this( PolyType.GEOMETRY );
this.SRID = NO_SRID;
WKTReader reader = new WKTReader();
int SRID = NO_SRID;
try {
wkt = wkt.trim();
// WKT is actually an extended EWKT with SRID before the WKT
if (wkt.startsWith( "SRID" )) {
if ( wkt.startsWith( "SRID" ) ) {
// in WKT semicolon is invalid character, so we could safely split by it
String[] ewktParts = wkt.split( ";" );
this.SRID = Integer.valueOf( ewktParts[0].replace( "SRID=", "" ) );
SRID = Integer.parseInt( ewktParts[0].replace( "SRID=", "" ) );
wkt = ewktParts[1];
}
this.jtsGeometry = reader.read( wkt );
if (!jtsGeometry.isValid()) {
throw new ParseException("Provided geometry is not valid.");
}
this.jtsGeometry.setSRID( this.SRID );
} catch ( ParseException | NumberFormatException e) {
throw new InvalidGeometryException(e.getMessage());
} catch ( NumberFormatException e ) {
throw new InvalidGeometryException( e.getMessage() );
}
this.geometryType = getPolyGeometryType();
init(wkt, SRID);
}

/**
* Constructor creates the {@link Geometry} from the WKT text using the provided SRID.
*
* @param wkt Well Know Text representation of the geometry
* @param SRID Spatial reference system of the geometry
* @throws InvalidGeometryException if {@link Geometry} is invalid or provided WKT is invalid.
*/
public PolyGeometry( @JsonProperty("wkt") @Deserialize("wkt") String wkt, int SRID ) throws InvalidGeometryException {
this( PolyType.GEOMETRY );
init( wkt, SRID );
}

public PolyGeometry( Geometry geometry ) {
Expand All @@ -109,33 +117,61 @@ public PolyGeometry( Geometry geometry ) {
this.geometryType = getPolyGeometryType();
}


protected PolyGeometry( PolyType type ) {
super( type );
}

private void init( String wkt, int SRID) throws InvalidGeometryException {
this.SRID = SRID;
WKTReader reader = new WKTReader();
try {
this.jtsGeometry = reader.read( wkt );
if ( !jtsGeometry.isValid() ) {
throw new ParseException( "Provided geometry is not valid." );
}
this.jtsGeometry.setSRID( this.SRID );
} catch ( ParseException | IllegalArgumentException e) {
// IllegalArgumentException is thrown in case geometry conditions are not met
throw new InvalidGeometryException( e.getMessage() );
}
this.geometryType = getPolyGeometryType();
}


public static PolyGeometry of( String wkt ) throws InvalidGeometryException {
return new PolyGeometry( wkt );
}

public static PolyGeometry of( String wkt, int SRID ) throws InvalidGeometryException {
return new PolyGeometry( wkt, SRID );
}


public static PolyGeometry of( Geometry geometry ) {
return new PolyGeometry( geometry );
}


protected PolyGeometryType getPolyGeometryType() {
switch ( jtsGeometry.getGeometryType() ) {
case "Point":
return PolyGeometryType.POINT;
case "LineString":
return PolyGeometryType.LINESTRING;
case "LinearRing":
return PolyGeometryType.LINEAR_RING;
default:
throw new NotImplementedException( "value" );
}
}


public boolean isPoint() {
return geometryType.equals( PolyGeometryType.POINT );
}


@NotNull
public PolyPoint asPoint() {
if ( isPoint() ) {
Expand All @@ -144,6 +180,32 @@ public PolyPoint asPoint() {
throw cannotParse( this, PolyPoint.class );
}

public boolean isLineString() {
return geometryType.equals( PolyGeometryType.LINESTRING );
}


@NotNull
public PolyLineString asLineString() {
if ( isLineString() ) {
return PolyLineString.of( jtsGeometry );
}
throw cannotParse( this, PolyLineString.class );
}

public boolean isLinearRing() {
return geometryType.equals( PolyGeometryType.LINEAR_RING );
}


@NotNull
public PolyLinearRing asLinearRing() {
if ( isLinearRing() ) {
return PolyLinearRing.of( jtsGeometry );
}
throw cannotParse( this, PolyLinearRing.class );
}


/**
* Tests whether this {@link Geometry} is simple.
Expand All @@ -154,8 +216,54 @@ public boolean isSimple() {
}


/**
* @return <code>true</code> if the set of points covered by this {@link Geometry} is empty.
*/
public boolean isEmpty() {
return jtsGeometry.isEmpty();
}


/**
* @return the count of this {@link Geometry} vertices.
*/
public int getNumPoints() {
return jtsGeometry.getNumPoints();
}


/**
* @return the dimension of this {@link Geometry}.
*/
public int getDimension() {
return jtsGeometry.getDimension();
}


/**
* Linear geometries return their length.
* Areal geometries return their perimeter.
*
* @return the length of this {@link Geometry}
*/
public double getLength() {
return jtsGeometry.getLength();
}


/**
* Areal Geometries have a non-zero area.
*
* @return the area of this {@link Geometry}
*/
public double getArea() {
return jtsGeometry.getArea();
}


/**
* Bound the {@link Geometry} my the minimum box that could fit this geometry.
*
* @return {@link PolyGeometry} with minimum bounding box
*/
public PolyGeometry getMinimumBoundingBox() {
Expand All @@ -169,11 +277,11 @@ public PolyGeometry getMinimumBoundingBox() {
*/
@Override
public boolean equals( Object o ) {
if ( !( o instanceof PolyGeometry )) {
if ( !(o instanceof PolyGeometry) ) {
return false;
}
PolyGeometry that = (PolyGeometry) o;
return jtsGeometry.equals( that.jtsGeometry ) && Objects.equals( SRID, that.SRID );
return geometryType.equals( that.geometryType ) && jtsGeometry.equals( that.jtsGeometry ) && Objects.equals( SRID, that.SRID );
}


Expand Down Expand Up @@ -217,9 +325,10 @@ public int compareTo( @NotNull PolyValue o ) {
*/
@Override
public String toString() {
return String.format( "SRID=%d;%s" , SRID, jtsGeometry.toString() );
return String.format( "SRID=%d;%s", SRID, jtsGeometry.toString() );
}


public static class PolyGeometrySerializerDef extends SimpleSerializerDef<PolyGeometry> {

@Override
Expand All @@ -230,6 +339,7 @@ public void encode( BinaryOutput out, PolyGeometry item ) {
out.writeUTF8( item.toString() );
}


@Override
public PolyGeometry decode( BinaryInput in ) throws CorruptedDataException {
try {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,8 +16,12 @@

package org.polypheny.db.type.entity.spatial;

/**
* Represent Geometry types supported by Polypheny.
*/
public enum PolyGeometryType {

POINT,
LINESTRING
LINESTRING,
LINEAR_RING
}
Loading

0 comments on commit 127c2c8

Please sign in to comment.