<?xml version="1.0" encoding="utf-8"?><feed xmlns="http://www.w3.org/2005/Atom" ><generator uri="https://jekyllrb.com/" version="3.8.5">Jekyll</generator><link href="http://emptypipes.org/feed.xml" rel="self" type="application/atom+xml" /><link href="http://emptypipes.org/" rel="alternate" type="text/html" /><updated>2019-05-07T01:13:11+00:00</updated><id>http://emptypipes.org/feed.xml</id><title type="html">Empty Pipes</title><subtitle>Blog / Website</subtitle><entry><title type="html">Selectable zoomable force directed graph in D3v4</title><link href="http://emptypipes.org/2017/04/29/d3v4-selectable-zoomable-force-directed-graph/" rel="alternate" type="text/html" title="Selectable zoomable force directed graph in D3v4" /><published>2017-04-29T00:00:00+00:00</published><updated>2017-04-29T00:00:00+00:00</updated><id>http://emptypipes.org/2017/04/29/d3v4-selectable-zoomable-force-directed-graph</id><content type="html" xml:base="http://emptypipes.org/2017/04/29/d3v4-selectable-zoomable-force-directed-graph/">&lt;p&gt;A &lt;a href=&quot;/2015/02/15/selectable-force-directed-graph/&quot;&gt;previous post&lt;/a&gt; described how
to use d3.js to create a force-directed graph we can zoom in to and select
nodes from. Such a tool is useful for displaying and arranging larger
networks. My colleagues and I personally used it to create &lt;a href=&quot;http://rna.tbi.univie.ac.at/forna/&quot;&gt;a small web
application for displaying RNA secondary
structure&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Since that post, a new version of D3 was released. D3 V4 introduced a lot of
useful new features (see &lt;a href=&quot;https://iros.github.io/d3-v4-whats-new/&quot;&gt;Irene Ros’s excellent overview of the differences
between v3 and v4&lt;/a&gt;). Unfortunately,
however, it did not maintain backward compatiblity with previous versions of
d3. This means that the &lt;a href=&quot;/2015/02/15/selectable-force-directed-graph/&quot;&gt;previous selectable zoomable force directed graph
example&lt;/a&gt; could not be used with
new code written with the latest version of the D3 library. Until now.&lt;/p&gt;

&lt;p&gt;As in the previous example, this graph provides the following selection
behavior:&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;Clicking on a node selects it and de-selects everything else.&lt;/li&gt;
  &lt;li&gt;Shift-clicking on a node toggles its selection status and leaves
all other nodes as they are.&lt;/li&gt;
  &lt;li&gt;Shift-dragging toggles the selection status of all nodes within
the selection area.&lt;/li&gt;
  &lt;li&gt;Dragging on a selected node drags all selected nodes.&lt;/li&gt;
  &lt;li&gt;Dragging an unselected node selects and drags it while
de-selecting everything else.&lt;/li&gt;
&lt;/ol&gt;

&lt;div align=&quot;center&quot; id=&quot;d3_selectable_force_directed_graph&quot; style=&quot;width: 400px; height: 300px; margin: auto; margin-bottom: 12px&quot;&gt;
    &lt;svg /&gt;
&lt;/div&gt;

&lt;p&gt;Upgrading the selectable zoomable force directed graph implementation to D3 v4
required a few minor and not-so-minor changes.&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;The new brush in v4 captures the shift, alt and meta keys to perform some
actions by default. To get around this, I forked &lt;code class=&quot;highlighter-rouge&quot;&gt;d3-brush&lt;/code&gt; and modified it
so that it doesn’t capture the shift events. The new version (d3-brush-lite)
can be found &lt;a href=&quot;https://github.com/pkerpedjiev/d3-brush-lite&quot;&gt;on github&lt;/a&gt;. There
is an &lt;a href=&quot;https://github.com/d3/d3-brush/issues/20&quot;&gt;open github issue&lt;/a&gt; to
disable this behavior in &lt;code class=&quot;highlighter-rouge&quot;&gt;d3-brush&lt;/code&gt;.&lt;/li&gt;
  &lt;li&gt;Because the d3-drag behavior consumes all events in v4, it is no longer
necessary to stop propagation.&lt;/li&gt;
  &lt;li&gt;The brush creates its own overlay which catches all events meaning that we
don’t need to turn the zoom behavior off when the shift key is pressed.&lt;/li&gt;
  &lt;li&gt;Whether a node is fixed is specified by the &lt;code class=&quot;highlighter-rouge&quot;&gt;.fx&lt;/code&gt; and &lt;code class=&quot;highlighter-rouge&quot;&gt;.fy&lt;/code&gt; parameters. This
eliminates the need to set the &lt;code class=&quot;highlighter-rouge&quot;&gt;.fixed&lt;/code&gt; parameter on each node.&lt;/li&gt;
  &lt;li&gt;The force layout in v4 lets us specify an &lt;a href=&quot;https://github.com/d3/d3-force#link_id&quot;&gt;accessor for the nodes that a link
connects&lt;/a&gt;. This lets us use ids for 
a link’s endpoint and makes the graph specification JSON easier to read:&lt;/li&gt;
&lt;/ul&gt;

&lt;div class=&quot;language-json highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
  &lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;nodes&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
    &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;id&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;Myriel&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;group&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;},&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
    &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;id&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;Napoleon&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;group&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;},&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
    &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;id&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;Mlle.Baptistine&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;group&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;},&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
    &lt;/span&gt;&lt;span class=&quot;err&quot;&gt;...&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
  &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;],&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
  &lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;links&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
    &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;source&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;Napoleon&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;target&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;Myriel&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;value&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;},&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
    &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;source&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;Mlle.Baptistine&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;target&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;Myriel&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;value&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;8&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;},&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
    &lt;/span&gt;&lt;span class=&quot;err&quot;&gt;...&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
  &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;The source code for this example can be found as &lt;a href=&quot;https://gist.github.com/pkerpedjiev/f2e6ebb2532dae603de13f0606563f5b&quot;&gt;a github
gist&lt;/a&gt; or
&lt;a href=&quot;https://bl.ocks.org/pkerpedjiev/f2e6ebb2532dae603de13f0606563f5b&quot;&gt;on
bl.ocks.org&lt;/a&gt;.&lt;/p&gt;

&lt;link rel=&quot;stylesheet&quot; href=&quot;/css/d3v4-selectable-zoomable-force-directed-graph.css&quot; /&gt;

&lt;script type=&quot;text/javascript&quot;&gt;
    var d3v3 = d3;
    d3 = d3v4;
    // load the lite brush into the d3v4 namespace
&lt;/script&gt;

&lt;script src=&quot;/js/d3v4-brush-lite.js&quot;&gt;&lt;/script&gt;

&lt;script type=&quot;text/javascript&quot;&gt;
    // restore the v3 namespace
    var d3 = d3v3;
&lt;/script&gt;

&lt;script src=&quot;/js/d3v4-selectable-force-directed-graph.js&quot;&gt;&lt;/script&gt;

&lt;script&gt;
    var svg = d3.select('#d3_selectable_force_directed_graph');

    d3.json('/jsons/miserables.with-ids.json', function(error, graph) {
        if (!error) {
            //console.log('graph', graph);
            createV4SelectableForceDirectedGraph(svg, graph);
        } else {
            console.error(error);
        }
    });
&lt;/script&gt;</content><author><name></name></author><category term="javascript" /><category term="d3.js" /><category term="d3v4.js" /><summary type="html">A previous post described how to use d3.js to create a force-directed graph we can zoom in to and select nodes from. Such a tool is useful for displaying and arranging larger networks. My colleagues and I personally used it to create a small web application for displaying RNA secondary structure.</summary></entry><entry><title type="html">D3v4 event filtering example</title><link href="http://emptypipes.org/2017/04/18/d3-event-filtering/" rel="alternate" type="text/html" title="D3v4 event filtering example" /><published>2017-04-18T00:00:00+00:00</published><updated>2017-04-18T00:00:00+00:00</updated><id>http://emptypipes.org/2017/04/18/d3-event-filtering</id><content type="html" xml:base="http://emptypipes.org/2017/04/18/d3-event-filtering/">&lt;link rel=&quot;stylesheet&quot; href=&quot;/css/d3-event-filtering.css&quot; /&gt;

&lt;script src=&quot;/js/d3-event-filtering-example.js&quot;&gt;&lt;/script&gt;

&lt;p&gt;D3 behaviors, such as &lt;code class=&quot;highlighter-rouge&quot;&gt;d3.zoom&lt;/code&gt;, work by responding to events which pass
through the element on which they are called. If the element has children, the
behavior will be called as long as the children don’t block events’
propagation. This is often beneficial. If we want to be able to zoom on a
populated SVG, we need only call the zoom behavior on the root node and we’ll
be able to pan and zoom even if we drag and scroll on the child elements.&lt;/p&gt;

&lt;p&gt;There are times, however, when we may want to ignore certain elements without
having the block the propagation of the event. For this, there is event
filtering. By filtering events, we can let them pass through without having to
block or process them. This can be seen in the example below where dragging
the background leads to panning, while dragging the circles has no effect.&lt;/p&gt;

&lt;div id=&quot;event-filtering-div&quot; style=&quot;width: 400px; margin: auto; margin-bottom: 10px&quot;&gt;&lt;/div&gt;

&lt;p&gt;The crux of the code for this example is a simple check to see that handled
events have not passed though an element with a &lt;code class=&quot;highlighter-rouge&quot;&gt;no-zoom&lt;/code&gt; class.&lt;/p&gt;

&lt;div class=&quot;language-javascript highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;kd&quot;&gt;var&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;zoom&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;d3v4&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;zoom&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;filter&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(()&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;!&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;d3v4&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;event&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;path&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;].&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;classList&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;contains&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;'no-zoom'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;})&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;on&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;'zoom'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;kd&quot;&gt;function&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;d&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;g&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;attr&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;'transform'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;d3v4&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;event&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;transform&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;A bl.ock of this example can be found &lt;a href=&quot;https://bl.ocks.org/pkerpedjiev/32b11b37be444082762443c4030d145d&quot;&gt;here&lt;/a&gt;.&lt;/p&gt;

&lt;script&gt;
    zoomFiltering('#event-filtering-div');
&lt;/script&gt;</content><author><name></name></author><category term="javascript" /><category term="d3.js" /><summary type="html"></summary></entry><entry><title type="html">Fast ES6 Development Using webpack-dev-server</title><link href="http://emptypipes.org/2016/12/06/webpack-dev-server/" rel="alternate" type="text/html" title="Fast ES6 Development Using webpack-dev-server" /><published>2016-12-06T00:00:00+00:00</published><updated>2016-12-06T00:00:00+00:00</updated><id>http://emptypipes.org/2016/12/06/webpack-dev-server</id><content type="html" xml:base="http://emptypipes.org/2016/12/06/webpack-dev-server/">&lt;h4 id=&quot;summary&quot;&gt;Summary&lt;/h4&gt;

&lt;p&gt;&lt;i&gt;Switching from &lt;code class=&quot;highlighter-rouge&quot;&gt;gulp&lt;/code&gt; and &lt;code class=&quot;highlighter-rouge&quot;&gt;webpack-stream&lt;/code&gt; to &lt;code class=&quot;highlighter-rouge&quot;&gt;webpack-dev-server&lt;/code&gt; reduces
the rebuild time for a 5500-line javascript project from ~11s to ~1.3 seconds.&lt;/i&gt;&lt;/p&gt;

&lt;h4 id=&quot;details&quot;&gt;Details&lt;/h4&gt;

&lt;p&gt;Whenever I create a javascript project, I do it using a very uniform directory
structure and configuration, as outlined in a previous &lt;a href=&quot;http://emptypipes.org/2016/03/02/es6-module/&quot;&gt;blog
post&lt;/a&gt;. With this configuration,
all the source files are transpiled using &lt;code class=&quot;highlighter-rouge&quot;&gt;babel&lt;/code&gt; and bundled using the
&lt;code class=&quot;highlighter-rouge&quot;&gt;webpack-stream&lt;/code&gt; module as part of a step in the build process managed by
&lt;code class=&quot;highlighter-rouge&quot;&gt;gulp&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;This is great because then I can run &lt;code class=&quot;highlighter-rouge&quot;&gt;gulp serve&lt;/code&gt; and have it recompile and
reload the resulting web page whenever I make any changes to the source code in
&lt;code class=&quot;highlighter-rouge&quot;&gt;app/scripts&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;This works like a charm until the source code and dependencies get to any
appreciable size. As more and more files need to be transpiled, the process
gets slower and slower until at about ~10 seconds, it starts to get annoying:&lt;/p&gt;

&lt;div class=&quot;language-shell highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;o&quot;&gt;[&lt;/span&gt;BS] 3 files changed &lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;main.js, playground.js, worker.js&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;o&quot;&gt;[&lt;/span&gt;08:31:20] Finished &lt;span class=&quot;s1&quot;&gt;'scripts'&lt;/span&gt; after 11 s
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;So how can this be sped up? Easy, stop using gulp and webpack-stream and
switch to the…&lt;/p&gt;

&lt;h5 id=&quot;webpack-dev-server&quot;&gt;&lt;a href=&quot;https://webpack.github.io/docs/webpack-dev-server.html&quot;&gt;Webpack dev server&lt;/a&gt;&lt;/h5&gt;

&lt;p&gt;The webpack dev server runs in its own terminal and watches the source files
listed in its config file (&lt;code class=&quot;highlighter-rouge&quot;&gt;webpack.config.js&lt;/code&gt;). When one of the files changes, it
recreates the output files specified in its config and reloads the web page. I
run it using the following command line:&lt;/p&gt;

&lt;div class=&quot;language-shell highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;webpack-dev-server &lt;span class=&quot;nt&quot;&gt;--content-base&lt;/span&gt; app &lt;span class=&quot;nt&quot;&gt;--display-exclude&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;--profile&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;--inline&lt;/span&gt; | &lt;span class=&quot;nb&quot;&gt;grep&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-v&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;se&quot;&gt;\\&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;se&quot;&gt;\\&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;d&lt;/span&gt;&lt;span class=&quot;se&quot;&gt;\*\\&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;]&quot;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;The grep at the end is to filter out some of the [overly] verbose output that webpack
produces. So how long does it take to regenerate the code when a source file is changed?&lt;/p&gt;

&lt;div class=&quot;language-shell highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;Version: webpack 1.12.15
Time: 1296ms
chunk    &lt;span class=&quot;o&quot;&gt;{&lt;/span&gt;0&lt;span class=&quot;o&quot;&gt;}&lt;/span&gt; main.js &lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;main&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt; 4.61 MB
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;This is about 10x faster than the configuration using gulp and webpack-stream.&lt;/p&gt;

&lt;p&gt;The resulting web page can be found at
&lt;code class=&quot;highlighter-rouge&quot;&gt;http://localhost:8080/index.html&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;The only thing I needed
to change in my &lt;code class=&quot;highlighter-rouge&quot;&gt;webpack.config.js&lt;/code&gt; file was to add &lt;code class=&quot;highlighter-rouge&quot;&gt;output: { publicPath:
'/scripts/'}&lt;/code&gt;.  This is because my &lt;code class=&quot;highlighter-rouge&quot;&gt;index.html&lt;/code&gt; file loads the compiled scripts
from the &lt;code class=&quot;highlighter-rouge&quot;&gt;scripts&lt;/code&gt; directory:&lt;/p&gt;

&lt;div class=&quot;language-html highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;nt&quot;&gt;&amp;lt;script &lt;/span&gt;&lt;span class=&quot;na&quot;&gt;src=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;'scripts/playground.js'&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;&amp;gt;&amp;lt;/script&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Below is the entire &lt;code class=&quot;highlighter-rouge&quot;&gt;webpack.config.js&lt;/code&gt; for this project. Notice that there’s
multiple different targets being built including a worker script that can be
used in a web worker to do compute intensive tasks off of the main UI thread.&lt;/p&gt;

&lt;p&gt;Other notable sights include the &lt;code class=&quot;highlighter-rouge&quot;&gt;devtool: &quot;cheap-source-map&quot;&lt;/code&gt; entry to make sure
we can easily see the source code when debugging.&lt;/p&gt;

&lt;div class=&quot;language-javascript highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;kd&quot;&gt;var&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;path&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;require&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;'path'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
&lt;span class=&quot;kd&quot;&gt;var&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;webpack&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;require&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;'webpack'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;

