Search in sources :

Example 1 with PreparedGeometry

use of org.locationtech.jts.geom.prep.PreparedGeometry in project risky by amsa-code.

the class Shapefile method load.

private Shapefile load() {
    if (state.compareAndSet(NOT_LOADED, LOADED)) {
        try {
            final List<PreparedGeometry> geometries = new ArrayList<>();
            for (String typeName : datastore.getTypeNames()) {
                SimpleFeatureSource source = datastore.getFeatureSource(typeName);
                crs = source.getBounds().getCoordinateReferenceSystem();
                final SimpleFeatureCollection features = source.getFeatures();
                SimpleFeatureIterator it = features.features();
                while (it.hasNext()) {
                    SimpleFeature feature = it.next();
                    Geometry g = (Geometry) feature.getDefaultGeometry();
                    if (bufferDistance > 0)
                        g = g.buffer(bufferDistance);
                    geometries.add(PreparedGeometryFactory.prepare(g));
                    this.features.add(feature);
                }
                it.close();
            }
            this.geometries = geometries;
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
    } else if (state.get() == CLOSED)
        throw new RuntimeException("Shapefile is closed and can't be accessed");
    return this;
}
Also used : PreparedGeometry(org.locationtech.jts.geom.prep.PreparedGeometry) Geometry(org.locationtech.jts.geom.Geometry) PreparedGeometry(org.locationtech.jts.geom.prep.PreparedGeometry) SimpleFeatureIterator(org.geotools.data.simple.SimpleFeatureIterator) SimpleFeatureSource(org.geotools.data.simple.SimpleFeatureSource) ArrayList(java.util.ArrayList) IOException(java.io.IOException) SimpleFeature(org.opengis.feature.simple.SimpleFeature) SimpleFeatureCollection(org.geotools.data.simple.SimpleFeatureCollection)

Example 2 with PreparedGeometry

use of org.locationtech.jts.geom.prep.PreparedGeometry in project risky by amsa-code.

the class ShipTypeBreakdownMain method main.

public static void main(String[] args) throws FileNotFoundException, IOException {
    // load a shapefile
    final GeometryFactory gf = new GeometryFactory();
    File file = new File("/home/dxm/temp/srr.shp");
    Map<String, Serializable> map = new HashMap<>();
    map.put("url", file.toURI().toURL());
    DataStore datastore = DataStoreFinder.getDataStore(map);
    String typeName = datastore.getTypeNames()[0];
    System.out.println(typeName);
    SimpleFeatureSource source = datastore.getFeatureSource(typeName);
    final SimpleFeatureCollection features = source.getFeatures();
    final List<PreparedGeometry> geometries = new ArrayList<>();
    SimpleFeatureIterator it = features.features();
    while (it.hasNext()) {
        SimpleFeature feature = it.next();
        Geometry g = (Geometry) feature.getDefaultGeometry();
        geometries.add(PreparedGeometryFactory.prepare(g));
    }
    // System.exit(0);
    String filename = "/media/analysis/nmea/2014/NMEA_ITU_20140815.gz";
    final Set<Long> mmsi = new HashSet<Long>();
    final Set<Long> mmsiA = new HashSet<Long>();
    final Set<Long> mmsiB = new HashSet<Long>();
    Streams.extract(Streams.nmeaFromGzip(filename)).flatMap(aisPositionsOnly).lift(Logging.<TimestampedAndLine<AisPosition>>logger().showCount().every(100000).log()).doOnNext(m -> {
        AisPosition p = m.getMessage().get().message();
        if (p.getLatitude() != null && p.getLongitude() != null && contains(gf, geometries, p.getLatitude(), p.getLongitude())) {
            long mmsiNo = m.getMessage().get().message().getMmsi();
            mmsi.add(mmsiNo);
            if (m.getMessage().get().message() instanceof AisPositionA)
                mmsiA.add(mmsiNo);
            else
                mmsiB.add(mmsiNo);
        }
    }).subscribe();
    final Map<ShipTypeClass, Set<Integer>> countsByShipType = new ConcurrentHashMap<>();
    Streams.extract(Streams.nmeaFromGzip(filename)).flatMap(aisShipStaticOnly).doOnNext(m -> {
        AisShipStatic s = m.getMessage().get().message();
        if (mmsi.contains(Long.valueOf(s.getMmsi()))) {
            boolean isClassA = s instanceof AisShipStaticA;
            ShipTypeClass shipTypeClass = new ShipTypeClass(isClassA, s.getShipType());
            if (countsByShipType.get(shipTypeClass) == null)
                countsByShipType.put(shipTypeClass, new HashSet<Integer>());
            else
                countsByShipType.get(shipTypeClass).add(s.getMmsi());
        }
    }).subscribe();
    System.out.println(countsByShipType);
    Set<String> set = new TreeSet<String>();
    int sizeA = 0;
    int sizeB = 0;
    for (Entry<ShipTypeClass, Set<Integer>> s : countsByShipType.entrySet()) {
        set.add(ShipTypeDecoder.getShipType(s.getKey().shipType) + "\t" + (s.getKey().isClassA ? "A" : "B") + "\t" + s.getValue().size());
        if (s.getKey().isClassA)
            sizeA += s.getValue().size();
        else
            sizeB += s.getValue().size();
    }
    set.stream().forEach(System.out::println);
    System.out.println("Unknown\tA\t" + (mmsiA.size() - sizeA));
    System.out.println("Unknown\tB\t" + (mmsiB.size() - sizeB));
    log.info("finished");
}
Also used : ShipTypeDecoder(au.gov.amsa.ais.ShipTypeDecoder) Logging(com.github.davidmoten.rx.slf4j.Logging) AisPosition(au.gov.amsa.ais.message.AisPosition) AisShipStatic(au.gov.amsa.ais.message.AisShipStatic) LoggerFactory(org.slf4j.LoggerFactory) Coordinate(org.locationtech.jts.geom.Coordinate) HashMap(java.util.HashMap) TreeSet(java.util.TreeSet) ArrayList(java.util.ArrayList) SimpleFeatureSource(org.geotools.data.simple.SimpleFeatureSource) Observable(rx.Observable) HashSet(java.util.HashSet) Func1(rx.functions.Func1) AisPositionA(au.gov.amsa.ais.message.AisPositionA) SimpleFeature(org.opengis.feature.simple.SimpleFeature) Streams(au.gov.amsa.ais.rx.Streams) Map(java.util.Map) DataStoreFinder(org.geotools.data.DataStoreFinder) PreparedGeometry(org.locationtech.jts.geom.prep.PreparedGeometry) TimestampedAndLine(au.gov.amsa.ais.rx.Streams.TimestampedAndLine) GeometryFactory(org.locationtech.jts.geom.GeometryFactory) Logger(org.slf4j.Logger) SimpleFeatureCollection(org.geotools.data.simple.SimpleFeatureCollection) Collection(java.util.Collection) ConcurrentHashMap(java.util.concurrent.ConcurrentHashMap) Set(java.util.Set) IOException(java.io.IOException) AisMessage(au.gov.amsa.ais.AisMessage) File(java.io.File) FileNotFoundException(java.io.FileNotFoundException) DataStore(org.geotools.data.DataStore) Serializable(java.io.Serializable) List(java.util.List) Entry(java.util.Map.Entry) Optional(java.util.Optional) Geometry(org.locationtech.jts.geom.Geometry) AisShipStaticA(au.gov.amsa.ais.message.AisShipStaticA) SimpleFeatureIterator(org.geotools.data.simple.SimpleFeatureIterator) Timestamped(au.gov.amsa.ais.Timestamped) PreparedGeometryFactory(org.locationtech.jts.geom.prep.PreparedGeometryFactory) Serializable(java.io.Serializable) GeometryFactory(org.locationtech.jts.geom.GeometryFactory) PreparedGeometryFactory(org.locationtech.jts.geom.prep.PreparedGeometryFactory) TreeSet(java.util.TreeSet) HashSet(java.util.HashSet) Set(java.util.Set) HashMap(java.util.HashMap) ConcurrentHashMap(java.util.concurrent.ConcurrentHashMap) SimpleFeatureSource(org.geotools.data.simple.SimpleFeatureSource) ArrayList(java.util.ArrayList) SimpleFeatureIterator(org.geotools.data.simple.SimpleFeatureIterator) AisPositionA(au.gov.amsa.ais.message.AisPositionA) TreeSet(java.util.TreeSet) DataStore(org.geotools.data.DataStore) AisShipStatic(au.gov.amsa.ais.message.AisShipStatic) TimestampedAndLine(au.gov.amsa.ais.rx.Streams.TimestampedAndLine) ConcurrentHashMap(java.util.concurrent.ConcurrentHashMap) AisShipStaticA(au.gov.amsa.ais.message.AisShipStaticA) HashSet(java.util.HashSet) SimpleFeature(org.opengis.feature.simple.SimpleFeature) SimpleFeatureCollection(org.geotools.data.simple.SimpleFeatureCollection) AisPosition(au.gov.amsa.ais.message.AisPosition) PreparedGeometry(org.locationtech.jts.geom.prep.PreparedGeometry) Geometry(org.locationtech.jts.geom.Geometry) PreparedGeometry(org.locationtech.jts.geom.prep.PreparedGeometry) File(java.io.File)

Example 3 with PreparedGeometry

use of org.locationtech.jts.geom.prep.PreparedGeometry in project qupath by qupath.

the class RoiTools method computeTiledROIs.

/**
 * Create a collection of tiled ROIs corresponding to a specified parentROI if it is larger than sizeMax, with optional overlaps.
 * <p>
 * The purpose of this is to create useful tiles whenever the exact tile size may not be essential, and overlaps may be required.
 * Tiles at the parentROI boundary will be trimmed to fit inside. If the parentROI is smaller, it is returned as is.
 *
 * @param parentROI main ROI to be tiled
 * @param sizePreferred the preferred size; in general tiles should have this size
 * @param sizeMax the maximum allowed size; occasionally it is more efficient to have a tile larger than the preferred size towards a ROI boundary to avoid creating very small tiles unnecessarily
 * @param fixedSize if true, the tile size is enforced so that complete tiles have the same size
 * @param overlap optional requested overlap between tiles
 * @return
 *
 * @see #makeTiles(ROI, int, int, boolean)
 */
public static Collection<? extends ROI> computeTiledROIs(ROI parentROI, ImmutableDimension sizePreferred, ImmutableDimension sizeMax, boolean fixedSize, int overlap) {
    ROI pathArea = parentROI != null && parentROI.isArea() ? parentROI : null;
    Rectangle2D bounds = AwtTools.getBounds2D(parentROI);
    if (pathArea == null || (bounds.getWidth() <= sizeMax.width && bounds.getHeight() <= sizeMax.height)) {
        return Collections.singletonList(parentROI);
    }
    Geometry geometry = pathArea.getGeometry();
    PreparedGeometry prepared = null;
    double xMin = bounds.getMinX();
    double yMin = bounds.getMinY();
    int nx = (int) Math.ceil(bounds.getWidth() / sizePreferred.width);
    int ny = (int) Math.ceil(bounds.getHeight() / sizePreferred.height);
    double w = fixedSize ? sizePreferred.width : (int) Math.ceil(bounds.getWidth() / nx);
    double h = fixedSize ? sizePreferred.height : (int) Math.ceil(bounds.getHeight() / ny);
    // Center the tiles
    xMin = (int) (bounds.getCenterX() - (nx * w * .5));
    yMin = (int) (bounds.getCenterY() - (ny * h * .5));
    // This can be very slow if we have an extremely large number of vertices/tiles.
    // For that reason, we try to split initially by either rows or columns if needed.
    boolean byRow = false;
    boolean byColumn = false;
    Map<Integer, Geometry> rowParents = null;
    Map<Integer, Geometry> columnParents = null;
    var envelope = geometry.getEnvelopeInternal();
    if (ny > 1 && nx > 1 && geometry.getNumPoints() > 1000) {
        // If we have a lot of points, create a prepared geometry so we can check covers/intersects quickly;
        // (for a regular geometry, it would be faster to just compute an intersection and see if it's empty)
        prepared = PreparedGeometryFactory.prepare(geometry);
        var prepared2 = prepared;
        var empty = geometry.getFactory().createEmpty(2);
        byRow = nx > ny;
        byColumn = !byRow;
        double yMin2 = yMin;
        double xMin2 = xMin;
        // Compute intersection by row so that later intersections are simplified
        if (byRow) {
            rowParents = IntStream.range(0, ny).parallel().mapToObj(yi -> yi).collect(Collectors.toMap(yi -> yi, yi -> {
                double y = yMin2 + yi * h - overlap;
                var row = GeometryTools.createRectangle(envelope.getMinX(), y, envelope.getMaxX(), h + overlap * 2);
                if (!prepared2.intersects(row))
                    return empty;
                else if (prepared2.covers(row))
                    return row;
                var temp = intersect(geometry, row);
                return temp == null ? geometry : temp;
            }));
        }
        if (byColumn) {
            columnParents = IntStream.range(0, nx).parallel().mapToObj(xi -> xi).collect(Collectors.toMap(xi -> xi, xi -> {
                double x = xMin2 + xi * w - overlap;
                var col = GeometryTools.createRectangle(x, envelope.getMinY(), w + overlap * 2, envelope.getMaxX());
                if (!prepared2.intersects(col))
                    return empty;
                else if (prepared2.covers(col))
                    return col;
                var temp = intersect(geometry, col);
                return temp == null ? geometry : temp;
            }));
        }
    }
    // Geometry local is the one we're working with for the current row or column
    // (often it's the same as the full ROI)
    Geometry geometryLocal = geometry;
    // Generate all the rectangles as geometries
    Map<Geometry, Geometry> tileGeometries = new LinkedHashMap<>();
    for (int yi = 0; yi < ny; yi++) {
        double y = yMin + yi * h - overlap;
        if (rowParents != null)
            geometryLocal = rowParents.getOrDefault(y, geometry);
        for (int xi = 0; xi < nx; xi++) {
            double x = xMin + xi * w - overlap;
            if (columnParents != null)
                geometryLocal = columnParents.getOrDefault(x, geometry);
            if (geometryLocal.isEmpty())
                continue;
            // Create the tile
            var rect = GeometryTools.createRectangle(x, y, w + overlap * 2, h + overlap * 2);
            // Use a prepared geometry if we have one to check covers/intersects & save some effort
            if (prepared != null) {
                if (!prepared.intersects(rect)) {
                    continue;
                } else if (prepared.covers(rect)) {
                    tileGeometries.put(rect, rect);
                    continue;
                }
            }
            // Checking geometryLocal.intersects(rect) first is actually much slower!
            // So add everything and filter out empty tiles later.
            tileGeometries.put(rect, geometryLocal);
        }
    }
    // Compute intersections & map to ROIs
    var plane = parentROI.getImagePlane();
    var tileROIs = tileGeometries.entrySet().parallelStream().map(entry -> intersect(entry.getKey(), entry.getValue())).filter(g -> g != null).map(g -> GeometryTools.geometryToROI(g, plane)).collect(Collectors.toList());
    // If there was an exception, the tile will be null
    if (tileROIs.size() < tileGeometries.size()) {
        logger.warn("Tiles lost during tiling: {}", tileGeometries.size() - tileROIs.size());
        logger.warn("You may be able to avoid tiling errors by calling 'Simplify shape' on any complex annotations first.");
    }
    // Remove any empty/non-area tiles
    return tileROIs.stream().filter(t -> !t.isEmpty() && t.isArea()).collect(Collectors.toList());
}
Also used : IntStream(java.util.stream.IntStream) Rectangle(java.awt.Rectangle) Area(java.awt.geom.Area) Rectangle2D(java.awt.geom.Rectangle2D) LoggerFactory(org.slf4j.LoggerFactory) HashMap(java.util.HashMap) PathIterator(java.awt.geom.PathIterator) ArrayList(java.util.ArrayList) LinkedHashMap(java.util.LinkedHashMap) Point2(qupath.lib.geom.Point2) Ellipse2D(java.awt.geom.Ellipse2D) ImageRegion(qupath.lib.regions.ImageRegion) Map(java.util.Map) PreparedGeometry(org.locationtech.jts.geom.prep.PreparedGeometry) AffineTransformation(org.locationtech.jts.geom.util.AffineTransformation) Shape(java.awt.Shape) Line2D(java.awt.geom.Line2D) Logger(org.slf4j.Logger) Collection(java.util.Collection) AwtTools(qupath.lib.awt.common.AwtTools) AffineTransform(java.awt.geom.AffineTransform) Collectors(java.util.stream.Collectors) Path2D(java.awt.geom.Path2D) ROI(qupath.lib.roi.interfaces.ROI) List(java.util.List) ImagePlane(qupath.lib.regions.ImagePlane) Geometry(org.locationtech.jts.geom.Geometry) ImmutableDimension(qupath.lib.geom.ImmutableDimension) Collections(java.util.Collections) PreparedGeometryFactory(org.locationtech.jts.geom.prep.PreparedGeometryFactory) Rectangle2D(java.awt.geom.Rectangle2D) ROI(qupath.lib.roi.interfaces.ROI) LinkedHashMap(java.util.LinkedHashMap) PreparedGeometry(org.locationtech.jts.geom.prep.PreparedGeometry) Geometry(org.locationtech.jts.geom.Geometry) PreparedGeometry(org.locationtech.jts.geom.prep.PreparedGeometry)

Example 4 with PreparedGeometry

use of org.locationtech.jts.geom.prep.PreparedGeometry in project risky by amsa-code.

the class Shapefile method mbr.

public Rect mbr() {
    // TODO assumes that shapefile is using WGS84?
    load();
    Rect r = null;
    for (PreparedGeometry g : geometries) {
        Coordinate[] v = g.getGeometry().getEnvelope().getCoordinates();
        System.out.println(Arrays.toString(v));
        Rect rect = new Rect(v[0].y, v[0].x, v[2].y, v[2].x);
        if (r == null)
            r = rect;
        else
            r = r.add(rect);
    }
    return r;
}
Also used : PreparedGeometry(org.locationtech.jts.geom.prep.PreparedGeometry) Coordinate(org.locationtech.jts.geom.Coordinate)

Example 5 with PreparedGeometry

use of org.locationtech.jts.geom.prep.PreparedGeometry in project risky by amsa-code.

the class ShapefileUtil method findRegionCrossingPoint.

public static TimedPosition findRegionCrossingPoint(Shapefile region, Fix fix1, Fix fix2) {
    Coordinate[] coords = new Coordinate[] { new Coordinate(fix1.lon(), fix1.lat()), new Coordinate(fix2.lon(), fix2.lat()) };
    LineString line = new GeometryFactory().createLineString(coords);
    for (PreparedGeometry g : region.geometries()) {
        if (g.crosses(line)) {
            Geometry intersection = g.getGeometry().intersection(line);
            // expecting just one point
            Coordinate coord = intersection.getCoordinate();
            double longitude = coord.x;
            double latitude = coord.y;
            Position a = Position.create(fix1.lat(), fix1.lon());
            Position b = Position.create(fix2.lat(), fix2.lon());
            Position c = Position.create(latitude, longitude);
            double ac = a.getDistanceToKm(c);
            double bc = b.getDistanceToKm(c);
            if (ac == 0) {
                return new TimedPosition(fix1.lat(), fix1.lon(), fix1.time());
            } else if (bc == 0) {
                return new TimedPosition(fix2.lat(), fix2.lon(), fix2.time());
            } else {
                // predict the timestamp based on distance from a and b
                long diff = fix2.time() - fix1.time();
                long t = Math.round(fix1.time() + ac * diff / (ac + bc));
                return new TimedPosition(latitude, longitude, t);
            }
        }
    }
    throw new RuntimeException("crossing not found");
}
Also used : Geometry(org.locationtech.jts.geom.Geometry) PreparedGeometry(org.locationtech.jts.geom.prep.PreparedGeometry) GeometryFactory(org.locationtech.jts.geom.GeometryFactory) PreparedGeometry(org.locationtech.jts.geom.prep.PreparedGeometry) Coordinate(org.locationtech.jts.geom.Coordinate) LineString(org.locationtech.jts.geom.LineString) Position(com.github.davidmoten.grumpy.core.Position)

Aggregations

PreparedGeometry (org.locationtech.jts.geom.prep.PreparedGeometry)5 Geometry (org.locationtech.jts.geom.Geometry)4 ArrayList (java.util.ArrayList)3 Coordinate (org.locationtech.jts.geom.Coordinate)3 IOException (java.io.IOException)2 Collection (java.util.Collection)2 HashMap (java.util.HashMap)2 List (java.util.List)2 Map (java.util.Map)2 SimpleFeatureCollection (org.geotools.data.simple.SimpleFeatureCollection)2 SimpleFeatureIterator (org.geotools.data.simple.SimpleFeatureIterator)2 SimpleFeatureSource (org.geotools.data.simple.SimpleFeatureSource)2 GeometryFactory (org.locationtech.jts.geom.GeometryFactory)2 PreparedGeometryFactory (org.locationtech.jts.geom.prep.PreparedGeometryFactory)2 SimpleFeature (org.opengis.feature.simple.SimpleFeature)2 Logger (org.slf4j.Logger)2 LoggerFactory (org.slf4j.LoggerFactory)2 AisMessage (au.gov.amsa.ais.AisMessage)1 ShipTypeDecoder (au.gov.amsa.ais.ShipTypeDecoder)1 Timestamped (au.gov.amsa.ais.Timestamped)1