SwiftAddress icon indicating copy to clipboard operation
SwiftAddress copied to clipboard

Load and display OSM elements with addr:housenumber from overpass.api.de

Open stephan75 opened this issue 3 years ago • 38 comments

What about the following feature request:

When the map view of SwiftAddress is zoomed in enough, enable a button that downloads all OSM elements from overpass-api.de that contain a tagging with addr:housenumber=*

and then display each element from that data collection on the map view.

In this way, a mapper can see where buildings are present in the OSM data which already have a tag addr:housenumber, and where this tag is missing.

Maybe as a start, try this method only for OSM nodes ... and extend this method to ways and relations later.


ToDo steps moved from a following comment to have github's progress bar:

  • [x] from current map view inside the app, determine a bounding box for the displayed area,
  • [x] have a correct user agent string for the following overpass-api request,
  • [x] do a query on overpass-api.de for the mentioned bounding box, for all nodes with addr:housenumber=* (ways and maybe relations should be handled later, not now.),
  • [x] download the query result and store it
  • [ ] Parse / single out relevant parts of the XML
  • [ ] Fix DelayedMapListener issue: see https://github.com/osmdroid/osmdroid/issues/1712
  • [ ] use this to display all those housenumber on the map view similar to how housenumber are displayed so far.
  • [ ] extend the query, storing and displaying also to OSM way objects,
  • [ ] extend the query, storing and displaying also to OSM relation objects (interpolation lines of housenumbers, building multipolygons?)
  • [ ] Potentially option to edit downloaded housenumber?
  • [ ] add an option to toggle the display of this layer on/off, or even delete it completely.
  • [ ] Make downloading efficient

stephan75 avatar Mar 16 '21 21:03 stephan75

Is this worth it? You can already see all the housenumbers on the default "Osm-carto" view. Adding this might help with other views. It could also mean that you can edit existing numbers. However, implementing the ability to edit existing numbers will be more difficult I think

IpswichMapper avatar Mar 28 '21 18:03 IpswichMapper

@stephan75 thoughts?

IpswichMapper avatar Mar 29 '21 09:03 IpswichMapper

When writing this feature request I had in mind certain POIs where the OSM standard carto style only displays its POI icon, but NOT the house number, which is definitively tagged on that node or building. So it is not clear for a normal user whether that POI has already its housenumber tagged in the OSM data. Example: image

stephan75 avatar Mar 30 '21 04:03 stephan75

Unfortunately I have no android programming / coding skills, but I will try to collect some needed steps for this feature:

MOVED TODO LIST TO FIRST ISSUE COMMENT

Maybe we can get some initial hints from @westnordost who is the developer of StreetComplete?

stephan75 avatar Apr 07 '21 20:04 stephan75

I don't think this will be very difficult to implement (maybe it will take some time). I've already worked with Overpass API to create the "dropdown" feature when you try and manually enter a housenumber (i.e., when you click on the street name in the keypad and start typing out the street, a dropdown will show displaying the names of all the streets that are close by). I've also worked with boundingboxes already to create the "proof of concept" for downloading map tiles.

All you have to do is parse the XML and display them as markers and the map.

I have other issues though, so as if I add the ability to "edit" these, then the .osm files generated will contain already existing nodes. Will this cause issues when merging? And also, large requests to Overpass API can take relatively long to parse too.

Also, would it clutter the map?

IpswichMapper avatar Apr 07 '21 21:04 IpswichMapper

I've written a Java library to query tgr overpass api. In case you are interested:

https://github.com/westnordost/osmapi-overpass

On April 7, 2021 11:35:59 PM GMT+02:00, IpswichMapper @.***> wrote:

I don't think this will be very difficult to implement (maybe it will take some time). I've already worked with Overpass API to create the "dropdown" feature when you try and manually enter a housenumber (i.e., when you click on the street name in the keypad and start typing out the street, a dropdown will show displaying the names of all the streets that are close by). I've also worked with boundingboxes already to create the "proof of concept" for downloading map tiles.

