Search in sources :

Example 6 with GeometryFinder

use of eu.esdihumboldt.hale.common.instance.geometry.GeometryFinder in project hale by halestudio.

the class StreamGmlWriter method partitionByExtent.

private void partitionByExtent(ProgressIndicator progress, IOReporter reporter) throws IOException {
    int maxNodes = getParameter(PARAM_PARTITION_BY_EXTENT_MAX_NODES).as(Integer.class, 1000);
    String mode = getParameter(PARAM_PARTITION_BY_EXTENT_MODE).as(String.class, PARTITION_BY_EXTENT_MODE_DATASET);
    final SubtaskProgressIndicator qtProgress = new SubtaskProgressIndicator(progress) {

        @Override
        protected String getCombinedTaskName(String taskName, String subtaskName) {
            return taskName + " (" + subtaskName + ")";
        }
    };
    // Map for instances that either contain no or multiple geometries
    Map<String, InstanceReference> unhandledInstances = new HashMap<>();
    QuadtreeBuilder<Point, InstanceReference> builder = new QuadtreeBuilder<>();
    try (ResourceIterator<Instance> it = getInstances().iterator()) {
        qtProgress.begin("Collecting geometries", getInstances().size());
        final XMLInspector gadget = new XMLInspector();
        int i = 0;
        while (it.hasNext()) {
            Instance inst = it.next();
            InstanceReference instRef = getInstances().getReference(inst);
            InstanceTraverser traverser = new DepthFirstInstanceTraverser();
            GeometryFinder finder = new GeometryFinder(getTargetCRS());
            traverser.traverse(inst, finder);
            List<GeometryProperty<?>> geoms = finder.getGeometries();
            if (geoms.isEmpty() || geoms.size() > 1) {
                unhandledInstances.put(gadget.getIdentity(inst), instRef);
            } else {
                GeometryProperty<?> geomProperty = geoms.get(0);
                Geometry geom = geomProperty.getGeometry();
                Point centroid;
                switch(mode) {
                    case PARTITION_BY_EXTENT_MODE_WORLD:
                        CoordinateReferenceSystem sourceCrs = geomProperty.getCRSDefinition().getCRS();
                        CodeDefinition wgs84 = new CodeDefinition("EPSG:4326");
                        try {
                            MathTransform toWgs84 = CRS.findMathTransform(sourceCrs, wgs84.getCRS());
                            Geometry geomWgs84 = JTS.transform(geom, toWgs84);
                            centroid = geomWgs84.getCentroid();
                        } catch (FactoryException | MismatchedDimensionException | TransformException e) {
                            log.error("Unable to transform geometry to WGS 84", e);
                            throw new IllegalStateException(e.getMessage(), e);
                        }
                        break;
                    case PARTITION_BY_EXTENT_MODE_DATASET:
                    // fall through to default
                    default:
                        centroid = geom.getCentroid();
                }
                builder.add(centroid, new IdentifiableInstanceReference(instRef, gadget.getIdentity(inst)));
            }
            qtProgress.advance(1);
            if (++i % 100 == 0) {
                qtProgress.setCurrentTask(MessageFormat.format("{0} instances processed", i));
            }
        }
        qtProgress.setCurrentTask("Building quadtree");
        FixedBoundaryQuadtree<InstanceReference> qt;
        switch(mode) {
            case PARTITION_BY_EXTENT_MODE_DATASET:
                qt = builder.build(maxNodes);
                break;
            case PARTITION_BY_EXTENT_MODE_WORLD:
                Envelope world = new Envelope(-180, 180, -90, 90);
                qt = builder.build(maxNodes, world);
                break;
            default:
                log.error(MessageFormat.format("Unrecognized extent partitioning mode \"{0}\", using dataset boundaries", mode));
                qt = builder.build(maxNodes);
        }
        qtProgress.setCurrentTask("Performing spatial partitioning");
        final Map<String, String> idToKeyMapping = new HashMap<>();
        final Map<String, Collection<InstanceReference>> keyToRefsMapping = new HashMap<>();
        // Instances without geometry or with multiple geometries
        keyToRefsMapping.put(ExtentPartsHandler.KEY_NO_GEOMETRY, unhandledInstances.values());
        unhandledInstances.keySet().stream().forEach(id -> idToKeyMapping.put(id, ExtentPartsHandler.KEY_NO_GEOMETRY));
        buildMappings(qt, idToKeyMapping, keyToRefsMapping);
        // Partition source instances based on quadtree tiles
        Iterator<InstanceCollection> collIt = new Iterator<InstanceCollection>() {

            private final Queue<String> keySet = new LinkedList<>(keyToRefsMapping.keySet());

            @Override
            public boolean hasNext() {
                return !keySet.isEmpty();
            }

            @Override
            public InstanceCollection next() {
                String key = keySet.poll();
                Collection<InstanceReference> refs = keyToRefsMapping.get(key);
                InstanceCollection instColl = new DefaultInstanceCollection(refs.stream().map(ref -> getInstances().getInstance(IdentifiableInstanceReference.getRootReference(ref))).collect(Collectors.toList()));
                return new ExtentPartsHandler.TreeKeyDecorator(instColl, key);
            }
        };
        final Map<String, URI> keyToTargetMapping = new HashMap<>();
        keyToRefsMapping.keySet().stream().forEach(k -> keyToTargetMapping.put(k, new File(ExtentPartsHandler.getTargetFilename(k, getTarget().getLocation())).toURI()));
        final ExtentPartsHandler handler = new ExtentPartsHandler(keyToTargetMapping, idToKeyMapping);
        qtProgress.end();
        try {
            writeParts(collIt, handler, progress, reporter);
        } catch (XMLStreamException e) {
            throw new IOException(e.getMessage(), e);
        }
    }
}
Also used : MathTransform(org.opengis.referencing.operation.MathTransform) HashMap(java.util.HashMap) Instance(eu.esdihumboldt.hale.common.instance.model.Instance) GeometryFinder(eu.esdihumboldt.hale.common.instance.geometry.GeometryFinder) FactoryException(org.opengis.referencing.FactoryException) IdentifiableInstanceReference(eu.esdihumboldt.hale.common.instance.model.IdentifiableInstanceReference) Envelope(org.locationtech.jts.geom.Envelope) DefaultInstanceCollection(eu.esdihumboldt.hale.common.instance.model.impl.DefaultInstanceCollection) MismatchedDimensionException(org.opengis.geometry.MismatchedDimensionException) URI(java.net.URI) CodeDefinition(eu.esdihumboldt.hale.common.instance.geometry.impl.CodeDefinition) ResourceIterator(eu.esdihumboldt.hale.common.instance.model.ResourceIterator) Iterator(java.util.Iterator) CoordinateReferenceSystem(org.opengis.referencing.crs.CoordinateReferenceSystem) Queue(java.util.Queue) DepthFirstInstanceTraverser(eu.esdihumboldt.hale.common.instance.helper.DepthFirstInstanceTraverser) InstanceTraverser(eu.esdihumboldt.hale.common.instance.helper.InstanceTraverser) GeometryProperty(eu.esdihumboldt.hale.common.schema.geometry.GeometryProperty) PerTypeInstanceCollection(eu.esdihumboldt.hale.common.instance.model.ext.impl.PerTypeInstanceCollection) DefaultInstanceCollection(eu.esdihumboldt.hale.common.instance.model.impl.DefaultInstanceCollection) InstanceCollection(eu.esdihumboldt.hale.common.instance.model.InstanceCollection) TransformException(org.opengis.referencing.operation.TransformException) SubtaskProgressIndicator(eu.esdihumboldt.hale.common.core.io.impl.SubtaskProgressIndicator) QuadtreeBuilder(eu.esdihumboldt.util.geometry.quadtree.QuadtreeBuilder) Point(org.locationtech.jts.geom.Point) IOException(java.io.IOException) Point(org.locationtech.jts.geom.Point) DepthFirstInstanceTraverser(eu.esdihumboldt.hale.common.instance.helper.DepthFirstInstanceTraverser) Geometry(org.locationtech.jts.geom.Geometry) XMLStreamException(javax.xml.stream.XMLStreamException) InstanceReference(eu.esdihumboldt.hale.common.instance.model.InstanceReference) IdentifiableInstanceReference(eu.esdihumboldt.hale.common.instance.model.IdentifiableInstanceReference) XMLInspector(eu.esdihumboldt.hale.common.instance.graph.reference.impl.XMLInspector) PerTypeInstanceCollection(eu.esdihumboldt.hale.common.instance.model.ext.impl.PerTypeInstanceCollection) DefaultInstanceCollection(eu.esdihumboldt.hale.common.instance.model.impl.DefaultInstanceCollection) Collection(java.util.Collection) InstanceCollection(eu.esdihumboldt.hale.common.instance.model.InstanceCollection) File(java.io.File)