&lt;span class=&quot;nx&quot;&gt;module&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;exports&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;na&quot;&gt;context&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;__dirname&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;'/app'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
  &lt;span class=&quot;na&quot;&gt;entry&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
      &lt;span class=&quot;na&quot;&gt;playground&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;'./scripts/playground.jsx'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;],&lt;/span&gt;
      &lt;span class=&quot;na&quot;&gt;main&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;'./scripts/main.jsx'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;],&lt;/span&gt;
      &lt;span class=&quot;na&quot;&gt;worker&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;'./scripts/worker.js'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;
  &lt;span class=&quot;p&quot;&gt;},&lt;/span&gt;
  &lt;span class=&quot;na&quot;&gt;devtool&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;cheap-source-map&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
  &lt;span class=&quot;na&quot;&gt;output&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;na&quot;&gt;path&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;__dirname&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;'/build'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;na&quot;&gt;publicPath&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;'/scripts/'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;na&quot;&gt;filename&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;'[name].js'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;na&quot;&gt;libraryTarget&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;'umd'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;na&quot;&gt;library&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;'[name]'&lt;/span&gt;
  &lt;span class=&quot;p&quot;&gt;},&lt;/span&gt;
  &lt;span class=&quot;na&quot;&gt;module&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;na&quot;&gt;loaders&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;
      &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;na&quot;&gt;test&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;sr&quot;&gt;/&lt;/span&gt;&lt;span class=&quot;se&quot;&gt;\.&lt;/span&gt;&lt;span class=&quot;sr&quot;&gt;jsx&lt;/span&gt;&lt;span class=&quot;se&quot;&gt;?&lt;/span&gt;&lt;span class=&quot;sr&quot;&gt;$/&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;c1&quot;&gt;//exclude: /node_modules/,&lt;/span&gt;
        &lt;span class=&quot;na&quot;&gt;include&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;path&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;resolve&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;__dirname&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;'app/scripts'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)],&lt;/span&gt;
        &lt;span class=&quot;na&quot;&gt;loader&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;'babel-loader'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;na&quot;&gt;query&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
          &lt;span class=&quot;na&quot;&gt;presets&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;'es2015'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;'react'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;
        &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
      &lt;span class=&quot;p&quot;&gt;},&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;na&quot;&gt;test&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;sr&quot;&gt;/&lt;/span&gt;&lt;span class=&quot;se&quot;&gt;\.&lt;/span&gt;&lt;span class=&quot;sr&quot;&gt;css$/&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;na&quot;&gt;loader&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;'style!css'&lt;/span&gt;
      &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;],&lt;/span&gt;
    &lt;span class=&quot;na&quot;&gt;postLoaders&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;
        &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
            &lt;span class=&quot;na&quot;&gt;include&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;path&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;resolve&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;__dirname&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;'node_modules/pixi.js'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;),&lt;/span&gt;
            &lt;span class=&quot;na&quot;&gt;loader&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;'transform?brfs'&lt;/span&gt;
        &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;],&lt;/span&gt;
    &lt;span class=&quot;na&quot;&gt;externals&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;

               &lt;span class=&quot;p&quot;&gt;},&lt;/span&gt;
    &lt;span class=&quot;na&quot;&gt;resolve&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
      &lt;span class=&quot;na&quot;&gt;extensions&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;'.js'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;'.jsx'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
  &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;};&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;</content><author><name></name></author><category term="javascript" /><category term="es6" /><summary type="html">Summary</summary></entry><entry><title type="html">Cambridge Tree Map</title><link href="http://emptypipes.org/2016/11/16/cambridge-tree-map/" rel="alternate" type="text/html" title="Cambridge Tree Map" /><published>2016-11-16T00:00:00+00:00</published><updated>2016-11-16T00:00:00+00:00</updated><id>http://emptypipes.org/2016/11/16/cambridge-tree-map</id><content type="html" xml:base="http://emptypipes.org/2016/11/16/cambridge-tree-map/">&lt;link rel=&quot;stylesheet&quot; href=&quot;/css/cambridge-tree-map.css&quot; /&gt;

&lt;script src=&quot;/js/cambridge-tree-map.js&quot;&gt;&lt;/script&gt;

&lt;script src=&quot;/js/lib/topojson.v1.min.js&quot;&gt;&lt;/script&gt;

&lt;p&gt;The city of Cambridge, MA maintains a wealth of geographic information on &lt;a href=&quot;https://www.cambridgema.gov/GIS/&quot;&gt;its
GIS website&lt;/a&gt;. One of the more unconvential
datasets is the &lt;a href=&quot;https://www.cambridgema.gov/GIS/gisdatadictionary/Environmental/ENVIRONMENTAL_StreetTrees&quot;&gt;list of
trees&lt;/a&gt;
lining the streets of the city. It contains the position and species of around
30 thousand trees and can be explored using the &lt;a href=&quot;https://gis.cambridgema.gov/dpw/trees/trees_walk.html&quot;&gt;Cambridge Tree
Walk&lt;/a&gt;) application.
While this app is incredily detailed and useful at high resolution, it loses
all information at low resolution. The identities and positions of the trees
are lost. And if they weren’t they would be too dense to display in a
meaningful and intelligible manner.&lt;/p&gt;

&lt;p&gt;To provide a different view, I calculated which tree species is most common on
each block in Cambridge and plotted the results using D3.js. The analysis shows
that Maple trees dominate the landscape in Cambridge. Further down the list are
Oaks, Lindens and Pears. While these are the most common trees on most street
blocks in Cambridge, there are a few which are dominated by less common species.
This isn’t to say that those species are only found on those blocks, just that
those are the only blocks where those species are in the majority.&lt;/p&gt;
&lt;hr /&gt;

&lt;div id=&quot;cambridge-tree-map&quot;&gt;&lt;/div&gt;

&lt;hr /&gt;

&lt;p&gt;How useful is this map? I don’t know. But it was fun to make and will hopefully
serve as a decent example for introducing how D3.js can be used for cartography
at &lt;a href=&quot;http://www.meetup.com/Maptime-Boston/&quot;&gt;Maptime Boston&lt;/a&gt;.  A tutorial
describing how this map is made is available on the &lt;a href=&quot;https://github.com/pkerpedjiev/cambridge-trees&quot;&gt;GitHub
page&lt;/a&gt; for the project. It’s
also avilable as a
&lt;a href=&quot;https://bl.ocks.org/pkerpedjiev/91fbba8179f5517348fdb7d5079be04a&quot;&gt;block&lt;/a&gt;.&lt;/p&gt;

&lt;script&gt;
    createMap('#cambridge-tree-map');
&lt;/script&gt;</content><author><name></name></author><category term="javascript" /><category term="d3.js" /><category term="maps" /><summary type="html"></summary></entry><entry><title type="html">Panning and Zooming with D3v4</title><link href="http://emptypipes.org/2016/07/03/d3-panning-and-zooming/" rel="alternate" type="text/html" title="Panning and Zooming with D3v4" /><published>2016-07-03T00:00:00+00:00</published><updated>2016-07-03T00:00:00+00:00</updated><id>http://emptypipes.org/2016/07/03/d3-panning-and-zooming</id><content type="html" xml:base="http://emptypipes.org/2016/07/03/d3-panning-and-zooming/">&lt;style&gt;
path.line {
  fill: none;
  stroke: #666;
  stroke-width: 1.5px;
}

path.area {
  fill: #e7e7e7;
}

.axis {
  shape-rendering: crispEdges;
}

.x.axis line,
.x.axis path {
  fill: none;
  stroke: #000;
}

.x.axis .minor {
  stroke-opacity: .5;
}

.x.axis path {
}

.y.axis line,
.y.axis path {
  fill: none;
  stroke: #000;
}
svg text {
        font-family: sans-serif;
            font-size: 13px;
        }


circle {
    fill: transparent;
    stroke: black;
    stroke-width: 1px;
}
&lt;/style&gt;

&lt;p&gt;All that’s necessary for panning and zooming is a translation
&lt;em&gt;[t&lt;sub&gt;x&lt;/sub&gt;, t&lt;sub&gt;y&lt;/sub&gt;]&lt;/em&gt; and a scale factor &lt;em&gt;k&lt;/em&gt;.  When
a zoom transform is applied to an element at position &lt;em&gt;[x&lt;sub&gt;0&lt;/sub&gt;,
y&lt;sub&gt;0&lt;/sub&gt;]&lt;/em&gt;, its new position becomes &lt;em&gt;[t&lt;sub&gt;x&lt;/sub&gt; + k ×
x&lt;sub&gt;0&lt;/sub&gt;, t&lt;sub&gt;y&lt;/sub&gt; + k × y&lt;sub&gt;0&lt;/sub&gt;]&lt;/em&gt;. That’s it. Everything else
is just sugar and spice on top of this simple transform.&lt;/p&gt;

&lt;p&gt;The major difference between zooming in D3v3 and and D3v4 is that the
behavior (dealing with events) and the transforms (positioning elements)
are more separated. In v3, they used to be part of the behavior whereas
in v4, they’re part of the element on which the behavior is called.&lt;/p&gt;

&lt;p&gt;To illustrate, let’s plot 4 points. The rest of this post will only deal
with data in one dimension. It should be trivial to expand to two dimensions.
The points will represent the values 1, 1010, 1020 and 5000:&lt;/p&gt;

&lt;div class=&quot;language-javascript highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;    &lt;span class=&quot;kd&quot;&gt;var&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;xScale&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;d3&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;scaleLinear&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;
        &lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;domain&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;([&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;5000&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;])&lt;/span&gt;
        &lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;range&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;([&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;100&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;500&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;])&lt;/span&gt;

    &lt;span class=&quot;kd&quot;&gt;var&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;dataPoints&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;1010&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;1020&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;5000&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;];&lt;/span&gt;

    &lt;span class=&quot;nx&quot;&gt;gMain&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;selectAll&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;'circle'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;data&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;dataPoints&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;enter&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;append&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;'circle'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;attr&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;'r'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;7&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;attr&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;'cx'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;kd&quot;&gt;function&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;d&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;xScale&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;d&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;svg class=&quot;fig1&quot;&gt;&lt;/svg&gt;

&lt;script&gt;

function figure1() {
    var margin = {'left': -50, 'top': 80, 'bottom': 20, 'right': 20};
    var width = 500, height=50;
    var svg = d3v4.selectAll(&quot;.fig1&quot;)
        .attr('height', height + margin.top + margin.bottom)
        .attr('width', width + margin.left + margin.right);

    var gMain = svg.append('g')
        .attr('transform', 'translate(' + margin.left + ',' + margin.top + ')');

    var xScale = d3v4.scaleLinear()
        .domain([0,5000])
        .range([100,500])

    var dataPoints = [1,1010,1020,5000];

    gMain.selectAll('circle')
    .data(dataPoints)
    .enter()
    .append('circle')
    .attr('r', 7)
    .attr('cx', function(d) { return xScale(d); });

    gMain.append('text')
    .attr('x', 300)
    .attr('y', -60)
    .attr('text-anchor', 'middle')
    .text('point value');

    gMain.append('text')
    .attr('x', 300)
    .attr('y', 55)
    .attr('text-anchor', 'middle')
    .text('screen position');


    var xTopAxis = d3v4.axisTop()
    .scale(xScale)
    .ticks(3)

    var gTopAxis = gMain.append('g')
    .classed('x axis', true)
    .attr('transform', 'translate(0,-15)')

    var xAxis = d3v4.axisBottom()
    .scale(d3v4.scaleLinear().domain([100,500]).range([100,500]))
    .ticks(3)

    var gAxis = gMain.append('g')
    .classed('x axis', true)
    .attr('transform', 'translate(0,15)')

    gAxis.call(xAxis);
    gTopAxis.call(xTopAxis);
}
figure1();
&lt;/script&gt;

&lt;p&gt;We can see that two of the points, 1010 and 1020, are virtually on top of each other. 
Using our &lt;code class=&quot;highlighter-rouge&quot;&gt;xScale&lt;/code&gt;, we can determine that they’re less than 1 pixel apart.&lt;/p&gt;

&lt;div class=&quot;language-javascript highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;    &lt;span class=&quot;nx&quot;&gt;xScale&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;1010&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;c1&quot;&gt;//180.8&lt;/span&gt;
    &lt;span class=&quot;nx&quot;&gt;xScale&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;1020&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;c1&quot;&gt;//181.6&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;What if we want to zoom in so that they’re 10 pixels apart? We’ll first need to calculate the scale factor, &lt;em&gt;k&lt;/em&gt;:&lt;/p&gt;

&lt;div class=&quot;language-javascript highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;    &lt;span class=&quot;kd&quot;&gt;var&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;k&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;10&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;/&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;xScale&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;1020&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;xScale&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;1010&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))&lt;/span&gt;  &lt;span class=&quot;c1&quot;&gt;//~ 12.5 &lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Let’s say we want the point 1010 to be positioned at pixel 200. We need to determine &lt;em&gt;t&lt;sub&gt;x&lt;/sub&gt;&lt;/em&gt; such that &lt;em&gt;200 = t&lt;sub&gt;x&lt;/sub&gt; + k × xScale(1010)&lt;/em&gt;&lt;/p&gt;

&lt;div class=&quot;language-javascript highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;    &lt;span class=&quot;kd&quot;&gt;var&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;tx&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;200&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;k&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;xScale&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;1010&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;c1&quot;&gt;//-2600&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;When we apply this to our plot.&lt;/p&gt;

&lt;div class=&quot;language-javascript highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;    &lt;span class=&quot;kd&quot;&gt;var&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;k&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;10&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;/&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;xScale&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;1020&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;xScale&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;1010&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))&lt;/span&gt;
    &lt;span class=&quot;kd&quot;&gt;var&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;tx&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;200&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;k&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;xScale&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;1010&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;kd&quot;&gt;var&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;t&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;d3&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;zoomIdentity&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;translate&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;tx&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;).&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;scale&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;k&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;

    &lt;span class=&quot;nx&quot;&gt;gMain&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;selectAll&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;'circle'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;data&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;dataPoints&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;enter&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;append&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;'circle'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;attr&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;'r'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;7&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;attr&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;'cx'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;kd&quot;&gt;function&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;d&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;t&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;applyX&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;xScale&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;d&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;));&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;We get two lovely separated circles.&lt;/p&gt;

&lt;svg class=&quot;fig2&quot;&gt;&lt;/svg&gt;

&lt;script&gt;

function fig2() {
    var margin = {'left': -50, 'top': 80, 'bottom': 20, 'right': 20};
    var width = 500, height=50;
    var svg = d3v4.selectAll(&quot;.fig2&quot;)
        .attr('height', height + margin.top + margin.bottom)
        .attr('width', width + margin.left + margin.right);

    var gMain = svg.append('g')
        .attr('transform', 'translate(' + margin.left + ',' + margin.top + ')');

    var xScale = d3v4.scaleLinear()
        .domain([0,5000])
        .range([100,500])

    var dataPoints = [1,1010,1020,5000];


    var k = 10 / (xScale(1020) - xScale(1010))
    var tx = 200 - k * xScale(1010)
    var t = d3v4.zoomIdentity.translate(tx, 0).scale(k)

    gMain.selectAll('circle')
    .data(dataPoints)
    .enter()
    .append('circle')
    .attr('r', 7)
    .attr('cx', function(d) { return t.applyX(xScale(d)); });

    gMain.append('text')
    .attr('x', 300)
    .attr('y', -60)
    .attr('text-anchor', 'middle')
    .text('point value');

    gMain.append('text')
    .attr('x', 300)
    .attr('y', 55)
    .attr('text-anchor', 'middle')
    .text('screen position');


    var xTopAxis = d3v4.axisTop()
    .scale(xScale)
    .ticks(3)

    var gTopAxis = gMain.append('g')
    .classed('x axis', true)
    .attr('transform', 'translate(0,-15)')

    var xAxis = d3v4.axisBottom()
    .scale(d3v4.scaleLinear().domain([100,500]).range([100,500]))
    .ticks(3)

    var gAxis = gMain.append('g')
    .classed('x axis', true)
    .attr('transform', 'translate(0,15)')

    gAxis.call(xAxis);
    gTopAxis.call(xTopAxis);
}
fig2();
&lt;/script&gt;

&lt;p&gt;Fantastic, right? But notice that the top axis still refers to the old domain. This is
because we never changed it. In the old version of D3, we would attach the axis to the
zoom behavior, set the &lt;code class=&quot;highlighter-rouge&quot;&gt;translate&lt;/code&gt; and &lt;code class=&quot;highlighter-rouge&quot;&gt;scale&lt;/code&gt; properties and be done with it. In v4,
we have to rescale our linear scale manually and use the rescaled version to create the
axis:&lt;/p&gt;

