use of eu.esdihumboldt.hale.common.instance.geometry.GeometryFinder 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.geometry.GeometryFinder 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.geometry.GeometryFinder 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();
}
use of eu.esdihumboldt.hale.common.instance.geometry.GeometryFinder in project hale by halestudio.
the class InteriorPoint method calculateInteriorPoint.
/**
* Calculate an interior point for a given geometry or object holding a
* geometry.
*
* @param geometryHolder {@link Geometry}, {@link GeometryProperty} or
* {@link Instance} holding a geometry
* @return an interior point of the geometry
* @throws TransformationException if the interior point could not be
* calculated
*/
public static GeometryProperty<?> calculateInteriorPoint(Object geometryHolder) throws TransformationException {
// 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(geometryHolder, geoFind);
List<GeometryProperty<?>> geoms = geoFind.getGeometries();
Geometry result;
CRSDefinition oldCRS = null;
// use the first geometry encountered
int index = 0;
Geometry geom = null;
while (geom == null && index < geoms.size()) {
geom = geoms.get(index).getGeometry();
oldCRS = geoms.get(index).getCRSDefinition();
index++;
}
if (geom != null) {
try {
result = geom.getInteriorPoint();
} catch (TopologyException e) {
// calculate the point for a geometry with a small buffer to
// avoid error with polygons that have overlapping lines
result = geom.buffer(0.000001).getInteriorPoint();
if (!result.within(geom)) {
// geometry
throw new TransformationException("Could not determine interior point for geometry");
}
}
} else {
return null;
}
return new DefaultGeometryProperty<Geometry>(oldCRS, result);
}
Aggregations