All you have to do is parse the XML and display them as markers and the map.

I have other issues though, so as if I add the ability to "edit" these, then the .osm files generated will contain already existing nodes. Will this cause issues when merging? And also, large requests to Overpass API can take relatively long to parse too.

-- You are receiving this because you were mentioned. Reply to this email directly or view it on GitHub: https://github.com/IpswichMapper/SwiftAddress/issues/27#issuecomment-815280344

-- Diese Nachricht wurde von meinem Android-Gerät mit K-9 Mail gesendet.

westnordost avatar Apr 07 '21 21:04 westnordost

This is what I wrote for the query:

boundingBox = mapView.boundingBox
Thread {
    val queryText = "https://overpass-api.de/api/interpreter?data=" +
                    "<query type='node'>" +
                    "<has-kv k='addr:housenumber' regv='.+'/>" +
                    "<bbox-query s='${boundingBox.latSouth}' w='${boundingBox.lonWest}' " +
                    "n='${boundingBox.latNorth}' e='${boundingBox.lonEast}' />" +
                    "</query> <print />"
            val query = URL(queryText)
            val result = query.readText()
}.start()

seems good enough, however, it isn't working reliably at the moment because osmdroid's "onZoom()" function doesn't activate properly when using a "DelayedMapListener" (which is a listener that activies only after you have finished zooming or scrolling). See osmdroid/osmdroid#1712

@westnordost

Is your library more efficient than the normal Kotlin API code I have shown above?

Another thing, how can I make this efficient / avoid redownloading housenumbers?

For example, if I were to scroll the map so that half of it still the old boundingBox, using a normal DelayedMapListener all the housenumbers would have to be downloaded (there is quite a bit of delay for this). Is there a way to only download sections that you haven't downloaded already?

@stephan75

I have checked off all the boxes that I did today and added some more detail to your checklist.

IpswichMapper avatar Apr 08 '21 00:04 IpswichMapper

Is your library more efficient than the normal Kotlin API code I have shown above?

The library is not about efficiency but convenience: It does the querying and the parsing of the data for you. If I remember correctly, it has built-in support for parsing the "out geom" result as well, so you directly get the geometry for each returned element too.

westnordost avatar Apr 08 '21 09:04 westnordost

val myDataHandler = object : MapDataWithGeometryHandler {
    fun handle(bounds: BoundingBox) {
        /* here you get returned the bounding box of your request */
    }

    fun handle(node: Node) {
        /* this is called for every node in the overpass result */
    }

    fun handle(way: Way, geometry: List<LatLon>) {
        /* this is called for every way in the overpass result, geometry is attached */
    }

    fun handle(relation: Relation, bounds: BoundingBox, nodeGeometries: Map<Long, LatLon>, wayGeometries: Map<Long, List<LatLon>>) {
        /* this is called for every relation in the overpass result, geometry is attached */
    }
}

// get all housenumbers on Malta
overpassApi.queryElementsWithGeometry(
    "[bbox:13.8,35.5,14.9,36.3]; nwr['addr:housenumber']; out meta geom;", 
    myDataHandler
)

What you do in myDataHandler is your choice. You could just put it all into a big list, or persist to database or whatever.

westnordost avatar Apr 08 '21 09:04 westnordost

val myDataHandler = object : MapDataWithGeometryHandler {
    fun handle(bounds: BoundingBox) {
        /* here you get returned the bounding box of your request */
    }

    fun handle(node: Node) {
        /* this is called for every node in the overpass result */
    }

    fun handle(way: Way, geometry: List<LatLon>) {
        /* this is called for every way in the overpass result, geometry is attached */
    }

    fun handle(relation: Relation, bounds: BoundingBox, nodeGeometries: Map<Long, LatLon>, wayGeometries: Map<Long, List<LatLon>>) {
        /* this is called for every relation in the overpass result, geometry is attached */
    }
}

// get all housenumbers on Malta
overpassApi.queryElementsWithGeometry(
    "[bbox:13.8,35.5,14.9,36.3]; nwr['addr:housenumber']; out meta geom;", 
    myDataHandler
)