&lt;div class=&quot;language-javascript highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;    &lt;span class=&quot;kd&quot;&gt;var&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;xNewScale&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;t&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;rescaleX&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;xScale&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;

    &lt;span class=&quot;kd&quot;&gt;var&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;xTopAxis&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;d3&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;axisTop&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;scale&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;xNewScale&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;ticks&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;3&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;svg class=&quot;fig3&quot;&gt;&lt;/svg&gt;

&lt;script&gt;

function fig3() {
    var margin = {'left': -50, 'top': 80, 'bottom': 20, 'right': 20};
    var width = 500, height=50;
    var svg = d3v4.selectAll(&quot;.fig3&quot;)
        .attr('height', height + margin.top + margin.bottom)
        .attr('width', width + margin.left + margin.right);

    var gMain = svg.append('g')
        .attr('transform', 'translate(' + margin.left + ',' + margin.top + ')');

    var xScale = d3v4.scaleLinear()
        .domain([0,5000])
        .range([100,500])

    var dataPoints = [1,1010,1020,5000];


    var k = 10 / (xScale(1020) - xScale(1010))
    var tx = 200 - k * xScale(1010)
    var t = d3v4.zoomIdentity.translate(tx, 0).scale(k)

    var xNewScale = t.rescaleX(xScale)

    gMain.selectAll('circle')
    .data(dataPoints)
    .enter()
    .append('circle')
    .attr('r', 7)
    .attr('cx', function(d) { return t.applyX(xScale(d)); });

    gMain.append('text')
    .attr('x', 300)
    .attr('y', -60)
    .attr('text-anchor', 'middle')
    .text('point value');

    gMain.append('text')
    .attr('x', 300)
    .attr('y', 55)
    .attr('text-anchor', 'middle')
    .text('screen position');


    var xTopAxis = d3v4.axisTop()
    .scale(xNewScale)
    .ticks(3)

    var gTopAxis = gMain.append('g')
    .classed('x axis', true)
    .attr('transform', 'translate(0,-15)')

    var xAxis = d3v4.axisBottom()
    .scale(d3v4.scaleLinear().domain([100,500]).range([100,500]))
    .ticks(3)

    var gAxis = gMain.append('g')
    .classed('x axis', true)
    .attr('transform', 'translate(0,15)')

    gAxis.call(xAxis);
    gTopAxis.call(xTopAxis);
}
fig3();

&lt;/script&gt;

&lt;p&gt;The examples above demonstrate how the zoom transforms work, but they don’t
actually use the zoom behavior. For that we need to create a behavior and
attach it to an element:&lt;/p&gt;

&lt;div class=&quot;language-javascript highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;    &lt;span class=&quot;kd&quot;&gt;var&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;circles&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;svg&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;selectAll&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;'circle'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
    &lt;span class=&quot;kd&quot;&gt;var&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;zoom&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;d3&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;zoom&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;().&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;on&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;'zoom'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;zoomed&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;

    &lt;span class=&quot;kd&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;zoomed&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;kd&quot;&gt;var&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;transform&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;d3&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;event&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;transform&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;

        &lt;span class=&quot;c1&quot;&gt;// rescale the x linear scale so that we can draw the top axis&lt;/span&gt;
        &lt;span class=&quot;kd&quot;&gt;var&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;xNewScale&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;transform&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;rescaleX&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;xScale&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
        &lt;span class=&quot;nx&quot;&gt;xTopAxis&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;scale&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;xNewScale&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
        &lt;span class=&quot;nx&quot;&gt;gTopAxis&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;call&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;xTopAxis&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;

        &lt;span class=&quot;c1&quot;&gt;// draw the circles in their new positions&lt;/span&gt;
        &lt;span class=&quot;nx&quot;&gt;circles&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;attr&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;'cx'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;kd&quot;&gt;function&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;d&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;transform&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;applyX&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;xScale&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;d&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;));&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;});&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;

    &lt;span class=&quot;nx&quot;&gt;gMain&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;call&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;zoom&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Here we recompute the zoom transform every time there is a zoom event and
reposition each circle. We also rescale the x-scale so that we can use it to
create an axis. The astute observer will note that
&lt;code class=&quot;highlighter-rouge&quot;&gt;transform.applyX(xScale(d))&lt;/code&gt; is actually equivalent to &lt;code class=&quot;highlighter-rouge&quot;&gt;xNewScale(d)&lt;/code&gt;.
Automatic rescaling was possible using v3 by calling &lt;code class=&quot;highlighter-rouge&quot;&gt;zoom.x(xScale)&lt;/code&gt;, but this
has been done away with in favor of explicit rescaling using
&lt;code class=&quot;highlighter-rouge&quot;&gt;transform.rescaleX(xScale)&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;The code above works but if we had programmatically zoomed in beforehand (as we
did in the previous section by applying the transform), then applying the zoom
behavior would remove that transform as soon as we start zooming.&lt;/p&gt;

&lt;p&gt;Why?&lt;/p&gt;

&lt;p&gt;Because in the &lt;code class=&quot;highlighter-rouge&quot;&gt;zoomed&lt;/code&gt; function we obtain a &lt;code class=&quot;highlighter-rouge&quot;&gt;transform&lt;/code&gt; from
&lt;code class=&quot;highlighter-rouge&quot;&gt;d3.event.transform&lt;/code&gt;.  In previous versions of D3, this would come from the
zoom behavior itself (&lt;code class=&quot;highlighter-rouge&quot;&gt;zoom.translate&lt;/code&gt; and &lt;code class=&quot;highlighter-rouge&quot;&gt;zoom.scale&lt;/code&gt;). In v4, it comes from
the element on which the zoom behavior is called (&lt;code class=&quot;highlighter-rouge&quot;&gt;gMain&lt;/code&gt;). To programmatically
zoom in and then apply the zoom behavior starting from there, we need to set the
zoom transform of the &lt;code class=&quot;highlighter-rouge&quot;&gt;gMain&lt;/code&gt; element before we call the behavior:&lt;/p&gt;

&lt;div class=&quot;language-javascript highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;kd&quot;&gt;var&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;k&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;10&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;/&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;xScale&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;1020&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;xScale&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;1010&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))&lt;/span&gt;
&lt;span class=&quot;kd&quot;&gt;var&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;tx&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;200&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;k&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;xScale&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;1010&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;kd&quot;&gt;var&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;t&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;d3&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;zoomIdentity&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;translate&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;tx&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;).&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;scale&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;k&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;

&lt;span class=&quot;nx&quot;&gt;gMain&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;call&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;zoom&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;transform&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;t&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
&lt;span class=&quot;nx&quot;&gt;gMain&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;call&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;zoom&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Now we start with an already zoomed in view &lt;strong&gt;and&lt;/strong&gt; can zoom in and out using the
mouse.&lt;/p&gt;

&lt;svg class=&quot;fig4&quot;&gt;&lt;/svg&gt;

&lt;script&gt;

function fig4() {
    var margin = {'left': -50, 'top': 80, 'bottom': 20, 'right': 20};
    var width = 500, height=50;
    var svg = d3v4.selectAll(&quot;.fig4&quot;)
        .attr('height', height + margin.top + margin.bottom)
        .attr('width', width + margin.left + margin.right);

    var gMain = svg.append('g')
        .attr('transform', 'translate(' + margin.left + ',' + margin.top + ')');

    gMain.append('rect')
    .attr('x', 50)
    .attr('y', -25)
    .attr('width', width)
    .attr('height', height)
    .style('fill', 'transparent');

    var xScale = d3v4.scaleLinear()
        .domain([0,5000])
        .range([100,500])

    var dataPoints = [1,1010,1020,5000];


    var k = 10 / (xScale(1020) - xScale(1010))
    var tx = 200 - k * xScale(1010)
    var t = d3v4.zoomIdentity.translate(tx, 0).scale(k)

    var xNewScale = t.rescaleX(xScale)


    var circles = gMain.selectAll('circle')
    .data(dataPoints)
    .enter()
    .append('circle')
    .attr('r', 7)
    //.attr('cx', function(d) { return t.applyX(xScale(d)); })




    gMain.append('text')
    .attr('x', 300)
    .attr('y', -60)
    .attr('text-anchor', 'middle')
    .text('point value');

    gMain.append('text')
    .attr('x', 300)
    .attr('y', 55)
    .attr('text-anchor', 'middle')
    .text('screen position');


    var xTopAxis = d3v4.axisTop()
    .scale(xNewScale)
    .ticks(3)

    var gTopAxis = gMain.append('g')
    .classed('x axis', true)
    .attr('transform', 'translate(0,-15)')

    var xAxis = d3v4.axisBottom()
    .scale(d3v4.scaleLinear().domain([100,500]).range([100,500]))
    .ticks(3)

    var gAxis = gMain.append('g')
    .classed('x axis', true)
    .attr('transform', 'translate(0,15)')

    var zoom = d3v4.zoom().on('zoom', zoomed);
    function zoomed() {
        var transform = d3v4.event.transform;

        var xNewScale = transform.rescaleX(xScale);
        xTopAxis.scale(xNewScale)  
        gTopAxis.call(xTopAxis);

        circles.attr('cx', function(d) { return xNewScale(d); });
    }
    gMain.call(zoom.transform, t);
    gMain.call(zoom)

    gAxis.call(xAxis);
    gTopAxis.call(xTopAxis);
}
fig4();
&lt;/script&gt;

&lt;p&gt;To wrap up this post, let’s combine these techniques to create a figure which automatically
zooms between random data points (a la &lt;a href=&quot;http://bl.ocks.org/mbostock/b783fbb2e673561d214e09c7fb5cedee&quot;&gt;M. Bostock’s Zoom Transitions Block&lt;/a&gt;). How do we do this?&lt;/p&gt;

&lt;p&gt;First, we need a function to call every time we want to jump to a point:&lt;/p&gt;

&lt;div class=&quot;language-javascript highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;    &lt;span class=&quot;kd&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;targetPoint&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;1010&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;

    &lt;span class=&quot;kd&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;transition&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;selection&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;kd&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;n&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;dataPoints&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;length&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
        &lt;span class=&quot;kd&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;prevTargetPoint&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;targetPoint&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;

        &lt;span class=&quot;c1&quot;&gt;// pick a new point to zoom to&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;while&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;targetPoint&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;==&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;prevTargetPoint&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
            &lt;span class=&quot;kd&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;i&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;Math&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;random&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;n&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;|&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;
            &lt;span class=&quot;nx&quot;&gt;targetPoint&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;dataPoints&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;i&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;];&lt;/span&gt;
        &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;

        &lt;span class=&quot;nx&quot;&gt;selection&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;transition&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;
        &lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;delay&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;300&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
        &lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;duration&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;2000&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
        &lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;call&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;zoom&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;transform&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;transform&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
        &lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;on&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;'end'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;kd&quot;&gt;function&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;circles&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;call&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;transition&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;});&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;

    &lt;span class=&quot;nx&quot;&gt;circles&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;call&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;transition&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;This function picks a random point (&lt;code class=&quot;highlighter-rouge&quot;&gt;targetPoint&lt;/code&gt;) and calls a
transition on the selection. In our case, the selection will be the circles.
When the transition is over, we simply call the function again to start it
over.&lt;/p&gt;

&lt;p&gt;Second, we need a transform to center the view on the target point:&lt;/p&gt;

&lt;div class=&quot;language-javascript highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;    &lt;span class=&quot;kd&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;transform&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;c1&quot;&gt;// put points that are 10 values apart 20 pixels apart&lt;/span&gt;
        &lt;span class=&quot;kd&quot;&gt;var&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;k&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;20&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;/&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;xScale&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;10&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;xScale&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))&lt;/span&gt;
        &lt;span class=&quot;c1&quot;&gt;// center in the middle of the visible area&lt;/span&gt;
        &lt;span class=&quot;kd&quot;&gt;var&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;tx&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;xScale&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;range&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()[&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;xScale&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;range&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()[&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;])&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;/&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;2&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;k&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;xScale&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;targetPoint&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
        &lt;span class=&quot;kd&quot;&gt;var&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;t&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;d3&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;zoomIdentity&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;translate&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;tx&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;).&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;scale&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;k&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;t&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;

&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;svg class=&quot;fig5&quot;&gt;&lt;/svg&gt;

&lt;script&gt;

function fig5() {
    var margin = {'left': -50, 'top': 80, 'bottom': 20, 'right': 20};
    var width = 500, height=50;
    var svg = d3v4.selectAll(&quot;.fig5&quot;)
        .attr('height', height + margin.top + margin.bottom)
        .attr('width', width + margin.left + margin.right);

    var gMain = svg.append('g')
        .attr('transform', 'translate(' + margin.left + ',' + margin.top + ')');

    gMain.append('rect')
    .attr('x', 50)
    .attr('y', -25)
    .attr('width', width)
    .attr('height', height)
    .style('fill', 'transparent');

    var xScale = d3v4.scaleLinear()
        .domain([0,5000])
        .range([100,500])

    var dataPoints = [1,1010,1020,5000];
    var targetPoint = 1015;


    var k = 10 / (xScale(1020) - xScale(1010))
    var tx = 200 - k * xScale(1010)
    var t = d3v4.zoomIdentity.translate(tx, 0).scale(k)

    var xNewScale = t.rescaleX(xScale)


    var circles = gMain.selectAll('circle')
    .data(dataPoints)
    .enter()
    .append('circle')
    .attr('r', 7)
    //.attr('cx', function(d) { return t.applyX(xScale(d)); })

    gMain.append('text')
    .attr('x', 300)
    .attr('y', -60)
    .attr('text-anchor', 'middle')
    .text('point value');

    gMain.append('text')
    .attr('x', 300)
    .attr('y', 55)
    .attr('text-anchor', 'middle')
    .text('screen position');

    var xTopAxis = d3v4.axisTop()
    .scale(xNewScale)
    .ticks(3)

    var gTopAxis = gMain.append('g')
    .classed('x axis', true)
    .attr('transform', 'translate(0,-15)')

    var xAxis = d3v4.axisBottom()
    .scale(d3v4.scaleLinear().domain([100,500]).range([100,500]))
    .ticks(3)

    var gAxis = gMain.append('g')
    .classed('x axis', true)
    .attr('transform', 'translate(0,15)')

    var zoom = d3v4.zoom().on('zoom', zoomed);
    function zoomed() {
        var transform = d3v4.event.transform;
        var xNewScale = transform.rescaleX(xScale);

        xTopAxis.scale(xNewScale)
        gTopAxis.call(xTopAxis);
        circles.attr('cx', function(d) { return transform.applyX(xScale(d)); });
    }
    gMain.call(zoom.transform, t);
    gMain.call(zoom)

    gAxis.call(xAxis);
    gTopAxis.call(xTopAxis);

    function transform() {
        // put points that are 10 values apart 20 pixels apart
        var k = 20 / (xScale(10) - xScale(0))
        // center in the middle of the visible area
        var tx = (xScale.range()[1] + xScale.range()[0])/2 - k * xScale(targetPoint)
        var t = d3v4.zoomIdentity.translate(tx, 0).scale(k)
        return t;
    }

    function transition(selection) {
        let n = dataPoints.length;
        let prevTargetPoint = targetPoint;

        // pick a new point to zoom to
        while (targetPoint == prevTargetPoint) {
            let i = Math.random() * n | 0
            targetPoint = dataPoints[i];
        }

        selection.transition()
        .delay(300)
        .duration(2000)
        .call(zoom.transform, transform)
        .on('end', function() { circles.call(transition); });
    }

    circles.call(transition);
}
fig5();
&lt;/script&gt;

&lt;p&gt;And that’s all. Just remember, when zooming and panning the position of the transformed point &lt;em&gt;[x&lt;sub&gt;1&lt;/sub&gt;,y&lt;sub&gt;1&lt;/sub&gt;] = [t&lt;sub&gt;x&lt;/sub&gt; + k ×
x&lt;sub&gt;0&lt;/sub&gt;, t&lt;sub&gt;y&lt;/sub&gt; + k × y&lt;sub&gt;0&lt;/sub&gt;]&lt;/em&gt;. Everything else is just window dressing.&lt;/p&gt;</content><author><name></name></author><category term="javascript" /><category term="d3.js" /><category term="zooming" /><summary type="html"></summary></entry><entry><title type="html">Isochrone Driving Maps of the World</title><link href="http://emptypipes.org/2016/03/04/isochrone-driving-map/" rel="alternate" type="text/html" title="Isochrone Driving Maps of the World" /><published>2016-03-04T00:00:00+00:00</published><updated>2016-03-04T00:00:00+00:00</updated><id>http://emptypipes.org/2016/03/04/isochrone-driving-map</id><content type="html" xml:base="http://emptypipes.org/2016/03/04/isochrone-driving-map/">&lt;meta charset=&quot;utf-8&quot; /&gt;

