What is d3.geo.pipeline?

If you follow Mike Bostock's bl.ocks, you know that for the past 8 months d3.geo.pipeline () has been a frequent component of his projects.

But what does he do?

You can see that he set up the pipelines like this:

var sketch = d3.geo.pipeline()
      .source(d3.geo.jsonSource)
      .pipe(resample, .020)
      .pipe(jitter, .004)
      .pipe(smooth, .005)
      .sink(d3.geo.jsonSink);

      

through

The d3.geo wiki lacks documentation .

Some embellished JS in unreleased D3 used in the sample code show this feature:

lo.geo.pipeline = function() {
        var n = [];
        return {
            source: function() {
                return n[0] = arguments, this
            },
            pipe: function() {
                return n.push(arguments), this
            },
            sink: function() {
                for (var t, e = arguments[0].apply(null, [].slice.call(arguments, 1)), r = e; t = n.pop();) {
                    var u = [].slice.call(t, 1);
                    u.push(e), e = t[0].apply(null, u)
                }
                return function() {
                    return e.apply(this, arguments), r.value && r.value()
                }
            }
        }

      

It also appears in these bl.ocks:

+3


source to share


1 answer


I'm not familiar with d3.js

, but I looked at its source code and found that this feature is on a branch graphics-pipeline

.

For example you can find related code here: https://github.com/mbostock/d3/commit/a3f2adab7f85e2a0c82288ead88c1e484c9e3ea3


A small piece of code to illustrate how it works:

var pipeline = function () {
    var pipes = [];
    return {
        source: function () {
            pipes[0] = arguments;
            return this;
        },
        pipe: function () {
            pipes.push(arguments);
            return this;
        },
        sink: function () {
            var sink = arguments[0].apply(null, [].slice.call(arguments, 1)),
                pipe;

            while (pipe = pipes.pop()) {
                var args = [].slice.call(pipe, 1);
                args.push(sink);
                sink = pipe[0].apply(null, args);
            }

            return sink;
        }
    };
};

var log = document.getElementById('log');

function f() {
    var argsAsString = Array.prototype.join.call(arguments, ', ');
    var resultName = 'r' + f.callCounter++;

    log.innerHTML += resultName + ' = f(' + argsAsString + ')<br>';

    return resultName;
}

f.callCounter = 1;

pipeline().
    source(f, 'a', 1).
    pipe(f, 'b', 2).
    pipe(f, 'c', 3).
    sink(f, 'd', 4);
      

<div id="log"></div>
      

Run code


A few comments about this function:



  • Methods source

    and pipe

    work with the same private property pipes

    . The only difference is that it source

    sets the initial value for pipes

    ( pipes[0]

    ) when each call pipe

    pushes a new pipe into the collection.
  • The previous fact gives us knowledge about the internal structure d3.geo.jsonSource

    . It should be similar to the arguments passed to pipe

    : the first argument is something called (a function), the rest of the arguments are parameters.
  • Suppose that arguments = [f, a, b, c]

    . Then the JavaScript template arguments[0].apply(null, [].slice.call(arguments, 1))

    means f(a, b, c)

    . You can see several places where it is used in implementation sink

    .

With regard to practical use.

We can use it if we need a "chain" (or "pipe") of data processing. For example, if we have code like this:

function f(a, b, previousResult) 
{
    return a * b + (previousResult || 0);
}

var p = pipeline().
    source(f, 1, 1).
    pipe(f, 2, 10).
    pipe(f, 3, 100).
    sink(f, 4, 1000);

      

Then the result (value p

) will be 4321

.

In this particular case, we need to clarify what d3.geo.jsonSink

and is d3.geo.jsonSource

, but I hope I helped you see the meaning of the function pipeline

.

+2


source







All Articles