districtr / districtr-v2

A free, open-source web app for drawing districting plans. Reboot of districtr.
MIT License
1 stars 1 forks source link

Alternatives to queryRenderedFeatures #115

Open nofurtherinformation opened 2 months ago

nofurtherinformation commented 2 months ago

Using map.queryRenderedFeatures has an issue when geometries are not rendered. The problem has two parts:

  1. Unrendered geometries in an area do not get assigned
  2. Since they don't get assigned, population totals may be unexpected

In most cases, this is more of an edge case, but there may be higher stakes situations where this matters more.

One potential solution discussed has been to use Postgis on the backend to confirm the selections, and send those back to the client. This is a possible approach, but adds complexity in the back and forth between the server and client, and potentially adds latency to the paint operations.

In discussing with Moon yesterday, one question asked was if there could be an advanced mode that does more than queryRenderedFeatures even if it came at the cost of performance. If the geospatial query were on the backend, performance of a client computer would not be a huge deal, aside from some additional data i/o and maybe a few more state updates. But this has non-trivial complexity.

I spent some time thinking about this today and wanted to rough out what a clientside solution could look like. One possible approach would be to RBush and have a local indexed point/bbox query, rather than the map. This has a couple challenges to consider:

I took a stab at a naive implementation and here's the class I roughed out, which can be used like this.

The good news:

The bad news:

I think the data transfer here can be acceptable (CSV of colorado VTDs was like 130kb, less gzipped), and we can send relevant child layer data when sending the parent/child edges after shatter. The main issue remains the time to build the index, but since it can be serialized, I believe we could pull that into a web worker and send back the RTree heirarchy, then load it into the main thread (this is unconventional but may work). Then, building the RTree is off the main thread, but when doing the actual queries we can get main thread performance. The whole RTree could just live on a webworker, if query performance is acceptable (not sure this is the case).

This may not be the exact set of parts we'd want to use, but this does sidestep issues with lots of back and forth on assignments -- I think it's worth considering clientside spatial queries to overcome the issues with tile rendering.

raphaellaude commented 1 month ago

Not sure how I missed this. This is super interesting–thanks for introducing me to rbush, looks cool. IMO, I don't think we've hit the point yet where we need to introduce this additional complexity to solve our problems but it's great to know this is an option.