Example 7 with GeometryFinder

use of eu.esdihumboldt.hale.common.instance.geometry.GeometryFinder in project hale by halestudio.

the class JacksonMapper method streamWriteGeoJSONInstance.

/**
 * Writes a single instance as GeoJSON.
 *
 * @param instance the instance to write
 * @param config the default geometry config
 * @param reporter the reporter
 * @throws IOException if writing the instance fails
 */
private void streamWriteGeoJSONInstance(Instance instance, GeoJSONConfig config, IOReporter reporter) throws IOException {
    jsonGen.writeStartObject();
    jsonGen.writeStringField("type", "Feature");
    PropertyEntityDefinition geomProperty = config.getDefaultGeometry(instance.getDefinition());
    GeometryFinder geomFinder = new GeometryFinder(null);
    // check whether a geometry property is set
    if (geomProperty != null) {
        // find all occurrences of the property
        Collection<Object> values = AlignmentUtil.getValues(instance, geomProperty, false);
        // find all geometries below any value (the values themselves might
        // be geometries)
        InstanceTraverser traverser = new DepthFirstInstanceTraverser(true);
        for (Object value : values) traverser.traverse(value, geomFinder);
    }
    Collection<GeometryProperty<?>> geometries = geomFinder.getGeometries();
    if (!geometries.isEmpty()) {
        // XXX It would be better to put CRS to each geometry.
        // This is currently not possible because geotools doesn't support
        // this.
        GeometryProperty<?> geomProp = geometries.iterator().next();
        if (geomProp.getCRSDefinition() != null) {
            jsonGen.writeFieldName("crs");
            jsonGen.writeRawValue(new FeatureJSON().toString(geomProp.getCRSDefinition().getCRS()));
        }
    }
    jsonGen.writeFieldName("geometry");
    if (geometries.isEmpty())
        jsonGen.writeNull();
    else if (geometries.size() == 1)
        streamWriteGeometryValue(geometries.iterator().next().getGeometry());
    else {
        jsonGen.writeStartObject();
        jsonGen.writeStringField("type", "GeometryCollection");
        jsonGen.writeArrayFieldStart("geometries");
        for (GeometryProperty<?> geom : geometries) streamWriteGeometryValue(geom.getGeometry());
        jsonGen.writeEndArray();
        jsonGen.writeEndObject();
    }
    jsonGen.writeFieldName("properties");
    jsonGen.writeStartObject();
    jsonGen.writeStringField("_type", instance.getDefinition().getName().getLocalPart());
    streamWriteProperties(instance, reporter);
    jsonGen.writeEndObject();
    jsonGen.writeEndObject();
}
Also used : InstanceTraverser(eu.esdihumboldt.hale.common.instance.helper.InstanceTraverser) DepthFirstInstanceTraverser(eu.esdihumboldt.hale.common.instance.helper.DepthFirstInstanceTraverser) GeometryProperty(eu.esdihumboldt.hale.common.schema.geometry.GeometryProperty) FeatureJSON(org.geotools.geojson.feature.FeatureJSON) PropertyEntityDefinition(eu.esdihumboldt.hale.common.align.model.impl.PropertyEntityDefinition) GeometryFinder(eu.esdihumboldt.hale.common.instance.geometry.GeometryFinder) DepthFirstInstanceTraverser(eu.esdihumboldt.hale.common.instance.helper.DepthFirstInstanceTraverser)

