Skip to content
Merged
Show file tree
Hide file tree
Changes from 5 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,7 @@ public class DebugStyleSpec {
private static final String MAGENTA = "#f21d52";
private static final String BRIGHT_GREEN = "#22DD9E";
private static final String DARK_GREEN = "#136b04";
private static final String RED = "#fc0f2a";
private static final String PURPLE = "#BC55F2";
private static final String BLACK = "#140d0e";

Expand All @@ -71,6 +72,7 @@ public class DebugStyleSpec {
private static final String STOPS_GROUP = "Stops";
private static final String VERTICES_GROUP = "Vertices";
private static final String TRAVERSAL_PERMISSIONS_GROUP = "Traversal permissions";
private static final String WHEELCHAIR_GROUP = "Wheelchair accessibility";

static StyleSpec build(
VectorSourceLayer regularStops,
Expand All @@ -90,6 +92,7 @@ static StyleSpec build(
allSources,
ListUtils.combine(
List.of(StyleBuilder.ofId("background").typeRaster().source(BACKGROUND_SOURCE).minZoom(0)),
wheelchair(edges),
traversalPermissions(edges),
edges(edges),
vertices(vertices),
Expand Down Expand Up @@ -252,6 +255,35 @@ private static List<StyleBuilder> traversalPermissions(VectorSourceLayer edges)
return ListUtils.combine(permissionStyles, List.of(textStyle));
}

private static List<StyleBuilder> wheelchair(VectorSourceLayer edges) {
return List.of(
StyleBuilder
.ofId("wheelchair-accessible")
.vectorSourceLayer(edges)
.group(WHEELCHAIR_GROUP)
.typeLine()
.lineColor(DARK_GREEN)
.booleanFilter("wheelchairAccessible", true)
.lineWidth(LINE_WIDTH)
.lineOffset(LINE_OFFSET)
.minZoom(6)
.maxZoom(MAX_ZOOM)
.intiallyHidden(),
StyleBuilder
.ofId("wheelchair-inaccessible")
.vectorSourceLayer(edges)
.group(WHEELCHAIR_GROUP)
.typeLine()
.lineColor(RED)
.booleanFilter("wheelchairAccessible", false)
.lineWidth(LINE_WIDTH)
.lineOffset(LINE_OFFSET)
.minZoom(6)
.maxZoom(MAX_ZOOM)
.intiallyHidden()
);
}

private static String permissionColor(StreetTraversalPermission p) {
return switch (p) {
case NONE -> "#000";
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.LinkedHashMap;
import java.util.List;
Expand Down Expand Up @@ -29,7 +30,7 @@ public class StyleBuilder {
private final Map<String, Object> layout = new LinkedHashMap<>();
private final Map<String, Object> metadata = new LinkedHashMap<>();
private final Map<String, Object> line = new LinkedHashMap<>();
private List<String> filter = List.of();
private List<Object> filter = List.of();

public static StyleBuilder ofId(String id) {
return new StyleBuilder(id);
Expand Down Expand Up @@ -227,6 +228,14 @@ public final StyleBuilder permissionsFilter(StreetTraversalPermission p) {
return this;
}

/**
* Filter the entities by a boolean property.
*/
public final StyleBuilder booleanFilter(String propertyName, boolean value) {
filter = List.of("==", propertyName, value);
return this;
}

/**
* Only apply the style to the given vertices.
*/
Expand Down Expand Up @@ -257,7 +266,7 @@ public JsonNode toJson() {

private StyleBuilder filterClasses(Class... classToFilter) {
var clazzes = Arrays.stream(classToFilter).map(Class::getSimpleName).toList();
filter = ListUtils.combine(List.of("in", "class"), clazzes);
filter = new ArrayList<>(ListUtils.combine(List.of("in", "class"), clazzes));
return this;
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -312,7 +312,7 @@ private List<VehicleParking.VehicleParkingEntranceCreator> createArtificialEntra
);
}

private VehicleParking createVehicleParkingObjectFromOsmEntity(
VehicleParking createVehicleParkingObjectFromOsmEntity(
boolean isCarParkAndRide,
Coordinate coordinate,
OsmWithTags entity,
Expand Down Expand Up @@ -421,7 +421,7 @@ private OptionalInt parseCapacity(OsmWithTags element) {
}

private OptionalInt parseCapacity(OsmWithTags element, String capacityTag) {
return element.getTagAsInt(
return element.parseIntOrBoolean(
capacityTag,
v -> issueStore.add(new InvalidVehicleParkingCapacity(element, v))
);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,8 @@ protected Collection<KeyValue> map(Edge input) {
private static List<KeyValue> mapStreetEdge(StreetEdge se) {
var props = Lists.newArrayList(
kv("permission", se.getPermission().toString()),
kv("bicycleSafetyFactor", roundTo2Decimals(se.getBicycleSafetyFactor()))
kv("bicycleSafetyFactor", roundTo2Decimals(se.getBicycleSafetyFactor())),
kv("wheelchairAccessible", se.isWheelchairAccessible())
);
if (se.hasBogusName()) {
props.addFirst(kv("name", "%s (generated)".formatted(se.getName().toString())));
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,7 @@ public class OsmWithTags {

private static final Set<String> LEVEL_TAGS = Set.of("level", "layer");
private static final Set<String> DEFAULT_LEVEL = Set.of("0");
private static final Consumer<String> NO_OP = i -> {};

/* To save memory this is only created when an entity actually has tags. */
private Map<String, String> tags;
Expand Down Expand Up @@ -220,6 +221,33 @@ public OptionalInt getTagAsInt(String tag, Consumer<String> errorHandler) {
return OptionalInt.empty();
}

/**
* Some tags are allowed to have values like 55, "true" or "false".
* <p>
* "true", "yes" is returned as 1.
* <p>
* "false", "no" is returned as 0
* <p>
* Everything else is returned as an emtpy optional.
*/
public OptionalInt parseIntOrBoolean(String tag, Consumer<String> errorHandler) {
var maybeInt = getTagAsInt(tag, NO_OP);
if (maybeInt.isPresent()) {
return maybeInt;
} else {
if (isTagTrue(tag)) {
return OptionalInt.of(1);
} else if (isTagFalse(tag)) {
return OptionalInt.of(0);
} else if (hasTag(tag)) {
errorHandler.accept(getTag(tag));
return OptionalInt.empty();
} else {
return OptionalInt.empty();
}
}
}

/**
* Checks is a tag contains the specified value.
*/
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
package org.opentripplanner.graph_builder.module.osm;

import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertFalse;
import static org.junit.jupiter.api.Assertions.assertNull;
import static org.junit.jupiter.api.Assertions.assertTrue;

import java.util.List;
import org.junit.jupiter.api.Test;
import org.opentripplanner._support.geometry.Coordinates;
import org.opentripplanner.framework.i18n.I18NString;
import org.opentripplanner.graph_builder.issue.api.DataImportIssueStore;
import org.opentripplanner.osm.wayproperty.specifier.WayTestData;
import org.opentripplanner.routing.graph.Graph;
import org.opentripplanner.street.model._data.StreetModelForTest;
import org.opentripplanner.street.model.vertex.IntersectionVertex;

class ParkingProcessorTest {

private static final IntersectionVertex INTERSECTION_VERTEX = StreetModelForTest.intersectionVertex(
1,
1
);
private static final ParkingProcessor PROCESSOR = new ParkingProcessor(
new Graph(),
DataImportIssueStore.NOOP,
(n, w) -> INTERSECTION_VERTEX
);

@Test
void noWheelchairParking() {
var entity = WayTestData.parkAndRide();
var parking = PROCESSOR.createVehicleParkingObjectFromOsmEntity(
true,
Coordinates.BERLIN,
entity,
I18NString.of("parking"),
List.of()
);

assertFalse(parking.hasWheelchairAccessibleCarPlaces());
assertNull(parking.getCapacity().getWheelchairAccessibleCarSpaces());
}

@Test
void wheelchairParking() {
var entity = WayTestData.parkAndRide();
entity.addTag("capacity:disabled", "yes");
var parking = PROCESSOR.createVehicleParkingObjectFromOsmEntity(
true,
Coordinates.BERLIN,
entity,
I18NString.of("parking"),
List.of()
);

assertTrue(parking.hasWheelchairAccessibleCarPlaces());
assertEquals(1, parking.getCapacity().getWheelchairAccessibleCarSpaces());
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,12 @@
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.OptionalInt;
import java.util.Set;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.params.ParameterizedTest;
import org.junit.jupiter.params.provider.Arguments;
import org.junit.jupiter.params.provider.MethodSource;
import org.opentripplanner.osm.wayproperty.specifier.WayTestData;

public class OsmWithTagsTest {
Expand Down Expand Up @@ -272,4 +276,26 @@ void fallbackName() {
var namedTunnel = WayTestData.carTunnel();
assertFalse(namedTunnel.hasNoName());
}

private static List<Arguments> parseIntOrBooleanCases() {
return List.of(
Arguments.of("true", OptionalInt.of(1)),
Arguments.of("yes", OptionalInt.of(1)),
Arguments.of("no", OptionalInt.of(0)),
Arguments.of("false", OptionalInt.of(0)),
Arguments.of("0", OptionalInt.of(0)),
Arguments.of("12", OptionalInt.of(12)),
Arguments.of("", OptionalInt.empty())
);
}

@ParameterizedTest
@MethodSource("parseIntOrBooleanCases")
void parseIntOrBoolean(String value, OptionalInt expected) {
var way = new OsmWithTags();
var key = "capacity:disabled";
way.addTag(key, value);
var maybeInt = way.parseIntOrBoolean(key, i -> {});
assertEquals(expected, maybeInt);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -224,4 +224,12 @@ public static OsmWithTags indoor(String value) {
way.addTag("indoor", value);
return way;
}

public static OsmWithTags parkAndRide() {
var way = new OsmWithTags();
way.addTag("amenity", "parking");
way.addTag("park_ride", "yes");
way.addTag("capacity", "10");
return way;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,104 @@
"group" : "Other"
}
},
{
"id" : "wheelchair-accessible",
"source" : "vectorSource",
"source-layer" : "edges",
"type" : "line",
"minzoom" : 6,
"maxzoom" : 23,
"paint" : {
"line-color" : "#136b04",
"line-width" : [
"interpolate",
[
"linear"
],
[
"zoom"
],
13,
0.2,
23,
8.0
],
"line-offset" : [
"interpolate",
[
"linear"
],
[
"zoom"
],
13,
0.3,
23,
6.0
]
},
"filter" : [
"==",
"wheelchairAccessible",
true
],
"layout" : {
"line-cap" : "round",
"visibility" : "none"
},
"metadata" : {
"group" : "Wheelchair accessibility"
}
},
{
"id" : "wheelchair-inaccessible",
"source" : "vectorSource",
"source-layer" : "edges",
"type" : "line",
"minzoom" : 6,
"maxzoom" : 23,
"paint" : {
"line-color" : "#fc0f2a",
"line-width" : [
"interpolate",
[
"linear"
],
[
"zoom"
],
13,
0.2,
23,
8.0
],
"line-offset" : [
"interpolate",
[
"linear"
],
[
"zoom"
],
13,
0.3,
23,
6.0
]
},
"filter" : [
"==",
"wheelchairAccessible",
false
],
"layout" : {
"line-cap" : "round",
"visibility" : "none"
},
"metadata" : {
"group" : "Wheelchair accessibility"
}
},
{
"id" : "NONE",
"source" : "vectorSource",
Expand Down
2 changes: 1 addition & 1 deletion client/src/components/MapView/GeometryPropertyPopup.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ export function GeometryPropertyPopup({
{Object.entries(properties).map(([key, value]) => (
<tr key={key}>
<th scope="row">{key}</th>
<td>{value}</td>
<td>{String(value)}</td>
Copy link
Member Author

@leonardehrenfried leonardehrenfried Nov 8, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@testower This is here so that booleans correctly show up in the frontend.

</tr>
))}
</tbody>
Expand Down
Loading