&lt;p&gt;&lt;img src=&quot;/img/isochrone_example.png&quot; itemprop=&quot;image&quot; style=&quot;display:none&quot; width=&quot;200&quot; height=&quot;170&quot; /&gt;&lt;/p&gt;

&lt;p&gt;One of my favorite things about maps is the context they provide for overlayed
information. This can range from the mundane and orthodox (such as roads and
boundaries) to the &lt;a href=&quot;http://imgur.com/NpUXT2e&quot;&gt;esoteric&lt;/a&gt; and
&lt;a href=&quot;https://atlasofprejudice.com/tearing-europe-apart-10d01e876eab#.vs8s28r1r&quot;&gt;abstract&lt;/a&gt;.
Nearly a year ago I wrote a &lt;a href=&quot;http://emptypipes.org/2015/05/20/europe-isochrone-map/&quot;&gt;blog
post&lt;/a&gt; which overlayed
travel time (isochrone) data on top of a map of Europe. It showed how long it
would take somebody to travel from a given city to any other point in Europe
using only public transportation. In this post, I do the exact same thing using
driving times.&lt;/p&gt;

&lt;div class=&quot;wp-caption alignright&quot; style=&quot;width: 183px&quot;&gt; 
&lt;a href=&quot;/supp/isochrone_driving/vienna&quot;&gt;&lt;img src=&quot;/img/isochrone-driving-distances/vienna.png&quot; width=&quot;183&quot; /&gt; &lt;/a&gt;
&lt;p class=&quot;wp-caption-text&quot;&gt;Driving times starting in Vienna, Austria. Notice how
the frontier of the contours is more rounded than in Lincoln, NE.&lt;/p&gt; &lt;/div&gt;
&lt;div class=&quot;wp-caption alignright&quot; style=&quot;width: 183px&quot;&gt; 
&lt;a href=&quot;/supp/isochrone_driving/lincoln&quot;&gt;&lt;img src=&quot;/img/isochrone-driving-distances/lincoln.png&quot; width=&quot;183&quot; /&gt;&lt;/a&gt; 
&lt;p class=&quot;wp-caption-text&quot;&gt;Driving times starting in Lincoln, Nebraska.&lt;/p&gt; &lt;/div&gt;

&lt;p&gt;
The wonderful thing about portraying driving times is that it's possible to
make such maps for cities from all over the world. In doing so, we can see the
how the transportation infrastructure of a region meshes with the natural
features to create a unique accessibility profile. Lincoln (Nebraska) is
centered in the USA and has a characteristic diamond shaped travel time
profile. Why? Anyone that has looked at a map of the region will certainly have
noticed that the roads are arranged in a grid pattern. Thus it takes much
longer to travel along the diagonal than to travel straight north and south.
Vienna, Austria, on the other hand, has a more circular accessibility profile
due to the abundance of roads going in all directions.
&lt;/p&gt;

&lt;div class=&quot;wp-caption alignleft&quot; style=&quot;width: 183px&quot;&gt;
&lt;a href=&quot;/supp/isochrone_driving/santiago&quot;&gt;&lt;img src=&quot;/img/isochrone-driving-distances/santiago.png&quot; width=&quot;183&quot; /&gt;&lt;/a&gt;
&lt;p class=&quot;wp-caption-text&quot;&gt;The Andes mountains block driving to the east of Santiago, Chile&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;wp-caption alignleft&quot; style=&quot;width: 183px&quot;&gt;
&lt;a href=&quot;/supp/isochrone_driving/panama_city&quot;&gt;&lt;img src=&quot;/img/isochrone-driving-distances/panama-city.png&quot; width=&quot;183&quot; /&gt;&lt;/a&gt;
&lt;p class=&quot;wp-caption-text&quot;&gt;The Darien Gap separates Central America from South America&lt;/p&gt;
&lt;/div&gt;

&lt;p&gt;Looking at the isochrone map of Santiago, Chile, one can clearly see the how
the Andes mountains block travel east of the city. Southeast of panama city,
the odd fact that you can’t drive between North / Central America and South
America becomes clear. Zooming in at identical levels, you can compare cities
and see the difference in accessibility of the relatively wealthy South Africa
with that of the less developed, wilder Congo. The differences in accessibility
between different cities of the world can range from the trivial (Denver, CO vs
Lincoln, NE) to the substantial (Perth, Australia vs. Sydney, Australia).
Individual cities can have a wide automobile-reachible area (Moscow, Russia) or
a narrow, geography, politics and infrastructure-constrained area (Irkutsk,
Russia).&lt;/p&gt;

&lt;div class=&quot;wp-caption alignright&quot; style=&quot;width: 183px&quot;&gt;
&lt;a href=&quot;/supp/isochrone_driving/kinshasa&quot;&gt;&lt;img src=&quot;/img/isochrone-driving-distances/kinshasa.png&quot; width=&quot;183&quot; /&gt;&lt;/a&gt;
&lt;p class=&quot;wp-caption-text&quot;&gt;The accessibility profile of Kinshasa, Democratic Republic of the Congo is rugged and discontinuous. &lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;wp-caption alignright&quot; style=&quot;width: 183px&quot;&gt;
&lt;a href=&quot;/supp/isochrone_driving/cape_town&quot;&gt;&lt;img src=&quot;/img/isochrone-driving-distances/cape-town.png&quot; width=&quot;183&quot; /&gt;&lt;/a&gt;
&lt;p class=&quot;wp-caption-text&quot;&gt;Cape Town, South Africa has good links to the interior of the country as well as to Namibia in the north.&lt;/p&gt;
&lt;/div&gt;

&lt;link rel=&quot;stylesheet&quot; href=&quot;/css/leaflet.css&quot; /&gt;

&lt;script src=&quot;/js/leaflet.js&quot;&gt;&lt;/script&gt;

&lt;script src=&quot;/js/isochrone_driving_map.js&quot;&gt;&lt;/script&gt;

&lt;script src=&quot;/js/cubehelix.js&quot;&gt;&lt;/script&gt;

&lt;script src=&quot;/js/tile.stamen.js&quot;&gt;&lt;/script&gt;

&lt;p&gt;Whatever the case, the places that are most interesting are always those that
are also most familiar. For this reason, I’ve provided overlays for most major
cities around the world. The map currently shows Vienna, but clicking any of
the links below will open a map for that particular city. The travel times were
obtained using GraphHopper and OpenStreetMap data so don’t be surprised if they
differ from those of Google maps.&lt;/p&gt;

&lt;div id=&quot;isochroneDrivingMap&quot; style=&quot;height: 400px; width: 550px;&quot;&gt;&lt;/div&gt;
&lt;div id=&quot;isochroneDrivingMapLegend&quot; style=&quot;height: 40px; width: 550px;&quot;&gt;&lt;/div&gt;

&lt;script type=&quot;text/javascript&quot;&gt;
        drawIsochroneMap(48.200, 16.3666, '/jsons/isochrone_driving_contours/vienna.json');
        &lt;/script&gt;

&lt;hr /&gt;

&lt;p&gt;&lt;b&gt;Other Cities&lt;/b&gt;
&lt;br /&gt;
&lt;br /&gt;&lt;/p&gt;

&lt;div class=&quot;accordion&quot; id=&quot;accordion2&quot;&gt;
    &lt;div class=&quot;accordion-group&quot;&gt;
        &lt;div class=&quot;accordion-heading&quot;&gt;
            &lt;a class=&quot;accordion-toggle&quot; data-toggle=&quot;collapse&quot; data-parent=&quot;#accordion2&quot; href=&quot;#collapseNorthAmerica&quot;&gt;
            &lt;b&gt;North and Central America&lt;/b&gt;
            &lt;/a&gt;
        &lt;/div&gt;
        &lt;div id=&quot;collapseNorthAmerica&quot; class=&quot;accordion-body collapse out&quot;&gt;
            &lt;div class=&quot;accordion-inner&quot;&gt;

            &lt;table style=&quot;width: 550px;&quot;&gt;
&lt;tr&gt;
&lt;td&gt;
&lt;a href=&quot;/supp/isochrone_driving/atlanta&quot;&gt;Atlanta&lt;/a&gt;&lt;/td&gt;
&lt;td&gt;
&lt;a href=&quot;/supp/isochrone_driving/juneau&quot;&gt;Juneau&lt;/a&gt;&lt;/td&gt;
&lt;td&gt;
&lt;a href=&quot;/supp/isochrone_driving/ottawa&quot;&gt;Ottawa&lt;/a&gt;&lt;/td&gt;
&lt;td&gt;
&lt;a href=&quot;/supp/isochrone_driving/tegucigalpa&quot;&gt;Tegucigalpa&lt;/a&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;
&lt;a href=&quot;/supp/isochrone_driving/belmopan&quot;&gt;Belmopan&lt;/a&gt;&lt;/td&gt;
&lt;td&gt;
&lt;a href=&quot;/supp/isochrone_driving/lincoln&quot;&gt;Lincoln&lt;/a&gt;&lt;/td&gt;
&lt;td&gt;
&lt;a href=&quot;/supp/isochrone_driving/panama_city&quot;&gt;Panama City&lt;/a&gt;&lt;/td&gt;
&lt;td&gt;
&lt;a href=&quot;/supp/isochrone_driving/toronto&quot;&gt;Toronto&lt;/a&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;
&lt;a href=&quot;/supp/isochrone_driving/charlotte&quot;&gt;Charlotte&lt;/a&gt;&lt;/td&gt;
&lt;td&gt;
&lt;a href=&quot;/supp/isochrone_driving/los_angeles&quot;&gt;Los Angeles&lt;/a&gt;&lt;/td&gt;
&lt;td&gt;
&lt;a href=&quot;/supp/isochrone_driving/philadelphia&quot;&gt;Philadelphia&lt;/a&gt;&lt;/td&gt;
&lt;td&gt;
&lt;a href=&quot;/supp/isochrone_driving/vancouver&quot;&gt;Vancouver&lt;/a&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;
&lt;a href=&quot;/supp/isochrone_driving/chicago&quot;&gt;Chicago&lt;/a&gt;&lt;/td&gt;
&lt;td&gt;
&lt;a href=&quot;/supp/isochrone_driving/managua&quot;&gt;Managua&lt;/a&gt;&lt;/td&gt;
&lt;td&gt;
&lt;a href=&quot;/supp/isochrone_driving/phoenix&quot;&gt;Phoenix&lt;/a&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;
&lt;a href=&quot;/supp/isochrone_driving/dallas&quot;&gt;Dallas&lt;/a&gt;&lt;/td&gt;
&lt;td&gt;
&lt;a href=&quot;/supp/isochrone_driving/mexico_city&quot;&gt;Mexico City&lt;/a&gt;&lt;/td&gt;
&lt;td&gt;
&lt;a href=&quot;/supp/isochrone_driving/pittsburgh&quot;&gt;Pittsburgh&lt;/a&gt;&lt;/td&gt;
&lt;td&gt;
&lt;a href=&quot;/supp/isochrone_driving/wichita&quot;&gt;Wichita&lt;/a&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;
&lt;a href=&quot;/supp/isochrone_driving/denver&quot;&gt;Denver&lt;/a&gt;&lt;/td&gt;
&lt;td&gt;
&lt;a href=&quot;/supp/isochrone_driving/miami&quot;&gt;Miami&lt;/a&gt;&lt;/td&gt;
&lt;td&gt;
&lt;a href=&quot;/supp/isochrone_driving/san_diego&quot;&gt;San Diego&lt;/a&gt;&lt;/td&gt;
&lt;td&gt;
&lt;a href=&quot;/supp/isochrone_driving/winnipeg&quot;&gt;Winnipeg&lt;/a&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;
&lt;a href=&quot;/supp/isochrone_driving/edmonton&quot;&gt;Edmonton&lt;/a&gt;&lt;/td&gt;
&lt;td&gt;
&lt;a href=&quot;/supp/isochrone_driving/minneapolis&quot;&gt;Minneapolis&lt;/a&gt;&lt;/td&gt;
&lt;td&gt;
&lt;a href=&quot;/supp/isochrone_driving/san_francisco&quot;&gt;San Francisco&lt;/a&gt;&lt;/td&gt;
&lt;td&gt;
&lt;a href=&quot;/supp/isochrone_driving/yellowknife&quot;&gt;Yellowknife&lt;/a&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;
&lt;a href=&quot;/supp/isochrone_driving/fairbanks&quot;&gt;Fairbanks&lt;/a&gt;&lt;/td&gt;
&lt;td&gt;
&lt;a href=&quot;/supp/isochrone_driving/montreal&quot;&gt;Montreal&lt;/a&gt;&lt;/td&gt;
&lt;td&gt;
&lt;a href=&quot;/supp/isochrone_driving/san_jose&quot;&gt;San Jose&lt;/a&gt;&lt;/td&gt;
&lt;td&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;
&lt;a href=&quot;/supp/isochrone_driving/guatemala_city&quot;&gt;Guatemala City&lt;/a&gt;&lt;/td&gt;
&lt;td&gt;
&lt;a href=&quot;/supp/isochrone_driving/new_york&quot;&gt;New York&lt;/a&gt;&lt;/td&gt;
&lt;td&gt;
&lt;a href=&quot;/supp/isochrone_driving/san_salvador&quot;&gt;San Salvador&lt;/a&gt;&lt;/td&gt;
&lt;td&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;
&lt;a href=&quot;/supp/isochrone_driving/houston&quot;&gt;Houston&lt;/a&gt;&lt;/td&gt;
&lt;td&gt;
&lt;a href=&quot;/supp/isochrone_driving/nome&quot;&gt;Nome&lt;/a&gt;&lt;/td&gt;
&lt;td&gt;
&lt;a href=&quot;/supp/isochrone_driving/seattle&quot;&gt;Seattle&lt;/a&gt;&lt;/td&gt;
&lt;td&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;/table&gt;



            &lt;/div&gt;
        &lt;/div&gt;
    &lt;/div&gt;

    &lt;div class=&quot;accordion-group&quot;&gt;
        &lt;div class=&quot;accordion-heading&quot;&gt;
            &lt;a class=&quot;accordion-toggle&quot; data-toggle=&quot;collapse&quot; data-parent=&quot;#accordion2&quot; href=&quot;#collapseEurope&quot;&gt;
            &lt;b&gt;Europe&lt;/b&gt;
            &lt;/a&gt;
        &lt;/div&gt;
        &lt;div id=&quot;collapseEurope&quot; class=&quot;accordion-body collapse out&quot;&gt;
            &lt;div class=&quot;accordion-inner&quot;&gt;

            &lt;table style=&quot;width: 550px;&quot;&gt;
