package de.westnordost.streetcomplete.util;
import com.vividsolutions.jts.geom.Coordinate;
import com.vividsolutions.jts.geom.Geometry;
import com.vividsolutions.jts.geom.GeometryFactory;
import com.vividsolutions.jts.geom.LineString;
import com.vividsolutions.jts.geom.LinearRing;
import com.vividsolutions.jts.geom.Point;
import com.vividsolutions.jts.geom.Polygon;
import com.vividsolutions.jts.operation.valid.IsValidOp;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import de.westnordost.osmapi.map.data.LatLon;
import de.westnordost.osmapi.map.data.OsmLatLon;
import de.westnordost.streetcomplete.data.osm.ElementGeometry;
public class JTSConst
{
private static GeometryFactory factory = new GeometryFactory();
public static Geometry toGeometry(ElementGeometry e)
{
GeometryFactory factory = new GeometryFactory();
if(e.polygons != null)
{
ElementGeometry.Polygons p = e.getPolygonsOrderedByOrientation();
return toPolygons(p.outer, p.inner);
}
else if (e.polylines != null)
{
return toLineStrings(e.polylines);
}
else
{
return toPoint(e.center);
}
}
public static Geometry toPolygons(List<List<LatLon>> outer, List<List<LatLon>> inner)
{
Map<LinearRing, ArrayList<LinearRing>> shellsWithHoles = toShellsWithHoles(outer, inner);
Polygon[] polys = new Polygon[shellsWithHoles.size()];
int i = 0;
for(LinearRing shell : shellsWithHoles.keySet())
{
ArrayList<LinearRing> holesList = shellsWithHoles.get(shell);
LinearRing[] holes = null;
if(holesList != null)
{
holes = holesList.toArray(new LinearRing[holesList.size()]);
}
polys[i++] = factory.createPolygon(shell, holes);
}
if(polys.length == 1) return polys[0];
else return factory.createMultiPolygon(polys);
}
public static Geometry toLineStrings(List<List<LatLon>> polylines)
{
LineString[] lineStrings = new LineString[polylines.size()];
int i = 0;
for(List<LatLon> polyline : polylines)
{
lineStrings[i++] = factory.createLineString(toCoordinates(polyline));
}
if(lineStrings.length == 1) return lineStrings[0];
else return factory.createMultiLineString(lineStrings);
}
private static Map<LinearRing, ArrayList<LinearRing>> toShellsWithHoles(
List<List<LatLon>> outerPolygons, List<List<LatLon>> innerPolygons)
{
// outer -> List of inner
Map<LinearRing, ArrayList<LinearRing>> shellsWithHoles = new HashMap<>();
for (List<LatLon> outer : outerPolygons)
{
LinearRing shell = factory.createLinearRing(toCoordinates(outer));
Geometry outerGeom = factory.createPolygon(shell);
shellsWithHoles.put(shell, null);
Iterator<List<LatLon>> it = innerPolygons.iterator();
while(it.hasNext())
{
List<LatLon> inner = it.next();
LinearRing hole = factory.createLinearRing(toCoordinates(inner));
Geometry holeGeom = factory.createPolygon(hole);
if(outerGeom.contains(holeGeom))
{
if(shellsWithHoles.get(shell) == null)
{
shellsWithHoles.put(shell, new ArrayList<LinearRing>());
}
shellsWithHoles.get(shell).add(hole);
it.remove();
}
}
}
return shellsWithHoles;
}
public static Coordinate[] toCoordinates(List<LatLon> latLons)
{
Coordinate[] result = new Coordinate[latLons.size()];
int i = 0;
for(LatLon latLon : latLons)
{
result[i++] = toCoordinate(latLon);
}
return result;
}
public static Coordinate toCoordinate(LatLon latLon)
{
return new Coordinate(latLon.getLongitude(), latLon.getLatitude());
}
public static Point toPoint(LatLon latLon)
{
return factory.createPoint(toCoordinate(latLon));
}
public static LatLon toLatLon(Point p)
{
return new OsmLatLon(p.getY(), p.getX());
}
public static LatLon toLatLon(Coordinate c)
{
return new OsmLatLon(c.y, c.x);
}
}