What you do in myDataHandler is your choice. You could just put it all into a big list, or persist to database or whatever.

How would you get the values for each node? For example, in the handler(node: Node), you could do node.position but I couldn't find any function that allowed me to get the value of specific tags. How is this possible (note: I don't know Overpass that well, I mostly stick to XML as I showed in my example).

Plus it gives me an error when building when I add this dependancy:

Duplicate class org.intellij.lang.annotations.Flow found in modules jetified-annotations-13.0 (org.jetbrains:annotations:13.0) and jetified-annotations-java5-18.0 (org.jetbrains:annotations-java5:18.0.0)
Duplicate class org.intellij.lang.annotations.Identifier found in modules jetified-annotations-13.0 (org.jetbrains:annotations:13.0) and jetified-annotations-java5-18.0 (org.jetbrains:annotations-java5:18.0.0)
Duplicate class org.intellij.lang.annotations.JdkConstants found in modules jetified-annotations-13.0 (org.jetbrains:annotations:13.0) and jetified-annotations-java5-18.0 (org.jetbrains:annotations-java5:18.0.0)
Duplicate class org.intellij.lang.annotations.JdkConstants$AdjustableOrientation found in modules jetified-annotations-13.0 (org.jetbrains:annotations:13.0) and jetified-annotations-java5-18.0 (org.jetbrains:annotations-java5:18.0.0)
Duplicate class org.intellij.lang.annotations.JdkConstants$BoxLayoutAxis found in modules jetified-annotations-13.0 (org.jetbrains:annotations:13.0) and jetified-annotations-java5-18.0 (org.jetbrains:annotations-java5:18.0.0)
Duplicate class org.intellij.lang.annotations.JdkConstants$CalendarMonth found in modules jetified-annotations-13.0 (org.jetbrains:annotations:13.0) and jetified-annotations-java5-18.0 (org.jetbrains:annotations-java5:18.0.0)
Duplicate class org.intellij.lang.annotations.JdkConstants$CursorType found in modules jetified-annotations-13.0 (org.jetbrains:annotations:13.0) and jetified-annotations-java5-18.0 (org.jetbrains:annotations-java5:18.0.0)
Duplicate class org.intellij.lang.annotations.JdkConstants$FlowLayoutAlignment found in modules jetified-annotations-13.0 (org.jetbrains:annotations:13.0) and jetified-annotations-java5-18.0 (org.jetbrains:annotations-java5:18.0.0)
Duplicate class org.intellij.lang.annotations.JdkConstants$FontStyle found in modules jetified-annotations-13.0 (org.jetbrains:annotations:13.0) and jetified-annotations-java5-18.0 (org.jetbrains:annotations-java5:18.0.0)
Duplicate class org.intellij.lang.annotations.JdkConstants$HorizontalAlignment found in modules jetified-annotations-13.0 (org.jetbrains:annotations:13.0) and jetified-annotations-java5-18.0 (org.jetbrains:annotations-java5:18.0.0)
Duplicate class org.intellij.lang.annotations.JdkConstants$InputEventMask found in modules jetified-annotations-13.0 (org.jetbrains:annotations:13.0) and jetified-annotations-java5-18.0 (org.jetbrains:annotations-java5:18.0.0)
Duplicate class org.intellij.lang.annotations.JdkConstants$ListSelectionMode found in modules jetified-annotations-13.0 (org.jetbrains:annotations:13.0) and jetified-annotations-java5-18.0 (org.jetbrains:annotations-java5:18.0.0)
Duplicate class org.intellij.lang.annotations.JdkConstants$PatternFlags found in modules jetified-annotations-13.0 (org.jetbrains:annotations:13.0) and jetified-annotations-java5-18.0 (org.jetbrains:annotations-java5:18.0.0)
Duplicate class org.intellij.lang.annotations.JdkConstants$TabLayoutPolicy found in modules jetified-annotations-13.0 (org.jetbrains:annotations:13.0) and jetified-annotations-java5-18.0 (org.jetbrains:annotations-java5:18.0.0)
Duplicate class org.intellij.lang.annotations.JdkConstants$TabPlacement found in modules jetified-annotations-13.0 (org.jetbrains:annotations:13.0) and jetified-annotations-java5-18.0 (org.jetbrains:annotations-java5:18.0.0)
Duplicate class org.intellij.lang.annotations.JdkConstants$TitledBorderJustification found in modules jetified-annotations-13.0 (org.jetbrains:annotations:13.0) and jetified-annotations-java5-18.0 (org.jetbrains:annotations-java5:18.0.0)
Duplicate class org.intellij.lang.annotations.JdkConstants$TitledBorderTitlePosition found in modules jetified-annotations-13.0 (org.jetbrains:annotations:13.0) and jetified-annotations-java5-18.0 (org.jetbrains:annotations-java5:18.0.0)
Duplicate class org.intellij.lang.annotations.JdkConstants$TreeSelectionMode found in modules jetified-annotations-13.0 (org.jetbrains:annotations:13.0) and jetified-annotations-java5-18.0 (org.jetbrains:annotations-java5:18.0.0)
Duplicate class org.intellij.lang.annotations.Language found in modules jetified-annotations-13.0 (org.jetbrains:annotations:13.0) and jetified-annotations-java5-18.0 (org.jetbrains:annotations-java5:18.0.0)
Duplicate class org.intellij.lang.annotations.MagicConstant found in modules jetified-annotations-13.0 (org.jetbrains:annotations:13.0) and jetified-annotations-java5-18.0 (org.jetbrains:annotations-java5:18.0.0)
Duplicate class org.intellij.lang.annotations.Pattern found in modules jetified-annotations-13.0 (org.jetbrains:annotations:13.0) and jetified-annotations-java5-18.0 (org.jetbrains:annotations-java5:18.0.0)
Duplicate class org.intellij.lang.annotations.PrintFormat found in modules jetified-annotations-13.0 (org.jetbrains:annotations:13.0) and jetified-annotations-java5-18.0 (org.jetbrains:annotations-java5:18.0.0)
Duplicate class org.intellij.lang.annotations.PrintFormatPattern found in modules jetified-annotations-13.0 (org.jetbrains:annotations:13.0) and jetified-annotations-java5-18.0 (org.jetbrains:annotations-java5:18.0.0)
Duplicate class org.intellij.lang.annotations.RegExp found in modules jetified-annotations-13.0 (org.jetbrains:annotations:13.0) and jetified-annotations-java5-18.0 (org.jetbrains:annotations-java5:18.0.0)
Duplicate class org.intellij.lang.annotations.Subst found in modules jetified-annotations-13.0 (org.jetbrains:annotations:13.0) and jetified-annotations-java5-18.0 (org.jetbrains:annotations-java5:18.0.0)
Duplicate class org.jetbrains.annotations.Contract found in modules jetified-annotations-13.0 (org.jetbrains:annotations:13.0) and jetified-annotations-java5-18.0 (org.jetbrains:annotations-java5:18.0.0)
Duplicate class org.jetbrains.annotations.Nls found in modules jetified-annotations-13.0 (org.jetbrains:annotations:13.0) and jetified-annotations-java5-18.0 (org.jetbrains:annotations-java5:18.0.0)
Duplicate class org.jetbrains.annotations.NonNls found in modules jetified-annotations-13.0 (org.jetbrains:annotations:13.0) and jetified-annotations-java5-18.0 (org.jetbrains:annotations-java5:18.0.0)
Duplicate class org.jetbrains.annotations.NotNull found in modules jetified-annotations-13.0 (org.jetbrains:annotations:13.0) and jetified-annotations-java5-18.0 (org.jetbrains:annotations-java5:18.0.0)
Duplicate class org.jetbrains.annotations.Nullable found in modules jetified-annotations-13.0 (org.jetbrains:annotations:13.0) and jetified-annotations-java5-18.0 (org.jetbrains:annotations-java5:18.0.0)
Duplicate class org.jetbrains.annotations.PropertyKey found in modules jetified-annotations-13.0 (org.jetbrains:annotations:13.0) and jetified-annotations-java5-18.0 (org.jetbrains:annotations-java5:18.0.0)
Duplicate class org.jetbrains.annotations.TestOnly found in modules jetified-annotations-13.0 (org.jetbrains:annotations:13.0) and jetified-annotations-java5-18.0 (org.jetbrains:annotations-java5:18.0.0)
Duplicate class org.xmlpull.v1.XmlPullParser found in modules jetified-kxml2-2.3.0 (net.sf.kxml:kxml2:2.3.0) and jetified-xmlpull-1.1.3.1 (xmlpull:xmlpull:1.1.3.1)
Duplicate class org.xmlpull.v1.XmlPullParserException found in modules jetified-kxml2-2.3.0 (net.sf.kxml:kxml2:2.3.0) and jetified-xmlpull-1.1.3.1 (xmlpull:xmlpull:1.1.3.1)
Duplicate class org.xmlpull.v1.XmlPullParserFactory found in modules jetified-kxml2-2.3.0 (net.sf.kxml:kxml2:2.3.0) and jetified-xmlpull-1.1.3.1 (xmlpull:xmlpull:1.1.3.1)
Duplicate class org.xmlpull.v1.XmlSerializer found in modules jetified-kxml2-2.3.0 (net.sf.kxml:kxml2:2.3.0) and jetified-xmlpull-1.1.3.1 (xmlpull:xmlpull:1.1.3.1)

