Accessing geometries for fly-to functionality #43
Replies: 4 comments 5 replies
-
|
Beta Was this translation helpful? Give feedback.
-
I agree with option two for the reasons stated above. However, when we consider the implementation of the capital projects geojson endpoint, I would like us to consider a deviation from how we implemented the tax lots geojson endpoint. The current implementation has a "geojson" path suffix ie) Regardless of whether we want to drop the If we're going to differentiate the responses based on the Accept/Content-Type headers, then we might as well rely on it as the sole differentiator. This will make the paths more concise |
Beta Was this translation helpful? Give feedback.
-
I like Option 2 with option 2 (using a new GeojsonLayer). Would this be strictly for the project selections or can this layer also be used to highlight a selected district? |
Beta Was this translation helpful? Give feedback.
-
Ok, I created issues to document and implement the new endpoint and then use it to add "fly to" functionality on the frontend: |
Beta Was this translation helpful? Give feedback.
-
In working on #16, I had trouble implementing this requirement:
I have some thoughts on next steps, but the complexity seemed significant enough to break out of the original Issue and capture those thoughts in a discussion.
Context
The requirements ask that the map should pan and zoom to center the selected the project. All parts of the project should be in the viewport and this functionality should be aware of route paths we're using to track the managing code and ID of the selected project. By that logic, if a user clicks a few projects in succession then clicks the back button in their browser, we would expect the map
viewstate
to move as they cycle backwards through the projects they selected.We implemented the a pan-on-selection pattern in ae-zoning-map-poc but there are a couple things to note about that implementation:
zoom
. This was fine for the proof of concept but for capital projects, we will need a more robust approach that gives us a proper bounding box of the project.What I tried
I had hoped we could accomplish this functionality using the geometries from the tiles and the various APIs Deck gives us but I don't think there's a solution that works consistently and is performant. If there is, it's going to introduce some seriously janky code. This issue really comes down to the nature of tiles. By their nature, they slice up the geoms of projects based on which tiles a project partially or fully lands in.
I made a throwaway branch from my feature branch for #16 that shows the closest I could get to having this working. Don't look at this code too long, for eventually it will stare back. This approach runs MVTLayer's getRenderedFeatures method once when the map first loads at the citywide viewport and puts that into state. That method is an expensive operation in the best of use cases, but this approach is especially bad because we're chucking thousands of project geoms into memory. What's worse, this approach seems to be flaky anyway, presumably because Deck is putting an upper bound on how many features it actually lets that method return and features it does return are still sliced up based on the tiling. Once I had that list of features, it's just a matter of grabbing the selected project feature based on the path params, getting its bounding box, and updating
viewstate
accordingly. The documentation for fitBounds was helpful for converting a bounding box to lat/long/zoom values.Solutions
Here are two approaches I see to solving this issue. Both require changes to ae-zoning-api
1. Add extend info to the existing capital project endpoint
We could add a field to the data returned by the existing
/capital-projects/:managing-code/:capital-project-id
endpoint containing the bounding box for the project expressed as[[number, number],[number, number]]
. We could use PostGIS' ST_Extent function to do the calculation in the database. We could then use this to updateviewstate
. Once the view state is updated to fit the entire project, the tiles will handle actually rendering it. This approach is relatively easy to implement but I have complicated feelings about it - mostly that it feels like we'd be adding a new field to an API for a pretty specific use case, which is a slippery slope if we're trying to build client-agnostic APIs. Also, having lat/lon arrays return in otherwise non-geospatial objects feels icky. We have a standards for sending geospatial data over the network: GeoJSON.2. Add an endpoint to return projects as geojson features
Similar to the approach we took in the PoC app, we could have another endpoint that return a single project as a geojson feature. The geometries for projects can be much more complex than tax lots, so we'd have to keep an eye on how much geojson we're sending over the wire. Once we have geojson of the full project on the front end, there are two ways we could use it:
GeojsonLayer
that takes in the geojson feature of the selected project. This might seem like an odd approach since we already have the projects on the map from the tiles but I think it does have some benefits. For one, because that new layer will only be as big as the individual feature, we can use it's bounds to update viewstate instead of calculating a bbox with something like turf.js (that's what the example for fitBounds does where you seelayer.getBounds()
). Another potential upside is that we could use this layer to render highlight the selected project instead of doing itgetFillColor
of the projects tile layer. The current approach rungetFillColor
for all rendered projects every time a new project is selected. Rendering the single selected project "on top" of the tiles might actually be a snappier experience for users.Next steps
I'm thinking we move forward with option two. If we do, the next step would be to create the new project geojson endpoint, including the corresponding updates to the openAPI yaml. The
properties
of the geojson feature would reuse the existingCapitalProjectBudgeted
schema. The geometry type would be dynamic based on the geom type for the given project.Beta Was this translation helpful? Give feedback.
All reactions