Example 8 with GeometryFinder

use of eu.esdihumboldt.hale.common.instance.geometry.GeometryFinder in project hale by halestudio.

the class AbstractHandlerTest method checkSingleGeometry.

/**
 * Check a single geometry contained in an instance (at an arbitrary path).
 *
 * @param instance the geometry instance
 * @param checker the checker (should throw an exception when the check
 *            fails)
 * @return the collection of encountered geometries
 */
protected Collection<GeometryProperty<?>> checkSingleGeometry(Instance instance, @Nullable Consumer<Geometry> checker) {
    GeometryFinder finder = new GeometryFinder(null);
    BreadthFirstInstanceTraverser traverser = new BreadthFirstInstanceTraverser();
    traverser.traverse(instance, finder);
    List<GeometryProperty<?>> geoms = finder.getGeometries();
    assertFalse("No geometry found in instances", geoms.isEmpty());
    assertEquals("More than one geometry found in instance", 1, geoms.size());
    Geometry geom = geoms.get(0).getGeometry();
    if (checker != null) {
        checker.accept(geom);
    }
    return geoms;
}
Also used : Geometry(org.locationtech.jts.geom.Geometry) GeometryProperty(eu.esdihumboldt.hale.common.schema.geometry.GeometryProperty) GeometryFinder(eu.esdihumboldt.hale.common.instance.geometry.GeometryFinder) BreadthFirstInstanceTraverser(eu.esdihumboldt.hale.common.instance.helper.BreadthFirstInstanceTraverser)

