gazetteerhk / census_explorer

Explore Hong Kong's neighborhoods through visualizations of census data
http://gazetteer.hk
MIT License
42 stars 12 forks source link

Frontend map directive and some services #21

Closed hxu closed 10 years ago

hxu commented 10 years ago

This branch implements a number of features. If anyone has time, please review and give comments. There are a few design decisions in here that I'm not so sure about (see bottom).

This fixes #5, #10, and #13.

Mappings Service

This services provides functions to go between Regions, Districts and Areas:

Note that all functions return promises. Not so sure about this design decision (see bottom for details). Also, going down the tree (Region -> district, district -> area) accepts a list of parents or string, and will returned the flattened set of children.

Internally, it stores a _data object, which has the list of all districts and regions initially, and is populated with the list of all areas.

GeoFiles Service

Handles the fetching and parsing of the district and area polygon files. I encoded the underlying json files as TopoJSON to save size (130kb vs. 4mb for the area polygons), so this requires an extra step with the topojson library, but this is handled by this service. Provides two functions:

This is a model that handles state when allowing users to add / remove areas from a selection. Basically only one function on this service:

Once you have an instance of the model (the AreaModel object), it has these methods on its prototype:

Internally, it stores the selection as the _selected object. We use an object instead of a list to have set-like functionality. When you give it districts or regions, it has to get the mappings from Mappings, so the model may not update immediately, since it has to wait for the Mappings promises to resolve.

hkMap Directive

This puts it all together and provides instances of a a Leaflet map with our GeoJSON layers overlayed. Use like this:

<hk-map 
  class="col-md-6"    # use the class to control width
  height="300px"   # Optional - use height to specify height in pixels - default is 300px
  map-center="centerObj"  # Optional - Can use this to link maps together.
  map-id="idString"  # Required if you have multiple maps, this is necessary to tell them apart internally
  selected-areas="AreaModelInstance">  # Optional, but recommended.  Uses this object to keep selection state
</hk-map>

Key features:

One current problem is that if you change the selection state from outside of the map, you have to emit a signal redrawMap in order for the map to update its layer styles.

See it in action at /#/map.

Easier conversion from HK1980 to WSG84

As it turns out, the ogr2ogr command line tool can easily convert from HK1980 to WSG84. See the convert_shapefiles.sh script for my notes on that. Basically if you know that HK1980 is commonly called EPSG:2326, then it's easy to convert.

I didn't go to the effort of making it an automated script, so you need to run these commands manually.

Miscellaneous

The full geo-tree.js is only 3kb uncompressed, so it actually wouldn't be so bad to just embed it in the code of the Mappings service. But I started out with as an asynchronous HTTP request, which means that you have to use lots of promises. Promises are OK, but it's a bit of potentially unnecessary complexity.

If you manipulate the selection state from outside of the hkMap directive (e.g. you add/remove selected areas not by clicking, but programatically), you have to remember to emit a signal to the hkMap directive.

I thought about making it a watch on the model object, but was afraid this would cause performance issues, because you have to loop through all the layers on the map to restyle them.

Anyone have any ideas?

Some of the larger districts, like Lantau and the Islands, don't always fit correctly when you zoom too far in, but you need to zoom in to choose individual areas. Maybe it's easier to just show the areas only?

Need a way to select a whole district at once, but not sure how to do this.

hxu commented 10 years ago

ping @hupili @vincentlaucy -- not sure if you guys see these automatically.

hupili commented 10 years ago

Just tested #/map and the zoom/selection works for me.

hxu commented 10 years ago

:+1: to merge then?

Before I merge, I think I'm going to in-line the geo-tree map. So while we'll have to load more on the front end, we won't have to deal with promise for that part of the functionality.

hupili commented 10 years ago

:+1: for merge. I can not make in depth review of this part but tested to work from an end user's point. It should serve as baseline for further development.