package com.revolsys.record.io.format.wkt;
import java.io.IOException;
import java.io.StringWriter;
import java.io.Writer;
import com.revolsys.geometry.model.Geometry;
import com.revolsys.geometry.model.LineString;
import com.revolsys.geometry.model.Lineal;
import com.revolsys.geometry.model.LinearRing;
import com.revolsys.geometry.model.Point;
import com.revolsys.geometry.model.Polygon;
import com.revolsys.geometry.model.Polygonal;
import com.revolsys.geometry.model.Punctual;
import com.revolsys.util.Exceptions;
import com.revolsys.util.MathUtil;
import com.revolsys.util.number.Doubles;
public class WktWriter {
public static void append(final StringBuilder wkt, final int axisCount, final Point point) {
for (int i = 0; i < axisCount; i++) {
if (i > 0) {
wkt.append(" ");
}
MathUtil.append(wkt, point.getCoordinate(i));
}
}
public static void appendLineString(final StringBuilder wkt, final Point... points) {
wkt.append("LINESTRING");
int axisCount = 2;
for (final Point point : points) {
axisCount = Math.max(axisCount, point.getAxisCount());
}
boolean first = true;
for (final Point point : points) {
if (first) {
first = false;
} else {
wkt.append(",");
}
append(wkt, axisCount, point);
}
wkt.append(")");
}
public static void appendPoint(final StringBuilder wkt, final Point point) {
wkt.append("POINT");
final int axisCount = point.getAxisCount();
append(wkt, axisCount, point);
wkt.append(")");
}
/**
* Generates the WKT for a <tt>LINESTRING</tt>
* specified by two {@link Coordinates}s.
*
* @param point1 the first coordinate
* @param point2 the second coordinate
*
* @return the WKT
*/
public static String lineString(final Point... points) {
final StringBuilder wkt = new StringBuilder();
appendLineString(wkt, points);
return wkt.toString();
}
/**
* Generates the WKT for a <tt>POINT</tt>
* specified by a {@link Coordinates}.
*
* @param p0 the point coordinate
*
* @return the WKT
*/
public static String point(final Point point) {
final StringBuilder wkt = new StringBuilder();
appendPoint(wkt, point);
return wkt.toString();
}
public static String toString(final Geometry geometry) {
final StringWriter out = new StringWriter();
write(out, geometry);
out.flush();
return out.toString();
}
public static void write(final Writer out, final Geometry geometry) {
if (geometry != null) {
if (geometry instanceof Point) {
final Point point = (Point)geometry;
write(out, point);
} else if (geometry instanceof Punctual) {
final Punctual punctual = (Punctual)geometry;
write(out, punctual);
} else if (geometry instanceof LinearRing) {
final LinearRing line = (LinearRing)geometry;
write(out, line);
} else if (geometry instanceof LineString) {
final LineString line = (LineString)geometry;
write(out, line);
} else if (geometry instanceof Lineal) {
final Lineal lineal = (Lineal)geometry;
write(out, lineal);
} else if (geometry instanceof Polygon) {
final Polygon polygon = (Polygon)geometry;
write(out, polygon);
} else if (geometry instanceof Polygonal) {
final Polygonal polygonal = (Polygonal)geometry;
write(out, polygonal);
} else if (geometry.isGeometryCollection()) {
writeGeometryCollection(out, geometry);
} else {
throw new IllegalArgumentException("Unknown geometry type" + geometry.getClass());
}
}
}
public static void write(final Writer out, final Geometry geometry, final int axisCount) {
try {
if (geometry != null) {
if (geometry instanceof Point) {
final Point point = (Point)geometry;
write(out, point, axisCount);
} else if (geometry instanceof Punctual) {
final Punctual punctual = (Punctual)geometry;
write(out, punctual, axisCount);
} else if (geometry instanceof LinearRing) {
final LinearRing line = (LinearRing)geometry;
write(out, line, axisCount);
} else if (geometry instanceof LineString) {
final LineString line = (LineString)geometry;
write(out, line, axisCount);
} else if (geometry instanceof Lineal) {
final Lineal lineal = (Lineal)geometry;
write(out, lineal, axisCount);
} else if (geometry instanceof Polygon) {
final Polygon polygon = (Polygon)geometry;
write(out, polygon, axisCount);
} else if (geometry instanceof Polygonal) {
final Polygonal polygonal = (Polygonal)geometry;
write(out, polygonal, axisCount);
} else if (geometry.isGeometryCollection()) {
writeGeometryCollection(out, geometry, axisCount);
} else {
throw new IllegalArgumentException("Unknown geometry type" + geometry.getClass());
}
}
} catch (final IOException e) {
throw Exceptions.wrap(e);
}
}
public static void write(final Writer out, final Lineal lineal) {
final int axisCount = Math.min(lineal.getAxisCount(), 4);
try {
write(out, lineal, axisCount);
} catch (final IOException e) {
throw Exceptions.wrap(e);
}
}
private static void write(final Writer out, final Lineal lineal, final int axisCount)
throws IOException {
writeGeometryType(out, "MULTILINESTRING", axisCount);
if (lineal.isEmpty()) {
out.write(" EMPTY");
} else {
out.write("(");
LineString line = (LineString)lineal.getGeometry(0);
LineString points = line;
writeCoordinates(out, points, axisCount);
for (int i = 1; i < lineal.getGeometryCount(); i++) {
out.write(",");
line = (LineString)lineal.getGeometry(i);
points = line;
writeCoordinates(out, points, axisCount);
}
out.write(")");
}
}
public static void write(final Writer out, final LinearRing line) {
final int axisCount = Math.min(line.getAxisCount(), 4);
try {
write(out, line, axisCount);
} catch (final IOException e) {
throw Exceptions.wrap(e);
}
}
private static void write(final Writer out, final LinearRing line, final int axisCount)
throws IOException {
writeGeometryType(out, "LINEARRING", axisCount);
if (line.isEmpty()) {
out.write(" EMPTY");
} else {
final LineString coordinates = line;
writeCoordinates(out, coordinates, axisCount);
}
}
public static void write(final Writer out, final LineString line) {
final int axisCount = Math.min(line.getAxisCount(), 4);
try {
write(out, line, axisCount);
} catch (final IOException e) {
throw Exceptions.wrap(e);
}
}
private static void write(final Writer out, final LineString line, final int axisCount)
throws IOException {
writeGeometryType(out, "LINESTRING", axisCount);
if (line.isEmpty()) {
out.write(" EMPTY");
} else {
final LineString coordinates = line;
writeCoordinates(out, coordinates, axisCount);
}
}
private static void write(final Writer out, final LineString coordinates, final int index,
final int axisCount) throws IOException {
writeOrdinate(out, coordinates, index, 0);
for (int j = 1; j < axisCount; j++) {
out.write(' ');
writeOrdinate(out, coordinates, index, j);
}
}
public static void write(final Writer out, final Point point) {
final int axisCount = Math.min(point.getAxisCount(), 4);
try {
write(out, point, axisCount);
} catch (final IOException e) {
throw Exceptions.wrap(e);
}
}
private static void write(final Writer out, final Point point, final int axisCount)
throws IOException {
writeGeometryType(out, "POINT", axisCount);
if (point.isEmpty()) {
out.write(" EMPTY");
} else {
out.write("(");
writeCoordinates(out, point, axisCount);
out.write(')');
}
}
public static void write(final Writer out, final Polygon polygon) {
final int axisCount = Math.min(polygon.getAxisCount(), 4);
try {
write(out, polygon, axisCount);
} catch (final IOException e) {
throw Exceptions.wrap(e);
}
}
private static void write(final Writer out, final Polygon polygon, final int axisCount)
throws IOException {
writeGeometryType(out, "POLYGON", axisCount);
if (polygon.isEmpty()) {
out.write(" EMPTY");
} else {
writePolygon(out, polygon, axisCount);
}
}
public static void write(final Writer out, final Polygonal polygonal) {
final int axisCount = Math.min(polygonal.getAxisCount(), 4);
try {
write(out, polygonal, axisCount);
} catch (final IOException e) {
throw Exceptions.wrap(e);
}
}
private static void write(final Writer out, final Polygonal polygonal, final int axisCount)
throws IOException {
writeGeometryType(out, "MULTIPOLYGON", axisCount);
if (polygonal.isEmpty()) {
out.write(" EMPTY");
} else {
out.write("(");
Polygon polygon = (Polygon)polygonal.getGeometry(0);
writePolygon(out, polygon, axisCount);
for (int i = 1; i < polygonal.getGeometryCount(); i++) {
out.write(",");
polygon = (Polygon)polygonal.getGeometry(i);
writePolygon(out, polygon, axisCount);
}
out.write(")");
}
}
public static void write(final Writer out, final Punctual punctual) {
final int axisCount = Math.min(punctual.getAxisCount(), 4);
try {
write(out, punctual, axisCount);
} catch (final IOException e) {
throw Exceptions.wrap(e);
}
}
private static void write(final Writer out, final Punctual punctual, final int axisCount)
throws IOException {
writeGeometryType(out, "MULTIPOINT", axisCount);
if (punctual.isEmpty()) {
out.write(" EMPTY");
} else {
Point point = punctual.getPoint(0);
out.write("((");
writeCoordinates(out, point, axisCount);
for (int i = 1; i < punctual.getGeometryCount(); i++) {
out.write("),(");
point = punctual.getPoint(i);
writeCoordinates(out, point, axisCount);
}
out.write("))");
}
}
private static void writeCoordinates(final Writer out, final LineString coordinates,
final int axisCount) throws IOException {
out.write('(');
write(out, coordinates, 0, axisCount);
for (int i = 1; i < coordinates.getVertexCount(); i++) {
out.write(',');
write(out, coordinates, i, axisCount);
}
out.write(')');
}
private static void writeCoordinates(final Writer out, final Point point, final int axisCount)
throws IOException {
writeOrdinate(out, point, 0);
for (int j = 1; j < axisCount; j++) {
out.write(' ');
writeOrdinate(out, point, j);
}
}
public static void writeGeometryCollection(final Writer out, final Geometry multiGeometry) {
final int axisCount = Math.min(multiGeometry.getAxisCount(), 4);
try {
writeGeometryCollection(out, multiGeometry, axisCount);
} catch (final IOException e) {
throw Exceptions.wrap(e);
}
}
private static void writeGeometryCollection(final Writer out, final Geometry multiGeometry,
final int axisCount) throws IOException {
writeGeometryType(out, "GEOMETRYCOLLECTION", axisCount);
if (multiGeometry.isEmpty()) {
out.write(" EMPTY");
} else {
out.write("(");
Geometry geometry = multiGeometry.getGeometry(0);
write(out, geometry, axisCount);
for (int i = 1; i < multiGeometry.getGeometryCount(); i++) {
out.write(',');
geometry = multiGeometry.getGeometry(i);
write(out, geometry, axisCount);
}
out.write(')');
}
}
private static void writeGeometryType(final Writer out, final String geometryType,
final int axisCount) throws IOException {
out.write(geometryType);
}
private static void writeOrdinate(final Writer out, final LineString coordinates, final int index,
final int ordinateIndex) throws IOException {
if (ordinateIndex > coordinates.getAxisCount()) {
out.write('0');
} else {
final double ordinate = coordinates.getCoordinate(index, ordinateIndex);
if (Double.isNaN(ordinate)) {
out.write('0');
} else {
out.write(Doubles.toString(ordinate));
}
}
}
private static void writeOrdinate(final Writer out, final Point coordinates,
final int ordinateIndex) throws IOException {
if (ordinateIndex > coordinates.getAxisCount()) {
out.write('0');
} else {
final double ordinate = coordinates.getCoordinate(ordinateIndex);
out.write(Doubles.toString(ordinate));
}
}
private static void writePolygon(final Writer out, final Polygon polygon, final int axisCount)
throws IOException {
out.write('(');
LinearRing shell = polygon.getShell();
shell = shell.toCounterClockwise();
final LineString coordinates = shell;
writeCoordinates(out, coordinates, axisCount);
for (int i = 0; i < polygon.getHoleCount(); i++) {
out.write(',');
LinearRing hole = polygon.getHole(i);
hole = hole.toClockwise();
writeCoordinates(out, hole, axisCount);
}
out.write(')');
}
}