Skip to content

Commit

Permalink
Add PolylinesNotOverlapping function
Browse files Browse the repository at this point in the history
  • Loading branch information
domi-b committed Dec 19, 2023
1 parent c069e6b commit 09a9120
Show file tree
Hide file tree
Showing 6 changed files with 142 additions and 21 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,79 @@
package ch.geowerkstatt.ilivalidator.extensions.functions;

import ch.interlis.ili2c.metamodel.PathEl;
import ch.interlis.ili2c.metamodel.Viewable;
import ch.interlis.iom.IomObject;
import ch.interlis.iom_j.itf.impl.jtsext.geom.CompoundCurve;
import ch.interlis.iox.IoxException;
import ch.interlis.iox_j.jts.Iox2jtsext;
import ch.interlis.iox_j.validator.Value;

import java.util.Collection;
import java.util.List;
import java.util.Objects;
import java.util.stream.Collectors;

public final class PolylinesNotOverlappingIoxPlugin extends BaseInterlisFunction {
@Override
public String getQualifiedIliName() {
return "GeoW_FunctionsExt.PolylinesNotOverlapping";
}

@Override
protected Value evaluateInternal(String validationKind, String usageScope, IomObject contextObject, Value[] arguments) {
Value argObjects = arguments[0];
Value argPath = arguments[1];

if (argObjects.isUndefined()) {
return Value.createSkipEvaluation();
}

if (argObjects.getComplexObjects() == null) {
return Value.createUndefined();
}

Collection<IomObject> polylineObjects;

if (argPath.isUndefined()) {
polylineObjects = argObjects.getComplexObjects();
} else {
Viewable contextClass = EvaluationHelper.getContextClass(td, contextObject, argObjects);
if (contextClass == null) {
throw new IllegalStateException("unknown class in " + usageScope);
}

PathEl[] attributePath = EvaluationHelper.getAttributePathEl(validator, contextClass, argPath);
polylineObjects = EvaluationHelper.evaluateAttributes(validator, argObjects, attributePath);
}

List<CompoundCurve> lines = convertToJTSLines(polylineObjects);
boolean hasOverlap = hasLineOverlap(lines);
return new Value(!hasOverlap);
}

private List<CompoundCurve> convertToJTSLines(Collection<IomObject> polylines) {
return polylines.stream()
.map(line -> {
try {
return Iox2jtsext.polyline2JTS(line, false, 0);
} catch (IoxException e) {
logger.addEvent(logger.logErrorMsg("Could not calculate {0}", getQualifiedIliName()));
return null;
}
})
.filter(Objects::nonNull)
.collect(Collectors.toList());
}

private static boolean hasLineOverlap(List<CompoundCurve> lines) {
for (int i = 0; i < lines.size(); i++) {
for (int j = i + 1; j < lines.size(); j++) {
if (lines.get(i).overlaps(lines.get(j))) {
return true;
}
}
}

return false;
}
}
6 changes: 6 additions & 0 deletions src/model/GeoW_FunctionsExt.ili
Original file line number Diff line number Diff line change
Expand Up @@ -39,4 +39,10 @@ MODEL GeoW_FunctionsExt
!!@ fn.return = "Zusammengefasste Flächen-Geometrie";
!!@ fn.since = "2023-12-13";
FUNCTION Union (Geometries: ANYSTRUCTURE): MULTIAREA;

!!@ fn.description = "Prüft, dass sich die Linien-Geometrien nicht überlappen. Für 'Objects' können Objekte oder Geometrien angegeben werden. Für 'LineAttr' soll der Pfad zur Linien-Geometrie in INTERLIS 2 Syntax angegeben werden. Falls 'Objects' bereits die Geometrien enthält, soll für 'LineAttr' 'UNDEFINED' übergeben werden.";
!!@ fn.param = "Objects: Ausgangsobjekte oder Geometrien. LineAttr: Pfad zum Geometrieattribut oder UNDEFINED";
!!@ fn.return = "TRUE, wenn sich die Linien nicht überlappen";
!!@ fn.since = "2023-12-18";
FUNCTION PolylinesNotOverlapping (Objects: OBJECTS OF ANYCLASS; LineAttr: TEXT): BOOLEAN;
END GeoW_FunctionsExt.
21 changes: 0 additions & 21 deletions src/test/data/DetectPolylineOverlay/DetectPolylineOverlay.ili

This file was deleted.

28 changes: 28 additions & 0 deletions src/test/data/PolylinesNotOverlapping/PolylinesNotOverlapping.ili
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
INTERLIS 2.4;

MODEL TestSuite
AT "mailto:[email protected]" VERSION "2023-12-14" =
IMPORTS GeoW_FunctionsExt;

DOMAIN
!!@CRS=EPSG:2056
CHKoord = COORD 2460000.000 .. 2870000.000 [INTERLIS.m],
1045000.000 .. 1310000.000 [INTERLIS.m],
ROTATION 2 -> 1;

TOPIC FunctionTestTopic =

CLASS TestClass =
geometry : POLYLINE WITH (STRAIGHTS) VERTEX CHKoord WITHOUT OVERLAPS > 0.001;
type : (t1,t2,t3);

SET CONSTRAINT setConstraintAll : GeoW_FunctionsExt.PolylinesNotOverlapping(ALL, "geometry");
SET CONSTRAINT setConstraintT1 : WHERE type == #t1 : GeoW_FunctionsExt.PolylinesNotOverlapping(ALL, "geometry");
SET CONSTRAINT setConstraintT2 : WHERE type == #t2 : GeoW_FunctionsExt.PolylinesNotOverlapping(ALL, "geometry");
SET CONSTRAINT setConstraintT3 : WHERE type == #t3 : GeoW_FunctionsExt.PolylinesNotOverlapping(ALL, "geometry");
SET CONSTRAINT setConstraintT2or3 : WHERE type == #t2 OR type == #t3 : GeoW_FunctionsExt.PolylinesNotOverlapping(ALL, "geometry");
END TestClass;

END FunctionTestTopic;

END TestSuite.
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
package ch.geowerkstatt.ilivalidator.extensions.functions;

import ch.interlis.ili2c.Ili2cFailure;
import ch.interlis.iox.IoxException;
import com.vividsolutions.jts.util.Assert;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;

public final class PolylinesNotOverlappingIoxPluginTest {
private static final String TEST_DATA = "PolylinesNotOverlapping/TestData.xtf";
private ValidationTestHelper vh = null;

@BeforeEach
void setUp() {
vh = new ValidationTestHelper();
vh.addFunction(new PolylinesNotOverlappingIoxPlugin());
}

@Test
void polylinesNotOverlapping() throws Ili2cFailure, IoxException {
vh.runValidation(new String[]{TEST_DATA}, new String[]{"PolylinesNotOverlapping/PolylinesNotOverlapping.ili"});
Assert.equals(2, vh.getErrs().size());
AssertionHelper.assertConstraintErrors(vh, 1, "setConstraintAll");
AssertionHelper.assertConstraintErrors(vh, 1, "setConstraintT1");
AssertionHelper.assertNoConstraintError(vh, "setConstraintT2");
AssertionHelper.assertNoConstraintError(vh, "setConstraintT3");
AssertionHelper.assertNoConstraintError(vh, "setConstraintT2or3");
}
}

0 comments on commit 09a9120

Please sign in to comment.