Go to the documentation to learn how to Fix dependency resolution errors.

Here are my dependancies:

implementation "org.jetbrains.kotlin:kotlin-stdlib:1.4.32"
    implementation 'androidx.core:core-ktx:1.3.2'
    implementation 'androidx.appcompat:appcompat:1.2.0'
    implementation 'com.google.android.material:material:1.3.0'
    implementation 'androidx.constraintlayout:constraintlayout:2.0.4'
    implementation 'androidx.legacy:legacy-support-v4:1.0.0'
    testImplementation 'junit:junit:4.13.2'
    androidTestImplementation 'androidx.test.ext:junit:1.1.2'
    androidTestImplementation 'androidx.test.espresso:espresso-core:3.3.0'
    implementation 'org.osmdroid:osmdroid-android:6.1.10'
    implementation 'com.github.MKergall:osmbonuspack:6.6.0'
    implementation 'androidx.preference:preference-ktx:1.1.1'
    implementation 'org.jetbrains.kotlinx:kotlinx-coroutines-android:1.3.0'
    implementation "com.github.mancj:SlideUp-Android:2.2.8"
    implementation 'ru.ztrap:RxSlideUp2:2.0.1' //optional, for reactive listeners based on RxJava-2
    implementation 'androidx.exifinterface:exifinterface:1.3.2'
    implementation 'de.westnordost:osmapi-overpass:1.3'