&lt;tr&gt;
&lt;td&gt;
&lt;a href=&quot;/supp/isochrone_driving/amsterdam&quot;&gt;Amsterdam&lt;/a&gt;&lt;/td&gt;
&lt;td&gt;
&lt;a href=&quot;/supp/isochrone_driving/budapest&quot;&gt;Budapest&lt;/a&gt;&lt;/td&gt;
&lt;td&gt;
&lt;a href=&quot;/supp/isochrone_driving/london&quot;&gt;London&lt;/a&gt;&lt;/td&gt;
&lt;td&gt;
&lt;a href=&quot;/supp/isochrone_driving/rome&quot;&gt;Rome&lt;/a&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;
&lt;a href=&quot;/supp/isochrone_driving/antwerp&quot;&gt;Antwerp&lt;/a&gt;&lt;/td&gt;
&lt;td&gt;
&lt;a href=&quot;/supp/isochrone_driving/copenhagen&quot;&gt;Copenhagen&lt;/a&gt;&lt;/td&gt;
&lt;td&gt;
&lt;a href=&quot;/supp/isochrone_driving/luxembourg&quot;&gt;Luxembourg&lt;/a&gt;&lt;/td&gt;
&lt;td&gt;
&lt;a href=&quot;/supp/isochrone_driving/sofia&quot;&gt;Sofia&lt;/a&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;
&lt;a href=&quot;/supp/isochrone_driving/athens&quot;&gt;Athens&lt;/a&gt;&lt;/td&gt;
&lt;td&gt;
&lt;a href=&quot;/supp/isochrone_driving/dublin&quot;&gt;Dublin&lt;/a&gt;&lt;/td&gt;
&lt;td&gt;
&lt;a href=&quot;/supp/isochrone_driving/madrid&quot;&gt;Madrid&lt;/a&gt;&lt;/td&gt;
&lt;td&gt;
&lt;a href=&quot;/supp/isochrone_driving/stockholm&quot;&gt;Stockholm&lt;/a&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;
&lt;a href=&quot;/supp/isochrone_driving/barcelona&quot;&gt;Barcelona&lt;/a&gt;&lt;/td&gt;
&lt;td&gt;
&lt;a href=&quot;/supp/isochrone_driving/frankfurt&quot;&gt;Frankfurt&lt;/a&gt;&lt;/td&gt;
&lt;td&gt;
&lt;a href=&quot;/supp/isochrone_driving/minsk&quot;&gt;Minsk&lt;/a&gt;&lt;/td&gt;
&lt;td&gt;
&lt;a href=&quot;/supp/isochrone_driving/tallinn&quot;&gt;Tallinn&lt;/a&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;
&lt;a href=&quot;/supp/isochrone_driving/belgrade&quot;&gt;Belgrade&lt;/a&gt;&lt;/td&gt;
&lt;td&gt;
&lt;a href=&quot;/supp/isochrone_driving/geneva&quot;&gt;Geneva&lt;/a&gt;&lt;/td&gt;
&lt;td&gt;
&lt;a href=&quot;/supp/isochrone_driving/oslo&quot;&gt;Oslo&lt;/a&gt;&lt;/td&gt;
&lt;td&gt;
&lt;a href=&quot;/supp/isochrone_driving/vienna&quot;&gt;Vienna&lt;/a&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;
&lt;a href=&quot;/supp/isochrone_driving/berlin&quot;&gt;Berlin&lt;/a&gt;&lt;/td&gt;
&lt;td&gt;
&lt;a href=&quot;/supp/isochrone_driving/helsinki&quot;&gt;Helsinki&lt;/a&gt;&lt;/td&gt;
&lt;td&gt;
&lt;a href=&quot;/supp/isochrone_driving/paris&quot;&gt;Paris&lt;/a&gt;&lt;/td&gt;
&lt;td&gt;
&lt;a href=&quot;/supp/isochrone_driving/vilnius&quot;&gt;Vilnius&lt;/a&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;
&lt;a href=&quot;/supp/isochrone_driving/bratislava&quot;&gt;Bratislava&lt;/a&gt;&lt;/td&gt;
&lt;td&gt;
&lt;a href=&quot;/supp/isochrone_driving/jena&quot;&gt;Jena&lt;/a&gt;&lt;/td&gt;
&lt;td&gt;
&lt;a href=&quot;/supp/isochrone_driving/podgorica&quot;&gt;Podgorica&lt;/a&gt;&lt;/td&gt;
&lt;td&gt;
&lt;a href=&quot;/supp/isochrone_driving/warsaw&quot;&gt;Warsaw&lt;/a&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;
&lt;a href=&quot;/supp/isochrone_driving/brussels&quot;&gt;Brussels&lt;/a&gt;&lt;/td&gt;
&lt;td&gt;
&lt;a href=&quot;/supp/isochrone_driving/lisbon&quot;&gt;Lisbon&lt;/a&gt;&lt;/td&gt;
&lt;td&gt;
&lt;a href=&quot;/supp/isochrone_driving/prague&quot;&gt;Prague&lt;/a&gt;&lt;/td&gt;
&lt;td&gt;
&lt;a href=&quot;/supp/isochrone_driving/zagreb&quot;&gt;Zagreb&lt;/a&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;
&lt;a href=&quot;/supp/isochrone_driving/bucharest&quot;&gt;Bucharest&lt;/a&gt;&lt;/td&gt;
&lt;td&gt;
&lt;a href=&quot;/supp/isochrone_driving/ljubljana&quot;&gt;Ljubljana&lt;/a&gt;&lt;/td&gt;
&lt;td&gt;
&lt;a href=&quot;/supp/isochrone_driving/riga&quot;&gt;Riga&lt;/a&gt;&lt;/td&gt;
&lt;td&gt;
&lt;a href=&quot;/supp/isochrone_driving/zurich&quot;&gt;Zurich&lt;/a&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/table&gt;



            &lt;/div&gt;
        &lt;/div&gt;
    &lt;/div&gt;

    &lt;div class=&quot;accordion-group&quot;&gt;
        &lt;div class=&quot;accordion-heading&quot;&gt;
            &lt;a class=&quot;accordion-toggle&quot; data-toggle=&quot;collapse&quot; data-parent=&quot;#accordion2&quot; href=&quot;#collapseSouthAmerica&quot;&gt;
            &lt;b&gt;South America&lt;/b&gt;
            &lt;/a&gt;
        &lt;/div&gt;
        &lt;div id=&quot;collapseSouthAmerica&quot; class=&quot;accordion-body collapse out&quot;&gt;
            &lt;div class=&quot;accordion-inner&quot;&gt;

            &lt;table style=&quot;width: 550px;&quot;&gt;
&lt;tr&gt;
&lt;td&gt;
&lt;a href=&quot;/supp/isochrone_driving/asuncion&quot;&gt;Asuncion&lt;/a&gt;&lt;/td&gt;
&lt;td&gt;
&lt;a href=&quot;/supp/isochrone_driving/cartagena&quot;&gt;Cartagena&lt;/a&gt;&lt;/td&gt;
&lt;td&gt;
&lt;a href=&quot;/supp/isochrone_driving/manaus&quot;&gt;Manaus&lt;/a&gt;&lt;/td&gt;
&lt;td&gt;
&lt;a href=&quot;/supp/isochrone_driving/santiago&quot;&gt;Santiago&lt;/a&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;
&lt;a href=&quot;/supp/isochrone_driving/bogota&quot;&gt;Bogota&lt;/a&gt;&lt;/td&gt;
&lt;td&gt;
&lt;a href=&quot;/supp/isochrone_driving/cayenne&quot;&gt;Cayenne&lt;/a&gt;&lt;/td&gt;
&lt;td&gt;
&lt;a href=&quot;/supp/isochrone_driving/montevideo&quot;&gt;Montevideo&lt;/a&gt;&lt;/td&gt;
&lt;td&gt;
&lt;a href=&quot;/supp/isochrone_driving/sao_paolo&quot;&gt;Sao Paolo&lt;/a&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;
&lt;a href=&quot;/supp/isochrone_driving/brasilia&quot;&gt;Brasilia&lt;/a&gt;&lt;/td&gt;
&lt;td&gt;
&lt;a href=&quot;/supp/isochrone_driving/georgetown&quot;&gt;Georgetown&lt;/a&gt;&lt;/td&gt;
&lt;td&gt;
&lt;a href=&quot;/supp/isochrone_driving/paramaribo&quot;&gt;Paramaribo&lt;/a&gt;&lt;/td&gt;
&lt;td&gt;
&lt;a href=&quot;/supp/isochrone_driving/ushuaia&quot;&gt;Ushuaia&lt;/a&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;
&lt;a href=&quot;/supp/isochrone_driving/buenos_aires&quot;&gt;Buenos Aires&lt;/a&gt;&lt;/td&gt;
&lt;td&gt;
&lt;a href=&quot;/supp/isochrone_driving/la_paz&quot;&gt;La Paz&lt;/a&gt;&lt;/td&gt;
&lt;td&gt;
&lt;a href=&quot;/supp/isochrone_driving/quito&quot;&gt;Quito&lt;/a&gt;&lt;/td&gt;
&lt;td&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;
&lt;a href=&quot;/supp/isochrone_driving/caracas&quot;&gt;Caracas&lt;/a&gt;&lt;/td&gt;
&lt;td&gt;
&lt;a href=&quot;/supp/isochrone_driving/lima&quot;&gt;Lima&lt;/a&gt;&lt;/td&gt;
&lt;td&gt;
&lt;a href=&quot;/supp/isochrone_driving/rio_de_janeiro&quot;&gt;Rio De Janeiro&lt;/a&gt;&lt;/td&gt;
&lt;td&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;/table&gt;



            &lt;/div&gt;
        &lt;/div&gt;
    &lt;/div&gt;


    &lt;div class=&quot;accordion-group&quot;&gt;
        &lt;div class=&quot;accordion-heading&quot;&gt;
            &lt;a class=&quot;accordion-toggle&quot; data-toggle=&quot;collapse&quot; data-parent=&quot;#accordion2&quot; href=&quot;#collapseAfrica&quot;&gt;
           &lt;b&gt;Africa&lt;/b&gt;
            &lt;/a&gt;
        &lt;/div&gt;
        &lt;div id=&quot;collapseAfrica&quot; class=&quot;accordion-body collapse out&quot;&gt;
            &lt;div class=&quot;accordion-inner&quot;&gt;

            &lt;table style=&quot;width: 550px;&quot;&gt;
&lt;tr&gt;
&lt;td&gt;
&lt;a href=&quot;/supp/isochrone_driving/abidjan&quot;&gt;Abidjan&lt;/a&gt;&lt;/td&gt;
&lt;td&gt;
&lt;a href=&quot;/supp/isochrone_driving/conakry&quot;&gt;Conakry&lt;/a&gt;&lt;/td&gt;
&lt;td&gt;
&lt;a href=&quot;/supp/isochrone_driving/lagos&quot;&gt;Lagos&lt;/a&gt;&lt;/td&gt;
&lt;td&gt;
&lt;a href=&quot;/supp/isochrone_driving/monrovia&quot;&gt;Monrovia&lt;/a&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;
&lt;a href=&quot;/supp/isochrone_driving/accra&quot;&gt;Accra&lt;/a&gt;&lt;/td&gt;
&lt;td&gt;
&lt;a href=&quot;/supp/isochrone_driving/dakar&quot;&gt;Dakar&lt;/a&gt;&lt;/td&gt;
&lt;td&gt;
&lt;a href=&quot;/supp/isochrone_driving/libreville&quot;&gt;Libreville&lt;/a&gt;&lt;/td&gt;
&lt;td&gt;
&lt;a href=&quot;/supp/isochrone_driving/n_djamena&quot;&gt;N Djamena&lt;/a&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;
&lt;a href=&quot;/supp/isochrone_driving/algiers&quot;&gt;Algiers&lt;/a&gt;&lt;/td&gt;
&lt;td&gt;
&lt;a href=&quot;/supp/isochrone_driving/dar_es_salaam&quot;&gt;Dar Es Salaam&lt;/a&gt;&lt;/td&gt;
&lt;td&gt;
&lt;a href=&quot;/supp/isochrone_driving/lilongwe&quot;&gt;Lilongwe&lt;/a&gt;&lt;/td&gt;
&lt;td&gt;
&lt;a href=&quot;/supp/isochrone_driving/nairobi&quot;&gt;Nairobi&lt;/a&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;
&lt;a href=&quot;/supp/isochrone_driving/antananarivo&quot;&gt;Antananarivo&lt;/a&gt;&lt;/td&gt;
&lt;td&gt;
&lt;a href=&quot;/supp/isochrone_driving/freetown&quot;&gt;Freetown&lt;/a&gt;&lt;/td&gt;
&lt;td&gt;
&lt;a href=&quot;/supp/isochrone_driving/lome&quot;&gt;Lome&lt;/a&gt;&lt;/td&gt;
&lt;td&gt;
&lt;a href=&quot;/supp/isochrone_driving/niamey&quot;&gt;Niamey&lt;/a&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;
&lt;a href=&quot;/supp/isochrone_driving/asmara&quot;&gt;Asmara&lt;/a&gt;&lt;/td&gt;
&lt;td&gt;
&lt;a href=&quot;/supp/isochrone_driving/gaborone&quot;&gt;Gaborone&lt;/a&gt;&lt;/td&gt;
&lt;td&gt;
&lt;a href=&quot;/supp/isochrone_driving/luanda&quot;&gt;Luanda&lt;/a&gt;&lt;/td&gt;
&lt;td&gt;
&lt;a href=&quot;/supp/isochrone_driving/nouakchott&quot;&gt;Nouakchott&lt;/a&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;
&lt;a href=&quot;/supp/isochrone_driving/banjul&quot;&gt;Banjul&lt;/a&gt;&lt;/td&gt;
&lt;td&gt;
&lt;a href=&quot;/supp/isochrone_driving/johannesburg&quot;&gt;Johannesburg&lt;/a&gt;&lt;/td&gt;
&lt;td&gt;
&lt;a href=&quot;/supp/isochrone_driving/lusaka&quot;&gt;Lusaka&lt;/a&gt;&lt;/td&gt;
&lt;td&gt;
&lt;a href=&quot;/supp/isochrone_driving/porto_novo&quot;&gt;Porto Novo&lt;/a&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;
&lt;a href=&quot;/supp/isochrone_driving/bissau&quot;&gt;Bissau&lt;/a&gt;&lt;/td&gt;
&lt;td&gt;
&lt;a href=&quot;/supp/isochrone_driving/juba&quot;&gt;Juba&lt;/a&gt;&lt;/td&gt;
&lt;td&gt;
&lt;a href=&quot;/supp/isochrone_driving/maputo&quot;&gt;Maputo&lt;/a&gt;&lt;/td&gt;
&lt;td&gt;
&lt;a href=&quot;/supp/isochrone_driving/rabat&quot;&gt;Rabat&lt;/a&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;
&lt;a href=&quot;/supp/isochrone_driving/brazzaville&quot;&gt;Brazzaville&lt;/a&gt;&lt;/td&gt;
&lt;td&gt;
&lt;a href=&quot;/supp/isochrone_driving/kampala&quot;&gt;Kampala&lt;/a&gt;&lt;/td&gt;
&lt;td&gt;
&lt;a href=&quot;/supp/isochrone_driving/marrakesh&quot;&gt;Marrakesh&lt;/a&gt;&lt;/td&gt;
&lt;td&gt;
&lt;a href=&quot;/supp/isochrone_driving/tripoli&quot;&gt;Tripoli&lt;/a&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;
&lt;a href=&quot;/supp/isochrone_driving/bujumbura&quot;&gt;Bujumbura&lt;/a&gt;&lt;/td&gt;
&lt;td&gt;
&lt;a href=&quot;/supp/isochrone_driving/khartoum&quot;&gt;Khartoum&lt;/a&gt;&lt;/td&gt;
&lt;td&gt;
&lt;a href=&quot;/supp/isochrone_driving/maseru&quot;&gt;Maseru&lt;/a&gt;&lt;/td&gt;
&lt;td&gt;
&lt;a href=&quot;/supp/isochrone_driving/tunis&quot;&gt;Tunis&lt;/a&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;
&lt;a href=&quot;/supp/isochrone_driving/cairo&quot;&gt;Cairo&lt;/a&gt;&lt;/td&gt;
&lt;td&gt;
&lt;a href=&quot;/supp/isochrone_driving/kigali&quot;&gt;Kigali&lt;/a&gt;&lt;/td&gt;
&lt;td&gt;
&lt;a href=&quot;/supp/isochrone_driving/mbabane&quot;&gt;Mbabane&lt;/a&gt;&lt;/td&gt;
&lt;td&gt;
&lt;a href=&quot;/supp/isochrone_driving/windhoek&quot;&gt;Windhoek&lt;/a&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;
&lt;a href=&quot;/supp/isochrone_driving/cape_town&quot;&gt;Cape Town&lt;/a&gt;&lt;/td&gt;
&lt;td&gt;
&lt;a href=&quot;/supp/isochrone_driving/kinshasa&quot;&gt;Kinshasa&lt;/a&gt;&lt;/td&gt;
&lt;td&gt;
&lt;a href=&quot;/supp/isochrone_driving/mogadishu&quot;&gt;Mogadishu&lt;/a&gt;&lt;/td&gt;
&lt;td&gt;
&lt;a href=&quot;/supp/isochrone_driving/yaounde&quot;&gt;Yaounde&lt;/a&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/table&gt;



            &lt;/div&gt;
        &lt;/div&gt;
    &lt;/div&gt;

    &lt;div class=&quot;accordion-group&quot;&gt;
        &lt;div class=&quot;accordion-heading&quot;&gt;
            &lt;a class=&quot;accordion-toggle&quot; data-toggle=&quot;collapse&quot; data-parent=&quot;#accordion2&quot; href=&quot;#collapseAsia&quot;&gt;
           &lt;b&gt;Asia&lt;/b&gt;
            &lt;/a&gt;
        &lt;/div&gt;
        &lt;div id=&quot;collapseAsia&quot; class=&quot;accordion-body collapse out&quot;&gt;
            &lt;div class=&quot;accordion-inner&quot;&gt;

            &lt;table style=&quot;width: 550px;&quot;&gt;
