use of org.locationtech.jts.geom.LineString in project hale by halestudio.
the class PolygonToLineString method convert.
/**
* @see GeometryConverter#convert(Geometry)
*/
@Override
public LineString convert(Polygon polygon) {
LineString exterior = polygon.getExteriorRing();
// the previously implemented behavior of creating a MultiLineString
// forming different segments causes problems due to the potentially
// massive amount of segments
Coordinate[] coordinates = exterior.getCoordinates();
int length = coordinates.length;
if (length > 1) {
// test if first equals last
boolean isRing = coordinates[0].equals(coordinates[length - 1]);
if (isRing) {
return exterior;
} else {
// create a ring line string
Coordinate[] org = exterior.getCoordinates();
Coordinate[] copy = new Coordinate[org.length + 1];
System.arraycopy(org, 0, copy, 0, org.length);
copy[org.length] = org[0];
return geomFactory.createLineString(copy);
}
} else {
return exterior;
}
}
use of org.locationtech.jts.geom.LineString in project hale by halestudio.
the class InstanceMarker method paintGeometry.
/**
* Paint a geometry.
*
* @param g the graphics to paint on
* @param crsDefinition the CRS definition associated with the geometry
* @param geometry the geometry
* @param context the context
* @param converter the pixel converter
* @param zoom the zoom level
* @param singleGeometry if this is the only geometry associated to the
* marker
* @param gBounds the graphics bounds
* @param mapCRS the map coordinate reference system
* @param calculateArea if the area representing the marker should be
* calculated, if <code>false</code> is given here the return
* value is ignored and should be <code>null</code>
* @return the area the geometry occupies (in pixel coordinates), or
* <code>null</code> if nothing has been painted
*/
protected Area paintGeometry(Graphics2D g, CRSDefinition crsDefinition, Geometry geometry, InstanceWaypoint context, PixelConverter converter, int zoom, boolean singleGeometry, Rectangle gBounds, CoordinateReferenceSystem mapCRS, boolean calculateArea) {
if (geometry instanceof GeometryCollection) {
// paint each geometry in a geometry collection
List<Area> areas = (calculateArea) ? (new ArrayList<Area>()) : (null);
GeometryCollection collection = (GeometryCollection) geometry;
for (int i = 0; i < collection.getNumGeometries(); i++) {
Geometry geom = collection.getGeometryN(i);
Area geomArea = paintGeometry(g, crsDefinition, geom, context, converter, zoom, singleGeometry && collection.getNumGeometries() == 1, gBounds, mapCRS, calculateArea);
if (areas != null && geomArea != null) {
areas.add(geomArea);
}
}
if (areas == null || areas.isEmpty()) {
return null;
} else {
return new MultiArea(areas);
}
}
// if it is the only geometry the check that was already made is OK
if (!calculateArea && !singleGeometry) {
// we can safely return null inside this method, as no area has to
// be calculated
// determine bounding box
BoundingBox geometryBB;
synchronized (geometryMapBBs) {
// retrieve cached bounding box
geometryBB = geometryMapBBs.get(geometry);
if (geometryBB == null) {
// if none available, try to calculate BB
BoundingBox calcBB = BoundingBox.compute(geometry);
if (calcBB != null && calcBB.checkIntegrity()) {
try {
// get CRS converter
CRSConverter conv = CRSConverter.getConverter(crsDefinition.getCRS(), mapCRS);
// manually convert to map CRS
geometryBB = conv.convert(calcBB);
// put BB in cache
geometryMapBBs.put(geometry, geometryBB);
} catch (Throwable e) {
log.error("Error checking geometry bounding box", e);
return null;
}
}
}
}
if (geometryBB != null) {
try {
GeoPosition minCorner = new GeoPosition(geometryBB.getMinX(), geometryBB.getMinY(), converter.getMapEpsg());
GeoPosition maxCorner = new GeoPosition(geometryBB.getMaxX(), geometryBB.getMaxY(), converter.getMapEpsg());
// determine pixel coordinates
Point2D minPixels = converter.geoToPixel(minCorner, zoom);
Point2D maxPixels = converter.geoToPixel(maxCorner, zoom);
// geometry pixel bounding box
int minX = Math.min((int) minPixels.getX(), (int) maxPixels.getX());
int minY = Math.min((int) minPixels.getY(), (int) maxPixels.getY());
int maxX = Math.max((int) minPixels.getX(), (int) maxPixels.getX());
int maxY = Math.max((int) minPixels.getY(), (int) maxPixels.getY());
// add overlap
minX -= GEOMETRY_PIXEL_BB_OVERLAP;
minY -= GEOMETRY_PIXEL_BB_OVERLAP;
maxX += GEOMETRY_PIXEL_BB_OVERLAP;
maxY += GEOMETRY_PIXEL_BB_OVERLAP;
// create bounding box
Rectangle geometryPixelBB = new Rectangle(minX, minY, maxX - minX, maxY - minY);
if (!gBounds.intersects(geometryPixelBB) && !gBounds.contains(geometryPixelBB)) {
// geometry does not lie in tile
return null;
}
} catch (Throwable e) {
log.error("Error checking geometry bounding box", e);
return null;
}
} else {
// empty or invalid bounding box
return null;
}
}
if (geometry instanceof Point) {
return paintPoint((Point) geometry, g, crsDefinition, context, converter, zoom, mapCRS, calculateArea);
}
if (geometry instanceof Polygon) {
return paintPolygon((Polygon) geometry, g, crsDefinition, context, converter, zoom, mapCRS, calculateArea);
}
if (geometry instanceof LineString) {
return paintLine((LineString) geometry, g, crsDefinition, context, converter, zoom, mapCRS, calculateArea);
}
return null;
}
use of org.locationtech.jts.geom.LineString in project hale by halestudio.
the class InstanceMarker method paintPolygon.
/**
* Paint a polygon geometry.
*
* @param geometry the polygon
* @param g the graphics object to paint on
* @param crsDefinition the CRS definition associated to the geometry
* @param context the context
* @param converter the pixel converter
* @param zoom the zoom level
* @param mapCRS the map coordinate reference system
* @param calculateArea if the area representing the marker should be
* calculated, if <code>false</code> is given here the return
* value is ignored and should be <code>null</code>
* @return the polygon area or <code>null</code> if painting failed
*/
protected Area paintPolygon(Polygon geometry, Graphics2D g, CRSDefinition crsDefinition, InstanceWaypoint context, PixelConverter converter, int zoom, CoordinateReferenceSystem mapCRS, boolean calculateArea) {
try {
// get CRS converter
CRSConverter conv = CRSConverter.getConverter(crsDefinition.getCRS(), mapCRS);
// exterior
Coordinate[] coordinates = geometry.getExteriorRing().getCoordinates();
java.awt.Polygon outerPolygon = createPolygon(coordinates, conv, converter, zoom);
if (geometry.getNumInteriorRing() > 0) {
// polygon has interior geometries
java.awt.geom.Area drawArea = new java.awt.geom.Area(outerPolygon);
// interior
for (int i = 0; i < geometry.getNumInteriorRing(); i++) {
LineString interior = geometry.getInteriorRingN(i);
java.awt.Polygon innerPolygon = createPolygon(interior.getCoordinates(), conv, converter, zoom);
drawArea.subtract(new java.awt.geom.Area(innerPolygon));
}
if (applyFill(g, context)) {
g.fill(drawArea);
}
if (applyStroke(g, context)) {
g.draw(drawArea);
}
if (calculateArea) {
return new AdvancedPolygonArea(drawArea, outerPolygon);
}
} else {
// visible)
if (applyFill(g, context)) {
g.fill(outerPolygon);
}
if (applyStroke(g, context)) {
g.draw(outerPolygon);
}
if (calculateArea) {
return new PolygonArea(outerPolygon);
}
}
// no calculateArea set
return null;
} catch (Exception e) {
log.error("Error painting instance polygon geometry", e);
return null;
}
}
use of org.locationtech.jts.geom.LineString in project hale by halestudio.
the class GridInterpolationTest method gridInterpolationTest.
// utility methods
private LineString gridInterpolationTest(ArcString arcs, double maxPositionalError, boolean moveAllToGrid) throws IOException {
GridInterpolation interpol = new GridInterpolation();
Map<String, String> properties = new HashMap<>();
if (moveAllToGrid) {
properties.put(GridInterpolation.PARAMETER_MOVE_ALL_TO_GRID, "true");
}
interpol.configure(new GeometryFactory(), maxPositionalError, properties);
LineString result = interpol.interpolateArcString(arcs);
double gridSize = GridUtil.getGridSize(maxPositionalError);
drawGridInterpolatedArcString(arcs, gridSize, result);
// test interpolated geometry
Coordinate[] coords = result.getCoordinates();
for (int i = 0; i < coords.length; i++) {
Coordinate c = coords[i];
boolean checkGrid = moveAllToGrid;
if (checkGrid) {
// check if coordinate on grid
GridUtilTest.checkOnGrid(c, gridSize);
}
// check if two coordinates are not the same
if (i < coords.length - 1) {
Coordinate c2 = coords[i + 1];
assertNotEquals(MessageFormat.format("Subsequent coordinates are equal ({0} and {1})", c, c2), c, c2);
if (checkGrid) {
// better check is to compare difference in x and y based on
// grid size
boolean xDifferent = Math.abs(c2.x - c.x) > (gridSize / 2);
boolean yDifferent = Math.abs(c2.y - c.y) > (gridSize / 2);
assertTrue("Subsequent coordinates are equal", xDifferent || yDifferent);
}
}
}
return result;
}
use of org.locationtech.jts.geom.LineString in project hale by halestudio.
the class CurveHelper method combineCurve.
/**
* Combine the given {@link LineString}s using the given builder.
*
* @param lineStrings the line strings
* @param strict if it should be checked if the geometry fulfills the strict
* requirements of a curve
* @param builder the builder function creating a combination of the
* individual {@link LineString}s
* @return the combined {@link MultiLineString} or <code>null</code> if the
* geometry did not meet the requirements of the strict mode
*/
@Nullable
public static <T> T combineCurve(List<? extends LineString> lineStrings, boolean strict, Function<List<LineString>, T> builder) {
// try to order by start/end point (e.g. for composite curves)
Map<Coordinate, LineString> endPoints = new HashMap<>();
for (LineString element : lineStrings) {
endPoints.put(element.getEndPoint().getCoordinate(), element);
}
Map<LineString, Set<LineString>> dependencies = new HashMap<>();
for (LineString element : lineStrings) {
// check if there is another line that ends at this line's start
// and build the dependency map accordingly
LineString dependsOn = endPoints.get(element.getStartPoint().getCoordinate());
@SuppressWarnings("unchecked") Set<LineString> deps = (Set<LineString>) ((dependsOn == null) ? Collections.emptySet() : Collections.singleton(dependsOn));
dependencies.put(element, deps);
}
// use dependency ordered list to achieve sorting
// will only yield a perfect result if all lines can be combined into
// one
DependencyOrderedList<LineString> ordered = new DependencyOrderedList<>(dependencies);
if (strict) {
Coordinate lastEndPoint = null;
for (LineString lineString : ordered.getInternalList()) {
if (lastEndPoint != null) {
// start point must be equal to last end point
if (!lineString.getStartPoint().getCoordinate().equals(lastEndPoint)) {
// not a strict curve
return null;
}
}
lastEndPoint = lineString.getEndPoint().getCoordinate();
}
} else {
// "best effort"
}
return builder.apply(ordered.getInternalList());
}
Aggregations