Even though your library isn't mentioned in the duplicate class StackTrace, removing that library fixes the problem for some reason.

IpswichMapper avatar Apr 08 '21 15:04 IpswichMapper

I don't know Overpass that well, I mostly stick to XML as I showed in my example

Should be not problem to use XML in the query. The library just passes the query string through to Overpass and does not do anything with it.

How would you get the values for each node? For example, in the handler(node: Node), you could do node.position but I couldn't find any function that allowed me to get the value of specific tags

node.tags?.get("addr:housenumber") (tags may be null if the node has no tags)

error

Right, it seems that on Android, certain classes (XmlPullParser, JetBrains annotations) are already defined, so you need to remove them from that dependency. StreetComplete is not using the library anymore since v26, so I can't copy any configuration from the current gradle. Does this work?

implementation 'de.westnordost:osmapi-overpass:1.3' {
    // xml pull parser already included in Android
    exclude group: 'net.sf.kxml', module: 'kxml2' 
    // NonNull etc annotations are already available in Android
    exclude group: 'org.jetbrains', module: 'annotations'
    exclude group: 'com.intellij', module: 'annotations'
    exclude group: 'org.intellij', module: 'annotations'
}

westnordost avatar Apr 08 '21 15:04 westnordost

In an old version of StreetComplete, I found this block

