use of eu.esdihumboldt.hale.common.instance.helper.DepthFirstInstanceTraverser 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();
}
use of eu.esdihumboldt.hale.common.instance.helper.DepthFirstInstanceTraverser 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.");
}
}
use of eu.esdihumboldt.hale.common.instance.helper.DepthFirstInstanceTraverser in project hale by halestudio.
the class ReprojectGeometry method evaluate.
@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("source").get(0);
Object inputValue = input.getValue();
InstanceTraverser traverser = new DepthFirstInstanceTraverser(true);
GeometryFinder geoFind = new GeometryFinder(null);
traverser.traverse(inputValue, geoFind);
List<GeometryProperty<?>> geoms = geoFind.getGeometries();
Geometry sourceGeometry = geoms.get(0).getGeometry();
CRSDefinition crsDef = geoms.get(0).getCRSDefinition();
if (crsDef == null) {
throw new TransformationException("Geometry does not have an associated Coordinate Reference System");
}
CoordinateReferenceSystem sourceCRS = crsDef.getCRS();
Geometry resultGeometry = sourceGeometry;
CoordinateReferenceSystem targetCRS = sourceCRS;
// Get input parameter
String srs = getParameterChecked(PARAMETER_REFERENCE_SYSTEM).as(String.class);
if (srs != null) {
try {
targetCRS = parseReferenceSystemParamter(srs);
} catch (Exception e) {
throw new TransformationException("Error determining destination Cordinate Reference System.", e);
}
// Retrieve transformation from cell context, or create a new
// instance
Map<Object, Object> cellContext = getExecutionContext().getCellContext();
MathTransform transform = getOrCreateMathTransform(sourceCRS, targetCRS, cellContext);
// Apply transformation
try {
resultGeometry = JTS.transform(sourceGeometry, transform);
} catch (MismatchedDimensionException | TransformException e) {
throw new TransformationException("Problem on execute transformation from: " + sourceCRS + " to " + targetCRS, e);
}
}
return new DefaultGeometryProperty<Geometry>(new CodeDefinition(CRS.toSRS(targetCRS), targetCRS), resultGeometry);
}
use of eu.esdihumboldt.hale.common.instance.helper.DepthFirstInstanceTraverser in project hale by halestudio.
the class AggregateTransformation method aggregateGeometries.
/**
* Aggregates geometries contained in the provided objects.
*
* @param geometries the geometries or instances containing geometries
* @param cell the currently process cell or <code>null</code>
* @param log the transformation log or <code>null</code>
* @return the aggregated geometry
* @throws TransformationException if source geometries don't have a common
* CRS
* @throws NoResultException if the result extent would be <code>null</code>
*/
public static GeometryProperty<?> aggregateGeometries(Iterable<?> geometries, @Nullable TransformationLog log, @Nullable Cell cell) throws NoResultException, TransformationException {
InstanceTraverser traverser = new DepthFirstInstanceTraverser(true);
GeometryFinder geoFind = new GeometryFinder(null);
CRSDefinition commonCrs = null;
Class<? extends Geometry> commonGeometryType = null;
List<Geometry> collectedGeometries = new ArrayList<>();
for (Object value : geometries) {
// find contained geometries
traverser.traverse(value, geoFind);
for (GeometryProperty<?> geom : geoFind.getGeometries()) {
// no CRS or one common CRS is OK
if (commonCrs == null) {
commonCrs = geom.getCRSDefinition();
} else {
if (geom.getCRSDefinition() != null && !geom.getCRSDefinition().equals(commonCrs)) {
// CRS doesn't match
throw new TransformationException("Source geometries don't have a common CRS.");
}
}
Geometry g = geom.getGeometry();
// determine common geometry type: point / line / polygon
if (commonGeometryType == null) {
commonGeometryType = getContainedGeometryType(g.getClass());
} else {
Class<? extends Geometry> currentType = getContainedGeometryType(g.getClass());
if (!commonGeometryType.isAssignableFrom(currentType)) {
if (currentType.isAssignableFrom(commonGeometryType)) {
commonGeometryType = currentType;
} else {
commonGeometryType = Geometry.class;
}
}
}
// collect geometry
for (int i = 0; i < g.getNumGeometries(); i++) {
collectedGeometries.add(g.getGeometryN(i));
}
}
geoFind.reset();
}
if (commonGeometryType != null && commonGeometryType.equals(Geometry.class)) {
if (log != null && cell != null) {
log.warn(new TransformationMessageImpl(cell, "Could not find common geometry type for aggregation", null));
}
}
if (commonGeometryType != null) {
Geometry combined = combineGeometries(collectedGeometries, commonGeometryType);
return new DefaultGeometryProperty<Geometry>(commonCrs, combined);
}
throw new NoResultException();
}
use of eu.esdihumboldt.hale.common.instance.helper.DepthFirstInstanceTraverser in project hale by halestudio.
the class ExtentTransformation method calculateExtent.
/**
* Calculate the extent of a set of geometries.
*
* @param geometries the geometries or instances containing geometries
* @param type the type of extent to calculate
* @return the calculated extent
* @throws TransformationException if source geometries don't have a common
* CRS
* @throws NoResultException if the result extent would be <code>null</code>
*/
public static GeometryProperty<?> calculateExtent(Iterable<?> geometries, ExtentType type) throws TransformationException, NoResultException {
InstanceTraverser traverser = new DepthFirstInstanceTraverser(true);
GeometryFinder geoFind = new GeometryFinder(null);
GeometryFactory fact = new GeometryFactory();
CRSDefinition commonCrs = null;
Geometry[] geomsCollectingArray = new Geometry[SIMULTAN_PROCESS_GEOMS];
short geomsCollectedIdx = 0;
for (Object value : geometries) {
traverser.traverse(value, geoFind);
for (GeometryProperty<?> geom : geoFind.getGeometries()) {
// no CRS or one common CRS is OK
if (commonCrs == null) {
commonCrs = geom.getCRSDefinition();
} else {
if (geom.getCRSDefinition() != null && !geom.getCRSDefinition().equals(commonCrs)) {
// CRS doesn't match
throw new TransformationException("Source geometries don't have a common CRS.");
}
}
Geometry g = geom.getGeometry();
// If geometry collecting array not filled.
if (geomsCollectedIdx < SIMULTAN_PROCESS_GEOMS - 1) {
geomsCollectingArray[geomsCollectedIdx++] = g;
} else // Geometry collecting array filled.
{
// add last
geomsCollectingArray[geomsCollectedIdx] = g;
// geometry
GeometryCollection gc = new GeometryCollection(geomsCollectingArray, fact);
geomsCollectingArray[0] = resolveParam(gc, type);
geomsCollectedIdx = 1;
}
}
geoFind.reset();
}
Geometry extent = resolveParam(new GeometryCollection(Arrays.copyOfRange(geomsCollectingArray, 0, geomsCollectedIdx), fact), type);
if (extent != null) {
return new DefaultGeometryProperty<Geometry>(commonCrs, extent);
}
throw new NoResultException();
}
Aggregations