&lt;tr&gt;
&lt;td&gt;
&lt;a href=&quot;/supp/isochrone_driving/abu_dhabi&quot;&gt;Abu Dhabi&lt;/a&gt;&lt;/td&gt;
&lt;td&gt;
&lt;a href=&quot;/supp/isochrone_driving/dubai&quot;&gt;Dubai&lt;/a&gt;&lt;/td&gt;
&lt;td&gt;
&lt;a href=&quot;/supp/isochrone_driving/moscow&quot;&gt;Moscow&lt;/a&gt;&lt;/td&gt;
&lt;td&gt;
&lt;a href=&quot;/supp/isochrone_driving/st_petersburg&quot;&gt;St Petersburg&lt;/a&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;
&lt;a href=&quot;/supp/isochrone_driving/almaty&quot;&gt;Almaty&lt;/a&gt;&lt;/td&gt;
&lt;td&gt;
&lt;a href=&quot;/supp/isochrone_driving/dushanbe&quot;&gt;Dushanbe&lt;/a&gt;&lt;/td&gt;
&lt;td&gt;
&lt;a href=&quot;/supp/isochrone_driving/mosul&quot;&gt;Mosul&lt;/a&gt;&lt;/td&gt;
&lt;td&gt;
&lt;a href=&quot;/supp/isochrone_driving/tashkent&quot;&gt;Tashkent&lt;/a&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;
&lt;a href=&quot;/supp/isochrone_driving/amman&quot;&gt;Amman&lt;/a&gt;&lt;/td&gt;
&lt;td&gt;
&lt;a href=&quot;/supp/isochrone_driving/hanoi&quot;&gt;Hanoi&lt;/a&gt;&lt;/td&gt;
&lt;td&gt;
&lt;a href=&quot;/supp/isochrone_driving/mumbai&quot;&gt;Mumbai&lt;/a&gt;&lt;/td&gt;
&lt;td&gt;
&lt;a href=&quot;/supp/isochrone_driving/tbilisi&quot;&gt;Tbilisi&lt;/a&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;
&lt;a href=&quot;/supp/isochrone_driving/ankara&quot;&gt;Ankara&lt;/a&gt;&lt;/td&gt;
&lt;td&gt;
&lt;a href=&quot;/supp/isochrone_driving/irkutsk&quot;&gt;Irkutsk&lt;/a&gt;&lt;/td&gt;
&lt;td&gt;
&lt;a href=&quot;/supp/isochrone_driving/muscat&quot;&gt;Muscat&lt;/a&gt;&lt;/td&gt;
&lt;td&gt;
&lt;a href=&quot;/supp/isochrone_driving/tehran&quot;&gt;Tehran&lt;/a&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;
&lt;a href=&quot;/supp/isochrone_driving/ashgabat&quot;&gt;Ashgabat&lt;/a&gt;&lt;/td&gt;
&lt;td&gt;
&lt;a href=&quot;/supp/isochrone_driving/islamabad&quot;&gt;Islamabad&lt;/a&gt;&lt;/td&gt;
&lt;td&gt;
&lt;a href=&quot;/supp/isochrone_driving/naypyidaw&quot;&gt;Naypyidaw&lt;/a&gt;&lt;/td&gt;
&lt;td&gt;
&lt;a href=&quot;/supp/isochrone_driving/tel_aviv&quot;&gt;Tel Aviv&lt;/a&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;
&lt;a href=&quot;/supp/isochrone_driving/astana&quot;&gt;Astana&lt;/a&gt;&lt;/td&gt;
&lt;td&gt;
&lt;a href=&quot;/supp/isochrone_driving/jakarta&quot;&gt;Jakarta&lt;/a&gt;&lt;/td&gt;
&lt;td&gt;
&lt;a href=&quot;/supp/isochrone_driving/new_delhi&quot;&gt;New Delhi&lt;/a&gt;&lt;/td&gt;
&lt;td&gt;
&lt;a href=&quot;/supp/isochrone_driving/thimphu&quot;&gt;Thimphu&lt;/a&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;
&lt;a href=&quot;/supp/isochrone_driving/baghdad&quot;&gt;Baghdad&lt;/a&gt;&lt;/td&gt;
&lt;td&gt;
&lt;a href=&quot;/supp/isochrone_driving/jeddah&quot;&gt;Jeddah&lt;/a&gt;&lt;/td&gt;
&lt;td&gt;
&lt;a href=&quot;/supp/isochrone_driving/novosibirsk&quot;&gt;Novosibirsk&lt;/a&gt;&lt;/td&gt;
&lt;td&gt;
&lt;a href=&quot;/supp/isochrone_driving/tianjin&quot;&gt;Tianjin&lt;/a&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;
&lt;a href=&quot;/supp/isochrone_driving/baku&quot;&gt;Baku&lt;/a&gt;&lt;/td&gt;
&lt;td&gt;
&lt;a href=&quot;/supp/isochrone_driving/jerusalem&quot;&gt;Jerusalem&lt;/a&gt;&lt;/td&gt;
&lt;td&gt;
&lt;a href=&quot;/supp/isochrone_driving/phnom_penh&quot;&gt;Phnom Penh&lt;/a&gt;&lt;/td&gt;
&lt;td&gt;
&lt;a href=&quot;/supp/isochrone_driving/tokyo&quot;&gt;Tokyo&lt;/a&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;
&lt;a href=&quot;/supp/isochrone_driving/bangkok&quot;&gt;Bangkok&lt;/a&gt;&lt;/td&gt;
&lt;td&gt;
&lt;a href=&quot;/supp/isochrone_driving/kabul&quot;&gt;Kabul&lt;/a&gt;&lt;/td&gt;
&lt;td&gt;
&lt;a href=&quot;/supp/isochrone_driving/pyongyang&quot;&gt;Pyongyang&lt;/a&gt;&lt;/td&gt;
&lt;td&gt;
&lt;a href=&quot;/supp/isochrone_driving/ulaanbaatar&quot;&gt;Ulaanbaatar&lt;/a&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;
&lt;a href=&quot;/supp/isochrone_driving/beijing&quot;&gt;Beijing&lt;/a&gt;&lt;/td&gt;
&lt;td&gt;
&lt;a href=&quot;/supp/isochrone_driving/karachi&quot;&gt;Karachi&lt;/a&gt;&lt;/td&gt;
&lt;td&gt;
&lt;a href=&quot;/supp/isochrone_driving/riyadh&quot;&gt;Riyadh&lt;/a&gt;&lt;/td&gt;
&lt;td&gt;
&lt;a href=&quot;/supp/isochrone_driving/vientiane&quot;&gt;Vientiane&lt;/a&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;
&lt;a href=&quot;/supp/isochrone_driving/beirut&quot;&gt;Beirut&lt;/a&gt;&lt;/td&gt;
&lt;td&gt;
&lt;a href=&quot;/supp/isochrone_driving/kathmandu&quot;&gt;Kathmandu&lt;/a&gt;&lt;/td&gt;
&lt;td&gt;
&lt;a href=&quot;/supp/isochrone_driving/sanaa&quot;&gt;Sanaa&lt;/a&gt;&lt;/td&gt;
&lt;td&gt;
&lt;a href=&quot;/supp/isochrone_driving/vladivostok&quot;&gt;Vladivostok&lt;/a&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;
&lt;a href=&quot;/supp/isochrone_driving/bishkek&quot;&gt;Bishkek&lt;/a&gt;&lt;/td&gt;
&lt;td&gt;
&lt;a href=&quot;/supp/isochrone_driving/kuwait_city&quot;&gt;Kuwait City&lt;/a&gt;&lt;/td&gt;
&lt;td&gt;
&lt;a href=&quot;/supp/isochrone_driving/seoul&quot;&gt;Seoul&lt;/a&gt;&lt;/td&gt;
&lt;td&gt;
&lt;a href=&quot;/supp/isochrone_driving/yerevan&quot;&gt;Yerevan&lt;/a&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;
&lt;a href=&quot;/supp/isochrone_driving/colombo&quot;&gt;Colombo&lt;/a&gt;&lt;/td&gt;
&lt;td&gt;
&lt;a href=&quot;/supp/isochrone_driving/lahore&quot;&gt;Lahore&lt;/a&gt;&lt;/td&gt;
&lt;td&gt;
&lt;a href=&quot;/supp/isochrone_driving/shanghai&quot;&gt;Shanghai&lt;/a&gt;&lt;/td&gt;
&lt;td&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;
&lt;a href=&quot;/supp/isochrone_driving/damascus&quot;&gt;Damascus&lt;/a&gt;&lt;/td&gt;
&lt;td&gt;
&lt;a href=&quot;/supp/isochrone_driving/manama&quot;&gt;Manama&lt;/a&gt;&lt;/td&gt;
&lt;td&gt;
&lt;a href=&quot;/supp/isochrone_driving/singapore&quot;&gt;Singapore&lt;/a&gt;&lt;/td&gt;
&lt;td&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;
&lt;a href=&quot;/supp/isochrone_driving/doha&quot;&gt;Doha&lt;/a&gt;&lt;/td&gt;
&lt;td&gt;
&lt;a href=&quot;/supp/isochrone_driving/manila&quot;&gt;Manila&lt;/a&gt;&lt;/td&gt;
&lt;td&gt;
&lt;a href=&quot;/supp/isochrone_driving/sochi&quot;&gt;Sochi&lt;/a&gt;&lt;/td&gt;
&lt;td&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;/table&gt;



            &lt;/div&gt;
        &lt;/div&gt;
    &lt;/div&gt;

    &lt;div class=&quot;accordion-group&quot;&gt;
        &lt;div class=&quot;accordion-heading&quot;&gt;
            &lt;a class=&quot;accordion-toggle&quot; data-toggle=&quot;collapse&quot; data-parent=&quot;#accordion2&quot; href=&quot;#collapseAustralia&quot;&gt;
           &lt;b&gt;Australia and Oceania&lt;/b&gt;
            &lt;/a&gt;
        &lt;/div&gt;
        &lt;div id=&quot;collapseAustralia&quot; class=&quot;accordion-body collapse out&quot;&gt;
            &lt;div class=&quot;accordion-inner&quot;&gt;

            &lt;table style=&quot;width: 550px;&quot;&gt;
&lt;tr&gt;
&lt;td&gt;
&lt;a href=&quot;/supp/isochrone_driving/adelaide&quot;&gt;Adelaide&lt;/a&gt;&lt;/td&gt;
&lt;td&gt;
&lt;a href=&quot;/supp/isochrone_driving/christchurch&quot;&gt;Christchurch&lt;/a&gt;&lt;/td&gt;
&lt;td&gt;
&lt;a href=&quot;/supp/isochrone_driving/noumea&quot;&gt;Noumea&lt;/a&gt;&lt;/td&gt;
&lt;td&gt;
&lt;a href=&quot;/supp/isochrone_driving/sydney&quot;&gt;Sydney&lt;/a&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;
&lt;a href=&quot;/supp/isochrone_driving/apia&quot;&gt;Apia&lt;/a&gt;&lt;/td&gt;
&lt;td&gt;
&lt;a href=&quot;/supp/isochrone_driving/hobart&quot;&gt;Hobart&lt;/a&gt;&lt;/td&gt;
&lt;td&gt;
&lt;a href=&quot;/supp/isochrone_driving/perth&quot;&gt;Perth&lt;/a&gt;&lt;/td&gt;
&lt;td&gt;
&lt;a href=&quot;/supp/isochrone_driving/wellington&quot;&gt;Wellington&lt;/a&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;
&lt;a href=&quot;/supp/isochrone_driving/auckland&quot;&gt;Auckland&lt;/a&gt;&lt;/td&gt;
&lt;td&gt;
&lt;a href=&quot;/supp/isochrone_driving/honiara&quot;&gt;Honiara&lt;/a&gt;&lt;/td&gt;
&lt;td&gt;
&lt;a href=&quot;/supp/isochrone_driving/port_moresby&quot;&gt;Port Moresby&lt;/a&gt;&lt;/td&gt;
&lt;td&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;
&lt;a href=&quot;/supp/isochrone_driving/brisbane&quot;&gt;Brisbane&lt;/a&gt;&lt;/td&gt;
&lt;td&gt;
&lt;a href=&quot;/supp/isochrone_driving/melbourne&quot;&gt;Melbourne&lt;/a&gt;&lt;/td&gt;
&lt;td&gt;
&lt;a href=&quot;/supp/isochrone_driving/suva&quot;&gt;Suva&lt;/a&gt;&lt;/td&gt;
&lt;td&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;/table&gt;



            &lt;/div&gt;
        &lt;/div&gt;
    &lt;/div&gt;

&lt;/div&gt;

&lt;hr /&gt;

&lt;p&gt;&lt;b&gt;Errata / Disclaimer&lt;/b&gt;
&lt;br /&gt;&lt;/p&gt;

&lt;p&gt;Everything is an estimate. Rounding errors abound. Don’t use this for anything
but entertainment and curiosity. But you already know that.&lt;/p&gt;

&lt;p&gt;Some data may be missing. There may be faster routes. Google Maps certainly
finds some better ones.  If you find issues, please let me know and I’ll do my
best to fix them.&lt;/p&gt;

&lt;hr /&gt;

&lt;p&gt;&lt;b&gt;How it’s made, technically&lt;/b&gt;&lt;/p&gt;

&lt;p&gt;For each starting city, an area encompassing 30 degrees north, east, south and
west was subdivided into a .1 degree grid. Directions from the starting city to
each point were calculated using
&lt;a href=&quot;https://github.com/graphhopper/graphhopper/&quot;&gt;graphhopper&lt;/a&gt; and the OSM map
files. From this, contours were extracted using matplotlib’s &lt;code class=&quot;highlighter-rouge&quot;&gt;contourf&lt;/code&gt;
function. These contour files are stored as JSONs and loaded as a D3.js
overlay on top of a leaflet map.&lt;/p&gt;

&lt;p&gt;All of the code used to create these maps &lt;a href=&quot;https://github.com/pkerpedjiev/roadway_routing&quot;&gt;is on
github&lt;/a&gt;. If you have any
questions, feel free to ask.&lt;/p&gt;
&lt;hr /&gt;

&lt;p&gt;&lt;b&gt;Background Information and Motivation&lt;/b&gt;&lt;/p&gt;

&lt;p&gt;This project was a logical extension of the &lt;a href=&quot;/2015/05/20/europe-isochrone-map/&quot;&gt;isochrone train
maps&lt;/a&gt; of Europe project.&lt;/p&gt;</content><author><name></name></author><category term="maps" /><category term="javascript" /><category term="d3.js" /><category term="leaflet" /><summary type="html"></summary></entry><entry><title type="html">ES6 Modules using Webpack and Gulp</title><link href="http://emptypipes.org/2016/03/02/es6-module/" rel="alternate" type="text/html" title="ES6 Modules using Webpack and Gulp" /><published>2016-03-02T00:00:00+00:00</published><updated>2016-03-02T00:00:00+00:00</updated><id>http://emptypipes.org/2016/03/02/es6-module</id><content type="html" xml:base="http://emptypipes.org/2016/03/02/es6-module/">&lt;h3 id=&quot;overview&quot;&gt;Overview&lt;/h3&gt;

&lt;p&gt;One of the most common scenarios I run into when creating javascript
applications is the following.&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;
    &lt;p&gt;I start working on some application (let’s call it &lt;code class=&quot;highlighter-rouge&quot;&gt;foo&lt;/code&gt;).&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;I start working on a different program (let’s call it &lt;code class=&quot;highlighter-rouge&quot;&gt;bar&lt;/code&gt;) and need some
of the functionality that I already implemented in &lt;code class=&quot;highlighter-rouge&quot;&gt;foo&lt;/code&gt;.&lt;/p&gt;
  &lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;In python, accomplishing this is trivial by placing the source files in the same
directory and saying &lt;code class=&quot;highlighter-rouge&quot;&gt;import foo&lt;/code&gt;. In javascript, it’s a little more
complicated. Rather than recapitulate a lot of existing documentation about the
different ways that one can implement modules in javascript (CommonJS, AMD,
etc…), I’ll just dive into how I use &lt;code class=&quot;highlighter-rouge&quot;&gt;gulp&lt;/code&gt; and &lt;code class=&quot;highlighter-rouge&quot;&gt;webpack&lt;/code&gt; to take advantage
of the &lt;a href=&quot;http://www.2ality.com/2014/09/es6-modules-final.html&quot;&gt;ECMAScript 6 syntax for
modules&lt;/a&gt; to create
reusable javascript components.&lt;/p&gt;