Example 9 with GeometryFinder

use of eu.esdihumboldt.hale.common.instance.geometry.GeometryFinder in project hale by halestudio.

the class SpatialIndexInstanceProcessor method process.

/**
 * @see eu.esdihumboldt.hale.common.instance.processing.InstanceProcessor#process(eu.esdihumboldt.hale.common.instance.model.Instance,
 *      eu.esdihumboldt.hale.common.instance.model.InstanceReference)
 */
@Override
public void process(Instance instance, InstanceReference reference) {
    SpatialIndexService<Localizable, Localizable> index = getSpatialIndexService();
    final GeometryFinder finder = new GeometryFinder(null);
    InstanceTraverser traverser = new DepthFirstInstanceTraverser(true);
    traverser.traverse(instance, finder);
    final List<Geometry> geometries = new ArrayList<>();
    for (GeometryProperty<?> property : finder.getGeometries()) {
        Geometry g = property.getGeometry();
        for (int i = 0; i < g.getNumGeometries(); i++) {
            geometries.add(g.getGeometryN(i));
        }
    }
    final BoundingBox boundingBox = new BoundingBox();
    for (Geometry geometry : geometries) {
        boundingBox.add(BoundingBox.compute(geometry));
    }
    if (boundingBox.checkIntegrity()) {
        TypedInstanceReference typedRef = new TypedInstanceReference(reference, instance.getDefinition());
        index.insert(new LocalizableInstanceReference(typedRef, boundingBox));
    }
}
Also used : LocalizableInstanceReference(eu.esdihumboldt.hale.common.instance.index.LocalizableInstanceReference) DepthFirstInstanceTraverser(eu.esdihumboldt.hale.common.instance.helper.DepthFirstInstanceTraverser) InstanceTraverser(eu.esdihumboldt.hale.common.instance.helper.InstanceTraverser) GeometryFinder(eu.esdihumboldt.hale.common.instance.geometry.GeometryFinder) ArrayList(java.util.ArrayList) Localizable(de.fhg.igd.geom.Localizable) DepthFirstInstanceTraverser(eu.esdihumboldt.hale.common.instance.helper.DepthFirstInstanceTraverser) Geometry(org.locationtech.jts.geom.Geometry) BoundingBox(de.fhg.igd.geom.BoundingBox) TypedInstanceReference(eu.esdihumboldt.hale.common.instance.index.TypedInstanceReference)

Example 10 with GeometryFinder

use of eu.esdihumboldt.hale.common.instance.geometry.GeometryFinder in project hale by halestudio.

the class CalculateLength method evaluate.

