|
1 | 1 | # osmfeatures
|
2 | 2 |
|
3 |
| -A dictionary of OSM map features, accessible by terms and by tags, for Java and Android. |
| 3 | +A Kotlin multiplatform dictionary of OSM map features, accessible by terms and by tags. Supported platforms are Android, JVM and iOS. |
4 | 4 |
|
5 |
| -Requires Java 8. |
| 5 | +Due to heavy use of indices, it is very fast. |
6 | 6 |
|
7 |
| -## Copyright and License |
8 |
| - |
9 |
| -© 2019-2022 Tobias Zwick. This library is released under the terms of the [Apache License Version 2.0](http://www.apache.org/licenses/LICENSE-2.0.txt). |
| 7 | +It is currently used in [StreetComplete](https://github.com/streetcomplete/streetcomplete). |
10 | 8 |
|
11 |
| -## Installation |
12 |
| - |
13 |
| -Add [`de.westnordost:osmfeatures:5.2`](https://mvnrepository.com/artifact/de.westnordost/osmfeatures/5.2) as a Maven dependency or download the jar from there. |
| 9 | +## Copyright and License |
14 | 10 |
|
15 |
| -For Android, use [`de.westnordost:osmfeatures-android:5.2`](https://mvnrepository.com/artifact/de.westnordost/osmfeatures-android/5.2). |
| 11 | +© 2019-2024 Tobias Zwick. This library is released under the terms of the Apache License Version 2.0. |
16 | 12 |
|
17 | 13 | ## Usage
|
18 | 14 |
|
| 15 | +Add [de.westnordost:osmfeatures:6.0](https://mvnrepository.com/artifact/de.westnordost/osmfeatures/6.0) as a Maven dependency or download the jar from there. |
| 16 | + |
19 | 17 | ### Get the data
|
20 | 18 |
|
21 | 19 | The data for the dictionary is not maintained in this repository.
|
22 |
| -It actually uses the [preset data from iD](https://github.com/openstreetmap/id-tagging-schema/blob/main/dist/presets.json) and [the translations of the presets](https://github.com/openstreetmap/id-tagging-schema/tree/main/dist/translations). |
23 |
| -Just dump all the translations and the presets.json into the same directory. |
24 |
| -Do not forget to give attribution to iD since you are using their data. |
25 |
| - |
26 |
| -If you use gradle as your build tool, the easiest way to get this data is to put this task into your `build.gradle` and either execute this task manually from time to time or make the build process depend on it (by adding `preBuild.dependsOn(downloadPresets)`): |
27 |
| - |
28 |
| -```groovy |
29 |
| -import groovy.json.JsonSlurper |
30 |
| -
|
31 |
| -task downloadPresets { |
32 |
| - doLast { |
33 |
| - def targetDir = "$projectDir/path/to/where/the/data/should/go" |
34 |
| - def presetsUrl = new URL("https://raw.githubusercontent.com/openstreetmap/id-tagging-schema/main/dist/presets.json") |
35 |
| - def contentsUrl = new URL("https://api.github.com/repos/openstreetmap/id-tagging-schema/contents/dist/translations") |
36 |
| -
|
37 |
| - new File("$targetDir/presets.json").withOutputStream { it << presetsUrl.openStream() } |
38 |
| -
|
39 |
| - def slurper = new JsonSlurper() |
40 |
| - slurper.parse(contentsUrl, "UTF-8").each { |
41 |
| - if(it.type == "file") { |
42 |
| - def filename = it.name.substring(0, it.name.indexOf(".")) |
43 |
| - def javaLanguageTag = Locale.forLanguageTag(filename.replace('@','-')).toLanguageTag() |
44 |
| - def translationsUrl = new URL(it.download_url) |
45 |
| - new File("$targetDir/${javaLanguageTag}.json").withOutputStream { it << translationsUrl.openStream() } |
46 |
| - } |
47 |
| - } |
48 |
| - } |
49 |
| -} |
50 |
| -``` |
| 20 | +It actually uses the [preset data from iD](https://github.com/openstreetmap/id-tagging-schema/blob/main/dist/presets.json), [its translations](https://github.com/openstreetmap/id-tagging-schema/tree/main/dist/translations) |
| 21 | +and optionally additionally the brand preset data from the [name suggestion index](https://github.com/osmlab/name-suggestion-index). |
| 22 | +Each are © iD contributors, licensed under the ISC license. |
| 23 | + |
51 | 24 |
|
52 |
| -In StreetComplete (app that uses this library), there is [UpdatePresetsTask.kt](https://github.com/streetcomplete/StreetComplete/blob/master/buildSrc/src/main/java/UpdatePresetsTask.kt) to do this. It's longer but it is maintained and takes care of some more edge cases. Also, take note of [UpdateNsiPresetsTask.kt](https://github.com/streetcomplete/StreetComplete/blob/master/buildSrc/src/main/java/UpdateNsiPresetsTask.kt) which fetches the [name suggestion index presets](https://github.com/osmlab/name-suggestion-index) (=brands). |
| 25 | +So, just dump all the translations and the presets.json into the same directory. To be always |
| 26 | +up-to-date, it is advisable to have an automatic build task that fetches the current version of the |
| 27 | +presets from the repository. |
| 28 | + |
| 29 | +The app for which this library was developed (StreetComplete), uses the following tasks: |
| 30 | +- [UpdatePresetsTask.kt](https://github.com/streetcomplete/StreetComplete/blob/master/buildSrc/src/main/java/UpdatePresetsTask.kt) to download presets and selected translations |
| 31 | +- [UpdateNsiPresetsTask.kt](https://github.com/streetcomplete/StreetComplete/blob/master/buildSrc/src/main/java/UpdateNsiPresetsTask.kt) to download the brand presets from the [name suggestion index](https://github.com/osmlab/name-suggestion-index) |
53 | 32 |
|
54 | 33 | ### Initialize dictionary
|
55 | 34 |
|
56 |
| -Point the dictionary to the directory where the data is located (see above). Use `FeatureDictionary` as a singleton. |
57 |
| -```java |
58 |
| -FeatureDictionary dictionary = FeatureDictionary.create("path/to/data")); |
| 35 | +Point the dictionary to the directory where the data is located (see above). Use `FeatureDictionary` as a singleton, as initialization takes a moment (loading files, building indices). |
| 36 | +```kotlin |
| 37 | +val dictionary = FeatureDictionary.create(fileSystem, "path/to/data") |
59 | 38 | ```
|
60 | 39 |
|
61 | 40 | For Android, use
|
62 |
| -```java |
63 |
| -FeatureDictionary dictionary = AndroidFeatureDictionary.create(assetManager, "path/within/assets/folder/to/data")); |
| 41 | +```kotlin |
| 42 | +val dictionary = FeatureDictionary.create(assetManager, "path/within/assets/folder/to/data") |
64 | 43 | ```
|
65 | 44 |
|
66 |
| -If brand features from the [name suggestion index](https://github.com/osmlab/name-suggestion-index) (see last paragraph in the previous "Get the data" section) should be included in the dictionary, you can specify the path to these presets as a further parameter. These will be loaded on-demand depending on for which countries you search for. |
| 45 | +If brand features from the [name suggestion index](https://github.com/osmlab/name-suggestion-index) should be included in the dictionary, you can specify the path to these presets as a third parameter. These will be loaded on-demand depending on for which countries you search for. |
| 46 | + |
| 47 | +Translations will also be loaded on demand when first querying features using a certain language. |
67 | 48 |
|
68 | 49 | ### Find matches by tags
|
69 |
| -```java |
70 |
| -List<Feature> matches = dictionary |
71 |
| - .byTags(Map.of("amenity", "bench")) // look for features that have the given tags |
72 |
| - .forGeometry(GeometryType.POINT) // limit the search to features that may be points |
73 |
| - .forLocale(Locale.GERMAN) // show results in German only, don't fall back to English or unlocalized results |
74 |
| - .find(); |
75 | 50 |
|
76 |
| -// prints "Parkbank" (or something like this) or index out of bounds exception |
77 |
| -// if no preset for amenity=bench exists that is localized to German |
78 |
| -println(matches.get(0).getName()); |
| 51 | +```kotlin |
| 52 | +val matches = dictionary.getByTags( |
| 53 | + tags = mapOf("amenity" to "bench"), // look for features that have the given tags |
| 54 | + languages = listOf("de"), // show results in German only, don't fall back to English or unlocalized results |
| 55 | + geometry = GeometryType.POINT, // limit the search to features that may be points |
| 56 | +) |
| 57 | + |
| 58 | + |
| 59 | +// prints "Parkbank" (or something like this) |
| 60 | +// or null if no preset for amenity=bench exists that is localized to German |
| 61 | +println(matches[0]?.getName()) |
79 | 62 | ```
|
80 | 63 |
|
81 | 64 | ### Find matches by search word
|
82 | 65 |
|
83 |
| -```java |
84 |
| -List<Feature> matches = dictionary |
85 |
| - .byTerm("Bank") // look for features matching "Bank" |
86 |
| - .forGeometry(GeometryType.AREA) // limit the search to features that may be areas |
87 |
| - .forLocale(Locale.GERMAN, null) // show results in German or fall back to unlocalized results |
| 66 | +```kotlin |
| 67 | +val matches = dictionary.getByTerm( |
| 68 | + term = "Bank", // look for features matching "Bank" |
| 69 | + languages = listOf("de", null), // show results in German or fall back to unlocalized results |
88 | 70 | // (brand features are usually not localized)
|
89 |
| - .inCountry("DE") // also include things (brands) that only exist in Germany |
90 |
| - .limit(10) // return at most 10 entries |
91 |
| - .find(); |
92 |
| -// result list will have matches with at least amenity=bank, but not amenity=bench because it is a point-feature |
| 71 | + country = "DE", // also include things (brands) that only exist in Germany |
| 72 | + geometry = GeometryType.AREA, // limit the search to features that may be areas |
| 73 | +) |
| 74 | +// result sequence will have matches with at least amenity=bank, but not amenity=bench because it is a point-feature |
| 75 | +// if the dictionary contains also brand presets, e.g. "Deutsche Bank" will certainly also be amongst the results |
93 | 76 | ```
|
94 | 77 |
|
95 | 78 | ### Find by id
|
96 | 79 |
|
| 80 | +```kotlin |
| 81 | +val match = dictionary.getById( |
| 82 | + id = "amenity/bank", |
| 83 | + languages = listOf("de", "en-US", null), // show results in German, otherwise fall back to American |
| 84 | + // English or otherwise unlocalized results |
| 85 | + country = "DE", // also include things (brands) that only exist in Germany |
| 86 | +) |
| 87 | +``` |
| 88 | + |
| 89 | +### Builders |
| 90 | + |
| 91 | +For a more convenient interface on Java, the above functions continue to be available as builders, |
| 92 | +e.g. |
| 93 | + |
97 | 94 | ```java
|
98 |
| -Feature feature = dictionary |
99 |
| - .byId("amenity/bank") |
100 |
| - .forLocale(Locale.GERMAN, // show results in German, otherwise fall back to English etc. |
101 |
| - Locale.ENGLISH, |
102 |
| - null) |
103 |
| - .inCountry("DE") // also include things (brands) that only exist in Germany |
104 |
| - .get(); |
| 95 | +List<Feature> matches = dictionary |
| 96 | + .byTags(Map.of("amenity", "bench")) |
| 97 | + .forGeometry(GeometryType.POINT) |
| 98 | + .inLanguage("de") |
| 99 | + .find(); |
105 | 100 | ```
|
| 101 | + |
0 commit comments