&lt;h4 id=&quot;goal&quot;&gt;Goal&lt;/h4&gt;

&lt;p&gt;The goal of this project is to create two components: &lt;code class=&quot;highlighter-rouge&quot;&gt;foo&lt;/code&gt; and &lt;code class=&quot;highlighter-rouge&quot;&gt;bar&lt;/code&gt;. &lt;code class=&quot;highlighter-rouge&quot;&gt;foo&lt;/code&gt;
will export a function called &lt;code class=&quot;highlighter-rouge&quot;&gt;drawCircle&lt;/code&gt; that we can import into &lt;code class=&quot;highlighter-rouge&quot;&gt;bar&lt;/code&gt;. &lt;code class=&quot;highlighter-rouge&quot;&gt;bar&lt;/code&gt;
will then draw a rectangle on top of the circle.&lt;/p&gt;

&lt;p&gt;Here’s the code for &lt;code class=&quot;highlighter-rouge&quot;&gt;app/scripts/bar.js&lt;/code&gt;&lt;/p&gt;

&lt;div class=&quot;language-javascript highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;d3&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;'d3'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;drawCircle&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;'foo'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;export&lt;/span&gt; &lt;span class=&quot;kd&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;drawRectangleAndCircle&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;divName&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;nx&quot;&gt;drawCircle&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;divName&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;

    &lt;span class=&quot;nx&quot;&gt;d3&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;select&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;'svg'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;append&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;'rect'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;attr&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;'x'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;75&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;attr&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;'y'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;75&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;attr&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;'width'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;100&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;attr&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;'height'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;100&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;classed&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;'bar-rectangle'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;kc&quot;&gt;true&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;attr&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;'opacity'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mf&quot;&gt;0.7&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;And the relevant code from &lt;code class=&quot;highlighter-rouge&quot;&gt;app/index.html&lt;/code&gt; which uses &lt;code class=&quot;highlighter-rouge&quot;&gt;bar.js&lt;/code&gt;:&lt;/p&gt;

&lt;div class=&quot;language-html highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt; &lt;span class=&quot;c&quot;&gt;&amp;lt;!-- build:js scripts/bar.js --&amp;gt;&lt;/span&gt;
  &lt;span class=&quot;nt&quot;&gt;&amp;lt;script &lt;/span&gt;&lt;span class=&quot;na&quot;&gt;src=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;'scripts/bar.js'&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;&amp;gt;&amp;lt;/script&amp;gt;&lt;/span&gt;
  &lt;span class=&quot;c&quot;&gt;&amp;lt;!-- endbuild --&amp;gt;&lt;/span&gt;

  &lt;span class=&quot;nt&quot;&gt;&amp;lt;script &lt;/span&gt;&lt;span class=&quot;na&quot;&gt;type=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;'text/javascript'&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;&amp;gt;&lt;/span&gt;

  &lt;span class=&quot;nx&quot;&gt;bar&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;drawRectangleAndCircle&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;'#circle'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;

  &lt;span class=&quot;nt&quot;&gt;&amp;lt;/script&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;In order for all of this to function, we need some tools to manage
which modules we have installed (&lt;code class=&quot;highlighter-rouge&quot;&gt;npm&lt;/code&gt;), resolve the import statements (&lt;code class=&quot;highlighter-rouge&quot;&gt;webpack&lt;/code&gt;),
translate the es6 to more universally understandable es5 (&lt;code class=&quot;highlighter-rouge&quot;&gt;babel&lt;/code&gt;) and to build
everything into one package (&lt;code class=&quot;highlighter-rouge&quot;&gt;gulp&lt;/code&gt;). The easiest way to get started is to use
&lt;a href=&quot;http://yeoman.io/&quot;&gt;&lt;code class=&quot;highlighter-rouge&quot;&gt;yeoman&lt;/code&gt;&lt;/a&gt; to scaffold out the application. To install yeoman, 
simply use &lt;code class=&quot;highlighter-rouge&quot;&gt;npm&lt;/code&gt;:&lt;/p&gt;

&lt;div class=&quot;highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;npm install -g yo
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Then, install the generator for this tutorial:&lt;/p&gt;

&lt;div class=&quot;highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;npm install -g generator-gulp-webpack-es6
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h4 id=&quot;setting-up-foo&quot;&gt;Setting up &lt;em&gt;foo&lt;/em&gt;&lt;/h4&gt;

&lt;p&gt;Create a directory to host the &lt;code class=&quot;highlighter-rouge&quot;&gt;foo&lt;/code&gt; module and scaffold it out:&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;mkdir foo
&lt;span class=&quot;nb&quot;&gt;cd &lt;/span&gt;foo
yo gulp-webpack-es6
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;When yeoman asks for &lt;code class=&quot;highlighter-rouge&quot;&gt;Your project name:&lt;/code&gt;, make sure to enter &lt;code class=&quot;highlighter-rouge&quot;&gt;foo&lt;/code&gt;:&lt;/p&gt;

&lt;p&gt;You can just use the default values for the other fields. The default values for author
name and email address are taken from your &lt;code class=&quot;highlighter-rouge&quot;&gt;~/.gitconfig&lt;/code&gt; if you have one.&lt;/p&gt;

&lt;p&gt;That’s it. We now have a module which simply draws a circle in the browser. Witness it
in all its glory by running:&lt;/p&gt;

&lt;div class=&quot;language-javascript highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;nx&quot;&gt;gulp&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;serve&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;And pointing your browser to &lt;code class=&quot;highlighter-rouge&quot;&gt;127.0.0.1:9000&lt;/code&gt;. The result should look like this:&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/img/es6_module/foo_browser.png&quot; width=&quot;320&quot; /&gt;&lt;/p&gt;

&lt;p&gt;Now, we want to install this package locally so that we can import it from our
soon-to-be-created package &lt;code class=&quot;highlighter-rouge&quot;&gt;bar&lt;/code&gt;. To do this we need to make one minor change
to our &lt;code class=&quot;highlighter-rouge&quot;&gt;webpack.config.js&lt;/code&gt; by adding the following lines:&lt;/p&gt;

&lt;div class=&quot;language-json highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;w&quot;&gt;  &lt;/span&gt;&lt;span class=&quot;err&quot;&gt;externals&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
      &lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;d3&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;d3&quot;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
  &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;},&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;These are necessary to tell webpack not to include d3 in the packaged file. Under
normal circumstances this wouldn’t be necessary but if I omit it and use &lt;code class=&quot;highlighter-rouge&quot;&gt;npm link&lt;/code&gt;
as described below, I get the following error:&lt;/p&gt;

&lt;div class=&quot;language-text highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;Uncaught TypeError: Cannot read property 'document' of undefined
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;It’s seems like it happens either because &lt;code class=&quot;highlighter-rouge&quot;&gt;webpack&lt;/code&gt; adds a &lt;code class=&quot;highlighter-rouge&quot;&gt;use strict;&lt;/code&gt;
somewhere in the bundled &lt;code class=&quot;highlighter-rouge&quot;&gt;foo&lt;/code&gt; package, or because d3 is included in both &lt;code class=&quot;highlighter-rouge&quot;&gt;foo&lt;/code&gt;
and &lt;code class=&quot;highlighter-rouge&quot;&gt;bar&lt;/code&gt;. In either case, specifying that it’s an external package seems to
resolve the problem.&lt;/p&gt;

&lt;p&gt;To build and install &lt;code class=&quot;highlighter-rouge&quot;&gt;foo&lt;/code&gt; so that it can be imported by other modules, just
run the following two commands.&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;gulp build
npm link
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;The first will compile the code into a single javascript file and the second
will install it as a global module on the local computer. From now on, whenever
we need to make changes to &lt;code class=&quot;highlighter-rouge&quot;&gt;foo&lt;/code&gt; we just need to run &lt;code class=&quot;highlighter-rouge&quot;&gt;gulp build&lt;/code&gt; and they
will be reflected in every local package that uses &lt;code class=&quot;highlighter-rouge&quot;&gt;foo&lt;/code&gt;.&lt;/p&gt;

&lt;h4 id=&quot;setting-up-bar&quot;&gt;Setting up &lt;em&gt;bar&lt;/em&gt;&lt;/h4&gt;

&lt;p&gt;To create the calling package &lt;code class=&quot;highlighter-rouge&quot;&gt;bar&lt;/code&gt; we follow a very similar procedure:&lt;/p&gt;

&lt;div class=&quot;language-javascript highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;nx&quot;&gt;mkdir&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;bar&lt;/span&gt;
&lt;span class=&quot;nx&quot;&gt;cd&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;bar&lt;/span&gt;
&lt;span class=&quot;nx&quot;&gt;yo&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;gulp&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;webpack&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;es6&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;When yeoman asks for &lt;code class=&quot;highlighter-rouge&quot;&gt;Your project name:&lt;/code&gt;, make sure to enter &lt;code class=&quot;highlighter-rouge&quot;&gt;bar&lt;/code&gt;. You can
use the default values for the other fields.&lt;/p&gt;

&lt;p&gt;Now because we want to use the functionality provided in &lt;code class=&quot;highlighter-rouge&quot;&gt;foo&lt;/code&gt;, we need to
install it:&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;npm link foo
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Adn then we need to modify &lt;code class=&quot;highlighter-rouge&quot;&gt;app/scripts/bar.js&lt;/code&gt; and have it implement
its own functionality:&lt;/p&gt;

&lt;div class=&quot;highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;import d3 from 'd3';
import {drawCircle} from 'foo';

export function drawRectangleAndCircle(divName) {
    drawCircle(divName);

    d3.select('svg')
    .append('rect')
    .attr('x', 75)
    .attr('y', 75)
    .attr('width', 100)
    .attr('height', 100)
    .classed('bar-rectangle', true)
    .attr('opacity', 0.7)
}
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;And finally we need to change the &lt;code class=&quot;highlighter-rouge&quot;&gt;&amp;lt;script&amp;gt;&lt;/code&gt; code inside &lt;code class=&quot;highlighter-rouge&quot;&gt;index.html&lt;/code&gt; to
call the newly created function from &lt;code class=&quot;highlighter-rouge&quot;&gt;bar&lt;/code&gt;:&lt;/p&gt;

&lt;div class=&quot;language-html highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;nt&quot;&gt;&amp;lt;script &lt;/span&gt;&lt;span class=&quot;na&quot;&gt;type=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;'text/javascript'&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;&amp;gt;&lt;/span&gt;

&lt;span class=&quot;nx&quot;&gt;bar&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;drawRectangleAndCircle&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;'#circle'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;

&lt;span class=&quot;nt&quot;&gt;&amp;lt;/script&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;If everything worked as it should, running &lt;code class=&quot;highlighter-rouge&quot;&gt;gulp serve&lt;/code&gt; should show a lovely
circle / square combination:&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/img/es6_module/bar_browser.png&quot; width=&quot;320&quot; /&gt;&lt;/p&gt;

&lt;h4 id=&quot;generator-directory-structure&quot;&gt;Generator directory structure&lt;/h4&gt;

&lt;p&gt;The directory structure of the componenets generated using &lt;code class=&quot;highlighter-rouge&quot;&gt;gulp-webpackes6&lt;/code&gt;
is organized so that the configuration files are in the root directory, all of
the code is in the &lt;code class=&quot;highlighter-rouge&quot;&gt;app&lt;/code&gt; subdirectory, unit tests are in &lt;code class=&quot;highlighter-rouge&quot;&gt;test&lt;/code&gt; and the compiled
javascript is in &lt;code class=&quot;highlighter-rouge&quot;&gt;dist&lt;/code&gt;:&lt;/p&gt;

&lt;div class=&quot;highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;.
├── app
│   ├── index.html
│   ├── scripts
│   │   ├── foo.js
│   │   └── helper_module.js
│   └── styles
│       └── foo.css
├── bower.json
├── dist
│   ├── index.html
│   └── scripts
│       └── foo.js
├── gulpfile.babel.js
├── package.json
└── webpack.config.js
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h4 id=&quot;changing-the-modules-name&quot;&gt;Changing the module’s name&lt;/h4&gt;

&lt;p&gt;The default module is created so that the main file is in
&lt;code class=&quot;highlighter-rouge&quot;&gt;app/scripts/module_name.js&lt;/code&gt; where &lt;code class=&quot;highlighter-rouge&quot;&gt;module_name&lt;/code&gt; is the name given in the
generator questionnaire. To change it to something else, you can either re-run
the generator or make the following changes:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;Rename &lt;code class=&quot;highlighter-rouge&quot;&gt;app/scripts/module_name.js&lt;/code&gt;&lt;/li&gt;
  &lt;li&gt;Change occurences of &lt;code class=&quot;highlighter-rouge&quot;&gt;module_name&lt;/code&gt; in &lt;code class=&quot;highlighter-rouge&quot;&gt;app/index.html&lt;/code&gt;&lt;/li&gt;
  &lt;li&gt;Change the &lt;code class=&quot;highlighter-rouge&quot;&gt;entry&lt;/code&gt; line in &lt;code class=&quot;highlighter-rouge&quot;&gt;webpack.config.js&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;</content><author><name></name></author><category term="javascript" /><category term="es6" /><category term="tutorial" /><summary type="html">Overview</summary></entry><entry><title type="html">Largest Ski Areas On Each Continent</title><link href="http://emptypipes.org/largest-ski-areas" rel="alternate" type="text/html" title="Largest Ski Areas On Each Continent" /><published>2015-11-29T00:00:00+00:00</published><updated>2015-11-29T00:00:00+00:00</updated><id>http://emptypipes.org/largest-ski-areas</id><content type="html" xml:base="http://emptypipes.org/largest-ski-areas">&lt;meta charset=&quot;utf-8&quot; /&gt;

&lt;p&gt;&lt;img itemprop=&quot;image&quot; src=&quot;/img/itemprop-largest-ski-areas.png&quot; style=&quot;display:none&quot; width=&quot;200&quot; height=&quot;130&quot; /&gt;&lt;/p&gt;

&lt;p&gt;The chart below shows the five largest ski areas on each continent (except
Antarctica). Africa only has three entries because those are the only ski areas
I found with annotated ski lifts and slopes.  Everything is calculated
according to &lt;a href=&quot;#how-its-made&quot;&gt;some reasonable yet arbitrary
heuristics&lt;/a&gt; so please take the rankings with a grain of salt. If you click
on a ski area, it will be displayed in the &lt;a href=&quot;#map-area-section&quot;&gt;map
below&lt;/a&gt;.&lt;/p&gt;

&lt;link rel=&quot;stylesheet&quot; href=&quot;/css/largest-ski-areas.css&quot; /&gt;

&lt;link rel=&quot;stylesheet&quot; href=&quot;/css/leaflet.css&quot; /&gt;

&lt;hr /&gt;

&lt;div id=&quot;compare-area&quot;&gt;&lt;/div&gt;
&lt;hr /&gt;

&lt;p&gt;&lt;b id=&quot;map-area-section&quot;&gt;The Map&lt;/b&gt;&lt;/p&gt;

&lt;p&gt;All the ski areas in the chart above are annotated on the map below. Clicking
on an area above centers the map below.&lt;/p&gt;

&lt;hr /&gt;

&lt;div id=&quot;map-area&quot; style=&quot;height: 300px; width: 550px;&quot;&gt;&lt;/div&gt;
&lt;hr /&gt;

&lt;p&gt;&lt;b id=&quot;how-its-made&quot;&gt;How it’s made&lt;/b&gt;&lt;/p&gt;

&lt;p&gt;Each ski area is defined by something like an &lt;a href=&quot;https://en.wikipedia.org/wiki/Alpha_shape&quot;&gt;alpha
shape&lt;/a&gt;, calculated over all the
lifts and slopes. Each “alpha shape” -like area is calculated by first creating
a Delaunay triangulation of all ski lift and slope waypoints. Every triangle
which has a side greater than 1km is then removed. The result is a set of
disconnected shapes all composed of multiple triangles. Each aggregation of
triangles is what I consider a ski area.&lt;/p&gt;

&lt;p&gt;In some cases, this can lead to two ski resorts being connected even though you
might have to walk up to 1km to get from one lift to another (e.g. Kitzbühel /
SkiWelt above). In the opposite case (e.g. Oukaimeden), a long lift may not
be counted simply because the points defining it create degenerate triangles.
Nevertheless, in most cases the shapes created reflect the ski areas they
represent quite well.&lt;/p&gt;

