Git Product home page Git Product logo

d3-plugins's Introduction

D3 Plugins

These plugins are not compatible with the latest version of D3, V4. For the latest versions, see:

Please note: the plugins in this repository will soon be broken up into separate repositories for easier distributed ownership. If you have a new plugin you’d like to share, please add a link to it from the D3 plugins wiki.

d3-plugins's People

Contributors

biovisualize avatar danse avatar hongtaobai avatar jasondavies avatar larskotthoff avatar mbostock avatar nmalkin avatar nsipplswezey avatar reidab avatar richmorin avatar saurfang avatar skokenes avatar syntagmatic avatar tmcw avatar zjonsson avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

d3-plugins's Issues

d3.geo.rotate

A public API for invoking d3.geo.rotate directly. Takes as input GeoJSON, returns rotated GeoJSON. The rotated GeoJSON may be split or rejoined to account for the antemeridian (and ideally the poles). For example, a Polygon might be converted into a MultiPolygon.

d3.simplify erases feature.properties, feature.id

I think returning new features (rather than simplifying in place) is still the right thing, but it would be great if d3.simplify returned features exactly as given, except for the simplified geometry.

Right now simplifyFeature creates a new Feature. At the very least it should copy the GeoJSON properties (deep copy?), but the given feature may also have it's own keys e.g. id that it would be nice to preserve as well.

Transverse Mercator

It would be nice to have a transverse Mercator projection with the 90° rotation built-in. That way, you can easily use a transverse Mercator without needing to also apply a 90° rotation to the rendered result. Should be a pretty simple transformation of d3.geo.mercator.raw.

interpolateZoom returns NaN

Certain values cause interpolateZoom to return NaN:

var f = d3.interpolateZoom([6317.937500000001,9242.5,2790.2034898924603], [6317.9375,9242.5,5945.00368923611 ]);
f(1)
[NaN, NaN, NaN]

This is tricky to handle as attrTween('transform', ...) would normally expect at least something valid.

d3.geo.interpolatedProjection

I wonder if this is worth adding:

d3.geo.interpolatedProjection = function(a, b) {
  var projection = d3.geo.projection(raw).scale(1),
      center = projection.center,
      translate = projection.translate,
      α;

  function raw(λ, φ) {
    var pa = a([λ *= 180 / Math.PI, φ *= 180 / Math.PI]), pb = b([λ, φ]);
    return [(1 - α) * pa[0] + α * pb[0], (α - 1) * pa[1] - α * pb[1]];
  }

  projection.alpha = function(_) {
    if (!arguments.length) return α;
    α = +_;
    var ca = a.center(), cb = b.center(),
        ta = a.translate(), tb = b.translate();
    center([(1 - α) * ca[0] + α * cb[0], (1 - α) * ca[1] + α * cb[1]]);
    translate([(1 - α) * ta[0] + α * tb[0], (1 - α) * ta[1] + α * tb[1]]);
    return projection;
  };

  delete projection.scale;
  delete projection.translate;
  delete projection.center;
  return projection.alpha(0);
};

Taken from http://bl.ocks.org/mbostock/5731632

d3.geo.graticule code missing

The current documentation would suggest that the graticule code should be in the geo/projection directory, and even the README.md file in this directory has something about the graticule code. There is no graticule code in the geo/projection/projection.js file, nor in any file in the d3-plugins tree.

Unit projection implementation functions should be immutable.