configurations {
    // it's already included in Android
    all*.exclude group: 'net.sf.kxml', module: 'kxml2'

    cleanedAnnotations
    compile.exclude group: 'org.jetbrains', module:'annotations'
    compile.exclude group: 'com.intellij', module:'annotations'
    compile.exclude group: 'org.intellij', module:'annotations'
}

This excludes the given dependencies not only for the specified dependency but for all dependencies.

Please if anything of that works, let me know, then I can update the README.md in that repos.

westnordost avatar Apr 08 '21 15:04 westnordost

I just tried using the OSMAPI library that you have for uploading/downloading OSM data (using APIv0.6). It says to add this to your code:

    compile ('de.westnordost:osmapi:3.11') {
        exclude group: 'net.sf.kxml', module: 'kxml12'
    }

(Note: compile is depreciated but I get the same bug with implementation)

Duplicate class org.xmlpull.v1.XmlPullParser found in modules jetified-kxml2-2.3.0 (net.sf.kxml:kxml2:2.3.0) and jetified-xmlpull-1.1.3.1 (xmlpull:xmlpull:1.1.3.1)
Duplicate class org.xmlpull.v1.XmlPullParserException found in modules jetified-kxml2-2.3.0 (net.sf.kxml:kxml2:2.3.0) and jetified-xmlpull-1.1.3.1 (xmlpull:xmlpull:1.1.3.1)
Duplicate class org.xmlpull.v1.XmlPullParserFactory found in modules jetified-kxml2-2.3.0 (net.sf.kxml:kxml2:2.3.0) and jetified-xmlpull-1.1.3.1 (xmlpull:xmlpull:1.1.3.1)
Duplicate class org.xmlpull.v1.XmlSerializer found in modules jetified-kxml2-2.3.0 (net.sf.kxml:kxml2:2.3.0) and jetified-xmlpull-1.1.3.1 (xmlpull:xmlpull:1.1.3.1)

So it seems like kxml is giving me bugs even after I explicitaly told it to excluded from the OSMapi.