&lt;p&gt;Here’s the recipe to re-create the graphic:&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;Download OpenStreetMap dumps of each continent&lt;/li&gt;
  &lt;li&gt;Filter for lifts and slopes&lt;/li&gt;
  &lt;li&gt;Sample points along long segments to make sure they’re not split&lt;/li&gt;
  &lt;li&gt;Calculate a Delaunay triangulation of all the OSM nodes and the sampled points&lt;/li&gt;
  &lt;li&gt;Exclude all triangles which have an edge longer than 1km (concave hull of sorts)&lt;/li&gt;
  &lt;li&gt;Polygonize&lt;/li&gt;
  &lt;li&gt;Google the towns near the resorts to figure out what the resorts are called&lt;/li&gt;
  &lt;li&gt;Convert to topojson and downsample to reduce the size&lt;/li&gt;
  &lt;li&gt;Make table using d3.js&lt;/li&gt;
  &lt;li&gt;Create zoomable map using leaflet.js and a d3.js overlay&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Questions? Comments? &lt;a href=&quot;https://twitter.com/pkerpedjiev&quot;&gt;Twitter (@pkerpedjiev)&lt;/a&gt; or email (&lt;a href=&quot;/about&quot;&gt;see about page&lt;/a&gt;).&lt;/p&gt;

&lt;script src=&quot;/js/lib/topojson.v1.min.js&quot;&gt;&lt;/script&gt;

&lt;script src=&quot;/js/lib/d3-grid.js&quot;&gt;&lt;/script&gt;

&lt;script src=&quot;/js/lib/leaflet.js&quot;&gt;&lt;/script&gt;

&lt;script src=&quot;/js/largest-ski-areas.js&quot;&gt;&lt;/script&gt;

&lt;script src=&quot;/js/ski-area-map.js&quot;&gt;&lt;/script&gt;

&lt;script&gt;

var skiAreasFn = '/jsons/largest-ski-areas/topn.topo'

var map = drawSkiMap('map-area', skiAreasFn);
compareMaps(skiAreasFn, map);

&lt;/script&gt;</content><author><name></name></author><category term="leaflet" /><category term="maps" /><category term="ski-areas" /><summary type="html"></summary></entry><entry><title type="html">Never Take The First Option</title><link href="http://emptypipes.org/2015/10/21/kings-jewels/" rel="alternate" type="text/html" title="Never Take The First Option" /><published>2015-10-21T00:00:00+00:00</published><updated>2015-10-21T00:00:00+00:00</updated><id>http://emptypipes.org/2015/10/21/kings-jewels</id><content type="html" xml:base="http://emptypipes.org/2015/10/21/kings-jewels/">&lt;meta charset=&quot;utf-8&quot; /&gt;

&lt;link rel=&quot;stylesheet&quot; href=&quot;/css/kings-jewels.css&quot; /&gt;

&lt;h4 id=&quot;the-kings-jewels-problem&quot;&gt;The King’s Jewels Problem&lt;/h4&gt;
&lt;p&gt;&lt;img itemprop=&quot;image&quot; src=&quot;/img/itemprop_kings_jewels.png&quot; style=&quot;display:none&quot; width=&quot;200&quot; height=&quot;150&quot; /&gt;&lt;/p&gt;

&lt;p&gt;A long time ago, the story goes, a hero rescues the king’s life. The elated
king promises the hero one of his crown jewels as a reward. He takes out his
bag of treasures and tells the hero to reach into the bag and randomly choose
one. If he likes it, he can keep it. If he doesn’t, he can throw it aside and
lose it forever. The hero, greedy as he is heroic, naturally wants to pick 
the best jewels. Looking at the bag, he judges there to be about 10 jewels
inside. He stops to ponder for a second.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;How should the hero proceed to maximize his chances of scoring the best
jewel in the bag?&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Should he just take the first one he picks or should he look at a few
before deciding on one to keep? If so, how many?&lt;/p&gt;

&lt;p&gt;We could try to answer this question analytically, but since “data science” is
all the rage, why not try and answer it stochastically? If we simulate the
hero’s choices, we should be able to come up with some numerically-grounded
recommendation for what he should do.&lt;/p&gt;

&lt;p&gt;Let’s assume a simple scenario. The hero first looks at &lt;em&gt;n&lt;/em&gt; jewels and then takes
the next best jewel. If none of the jewels that come up after the first &lt;em&gt;n&lt;/em&gt; are
better, he must settle for the last.&lt;/p&gt;

&lt;hr /&gt;

&lt;div id=&quot;kj-plotting-area&quot;&gt;&lt;/div&gt;
&lt;hr /&gt;

&lt;p&gt;The results are striking! If he doesn’t look at any jewels and always pick the
first one, he’s equally likely to get any of the jewels. That is, the
chances of picking the best one are 1/9. If he looks at one, discards it and
then pick the next jewel which is better than any of the discarded, the chances of
picking the best jewel increase dramatically to almost 4 / 10! In fact, the
entire distribution gets skewed right and the chances of picking the second
and third best jewels also significantly increase.&lt;/p&gt;

&lt;p&gt;But the hero is after the best. From the histogram above, it’s hard to see how
many he has to see and discard to maximize the chances of picking the
best one. For that we can either run a simulation with lots of jewels and lots
of iterations. Or we can run simulations for increasing numbers of jewels and 
plot how many one has to look at, to maximize his/her chances of getting the best:&lt;/p&gt;

&lt;hr /&gt;

&lt;div id=&quot;kj-regression-area&quot; style=&quot;width: 400px; margin-left: auto; margin-right: auto;&quot;&gt;&lt;/div&gt;
&lt;hr /&gt;

&lt;p&gt;What this chart shows is that the number one needs look at and throw out to
maximize the chances of finding the best grows linearly with the number of
jewels. The slope of the line (0.36), indicates the fraction of the total
number of jewels that we should examine before picking the next best.&lt;/p&gt;

&lt;p&gt;The red line shows how many we one should look at to maximize the average value
of the kept jewel. If we try and maximize the chances of bagging the best
jewel, we also increase the chances that we end up with the worst. When trying
to get the highest value on average, one should look at fewer options before
deciding to stick with the next best.&lt;/p&gt;

&lt;h4 id=&quot;what-if-the-jewels-are&quot;&gt;What if the jewels are…?&lt;/h4&gt;

&lt;p&gt;But what if the values of the jewels are not uniformly distributed? What if most
jewels are average in value and only a few are either precious or worthless? Or
what if most jewels have a low value with only a few true gems? The next two sections
show the results when the jewels are normally distributed (mostly average) and
exponentially distributed (mostly low-value).&lt;/p&gt;

&lt;div class=&quot;accordion&quot; id=&quot;accordion_kings_jewels&quot;&gt;
    &lt;div class=&quot;accordion-group&quot;&gt;
        &lt;div class=&quot;accordion-heading&quot;&gt;
            &lt;a class=&quot;accordion-toggle&quot; data-toggle=&quot;collapse&quot; data-parent=&quot;#accordion_kings_jewels&quot; href=&quot;#collapseNormalJewelDist&quot;&gt;
            &lt;b&gt;Normally Distributed Jewels&lt;/b&gt;
            &lt;/a&gt;
        &lt;/div&gt;

        &lt;div id=&quot;collapseNormalJewelDist&quot; class=&quot;accordion-body collapse out&quot;&gt;
            &lt;div class=&quot;accordion-inner&quot;&gt;

            &lt;div id=&quot;kj-plotting-area-normal&quot;&gt;&lt;/div&gt;
            &lt;hr /&gt;
            &lt;div id=&quot;kj-regression-area-normal&quot; style=&quot;width: 400px; margin-left: auto; margin-right: auto;&quot;&gt;&lt;/div&gt;

            &lt;/div&gt;
        &lt;/div&gt;
    &lt;/div&gt;

    &lt;div class=&quot;accordion-group&quot;&gt;
        &lt;div class=&quot;accordion-heading&quot;&gt;
            &lt;a class=&quot;accordion-toggle&quot; data-toggle=&quot;collapse&quot; data-parent=&quot;#accordion_kings_jewels&quot; href=&quot;#collapseExponentialJewelDist&quot;&gt;
            &lt;b&gt;Exponentially Distributed Jewels&lt;/b&gt;
            &lt;/a&gt;
        &lt;/div&gt;
        &lt;div id=&quot;collapseExponentialJewelDist&quot; class=&quot;accordion-body collapse out&quot;&gt;
            &lt;div class=&quot;accordion-inner&quot;&gt;

            &lt;div id=&quot;kj-plotting-area-exponential&quot;&gt;&lt;/div&gt;
            &lt;hr /&gt;
            &lt;div id=&quot;kj-regression-area-exponential&quot; style=&quot;width: 400px; margin-left: auto; margin-right: auto;&quot;&gt;&lt;/div&gt;

            &lt;/div&gt;
        &lt;/div&gt;
    &lt;/div&gt;
&lt;/div&gt;

&lt;h4 id=&quot;moral-of-the-story&quot;&gt;Moral of the Story&lt;/h4&gt;

&lt;p&gt;So what should we tell our king-saving friend?&lt;/p&gt;

&lt;p&gt;As long as there’s more than one option and you want to get the best reward
possible, always discard the first third (or 1/&lt;i&gt;e&lt;/i&gt;‘th, where &lt;i&gt;e&lt;/i&gt; is &lt;a href=&quot;https://en.wikipedia.org/wiki/E_(mathematical_constant)&quot;&gt;Euler’s Number&lt;/a&gt;, to be more precise) of the options and then pick the next
one which is better than any you have seen so far. If you want something better
than average but not necessarily the best, discard fewer. Or, to put it more
succintly:&lt;/p&gt;

&lt;center&gt;&lt;b&gt;NEVER take the first offer when you have more than one choice!&lt;/b&gt;&lt;/center&gt;

&lt;script src=&quot;/js/lib/d3-grid.js&quot;&gt;&lt;/script&gt;

&lt;script src=&quot;/js/kings-jewels.js&quot;&gt;&lt;/script&gt;

&lt;script type=&quot;text/javascript&quot;&gt;
    kingsJewelsExample();
&lt;/script&gt;

&lt;h4 id=&quot;acknowledgements&quot;&gt;Acknowledgements&lt;/h4&gt;

&lt;ul&gt;
    &lt;li&gt;Huge thanks to &lt;a href=&quot;http://www.cs.cmu.edu/~rudich/&quot;&gt;Steven Rudich&lt;/a&gt; for introducing me to the
    King's Jewels problem a long time ago during a summer lecture at the
    &lt;a href=&quot;http://www.cs.cmu.edu/~./leap/&quot;&gt;Andrew's Leap program at CMU.&lt;/a&gt;&lt;/li&gt;

    &lt;li&gt; Thanks to &lt;a href=&quot;http://trentrichardson.com/2010/04/06/compute-linear-regressions-in-javascript/&quot;&gt;Trent Richardson&lt;/a&gt; for the javascript implementation of a linear regression
    function.  &lt;/li&gt;
&lt;/ul&gt;</content><author><name></name></author><category term="problem" /><summary type="html"></summary></entry><entry><title type="html">Graph Proportions and Label Sizes</title><link href="http://emptypipes.org/2015/10/18/publication-figure-sizes/" rel="alternate" type="text/html" title="Graph Proportions and Label Sizes" /><published>2015-10-18T00:00:00+00:00</published><updated>2015-10-18T00:00:00+00:00</updated><id>http://emptypipes.org/2015/10/18/publication-figure-sizes</id><content type="html" xml:base="http://emptypipes.org/2015/10/18/publication-figure-sizes/">&lt;meta charset=&quot;utf-8&quot; /&gt;

&lt;p&gt;&lt;img itemprop=&quot;image&quot; src=&quot;/img/layouts_upon_layouts_itemprop.png&quot; style=&quot;display:none&quot; width=&quot;200&quot; height=&quot;130&quot; /&gt;&lt;/p&gt;

&lt;p&gt;The example below shows how to create a graph that is both aesthetically
pleasing and sensibly proportioned. I used these parameters to generate the
majority of the figures in my PhD thesis.  The &lt;code class=&quot;highlighter-rouge&quot;&gt;savefig&lt;/code&gt; function can also be
used to save a pdf or an svg file for modification in your favorite image
editor (e.g. inkscape).&lt;/p&gt;

&lt;hr /&gt;

&lt;p&gt;&lt;img src=&quot;/img/trigonometric_functions.png&quot; width=&quot;250&quot; align=&quot;middle&quot; /&gt;&lt;/p&gt;
&lt;hr /&gt;

&lt;p&gt;The code to generate this plot uses the &lt;a href=&quot;http://stanford.edu/~mwaskom/software/seaborn/&quot;&gt;seaborn&lt;/a&gt; library in
 an &lt;a href=&quot;http://ipython.org/notebook.html&quot;&gt;IPython notebook:&lt;/a&gt;&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-python&quot; data-lang=&quot;python&quot;&gt;&lt;span class=&quot;o&quot;&gt;%&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;load_ext&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;autoreload&lt;/span&gt;
&lt;span class=&quot;o&quot;&gt;%&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;autoreload&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;2&lt;/span&gt;
&lt;span class=&quot;o&quot;&gt;%&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;pylab&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;inline&lt;/span&gt;

&lt;span class=&quot;kn&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;numpy&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;as&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;np&lt;/span&gt;
&lt;span class=&quot;kn&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;seaborn&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;as&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;sns&lt;/span&gt;

&lt;span class=&quot;n&quot;&gt;rc&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;'text'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;usetex&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;bp&quot;&gt;True&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;plt&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;rc&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;'font'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;family&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;'Palatino'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;sns&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;set_style&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;'white'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;sns&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;set_context&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;notebook&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;font_scale&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;mf&quot;&gt;1.0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;rc&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;lines.linewidth&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;})&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;rc&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;'text'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;usetex&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;bp&quot;&gt;True&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;    &lt;span class=&quot;c&quot;&gt;# use latex in the labels&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;pylab&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;rcParams&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;'figure.figsize'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mf&quot;&gt;1.3&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;mf&quot;&gt;1.0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;


&lt;span class=&quot;n&quot;&gt;font&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;'family'&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;'serif'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;s&quot;&gt;'serif'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;'Palatino'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;s&quot;&gt;'weight'&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;'bold'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;s&quot;&gt;'size'&lt;/span&gt;   &lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;11&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;n&quot;&gt;matplotlib&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;rc&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;'font'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;**&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;font&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;

&lt;span class=&quot;c&quot;&gt;# create the dummy data&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;x&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;np&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;linspace&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;math&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;pi&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;100&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;y&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;sin&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;x&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;z&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;cos&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;x&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;

&lt;span class=&quot;c&quot;&gt;# plot that sucker&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;fig&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;ax&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;plt&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;subplots&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;ax&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;plot&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;x&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;y&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;label&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;'sin'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;ax&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;plot&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;x&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;z&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;label&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;'cos'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;

&lt;span class=&quot;n&quot;&gt;ax&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;set_xlabel&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;'x'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;ax&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;set_ylabel&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;'y'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;ax&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;axvline&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;x&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;3&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;color&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;'red'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;ls&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;'dashed'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;ax&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;set_title&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;'Trigonometric Functions'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;y&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;mf&quot;&gt;1.08&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;

&lt;span class=&quot;n&quot;&gt;ax&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;spines&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;'right'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;set_visible&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;bp&quot;&gt;False&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;ax&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;spines&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;'top'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;set_visible&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;bp&quot;&gt;False&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;

&lt;span class=&quot;n&quot;&gt;pyplot&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;locator_params&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;nbins&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;7&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;for&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;item&lt;/span&gt; &lt;span class=&quot;ow&quot;&gt;in&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;([&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;ax&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;title&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;ax&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;xaxis&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;label&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;ax&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;yaxis&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;label&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;+&lt;/span&gt;
         &lt;span class=&quot;n&quot;&gt;ax&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;get_xticklabels&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;ax&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;get_yticklabels&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()):&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;item&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;set_fontsize&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;10&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;

&lt;span class=&quot;n&quot;&gt;handles&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;labels&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;ax&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;get_legend_handles_labels&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;ax&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;legend&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;handles&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;labels&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;bbox_to_anchor&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mf&quot;&gt;1.8&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mf&quot;&gt;0.85&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))&lt;/span&gt;

&lt;span class=&quot;n&quot;&gt;plt&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;savefig&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;'img/trigonometric_functions.png'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;dpi&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;500&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;bbox_inches&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;tight&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;</content><author><name></name></author><category term="python" /><category term="matplotlib" /><category term="research" /><summary type="html"></summary></entry></feed>