Hi Gerd
I've re-implemented the POINT test within IsInFunction, using the
stopping methods etc, which are now coded, but only relevant for this
context at the moment. This implementation has other advantage in that
the method can control the onBoundary condition. Also the logic in
calcInsideness can give the wrong answer for POINT is_in(..., 'on').
I didn't want to change IsInUtil while you are working on it and I'm
not sure yet of the best way to handle the LINE/POLYGON versions.
There are a couple of aspects of these that occur to me:
It would be clearer to test for kind=POINT/LINE/POLYGON etc rather than
el instanceof.
w.isComplete():
- Will this will cause different answers depending on tile splitting,
or is the complete polygon represented; even the bits outside the tile?
- The ANY methods should be processed and will be correct.
Thanks for spotting my error with tstMethod.
This patch also improves the method error message; listing the possible
methods for the context.
Ticker
On Mon, 2020-02-10 at 13:14 +0000, Gerd Petermann wrote:
> Hi all,
>
> see
> http://www.mkgmap.org.uk/websvn/revision.php?repname=mkgmap&rev=4442
>
> @Ticker:
> I assume you are working on an alternative implementation of the
> methods in IsInUtil?
> If not I'd like to remove all the code duplication introduced with
> the last patch.
>
> Gerd
> _______________________________________________
> mkgmap-dev mailing list
> [email protected]
> http://www.mkgmap.org.uk/mailman/listinfo/mkgmap-dev
Index: src/uk/me/parabola/mkgmap/osmstyle/function/IsInFunction.java
===================================================================
--- src/uk/me/parabola/mkgmap/osmstyle/function/IsInFunction.java (revision 4443)
+++ src/uk/me/parabola/mkgmap/osmstyle/function/IsInFunction.java (working copy)
@@ -21,6 +21,7 @@
import java.util.stream.Collectors;
import uk.me.parabola.imgfmt.app.Area;
+import uk.me.parabola.imgfmt.app.Coord;
import uk.me.parabola.mkgmap.reader.osm.Element;
import uk.me.parabola.mkgmap.reader.osm.ElementSaver;
import uk.me.parabola.mkgmap.reader.osm.FeatureKind;
@@ -39,27 +40,33 @@
public class IsInFunction extends StyleFunction {
private enum MethodArg {
- // TODO: also maybe aliases, which flags can stop processing, etc
- POINT_IN("in", FeatureKind.POINT),
- POINT_IN_OR_ON("in_or_on", FeatureKind.POINT),
- POINT_ON("on", FeatureKind.POINT),
+ // can stop when: IN ON OUT
+ POINT_IN("in", FeatureKind.POINT, true, false, false),
+ POINT_IN_OR_ON("in_or_on", FeatureKind.POINT, true, true, false),
+ POINT_ON("on", FeatureKind.POINT, false, true, false),
- LINE_SOME_IN_NONE_OUT("all", FeatureKind.POLYLINE),
- LINE_ALL_IN_OR_ON("all_in_or_on", FeatureKind.POLYLINE),
- LINE_ALL_ON("on", FeatureKind.POLYLINE),
- LINE_ANY_IN("any", FeatureKind.POLYLINE),
- LINE_ANY_IN_OR_ON("any_in_or_on", FeatureKind.POLYLINE),
+ LINE_SOME_IN_NONE_OUT("all", FeatureKind.POLYLINE, false, false, true),
+ LINE_ALL_IN_OR_ON("all_in_or_on", FeatureKind.POLYLINE, false, false, true),
+ LINE_ALL_ON("on", FeatureKind.POLYLINE, true, false, true),
+ LINE_ANY_IN("any", FeatureKind.POLYLINE, true, false, false),
+ LINE_ANY_IN_OR_ON("any_in_or_on", FeatureKind.POLYLINE, true, true, false),
- POLYGON_ALL("all", FeatureKind.POLYGON),
- POLYGON_ANY("any", FeatureKind.POLYGON);
+ POLYGON_ALL("all", FeatureKind.POLYGON, false, false, true),
+ POLYGON_ANY("any", FeatureKind.POLYGON, true, false, false);
private final String methodName;
private final FeatureKind kind;
+ private final boolean stopIn;
+ private final boolean stopOn;
+ private final boolean stopOut;
- MethodArg(String methodName, FeatureKind kind) {
+ MethodArg(String methodName, FeatureKind kind, boolean stopIn, boolean stopOn, boolean stopOut) {
this.methodName = methodName;
this.kind = kind;
+ this.stopIn = stopIn;
+ this.stopOn = stopOn;
+ this.stopOut = stopOut;
}
public String toString() {
@@ -70,19 +77,14 @@
return kind;
}
-/*
-following 3 methods are not implement yet and not applicable to current interface of IsInUtil.calcInsideness
-An idea was that it would call setIn/On/Out and logic flags here would know if this was enough to
-determine the answer and stop further processing. probably with flag per IN/ON/OUT for each enum...
-*/
public boolean canStopIn() {
- return false;
+ return stopIn;
}
public boolean canStopOn() {
- return false;
+ return stopOn;
}
public boolean canStopOut() {
- return false;
+ return stopOut;
}
}
@@ -96,10 +98,10 @@
public IsInFunction() {
super(null);
- reqdNumParams = 3; // ??? maybe have something to indicate variable...
+ reqdNumParams = 3;
// 1: polygon tagName
// 2: value for above tag
- // 3: method keyword, eg any, all, on...
+ // 3: method keyword, see above
}
protected String calcImpl(Element el) {
@@ -130,13 +132,21 @@
public void setParams(List<String> params, FeatureKind kind) {
super.setParams(params, kind);
String methodStr = params.get(2);
+ boolean knownMethod = false;
+ List<String> methodsForKind = new ArrayList<>();
for (MethodArg tstMethod : MethodArg.values()) {
- if (tstMethod.getKind() == kind && methodStr.equalsIgnoreCase(tstMethod.toString())) {
- this.method = tstMethod;
- return;
- }
+ if (methodStr.equalsIgnoreCase(tstMethod.toString())) {
+ if (tstMethod.getKind() == kind) {
+ this.method = tstMethod;
+ return;
+ } else
+ knownMethod = true;
+ } else if (tstMethod.getKind() == kind)
+ methodsForKind.add(tstMethod.toString());
}
- throw new SyntaxException(String.format("Third parameter '%s' of function %s is not supported", methodStr, getName()));
+ throw new SyntaxException(String.format("Third parameter '%s' of function %s is not " +
+ (knownMethod ? "supported for this style section" : "understood") +
+ ", valid are: %s" , methodStr, getName(), methodsForKind));
}
private void setIn() {
@@ -183,7 +193,36 @@
}
private void doPointTest(Node el) {
- doCommonTest(el);
+ //doCommonTest(el);
+ Coord c = el.getLocation();
+ Area elementBbox = Area.getBBox(Collections.singletonList(c));
+ Set<Way> polygons = qt.get(elementBbox).stream().map(e -> (Way) e)
+ .collect(Collectors.toCollection(LinkedHashSet::new));
+ /*
+ We can use the method to control the onBoundary condition of insidePolygon.
+
+ Because we are processing polygons one-by-one, OUT is only meaningful once we have
+ checked all the polygons and haven't satisfied IN/ON, so no point is calling setOut()
+ and it wouldn't stop the processing or effect the answer anyway
+ */
+ for (Way polygon : polygons) {
+ List<Coord> shape = polygon.getPoints();
+ switch (method) {
+ case POINT_IN:
+ if (IsInUtil.insidePolygon(c, false, shape))
+ setIn();
+ break;
+ case POINT_IN_OR_ON:
+ if (IsInUtil.insidePolygon(c, true, shape))
+ setIn(); // don't care about setOn()
+ break;
+ case POINT_ON:
+ if (IsInUtil.insidePolygon(c, true, shape) &&
+ !IsInUtil.insidePolygon(c, false, shape))
+ setOn(); // don't care about setIn()
+ break;
+ }
+ }
}
private void doLineTest(Way el) {
_______________________________________________
mkgmap-dev mailing list
[email protected]
http://www.mkgmap.org.uk/mailman/listinfo/mkgmap-dev