package jeql.jts.geodetic;
import com.vividsolutions.jts.geom.Coordinate;
import com.vividsolutions.jts.geom.Geometry;
import com.vividsolutions.jts.geom.LineString;
import com.vividsolutions.jts.geom.MultiLineString;
public class GeodeticSplitter
{
private Geometry line;
public GeodeticSplitter(Geometry line)
{
this.line = line;
}
public Geometry split()
{
MultiCoordinateList mcl = new MultiCoordinateList(false);
Coordinate[] pts = line.getCoordinates();
mcl.add(pts[0]);
for (int i = 1; i < pts.length; i++) {
Coordinate p0 = pts[i-1];
Coordinate p1 = pts[i];
if (crossesDateLine(p0, p1)) {
double latCross = latitudeOfCrossing(p0, p1);
if (p0.x < 0) {
mcl.add(new Coordinate(-180, latCross));
mcl.finish();
mcl.add(new Coordinate(180, latCross));
}
else {
mcl.add(new Coordinate(180, latCross));
mcl.finish();
mcl.add(new Coordinate(-180, latCross));
}
}
mcl.add(p1);
}
return toMultiLineString(mcl);
}
private static boolean crossesDateLine(Coordinate p0, Coordinate p1)
{
if (p0.x < -90 && p1.x > 90) return true;
if (p1.x < -90 && p0.x > 90) return true;
return false;
}
private static double latitudeOfCrossing(Coordinate p0, Coordinate p1)
{
// compute in the lon-lat plane - which isn't accurate for long lines
double x0 = p0.x;
double y0 = p0.y;
double x1 = p1.x + 360;;
double y1 = p1.y;
if (p0.x < 0) {
x0 = p1.x;
y0 = p1.y;
x1 = p0.x + 360;
y1 = p0.y;
}
double dx = x1 - x0;
double dy = y1 - y0;
double x = 180 - x0;
double y = dy/dx * x;
return y + y0;
}
private MultiLineString toMultiLineString(MultiCoordinateList mcl)
{
Coordinate[][] pts = mcl.toCoordinateArrays();
LineString[] lines = new LineString[pts.length];
for (int i = 0; i < pts.length; i++) {
lines[i] = toLineString(pts[i]);
}
return line.getFactory().createMultiLineString(lines);
}
private LineString toLineString(Coordinate[] pts)
{
// prevent lines of length 1
if (pts.length == 1) {
pts = new Coordinate[] { pts[0], new Coordinate(pts[0]) };
}
return line.getFactory().createLineString(pts);
}
}