It might be cleaner (I'd like to try and see) if the projection implementation functions were all immutable. This is already the case for the non-configurable projections such as winkel3 and wagner6. However projections such as cylindricalEqualArea and conicConformal take configurable parallels to change their behavior.

So rather than each projection defining its own parallel or parallels method, I was thinking a projection could be implemented like so:

function bonne(φ0) {
  var cotφ0 = 1 / Math.tan(φ0);
  return function(λ, φ) {
    var ρ = cotφ0 + φ0 - φ,
        E = λ * Math.cos(φ) / ρ;
    return [
      ρ * Math.sin(E),
      cotφ0 - ρ * Math.cos(E)
    ];
  };
}

Then to make a usable projection, you would say:

function singleParallelProjection(projectAt) {
  var φ0 = 0,
      project = newProject(φ0),
      p = projection(function(λ, φ) { return project(λ, φ); });

  p.parallel = function(_) {
    if (!arguments.length) return φ0 / π * 180;
    project = projectAt(φ0 = _ * π / 180);
    return p;
  };

  return p;
}

This should simplify the projection implementations slightly, and also make it easier to support copying a projection because the projection implementation is immutable. (Having a projection.copy function would make it easier to do enter and exit with changing projections.)

/cc @jasondavies

Need a better identity projection.

e.g., for d3.simplify:

var path = d3.geo.path()
    .projection({
  polygon: function(polygon, context) {
    polygon.forEach(function(ring) {
      var n = ring.length,
          i = 0,
          point;
      context.moveTo((point = ring[0])[0], point[1]);
      while (++i < n) context.lineTo((point = ring[i])[0], point[1]);
      context.closePath();
    });
  }
});

Related: it should be possible to use d3.simplify and output latitude & longitude.

Missing inverse projections.

I know some of these are difficult to compute (requiring Newton’s method, say), but I thought it would be worthwhile to track. Here are the projections that are missing an inverse:

  • aitoff
  • albersUsa (from core; see d3/d3#1096)
  • armadillo (incomplete)
  • august
  • baker
  • berghaus
  • boggs
  • craig
  • eisenlohr
  • gringorten
  • guyou
  • hammerRetroazimuthal
  • healpix
  • homolosine
  • lagrange
  • laskowski
  • littrow
  • peirceQuincuncial
  • polyconic
  • rectangularPolyconic
  • robinson
  • sinuMollweide
  • vanDerGrinten2
  • vanDerGrinten3
  • vanDerGrinten4
  • wiechel
  • winkel3

I can immediately add inverses for sinuMollweide and homolosine since those are fairly easy and also common projections. After that, next on my list would probably be robinson, winkel3 and aitoff. I know robinson & winkel3 require numeric integration, though.

Optimize d3.geo.projection implementations.

When the implementations are mature, we should probably take another pass over them and see if we can optimize anything (for example, pulling out constants such as 2 / 3 * π). This makes the code less readable but it could be worth doing since projections are often in the inner loop.

projection compilation documentation

I would like to just use the robinson geo projection. Can you provide documentation on how to use the make-file to produce a usable projections file containing only the projects I need?

d3.geo.tile should actually do geo stuff

d3.geo.tile holds promise, but right now it's seriously lacking for all but demo maps because there's no built-in support for working with geographic coordinates. E.g.:

var tile = d3.geo.tile()
  .center([-76.3429, 38.7351]) // geographic center
  .zoom(12); // in tile coordinates

Are there plans to support this? I'm wondering aloud if @tmcw, @migurski, or @RandomEtc might be working on this already.

Sankey: Besides circular references, are there other forbidden combinations?

Why does the json make Chrome crash? How can I avoid crashes?

var nodes = [
{"name":"Depósito"},
{"name":"Gas-Oil"},
{"name":"Cisterna"},
{"name":"020600 Pestillo Correa BR"},
{"name":"En uso por personal"},
{"name":"010030 Correa SRZ-120 100"},
{"name":"CC Maquinarias"},
{"name":"028710 Carro Desplaz"},
{"name":"018060 Grupilla"},
{"name":"Electric Light"},
{"name":"Picadora de carne"},
{"name":"Carni"},
{"name":"Balanza para carnes"},
{"name":"Botines de Seguridad"},
{"name":"En uso por personal"},
{"name":"Anteojos de seguridad"},
{"name":"Cono de seguridad vial"}];
var links = [
{"source":0,"target":1,"value":2.0},
{"source":1,"target":2,"value":2.0},
{"source":4,"target":3,"value":12.0},
{"source":3,"target":0,"value":12.0},
{"source":0,"target":5,"value":1.0},
{"source":5,"target":6,"value":1.0},
{"source":0,"target":3,"value":2.0},
{"source":3,"target":6,"value":2.0},
{"source":0,"target":7,"value":3.0},
{"source":7,"target":6,"value":3.0},
{"source":9,"target":8,"value":8.0},
{"source":8,"target":0,"value":100.0},
{"source":11,"target":10,"value":1.0},
{"source":10,"target":0,"value":1.0},
{"source":11,"target":12,"value":2.0},
{"source":12,"target":0,"value":2.0},
{"source":0,"target":13,"value":1.0},
{"source":13,"target":14,"value":1.0},
{"source":0,"target":15,"value":1.0},
{"source":15,"target":14,"value":1.0},
{"source":0,"target":16,"value":2.0},
{"source":16,"target":14,"value":2.0}];

Interrupted projections

It would be nice to provide a set of standard interruptions e.g. avoiding the oceans or avoiding continents, as well as making it easy to define arbitrary interruptions.

I think d3.geo.graticule could support interruptions better. Here's a simple example of interrupting the sinusoidal projection: http://bl.ocks.org/3737384. You can see that I had to use two graticule instances, with the second beginning at 1e-9° longitude. It would be nice to just use a single graticule instance here.

Geographic transformations prior to 2D projection

This question came up when attempting to rewrite d3.geo.gilbert. Gilbert’s “projection” is really a conformal transformation of the sphere onto a hemisphere, which can then be projected using any projection, most commonly the orthographic projection.

Similarly, we have the concept of an “auxiliary sphere”, implemented in #54 and mentioned in d3/d3#1293, which transforms coordinates from a given ellipsoidal datum to a sphere, while preserving a given property (area, angles, etc.)

Mike suggested making d3.geo.gilbert into a constructor taking a raw projection function, defaulting to d3.geo.orthographic.raw. However, this would exclude more exotic projections, which have custom streams not created by d3.geo.projection(raw). In other words, a map projection is fully defined not only by a point-wise function, but its (clip) stream, too.

Moreover, the auxiliary sphere branch makes me think that we should have a way to perform arbitrary geographic transformations (that is, in “unprojected” coordinates) prior to projection.

I think this would have to be supported by d3.geo.projection itself so that projection.center takes coordinates in the source datum, which are then transformed to the projection datum. Originally I was thinking of adding d3.geo.projection.auxiliary as discussed in d3/d3#1293, but perhaps the name “auxiliary” is too restrictive?

Either way, something like d3.geo.orthographic().auxiliary(gilbert) is a potential solution.

Integrate geo-projection back into D3 core.

Required items:

  • Added generic projection.origin.
  • Renamed d3.geo.albersEqualArea to d3.geo.albers.
  • Backwards-compatibility for azimuthal.mode (using orthographic, stereographic, etc.).
  • Set default scales appropriate for 960×500? Or at least backwards-compatible.

Nice-to-have:

  • Clip support in d3.geo.path.
  • d3.geo.rotate
  • d3.geo.clip
  • More projection tests.

Well-known projection definitions.

It would be handy to have an easy way to lookup GIS-style projection definitions. For example, EPSG:2163 could map to:

d3.geo.azimuthalEqualArea().rotate([100, -45])

while ESRI:102003 would map to

d3.geo.albers().rotate([-96, 0]).center([0, 37.5]).parallels([29.5, 45.5])

And likewise maybe even support for parsing Proj4-style projection definitions of the form

+proj=aea +lat_1=29.5 +lat_2=45.5 +lat_0=37.5 +lon_0=-96 +x_0=0 +y_0=0

d3.simplify should provide access to edge data

Topological simplification is awesome, but what would make it even more awesome is access to the topological edge data with references back to the features that contain them. I've been trying to figure out how to get a data structure like this out of it:

[
  // this edge borders two features
  {
    "features": [
      <feature>,
      <feature>
    ],
    "coordinates": [...]
  }
  // other edges
]

Which would pave a very clear path to building interactive cartograms, as well as building visualizations of the algorithm itself that could highlight individual edges.

My first attempt involved setting a "topology" property on the feature object inside simplify.project() to export the current state of all the algorithm, like so:

feature.topology = {
  idByPoint: idByPoint,
  idByRings: idByRings,
  ringsByPoint: ringsByPoint,
  sharedPoints: sharedPoints,
  isShared: isShared,
  lastRingByPoint: lastRingByPoint,
  graph: graph
};

I thought that by iterating over each of the features in a collection, then each of their rings, I could then look up each point in idByPoint and group the points by their edge id within each feature. What I end up with, though, is an incomplete list of points for each edge and some bad connections between them.

Ideally the simplify API would expose a method to get the edges:

var edges = simplify.edges(feature);

But I'm not sure how this would work, because simplify.project() unsets all of the state variables, and I'm not even sure if the state variables that I'm tracking contain the information necessary to build that structure by the time simplify.project() is finished.

Can somebody point me in the right direction?

sankey.js trys to access global variable

in line 130, it seems to access global variable "width"
It works in the example but it might cause errors in other cases.

I suggest to change it to "size[0]"

Thanks

Displaying dropouts at nodes

I'm using Sankey and it is great!

I do however need to display the dropouts at each node.
For example, if there is an inbound link with a value of 100 and an outbound link with a value of 75,
I need to display a 25 dropout (like in Google's Multi-Channel Funnel).

Any thought on how this can be done?

Prevent bullet charts from reordering measures?

I'm using bullet charts for monitoring solar production:

unbenannt

While one measure denotes today's performance, the other shows yesterday.

Unfortunately, bullet.js reoders the measures. Once today > yesterday, the colors in the chart get swapped. Instead I'd need yesterday to be hidden below today.

I've looked at preventing the sorting in bullet.js but unsuccessfully. Any ideas how to make this possible with bullet.js?

This json makes all explorer crash with sankey module

Using the exact same code as the example http://bost.ocks.org/mike/sankey/, it work fine on my computer.
However, when i just change the json link to point to the above json that has the same structure it makes all types of explorer crash. The force layout renders this graph perfectly so I don't see where the problem is.

{"nodes": [
{"name": "United-Kingdom"},
{"name": "Lithuania"},
{"name": "France"},
{"name": "Italia"},
{"name": "Slovakia"},
{"name": "Ireland"},
{"name": "Norway"},
{"name": "Slovenia"},
{"name": "Germany"},
{"name": "Belgium"},
{"name": "Spain"},
{"name": "Ukraine"},
{"name": "Netherlands"},
{"name": "Bosnia"},
{"name": "Denmark"},
{"name": "Poland"},
{"name": "Finland"},
{"name": "Macedonia"},
{"name": "Sweden"},
{"name": "Latvia"},
{"name": "Czech-Republic"},
{"name": "Hungary"},
{"name": "Swiss"},
{"name": "Bulgaria"},
{"name": "Romania"},
{"name": "Albania"},
{"name": "Portugal"},
{"name": "Estonia"},
{"name": "Serbia"},
{"name": "Austria"},
{"name": "Greece"},
{"name": "Croatia"}],
"links": [
{"source": 0, "target": 12, "value": 0.0},
{"source": 0, "target": 5, "value": 394.27152014652034},
{"source": 0, "target": 2, "value": 1710.389120879121},
{"source": 1, "target": 19, "value": 562.4308424908422},
{"source": 2, "target": 22, "value": 3060.7918864468857},
{"source": 2, "target": 3, "value": 2994.6647161172173},
{"source": 2, "target": 9, "value": 1689.7085164835162},
{"source": 2, "target": 8, "value": 4572.282133699634},
{"source": 2, "target": 10, "value": 1270.9172527472526},
{"source": 3, "target": 22, "value": 5728.591043956041},
{"source": 3, "target": 7, "value": 1081.7596245421255},
{"source": 3, "target": 29, "value": 240.58763736263728},
{"source": 3, "target": 30, "value": 452.9039926739924},
{"source": 4, "target": 21, "value": 1857.8078296703286},
{"source": 4, "target": 15, "value": 703.173772893773},
{"source": 4, "target": 20, "value": 1562.1682783882788},
{"source": 6, "target": 14, "value": 1117.9031593406592},
{"source": 6, "target": 12, "value": 604.1978663003666},
{"source": 6, "target": 16, "value": 37.00898351648352},
{"source": 6, "target": 6, "value": 71.36014652014653},
{"source": 6, "target": 18, "value": 136.60347985347985},
{"source": 7, "target": 29, "value": 598.8780402930406},
{"source": 7, "target": 31, "value": 642.6279761904757},
{"source": 8, "target": 12, "value": 1715.58423992674},
{"source": 8, "target": 14, "value": 755.765723443224},
{"source": 8, "target": 15, "value": 1227.313434065934},
{"source": 8, "target": 18, "value": 167.16668498168497},
{"source": 8, "target": 29, "value": 1797.8848351648357},
{"source": 8, "target": 20, "value": 1778.5800549450541},
{"source": 8, "target": 22, "value": 2771.7167673992694},
{"source": 9, "target": 12, "value": 1900.7907600732606},
{"source": 10, "target": 26, "value": 1371.0025366300367},
{"source": 11, "target": 21, "value": 833.2233791208791},
{"source": 11, "target": 24, "value": 357.0193131868132},
{"source": 13, "target": 31, "value": 627.9329212454212},
{"source": 14, "target": 14, "value": 180.27889194139192},
{"source": 14, "target": 18, "value": 167.17994505494505},
{"source": 15, "target": 18, "value": 109.07065934065933},
{"source": 15, "target": 20, "value": 1706.4577472527467},
{"source": 16, "target": 18, "value": 305.363717948718},
{"source": 16, "target": 27, "value": 489.7703205128206},
{"source": 17, "target": 30, "value": 333.4131868131865},
{"source": 17, "target": 28, "value": 0.0},
{"source": 17, "target": 23, "value": 0.0},
{"source": 18, "target": 18, "value": 0.8676739926739928},
{"source": 19, "target": 27, "value": 579.218553113553},
{"source": 20, "target": 29, "value": 2266.835540293041},
{"source": 21, "target": 24, "value": 259.5148076923077},
{"source": 21, "target": 28, "value": 216.2569230769231},
{"source": 21, "target": 29, "value": 431.3127930402932},
{"source": 21, "target": 31, "value": 1405.1164102564105},
{"source": 22, "target": 29, "value": 1193.6274908424919},
{"source": 23, "target": 24, "value": 444.2263095238097},
{"source": 23, "target": 28, "value": 0.0},
{"source": 23, "target": 30, "value": 633.9733333333336},
{"source": 24, "target": 28, "value": 546.0507326007325},
{"source": 25, "target": 30, "value": 492.10853479853455},
{"source": 28, "target": 31, "value": 273.98855311355305}]}

d3.geo.gringorten needs an extra cut?

It appears the Gringorten projection requires an extra cut. The land stroke in the image below is dividing each hemisphere’s square in half vertically:

Screen Shot 2013-01-11 at 9 06 29 AM

This bug is low priority, but since I noticed, I thought I'd track it here.

d3.geo.clip

My new clipping code in the clip branch is a modified version of Weiler–Atherton that clips against a great circle. The great thing is that it can handle holes, and can also be modified further to clip against a great semicircle e.g. for the splitting required in #9.

However:

It can't handle self-intersecting polygons. Self-intersecting lines should be okay. Unfortunately, self-intersecting polygons can arise when using most line-simplification algorithms e.g. d3.simplify. It's possible to detect and "unsimplify" offending segments (I've made some headway with this via Bentley–Ottmann) but it's not quite there yet.

This is why examples like http://bl.ocks.org/3734168 break! It would be nice to break more gracefully.

Another related issue is that due to precision errors it very occasionally exhibits the above problem because two intersection points that are very close can become "swapped". This is more easily fixed by adjusting the sorting of intersection points to operate on small chunks to maintain the correct order. It's possible that this kind of solution could be used to work around self-intersections, although I'm not sure if the output would be correct in that case.

Both issues currently cause an error like "Uncaught TypeError: Cannot read property 'angle' of undefined". This is because there is a linked list that expect intersections to be in in-out order, and self-intersections (or precision errors) can break this assumption.

Tearing in Winkel Tripel on Firefox, iOS 6 Safari

I am seeing some tearing in some browsers using Winkel 3, apparently in places where geographic features wrap from the right side of the map to the left.

You can see this in action at: http://concept.newcitystaging.com/ccmap/

I've seen this in Firefox 16.0.2 and Safari on my iOS6 iPad.

The path data is from NaturalEarth, so it's a different data set than you are using in the Readme documentation.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.