use of com.vividsolutions.jts.geom.util.AffineTransformation in project spatial-portal by AtlasOfLivingAustralia.
the class Util method fixWkt.
public static String fixWkt(String wkt) {
if (wkt == null || !(wkt.startsWith("POLYGON") || wkt.startsWith("MULTIPOLYGON"))) {
return wkt;
}
String newWkt = wkt;
try {
WKTReader wktReader = new WKTReader();
com.vividsolutions.jts.geom.Geometry g = wktReader.read(wkt);
// NC 20130319: Ensure that the WKT is valid according to the WKT standards.
// if outside -180 to 180, cut and fit
Envelope env = g.getEnvelopeInternal();
if (env.getMinX() < -180 || env.getMaxX() > 180) {
int minx = -180;
while (minx > env.getMinX()) {
minx -= 360;
}
int maxx = 180;
while (maxx < env.getMaxX()) {
maxx += 360;
}
// divide, translate and rejoin
Geometry newGeometry = null;
for (int i = minx; i < maxx; i += 360) {
Geometry cutter = wktReader.read("POLYGON((" + i + " -90," + i + " 90," + (i + 360) + " 90," + (i + 360) + " -90," + i + " -90))");
Geometry part = cutter.intersection(g);
// offset cutter
if (i != -180) {
AffineTransformation at = AffineTransformation.translationInstance(-180 - i, 0);
part.apply(at);
}
if (part.getArea() > 0) {
if (newGeometry == null) {
newGeometry = part;
} else {
newGeometry = newGeometry.union(part);
}
}
}
newWkt = newGeometry.toText();
}
IsValidOp op = new IsValidOp(g);
if (!op.isValid()) {
// this will fix some issues
g = g.buffer(0);
op = new IsValidOp(g);
}
if (!op.isValid()) {
// give up?
} else if (g.isRectangle()) {
// NC 20130319: When the shape is a rectangle ensure that the points a specified in the correct order.
// get the new WKT for the rectangle will possibly need to change the order.
com.vividsolutions.jts.geom.Envelope envelope = g.getEnvelopeInternal();
newWkt = StringConstants.POLYGON + "((" + envelope.getMinX() + " " + envelope.getMinY() + "," + envelope.getMaxX() + " " + envelope.getMinY() + "," + envelope.getMaxX() + " " + envelope.getMaxY() + "," + envelope.getMinX() + " " + envelope.getMaxY() + "," + envelope.getMinX() + " " + envelope.getMinY() + "))";
}
} catch (ParseException parseException) {
LOGGER.error("error fixing WKT", parseException);
}
return newWkt;
}
use of com.vividsolutions.jts.geom.util.AffineTransformation in project Osmand by osmandapp.
the class JtsAdapter method createTileGeom.
/**
* Create geometry clipped and then converted to MVT 'extent' coordinates. Result
* contains both clipped geometry (intersection) and transformed geometry for encoding to MVT.
*
* @param g original 'source' geometry, passed through {@link #flatFeatureList(Geometry)}
* @param tileEnvelope world coordinate bounds for tile
* @param geomFactory creates a geometry for the tile envelope
* @param mvtLayerParams specifies vector tile properties
* @param filter geometry values that fail filter after transforms are removed
* @return tile geometry result
* @see TileGeomResult
*/
public static TileGeomResult createTileGeom(List<Geometry> g, Envelope tileEnvelope, GeometryFactory geomFactory, MvtLayerParams mvtLayerParams, IGeometryFilter filter) {
final Geometry tileEnvelopeGeom = geomFactory.toGeometry(tileEnvelope);
final AffineTransformation t = new AffineTransformation();
final double xDiff = tileEnvelope.getWidth();
final double yDiff = tileEnvelope.getHeight();
final double xOffset = -tileEnvelope.getMinX();
final double yOffset = -tileEnvelope.getMinY();
// Transform Setup: Shift to 0 as minimum value
t.translate(xOffset, yOffset);
// Transform Setup: Scale X and Y to tile extent values, flip Y values
t.scale(1d / (xDiff / (double) mvtLayerParams.extent), -1d / (yDiff / (double) mvtLayerParams.extent));
// Transform Setup: Bump Y values to positive quadrant
t.translate(0d, (double) mvtLayerParams.extent);
// The area contained in BOTH the 'original geometry', g, AND the 'tile envelope geometry' is the 'tile geometry'
final List<Geometry> intersectedGeoms = flatIntersection(tileEnvelopeGeom, g);
final List<Geometry> transformedGeoms = new ArrayList<>(intersectedGeoms.size());
// Transform intersected geometry
Geometry nextTransformGeom;
Object nextUserData;
for (Geometry nextInterGeom : intersectedGeoms) {
nextUserData = nextInterGeom.getUserData();
nextTransformGeom = t.transform(nextInterGeom);
// Floating --> Integer, still contained within doubles
nextTransformGeom.apply(RoundingFilter.INSTANCE);
// TODO: Refactor line simplification
// Can't use 0d, specify value < .5d
nextTransformGeom = TopologyPreservingSimplifier.simplify(nextTransformGeom, .1d);
nextTransformGeom.setUserData(nextUserData);
// Apply filter on transformed geometry
if (filter.accept(nextTransformGeom)) {
transformedGeoms.add(nextTransformGeom);
}
}
return new TileGeomResult(intersectedGeoms, transformedGeoms);
}
use of com.vividsolutions.jts.geom.util.AffineTransformation in project OpenTripPlanner by opentripplanner.
the class TileRendererManager method renderTile.
public BufferedImage renderTile(final TileRequest tileRequest, String layer) {
TileRenderContext context = new TileRenderContext() {
@Override
public Envelope expandPixels(double marginXPixels, double marginYPixels) {
Envelope retval = new Envelope(bbox);
retval.expandBy(marginXPixels / tileRequest.width * (bbox.getMaxX() - bbox.getMinX()), marginYPixels / tileRequest.height * (bbox.getMaxY() - bbox.getMinY()));
return retval;
}
};
context.graph = graph;
TileRenderer renderer = renderers.get(layer);
if (renderer == null)
throw new IllegalArgumentException("Unknown layer: " + layer);
// The best place for caching tiles may be here
BufferedImage image = new BufferedImage(tileRequest.width, tileRequest.height, renderer.getColorModel());
context.graphics = image.createGraphics();
Envelope2D trbb = tileRequest.bbox;
context.bbox = new Envelope(trbb.x, trbb.x + trbb.width, trbb.y, trbb.y + trbb.height);
context.transform = new AffineTransformation();
double xScale = tileRequest.width / trbb.width;
double yScale = tileRequest.height / trbb.height;
context.transform.translate(-trbb.x, -trbb.y - trbb.height);
context.transform.scale(xScale, -yScale);
context.metersPerPixel = Math.toRadians(trbb.height) * 6371000 / tileRequest.height;
context.tileWidth = tileRequest.width;
context.tileHeight = tileRequest.height;
long start = System.currentTimeMillis();
renderer.renderTile(context);
LOG.debug("Rendered tile at {},{} in {} ms", tileRequest.bbox.y, tileRequest.bbox.x, System.currentTimeMillis() - start);
return image;
}
Aggregations