Skip to content

Commit

Permalink
AER-2804 Added option to not add receptor hexagon representation in r…
Browse files Browse the repository at this point in the history
…esults in GML (#301)
  • Loading branch information
Hilbrand authored Sep 24, 2024
1 parent fbe55ef commit c23f593
Show file tree
Hide file tree
Showing 9 changed files with 311 additions and 38 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -82,6 +82,7 @@ public class GMLWriter {

private final AeriusGMLVersion version;
private Boolean formattedOutput = Boolean.TRUE;
private boolean withRepresentation = true;

public GMLWriter(final ReceptorGridSettings rgs, final ReferenceGenerator referenceGenerator) {
this(rgs, referenceGenerator, LATEST_WRITER_VERSION);
Expand All @@ -102,6 +103,13 @@ public void setFormattedOutput(final Boolean formattedOutput) {
this.formattedOutput = formattedOutput;
}

/**
* If called GML Receptors won't be generated with the hexagon representation geometry.
*/
public void setNoReceptorRepresentation() {
this.withRepresentation = false;
}

/**
* Get a map of the GML representation (String) for each {@link EmissionSourceFeature} object.
*
Expand Down Expand Up @@ -359,7 +367,7 @@ public void write(final OutputStream outputStream, final IsScenario scenario, fi
}

private InternalGMLWriter createInternalWriter() throws AeriusException {
return new InternalGMLWriter(receptorGridSettings, referenceGenerator, formattedOutput, version);
return new InternalGMLWriter(receptorGridSettings, referenceGenerator, formattedOutput, version, withRepresentation);
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -87,8 +87,9 @@ final class InternalGMLWriter {
private final Boolean formattedOutput;

InternalGMLWriter(final ReceptorGridSettings rgs, final ReferenceGenerator referenceGenerator, final Boolean formattedOutput,
final AeriusGMLVersion version) throws AeriusException {
writer = GMLVersionWriterFactory.createGMLVersionWriter(rgs.getZoomLevel1(), GMLSchema.getSRSName(rgs.getEPSG().getSrid()), version);
final AeriusGMLVersion version, final boolean withRepresentation) throws AeriusException {
writer = GMLVersionWriterFactory.createGMLVersionWriter(rgs.getZoomLevel1(), GMLSchema.getSRSName(rgs.getEPSG().getSrid()), version,
withRepresentation);
this.referenceGenerator = referenceGenerator;
this.schema = GMLVersionWriterFactory.getSchema(version);
this.formattedOutput = formattedOutput;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,18 +23,19 @@
import nl.overheid.aerius.shared.domain.geo.HexagonZoomLevel;
import nl.overheid.aerius.shared.exception.AeriusException;

public class GMLVersionWriterFactory {
public final class GMLVersionWriterFactory {

private GMLVersionWriterFactory() {
// Util class
}

public static GMLVersionWriter createGMLVersionWriter(final HexagonZoomLevel zoomLevel1, final String srsName,
final AeriusGMLVersion aeriusGMLVersion) {
switch (aeriusGMLVersion) {
case V5_1:
return new GMLVersionWriterV51(zoomLevel1, srsName);
case V6_0:
return new GMLVersionWriterV60(zoomLevel1, srsName);
default:
throw new IllegalArgumentException("Aerius GML version is not supported");
}
final AeriusGMLVersion aeriusGMLVersion, final boolean withRepresentation) {
return switch (aeriusGMLVersion) {
case V5_1 -> new GMLVersionWriterV51(zoomLevel1, srsName);
case V6_0 -> new GMLVersionWriterV60(zoomLevel1, srsName, withRepresentation);
default -> throw new IllegalArgumentException("Aerius GML version is not supported");
};
}

public static Schema getSchema(final AeriusGMLVersion aeriusGMLVersion) throws AeriusException {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -81,11 +81,11 @@ public class GMLVersionWriterV60 implements GMLVersionWriter {
private final CIMLKMeasure2GML measure2gml;
private final CIMLKDispersionLine2GML dispersionLine2gml;

public GMLVersionWriterV60(final HexagonZoomLevel zoomLevel1, final String srsName) {
public GMLVersionWriterV60(final HexagonZoomLevel zoomLevel1, final String srsName, final boolean withRepresentation) {
geometry2gml = new Geometry2GML(srsName);
source2gml = new Source2GML(geometry2gml);
building2gml = new Building2GML(geometry2gml);
result2gml = new Result2GML(geometry2gml, zoomLevel1);
result2gml = new Result2GML(geometry2gml, zoomLevel1, withRepresentation);
measure2gml = new CIMLKMeasure2GML(geometry2gml);
dispersionLine2gml = new CIMLKDispersionLine2GML(geometry2gml);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -60,10 +60,12 @@ final class Result2GML {

private final Geometry2GML geometry2gml;
private final HexagonZoomLevel zoomLevel1;
private final boolean withRepresentation;

public Result2GML(final Geometry2GML geometry2gml, final HexagonZoomLevel zoomLevel1) {
public Result2GML(final Geometry2GML geometry2gml, final HexagonZoomLevel zoomLevel1, final boolean withRepresentation) {
this.geometry2gml = geometry2gml;
this.zoomLevel1 = zoomLevel1;
this.withRepresentation = withRepresentation;
}

/**
Expand Down Expand Up @@ -147,7 +149,7 @@ private List<EntityReferenceProperty> fromEntityReferences(final List<nl.overhei
return converted;
}

private EntityReference convert(final nl.overheid.aerius.shared.domain.v2.point.EntityReference entityReference) {
private static EntityReference convert(final nl.overheid.aerius.shared.domain.v2.point.EntityReference entityReference) {
final EntityReference gmlEntityReference = new EntityReference();
gmlEntityReference.setEntityType(entityReference.getEntityType().name());
gmlEntityReference.setCode(entityReference.getCode());
Expand All @@ -169,15 +171,15 @@ private static int compare(final CriticalLevelProperty o1, final CriticalLevelPr
return sort;
}

private CriticalLevel convert(final EmissionResultKey key, final Double value) {
private static CriticalLevel convert(final EmissionResultKey key, final Double value) {
final CriticalLevel criticalLevel = new CriticalLevel();
criticalLevel.setResultType(key.getEmissionResultType());
criticalLevel.setSubstance(key.getSubstance());
criticalLevel.setValue(value);
return criticalLevel;
}

private AbstractCalculationPoint fromCustomPoint(final nl.overheid.aerius.shared.domain.v2.point.CustomCalculationPoint aeriusPoint) {
private static AbstractCalculationPoint fromCustomPoint(final nl.overheid.aerius.shared.domain.v2.point.CustomCalculationPoint aeriusPoint) {
//treat as a custom calculation point
//The proper representation of a custompoint would be a circle with a surface of 1ha.
//Unclear at this point if this is required for GML and if it should be implemented by a GML polygon, arc or circle.
Expand All @@ -187,13 +189,13 @@ private AbstractCalculationPoint fromCustomPoint(final nl.overheid.aerius.shared
return returnPoint;
}

private void setCustomProperties(final nl.overheid.aerius.shared.domain.v2.point.CustomCalculationPoint aeriusPoint,
private static void setCustomProperties(final nl.overheid.aerius.shared.domain.v2.point.CustomCalculationPoint aeriusPoint,
final AbstractCalculationPoint returnPoint) {
returnPoint.setAssessmentCategory(aeriusPoint.getAssessmentCategory() == null ? null : aeriusPoint.getAssessmentCategory().name());
returnPoint.setHeight(aeriusPoint.getHeight());
}

private AbstractCalculationPoint fromSubPoint(final nl.overheid.aerius.shared.domain.v2.point.SubPoint aeriusPoint) {
private static AbstractCalculationPoint fromSubPoint(final nl.overheid.aerius.shared.domain.v2.point.SubPoint aeriusPoint) {
final SubPoint returnSubPoint = new SubPoint();
returnSubPoint.setSubPointId(aeriusPoint.getSubPointId());
returnSubPoint.setReceptorPointId(aeriusPoint.getReceptorId());
Expand All @@ -206,17 +208,30 @@ private AbstractCalculationPoint fromReceptorPoint(final nl.overheid.aerius.shar
throws AeriusException {
//treat as receptor point.
final ReceptorPoint returnReceptorPoint = new ReceptorPoint();

returnReceptorPoint.setReceptorPointId(aeriusPoint.getId());
returnReceptorPoint.setEdgeEffect(aeriusPoint.getEdgeEffect());
//receptor are represented by a hexagon.
final Geometry geometry = HexagonUtil.createHexagon(point, zoomLevel1);
if (geometry instanceof final nl.overheid.aerius.shared.domain.v2.geojson.Polygon polygon) {
returnReceptorPoint.setRepresentation(
geometry2gml.toXMLPolygon(polygon, new Polygon()));
}
setRepresentation(point, returnReceptorPoint);
return returnReceptorPoint;
}

/**
* Receptors are represented by a hexagon.
*
* @param point
* @param receptorPoint
* @throws AeriusException
*/
private void setRepresentation(final Point point, final ReceptorPoint receptorPoint) throws AeriusException {
if (withRepresentation) {
final Geometry geometry = HexagonUtil.createHexagon(point, zoomLevel1);

if (geometry instanceof final nl.overheid.aerius.shared.domain.v2.geojson.Polygon polygon) {
receptorPoint.setRepresentation(geometry2gml.toXMLPolygon(polygon, new Polygon()));
}
}
}

private static List<ResultProperty> getResults(final CalculationPoint aeriusPoint, final Substance[] substances) {
final List<Substance> substanceList = Arrays.asList(substances);
final List<ResultProperty> results = toResultProperties(aeriusPoint, substanceList);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -229,7 +229,7 @@ private static MetaData getMetaData() throws AeriusException {
metaDataInput.getOptions().getRblCalculationOptions().setMonitorSrm2Year(MONITOR_SRM2_YEAR);
metaDataInput.setResultsIncluded(true);
final InternalGMLWriter writer = new InternalGMLWriter(gridSettings, GMLTestDomain.TEST_REFERENCE_GENERATOR, Boolean.TRUE,
GMLWriter.LATEST_WRITER_VERSION);
GMLWriter.LATEST_WRITER_VERSION, true);
return writer.getWriter().metaData2GML(metaDataInput);
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,7 @@ class GMLWriterPerformanceTest {
@Test
void testConvertMetaData() throws IOException, AeriusException {
final InternalGMLWriter writer = new InternalGMLWriter(GMLTestDomain.getExampleGridSettings(), GMLTestDomain.TEST_REFERENCE_GENERATOR,
Boolean.TRUE, GMLWriter.LATEST_WRITER_VERSION);
Boolean.TRUE, GMLWriter.LATEST_WRITER_VERSION, true);

final int numberOfSources = 800000;
final List<EmissionSourceFeature> sourceFeatures = new ArrayList<>(numberOfSources);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@
import java.util.ArrayList;
import java.util.List;
import java.util.Optional;
import java.util.Set;
import java.util.stream.Stream;

import org.junit.jupiter.api.Test;
Expand Down Expand Up @@ -69,6 +70,7 @@ class GMLWriterTest {
private static final String RECEPTORS_CONCENTRATION_ONLY_FILE = "test_receptors_concentration_only";
private static final String RECEPTORS_EDGE_EFFECT_FILE = "test_receptors_edge_effect";
private static final String RECEPTORS_ALL_FILE = "test_receptors";
private static final Object RECEPTORS_NO_REPRESENTATION = "test_receptors_no_representation";
private static final String MIXED_FEATURES_FILE = "test_mixed_features";
private static final String PATH_CURRENT_VERSION = GMLWriter.LATEST_WRITER_VERSION.name().toLowerCase() + "/";

Expand Down Expand Up @@ -110,7 +112,7 @@ void testConvertInvalidSources() throws IOException, AeriusException {
final List<EmissionSourceFeature> sources1 = getExampleEmissionSources();
sources1.get(0).setGeometry(null);

final IllegalArgumentException e = assertThrows(
assertThrows(
IllegalArgumentException.class,
() -> getConversionResult(converter, sources1),
"Emissionsource not allowed to have no geometry.");
Expand Down Expand Up @@ -216,24 +218,32 @@ private List<EmissionSourceFeature> getExampleEmissionSources() {

private static Stream<Arguments> convertReceptorsData() {
return Stream.of(
Arguments.of(RECEPTORS_ALL_FILE, true, true, false),
Arguments.of(RECEPTORS_DEPOSITION_ONLY_FILE, true, false, false),
Arguments.of(RECEPTORS_CONCENTRATION_ONLY_FILE, false, true, false),
Arguments.of(RECEPTORS_EDGE_EFFECT_FILE, true, true, true));
Arguments.of(RECEPTORS_ALL_FILE, Set.of(ConvertReceptorsOptions.INCLUDE_DEPOSITION, ConvertReceptorsOptions.INCLUDE_CONCENTRATION)),
Arguments.of(RECEPTORS_DEPOSITION_ONLY_FILE, Set.of(ConvertReceptorsOptions.INCLUDE_DEPOSITION)),
Arguments.of(RECEPTORS_CONCENTRATION_ONLY_FILE, Set.of(ConvertReceptorsOptions.INCLUDE_CONCENTRATION)),
Arguments.of(RECEPTORS_EDGE_EFFECT_FILE, Set.of(ConvertReceptorsOptions.INCLUDE_DEPOSITION, ConvertReceptorsOptions.INCLUDE_CONCENTRATION,
ConvertReceptorsOptions.INCLUDE_OVERLAPPING)),
Arguments.of(RECEPTORS_NO_REPRESENTATION, Set.of(ConvertReceptorsOptions.INCLUDE_DEPOSITION, ConvertReceptorsOptions.INCLUDE_CONCENTRATION,
ConvertReceptorsOptions.NO_REPRESENTATION)));
}

@ParameterizedTest(name = "Testfile: {0}")
@MethodSource("convertReceptorsData")
void testConvertReceptors(final String receptorFile, final boolean includeDeposition, final boolean includeConcentration,
final boolean includeOverlapping) throws IOException, AeriusException {
final ArrayList<CalculationPointFeature> receptors = getExampleAeriusPoints(includeDeposition, includeConcentration, includeOverlapping);
void testConvertReceptors(final String receptorFile, final Set<ConvertReceptorsOptions> options) throws IOException, AeriusException {
final ArrayList<CalculationPointFeature> receptors = getExampleAeriusPoints(
ConvertReceptorsOptions.INCLUDE_DEPOSITION.in(options),
ConvertReceptorsOptions.INCLUDE_CONCENTRATION.in(options),
ConvertReceptorsOptions.INCLUDE_OVERLAPPING.in(options));
final MetaDataInput metaDataInput = getMetaDataInput(new ScenarioMetaData());
metaDataInput.setName(null);
metaDataInput.setReference(null);
metaDataInput.setSituationType(null);
metaDataInput.setResultsIncluded(true);
final GMLWriter writer = new GMLWriter(RECEPTOR_GRID_SETTINGS, GMLTestDomain.TEST_REFERENCE_GENERATOR);
String result;
if (ConvertReceptorsOptions.NO_REPRESENTATION.in(options)) {
writer.setNoReceptorRepresentation();
}
final String result;
try (ByteArrayOutputStream bos = new ByteArrayOutputStream()) {
writer.writeAeriusPoints(bos, receptors, metaDataInput);
result = bos.toString(StandardCharsets.UTF_8.name());
Expand Down Expand Up @@ -387,4 +397,26 @@ private ScenarioMetaData getScenarioMetaData() {
return metaData;
}

private enum ConvertReceptorsOptions {
/**
* Include deposition results.
*/
INCLUDE_DEPOSITION,
/**
* Include concentration results.
*/
INCLUDE_CONCENTRATION,
/**
* Include edge effect results.
*/
INCLUDE_OVERLAPPING,
/**
* Don't include hexagon representation geometry.
*/
NO_REPRESENTATION;

public boolean in(final Set<ConvertReceptorsOptions> options) {
return options.contains(this);
}
}
}
Loading

0 comments on commit c23f593

Please sign in to comment.