So I'm experimenting a bit with D3's geo stream
API
, and things feel a bit hazy. I've been reading through the documentation here:
https://github.com/mbostock/d3/wiki/Geo-Streams
One point of confusion I have is the proper implementation of stream transforms. Let's say I create one:
//a stream transform that applies a simple translate [20,5]: var transform = d3.geo.transform({ point:function(){this.stream.point(x+20,y+5)} })
Per the documentation, this.stream references the "wrapped stream." But what is the stream, really? From what I can gather, it is more of a procedure than explicit data structure--a sequence of data and function calls to transform the data. The syntax above seems to suggest that the wrapped stream is simply the object containing "stream listeners"
Moving on, I'm able to apply the stream transform using the projection method:
//a path generator with the transform applied using the projection() method var path = d3.geo.path().projection(transform);
While I don't quite understand the underlying mechanics, the effect seems relatively straightforward: the underlying transform function of the path generator is called with transformed x,y
arguments.
For my use case, I don't find this that helpful, particularly because my input data is not already projected. I'd like to use a projection to transform the data first, then transform those outputted coordinates. To that end, is there a general pattern for layering transforms?
I see that D3
does provide the projection.stream(listener) pattern which applies the projecting transform first, before applying the listener, but I'm not sure how to implement this. What should the listener argument be? Here's an example: http://jsfiddle.net/kv7yn8rw/2/.
Any guidance would be greatly appreciated!
A key fact from the documentation is that "a geographic projection is one example of a stream transform."
Streams just allow one to transform (e.g. project) data multiple times without saving the intermediate data. A projection can just be an object with a stream attribute, e.g. proj_then_transform
below.
The way to chain streams is as follows:
// stream 1 var proj = d3.geo.equirectangular(); // stream 2 var transform = d3.geo.transform({ point:function(x,y){this.stream.point(x+20,y+5)} }); // stream 1 then stream 2 var proj_then_transform = { stream: function(s) { return proj.stream(transform.stream(s)); } };
I've updated the example with a working solution: http://jsfiddle.net/cvs5d7o9/2/
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With