/**
 * @see eu.esdihumboldt.hale.common.align.transformation.function.impl.AbstractSingleTargetPropertyTransformation#evaluate(java.lang.String,
 *      eu.esdihumboldt.hale.common.align.transformation.engine.TransformationEngine,
 *      com.google.common.collect.ListMultimap, java.lang.String,
 *      eu.esdihumboldt.hale.common.align.model.impl.PropertyEntityDefinition,
 *      java.util.Map,
 *      eu.esdihumboldt.hale.common.align.transformation.report.TransformationLog)
 */
@Override
protected Object evaluate(String transformationIdentifier, TransformationEngine engine, ListMultimap<String, PropertyValue> variables, String resultName, PropertyEntityDefinition resultProperty, Map<String, String> executionParameters, TransformationLog log) throws TransformationException, NoResultException {
    // get input geometry
    PropertyValue input = variables.get(null).get(0);
    Object inputValue = input.getValue();
    // depth first traverser that on cancel continues traversal but w/o the
    // children of the current object
    InstanceTraverser traverser = new DepthFirstInstanceTraverser(true);
    GeometryFinder geoFind = new GeometryFinder(null);
    traverser.traverse(inputValue, geoFind);
    List<GeometryProperty<?>> geoms = geoFind.getGeometries();
    Geometry geom = null;
    if (geoms.size() > 1) {
        int length = 0;
        for (GeometryProperty<?> geoProp : geoms) {
            length += geoProp.getGeometry().getLength();
        }
        return length;
    } else {
        geom = geoms.get(0).getGeometry();
    }
    if (geom != null) {
        return geom.getLength();
    } else {
        throw new TransformationException("Geometry for calculate length could not be retrieved.");
    }
}
Also used : Geometry(org.locationtech.jts.geom.Geometry) DepthFirstInstanceTraverser(eu.esdihumboldt.hale.common.instance.helper.DepthFirstInstanceTraverser) InstanceTraverser(eu.esdihumboldt.hale.common.instance.helper.InstanceTraverser) GeometryProperty(eu.esdihumboldt.hale.common.schema.geometry.GeometryProperty) TransformationException(eu.esdihumboldt.hale.common.align.transformation.function.TransformationException) GeometryFinder(eu.esdihumboldt.hale.common.instance.geometry.GeometryFinder) PropertyValue(eu.esdihumboldt.hale.common.align.transformation.function.PropertyValue) DepthFirstInstanceTraverser(eu.esdihumboldt.hale.common.instance.helper.DepthFirstInstanceTraverser)

Aggregations

GeometryFinder (eu.esdihumboldt.hale.common.instance.geometry.GeometryFinder)14 DepthFirstInstanceTraverser (eu.esdihumboldt.hale.common.instance.helper.DepthFirstInstanceTraverser)13 InstanceTraverser (eu.esdihumboldt.hale.common.instance.helper.InstanceTraverser)13 Geometry (org.locationtech.jts.geom.Geometry)11 GeometryProperty (eu.esdihumboldt.hale.common.schema.geometry.GeometryProperty)10 TransformationException (eu.esdihumboldt.hale.common.align.transformation.function.TransformationException)7 DefaultGeometryProperty (eu.esdihumboldt.hale.common.instance.geometry.DefaultGeometryProperty)6 CRSDefinition (eu.esdihumboldt.hale.common.schema.geometry.CRSDefinition)6 PropertyValue (eu.esdihumboldt.hale.common.align.transformation.function.PropertyValue)3 NoResultException (eu.esdihumboldt.hale.common.align.transformation.function.impl.NoResultException)3 Point (org.locationtech.jts.geom.Point)3 CodeDefinition (eu.esdihumboldt.hale.common.instance.geometry.impl.CodeDefinition)2 ArrayList (java.util.ArrayList)2 GeometryFactory (org.locationtech.jts.geom.GeometryFactory)2 MismatchedDimensionException (org.opengis.geometry.MismatchedDimensionException)2 FactoryException (org.opengis.referencing.FactoryException)2 CoordinateReferenceSystem (org.opengis.referencing.crs.CoordinateReferenceSystem)2 MathTransform (org.opengis.referencing.operation.MathTransform)2 TransformException (org.opengis.referencing.operation.TransformException)2 BoundingBox (de.fhg.igd.geom.BoundingBox)1