diff --git a/contribs/application/src/main/java/org/matsim/application/prepare/network/params/NetworkParamsOpt.java b/contribs/application/src/main/java/org/matsim/application/prepare/network/params/NetworkParamsOpt.java index ab8c65b5639..c008f2cf583 100644 --- a/contribs/application/src/main/java/org/matsim/application/prepare/network/params/NetworkParamsOpt.java +++ b/contribs/application/src/main/java/org/matsim/application/prepare/network/params/NetworkParamsOpt.java @@ -60,10 +60,13 @@ static NetworkModel load(Class modelClazz) { */ static Map, Feature> readFeatures(String input, Map, ? extends Link> links) throws IOException { - // TODO: read features from link attributes as well, if not present as input - Map, Feature> features = new IdMap<>(Link.class, links.size()); + // Create features from link attributes + for (Link link : links.values()) { + features.put(link.getId(), createDefaultFeature(link)); + } + try (CSVParser reader = new CSVParser(IOUtils.getBufferedReader(input), CSVFormat.DEFAULT.builder().setHeader().setSkipHeaderRecord(true).build())) { @@ -73,32 +76,57 @@ static Map, Feature> readFeatures(String input, Map, ? extends Id id = Id.createLinkId(row.get("linkId")); Link link = links.get(id); - - Object2DoubleOpenHashMap ft = new Object2DoubleOpenHashMap<>(); - ft.defaultReturnValue(Double.NaN); - Object2ObjectMap categories = new Object2ObjectOpenHashMap<>(); + Feature ft = features.computeIfAbsent(id, (k) -> createDefaultFeature(link)); for (String column : header) { String v = row.get(column); try { - ft.put(column, Double.parseDouble(v)); + ft.features.put(column, Double.parseDouble(v)); } catch (NumberFormatException e) { // every not equal to True will be false - ft.put(column, Boolean.parseBoolean(v) ? 1 : 0); - categories.put(column, v); + ft.features.put(column, Boolean.parseBoolean(v) ? 1 : 0); + ft.categories.put(column, v); } } String highwayType = header.contains(NetworkUtils.TYPE) ? row.get(NetworkUtils.TYPE) : (link != null ? NetworkUtils.getHighwayType(link) : null); - features.put(id, new Feature(row.get("junction_type").intern(), highwayType, ft, categories)); + features.put(id, new Feature(row.get("junction_type").intern(), highwayType, ft.features, ft.categories)); } } return features; } + /** + * Create default feature based on link attributes. + */ + private static Feature createDefaultFeature(Link link) { + Object2DoubleOpenHashMap ft = new Object2DoubleOpenHashMap<>(); + ft.defaultReturnValue(Double.NaN); + Object2ObjectMap categories = new Object2ObjectOpenHashMap<>(); + + categories.put("highway_type", NetworkUtils.getHighwayType(link)); + ft.put("speed", NetworkUtils.getAllowedSpeed(link)); + ft.put("num_lanes", link.getNumberOfLanes()); + ft.put("length", link.getLength()); + + for (Map.Entry e : link.getAttributes().getAsMap().entrySet()) { + String key = e.getKey(); + Object value = e.getValue(); + if (value instanceof Number) { + ft.put(key, ((Number) value).doubleValue()); + } else if (value instanceof Boolean) { + ft.put(key, (Boolean) value ? 1 : 0); + } else { + categories.put(key, value.toString()); + } + } + + return new Feature("", NetworkUtils.getHighwayType(link), ft, categories); + } + /** * Read validation files and calc target speed. */