Also, another thing that is confusing me is branches. I made the above compile ('de.westnordost:osmapi:3.11') in the uploadToOsm branch, but when I checkout the main branch, the changes appear in the main branch too??? I thought the advantages of branches was that you code write code in one branch and not affect another one until you merge? So why is this happening? (Sorry if this is something basic I am missing out, I've not used branches in git before this).

IpswichMapper avatar Apr 08 '21 15:04 IpswichMapper

but when I checkout the main branch, the changes appear in the main branch too???

This does not happen. What made you think this is what happened? If you switch branches, I recommend re-sync the project with the gradle files and running hte clean task.

I just tried using the OSMAPI library that you have for uploading/downloading OSM data (using APIv0.6). It says to add this to your code:

Okay, just as a test, what about only

    implementation 'de.westnordost:osmapi-core:1.4' {
        exclude group: 'net.sf.kxml', module: 'kxml12'
    }

?

And if this gives an error, what about

dependencies {
    implementation 'de.westnordost:osmapi-core:1.4'
}

configurations {
    all*.exclude group: 'net.sf.kxml', module: 'kxml2'
}

westnordost avatar Apr 08 '21 16:04 westnordost

This does not happen. What made you think this is what happened?

Turns out you have to commit changes in order for them to be tied to that branch. (Other option is to use git stash of course). Sorry about that, that was a really simple thing.

implementation 'de.westnordost:osmapi-core:1.4' {
   exclude group: 'net.sf.kxml', module: 'kxml12'
}

Note, even with implementation the actual library needs to be in brackets if you want to do that:

implementation ('de.westnordost:osmapi-core:1.4') {
    exclude group: 'net.sf.kxml', module: 'kxml12'
}

That didn't work, however, the bug still showed up.

This, however, even with implementation the actual library needs to be in brackets if you want to do that:

implementation ('de.westnordost:osmapi-core:1.4') {
    exclude group: 'net.sf.kxml', module: 'kxml12'
}

That didn't work, however, the bug still showed up.

This, however, worked fine:

dependancies {
    implementation 'de.westnordost:osmapi-core:1.4'
}
configurations {
    all*.exclude group: 'net.sf.kxml', module: 'kxml2'
}

IpswichMapper avatar Apr 08 '21 16:04 IpswichMapper

Seems like, in your documention, this:

compile ('de.westnordost:osmapi:3.11')
{
	exclude group: 'net.sf.kxml', module: 'kxml2' // already included in Android
}

needs to be replaced with this:

dependancies {
    implementation 'de.westnordost:osmapi:3.11'
}
configurations {
    all*.exclude group: 'net.sf.kxml', module: 'kxml2'
}

IpswichMapper avatar Apr 08 '21 16:04 IpswichMapper

Hm?

westnordost avatar Apr 08 '21 16:04 westnordost

In the documentation for OSMAPI (the api v0.6 version), it says to use the "exclude" command to remove the kxml library.

However, that doesn't work, but rather configuration{} works. So the documentatino should be updated to show this

IpswichMapper avatar Apr 08 '21 16:04 IpswichMapper

Got it working. However, on my first run, I got rate limited (it says Too Many Requests (429)). Is there a user agent that I need to enter to be able to do more requests?

Not only this, but the downloading really lagged the app. I changed the zoomLevel from 14 to 17 and this was fixed, however I am still getting the Too Many Requests message

IpswichMapper avatar Apr 08 '21 17:04 IpswichMapper

@stephan75 I don't think continuous download of housenumbers when you are zoomed in is possible. Not only would it send far too many requests to the server, it would also lead to duplication of markers and would lag the app. I think a better solution is to be able to download already existing markers in the "DownloadTilesFragment". This can be accessed from the Imagery icon in the top right of the map. When downloading tiles, I could add an option to also download existing housenumbers in that area.

IpswichMapper avatar Apr 08 '21 17:04 IpswichMapper

Got it working. However, on my first run, I got rate limited (it says Too Many Requests (429)). Is there a user agent that I need to enter to be able to do more requests?

On your first request? Well, the request limiting is per IP. So if you made requests earlier, you have to wait. Note the other methods of the OverpassMapDataDao. You can actually query how long more you have to wait until you are allowed to do the next request. But in any way, you should specify the correct user agent (in this case, "SwiftAddress")

Anyway, check how many requests you do. Maybe you do too many requests.

Not only this, but the downloading really lagged the app.

You are downloading in a background thread, right? OverpassMapDataDao doesn't do any threading on its own.

westnordost avatar Apr 08 '21 17:04 westnordost

On your first request?

Sorry, I meant my first run of the app. I was using a "DelayedMapListener" to call the function. That means that everytime I stop scrolling or stop zooming, it calls the function.

Not only this, but the downloading really lagged the app.

You are downloading in a background thread, right? OverpassMapDataDao doesn't do any threading on its own.

Placing the markers has to happen on a main thread, however. Since then I increased the zoom level, and that issue went away.

That being said, do you think it is possible to have a continuous download like @Stephan75 wants?

Streetcomplete only downloads data when you tell it to. Would it be possible to use the overpass API to download data continuously when you scroll the map?

IpswichMapper avatar Apr 08 '21 17:04 IpswichMapper

That means that everytime I stop scrolling or stop zooming, it calls the function.

That's too much. You should memorize which areas you already downloaded and memorize the results. StreetComplete does this like this:

  • Persist in a database which tiles (at zoom level 16) have already been downloaded: https://github.com/streetcomplete/StreetComplete/blob/master/app/src/main/java/de/westnordost/streetcomplete/data/download/tiles/DownloadedTilesDao.kt
  • in principle, download not by free bbox but fit the viewed bbox to tiles at zoom level 16: https://github.com/streetcomplete/StreetComplete/blob/master/app/src/main/java/de/westnordost/streetcomplete/data/download/DownloadController.kt#L57
  • after download completed, memorize that this tile / these tiles have been downloaded already
  • before downloading, check if that tile has been downloaded already: https://github.com/streetcomplete/StreetComplete/blob/master/app/src/main/java/de/westnordost/streetcomplete/data/download/QuestDownloader.kt#L57

iD does it the same, and I assume that every other proper editor that allows free scrolling (OsmInEdit, Osm Go, .... for example) does it the same. Maybe not persisting it into a DB, but at least persisting the information into memory.

Streetcomplete only downloads data when you tell it to.

No, StreetComplete downloads automatically areas around the user's current location. The logic is functionally the same as the "download everything that comes into view" as it is done for iD etc.

westnordost avatar Apr 08 '21 18:04 westnordost

Though in all fairness, I have to tell you that it is almost certain that I will implement a view that looks something like this

in StreetComplete within the next 3-4 months or so, as described in detail here https://github.com/streetcomplete/StreetComplete/issues/2461

westnordost avatar Apr 08 '21 18:04 westnordost

No, StreetComplete downloads automatically areas around the user's current location. The logic is functionally the same as the "download everything that comes into view" as it is done for iD etc.

So tasks are downloaded automatically? I think I got confused there because when I used to use it, I would always tell it to download manually tasks in an area.

When they are downloaded automatically, isn't it in the area surrounding your current location? I'm pretty sure it doesn't start downloading tasks when you zoom in. Could you create code where housenumbers are downloaded when you zoom in enough using the techniques you have shown?

IpswichMapper avatar Apr 08 '21 18:04 IpswichMapper

So tasks are downloaded automatically?

Yes, around your GPS location. You can additionally download areas manually, if you want to download areas not around your location in advance.

When they are downloaded automatically, isn't it in the area surrounding your current location

Correct.

Could you create code where housenumbers are downloaded when you zoom in enough using the techniques you have shown?

What do you mean exactly? If I can theoretically?

westnordost avatar Apr 08 '21 18:04 westnordost

Could you create code where housenumbers are downloaded when you zoom in enough using the techniques you have shown?

Sorry, bad phrasing. I essentially meant, "can it be done". I'm not asking you to do it for me 😅.

IpswichMapper avatar Apr 08 '21 18:04 IpswichMapper

Yes, of course.

val downloadedTiles = HashSet<Tile>()

@Synchronized fun download(bbox: Bounds) {
    val  tiles = bbox.asTilesAtZoomLevel(16)
    if (downloadedTiles.containsAll(tiles)) return

    val bboxExpandedToTileEdges = tiles.toBbox()
    doTheDownloadNow(bboxExpandedToTileEdges )
    
    downloadedTiles.putAll(tiles)
}

fun onMapViewHasChangedInAnyWay() {
    val bbox = getDisplayedBoundingBox()
    download(bbox)
}

westnordost avatar Apr 08 '21 18:04 westnordost

This may be helpful: https://github.com/streetcomplete/StreetComplete/blob/master/app/src/main/java/de/westnordost/streetcomplete/util/SlippyMapMath.kt

westnordost avatar Apr 08 '21 18:04 westnordost

Thanks for all the help.

Currently I'm trying to login to the "sandbox api". How do you get an OAuthConsumer?


        val provider: OAuthProvider = DefaultOAuthProvider(
            "https://api06.dev.openstreetmap.org/oauth/request_token",
            "https://api06.dev.openstreetmap.org/oauth/access_token",
            "https://api06.dev.openstreetmap.org/oauth/authorize"
        )

        

        val connection = OsmConnection("https://api06.dev.openstreetmap.org/", null, null)

You do you get this "consumer" after the user has entered a username and password?

https://github.com/mttkay/signpost/blob/master/docs/GettingStarted.md

This guide does not mention what role the username and password play.

IpswichMapper avatar Apr 08 '21 18:04 IpswichMapper