<?xml version="1.0" encoding="UTF-8"?>
<?xml-stylesheet type="text/xsl" media="screen" href="/~d/styles/atom10full.xsl"?><?xml-stylesheet type="text/css" media="screen" href="http://feeds.feedburner.com/~d/styles/itemcontent.css"?><feed xmlns="http://www.w3.org/2005/Atom" xmlns:feedburner="http://rssnamespace.org/feedburner/ext/1.0">
  <title>Tom MacWright</title>
  
  <link href="http://macwright.org/" />
  <updated>2012-02-19T15:42:14-08:00</updated>
  <id>http://macwright.org/</id>
  <author>
    <name>Tom MacWright</name>
    <email>tom@macwright.org</email>
  </author>
  
  <atom10:link xmlns:atom10="http://www.w3.org/2005/Atom" rel="self" type="application/atom+xml" href="http://feeds.feedburner.com/tommacwright/odWX" /><feedburner:info uri="tommacwright/odwx" /><atom10:link xmlns:atom10="http://www.w3.org/2005/Atom" rel="hub" href="http://pubsubhubbub.appspot.com/" /><feedburner:feedFlare href="http://add.my.yahoo.com/rss?url=http%3A%2F%2Ffeeds.feedburner.com%2Ftommacwright%2FodWX" src="http://us.i1.yimg.com/us.yimg.com/i/us/my/addtomyyahoo4.gif">Subscribe with My Yahoo!</feedburner:feedFlare><feedburner:feedFlare href="http://www.newsgator.com/ngs/subscriber/subext.aspx?url=http%3A%2F%2Ffeeds.feedburner.com%2Ftommacwright%2FodWX" src="http://www.newsgator.com/images/ngsub1.gif">Subscribe with NewsGator</feedburner:feedFlare><feedburner:feedFlare href="http://feeds.my.aol.com/add.jsp?url=http%3A%2F%2Ffeeds.feedburner.com%2Ftommacwright%2FodWX" src="http://o.aolcdn.com/favorites.my.aol.com/webmaster/ffclient/webroot/locale/en-US/images/myAOLButtonSmall.gif">Subscribe with My AOL</feedburner:feedFlare><feedburner:feedFlare href="http://www.bloglines.com/sub/http://feeds.feedburner.com/tommacwright/odWX" src="http://www.bloglines.com/images/sub_modern11.gif">Subscribe with Bloglines</feedburner:feedFlare><feedburner:feedFlare href="http://www.netvibes.com/subscribe.php?url=http%3A%2F%2Ffeeds.feedburner.com%2Ftommacwright%2FodWX" src="http://www.netvibes.com/img/add2netvibes.gif">Subscribe with Netvibes</feedburner:feedFlare><feedburner:feedFlare href="http://fusion.google.com/add?feedurl=http%3A%2F%2Ffeeds.feedburner.com%2Ftommacwright%2FodWX" src="http://buttons.googlesyndication.com/fusion/add.gif">Subscribe with Google</feedburner:feedFlare><feedburner:feedFlare href="http://www.pageflakes.com/subscribe.aspx?url=http%3A%2F%2Ffeeds.feedburner.com%2Ftommacwright%2FodWX" src="http://www.pageflakes.com/ImageFile.ashx?instanceId=Static_4&amp;fileName=ATP_blu_91x17.gif">Subscribe with Pageflakes</feedburner:feedFlare><feedburner:feedFlare href="http://www.plusmo.com/add?url=http%3A%2F%2Ffeeds.feedburner.com%2Ftommacwright%2FodWX" src="http://plusmo.com/res/graphics/fbplusmo.gif">Subscribe with Plusmo</feedburner:feedFlare><feedburner:feedFlare href="http://www.thefreedictionary.com/_/hp/AddRSS.aspx?http%3A%2F%2Ffeeds.feedburner.com%2Ftommacwright%2FodWX" src="http://img.tfd.com/hp/addToTheFreeDictionary.gif">Subscribe with The Free Dictionary</feedburner:feedFlare><feedburner:feedFlare href="http://www.bitty.com/manual/?contenttype=rssfeed&amp;contentvalue=http%3A%2F%2Ffeeds.feedburner.com%2Ftommacwright%2FodWX" src="http://www.bitty.com/img/bittychicklet_91x17.gif">Subscribe with Bitty Browser</feedburner:feedFlare><feedburner:feedFlare href="http://www.live.com/?add=http%3A%2F%2Ffeeds.feedburner.com%2Ftommacwright%2FodWX" src="http://tkfiles.storage.msn.com/x1piYkpqHC_35nIp1gLE68-wvzLZO8iXl_JMledmJQXP-XTBOLfmQv4zhj4MhcWEJh_GtoBIiAl1Mjh-ndp9k47If7hTaFno0mxW9_i3p_5qQw">Subscribe with Live.com</feedburner:feedFlare><feedburner:feedFlare href="http://mix.excite.eu/add?feedurl=http%3A%2F%2Ffeeds.feedburner.com%2Ftommacwright%2FodWX" src="http://image.excite.co.uk/mix/addtomix.gif">Subscribe with Excite MIX</feedburner:feedFlare><feedburner:feedFlare href="http://www.webwag.com/wwgthis.php?url=http%3A%2F%2Ffeeds.feedburner.com%2Ftommacwright%2FodWX" src="http://www.webwag.com/images/wwgthis.gif">Subscribe with Webwag</feedburner:feedFlare><feedburner:feedFlare href="http://www.podcastready.com/oneclick_bookmark.php?url=http%3A%2F%2Ffeeds.feedburner.com%2Ftommacwright%2FodWX" src="http://www.podcastready.com/images/podcastready_button.gif">Subscribe with Podcast Ready</feedburner:feedFlare><feedburner:feedFlare href="http://www.wikio.com/subscribe?url=http%3A%2F%2Ffeeds.feedburner.com%2Ftommacwright%2FodWX" src="http://www.wikio.com/shared/img/add2wikio.gif">Subscribe with Wikio</feedburner:feedFlare><feedburner:feedFlare href="http://www.dailyrotation.com/index.php?feed=http%3A%2F%2Ffeeds.feedburner.com%2Ftommacwright%2FodWX" src="http://www.dailyrotation.com/rss-dr2.gif">Subscribe with Daily Rotation</feedburner:feedFlare><entry>
    <title>Minute</title>
    <link href="http://feedproxy.google.com/~r/tommacwright/odWX/~3/T5TqtFe__W0/minute.html" />
    <updated>2012-02-15T10:00:00Z</updated>
    <id>http://macwright.org/2012/02/15/minute</id>
    <content type="html">&lt;p&gt;&lt;a href='http://macwright.org/minute/'&gt;&lt;img width='640' src='/graphics/minute_new.png' title='around 1 million keystrokes' /&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;img width='640' height='200' src='/graphics/minute_flow.png' title='flow between the alphabet' /&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="http://macwright.org/minute/"&gt;Minute&lt;/a&gt; counts keystrokes and every
two minutes records how many keystrokes
have transpired in a &lt;a href="http://en.wikipedia.org/wiki/Comma-separated_values"&gt;CSV file&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;&lt;a href="http://github.com/tmcw/minute"&gt;Minute-reader&lt;/a&gt; uses &lt;a href="http://mbostock.github.com/d3/"&gt;d3&lt;/a&gt;
to build a visualization in the style of &lt;a href="http://en.wikipedia.org/wiki/Gel_electrophoresis"&gt;gel electrophoresis&lt;/a&gt;.
It loads minute&amp;rsquo;s data directly using d3&amp;rsquo;s
CSV reader &amp;ndash; the data is compact, so months of data should still be usable.&lt;/p&gt;

&lt;p&gt;It&amp;rsquo;s a subset of functionality that I found to
be really compelling in &lt;a href="http://www.workrave.org/"&gt;workrave&lt;/a&gt;
and &lt;a href="https://www.rescuetime.com/"&gt;RescueTime&lt;/a&gt; &amp;ndash; it doesn&amp;rsquo;t do anything
with the internet, like RescueTime, or tell you to change your ways
like WorkRave and other RSI-related applications.&lt;/p&gt;

&lt;p&gt;It&amp;rsquo;s easier for me to track my usage of technology
accurately than it is to track non-usage, so I&amp;rsquo;ll treat leisure and sleep
time as the inverse and make no attempt to do some kind of &lt;a href="http://arduino.cc"&gt;Arduino&lt;/a&gt;
hack to track hours of sleep.&lt;/p&gt;

&lt;p&gt;&lt;img width='640' height='100' src='/graphics/minute_bar.png' title='tracking keystrokes-containing time versus total' /&gt;&lt;/p&gt;

&lt;p&gt;The code is open-source and adaptable, but the Objective-C is shoddy
and would love improvement. For what it&amp;rsquo;s worth, &lt;a href="http://www.apple.com/"&gt;Apple&lt;/a&gt;
makes keylogger-writing easy with a very direct API:&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre&gt;&lt;code class="objc"&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;NSEvent&lt;/span&gt;
     &lt;span class="nl"&gt;addGlobalMonitorForEventsMatchingMask:&lt;/span&gt;&lt;span class="n"&gt;NSKeyDownMask&lt;/span&gt;
     &lt;span class="nl"&gt;handler:&lt;/span&gt;&lt;span class="o"&gt;^&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;NSEvent&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;event&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;




&lt;div class="highlight"&gt;&lt;pre&gt;&lt;code class="sh"&gt;~⇾ tail ~/log/keystrokes.log
1323966900, 206
1323967020, 76
1323967140, 27
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;


&lt;p&gt;Minute doesn&amp;rsquo;t log which keys &amp;ndash; only their frequency. An evil version,
&amp;lsquo;thisisakeylogger&amp;rsquo;, does track keys but isn&amp;rsquo;t open source. It&amp;rsquo;s what I used to
generate graphs of key transitions.&lt;/p&gt;

&lt;p&gt;&lt;img width='640' height='65' src='/graphics/minute_incidence.png' title='transitions between lowercase keys' /&gt;&lt;/p&gt;

&lt;p&gt;&lt;img width='640' height='200' src='/graphics/minute_sleep.png' title='hours of sleep per night' /&gt;&lt;/p&gt;

&lt;p&gt;Incidence statistics make my &lt;a href="http://www.vim.org/"&gt;vim&lt;/a&gt; usage apparent: jj, kk, ww, and bb
are all &amp;lsquo;gestures&amp;rsquo; in the editor.&lt;/p&gt;

&lt;p&gt;The above charts (besides minute&amp;rsquo;s own output) are generated using
really simple bits of code with &lt;a href="https://github.com/LearnBoost/node-canvas"&gt;node-canvas&lt;/a&gt;
as my preferred drawing toolkit. It&amp;rsquo;s simple and near-perfect &amp;ndash;
the Canvas specification doesn&amp;rsquo;t jive with bitmap fonts, so I might
need to write some custom code to make &lt;a href="http://kottke.org/plus/type/silkscreen/"&gt;Silkscreen&lt;/a&gt; usable.&lt;/p&gt;

&lt;p&gt;I&amp;rsquo;ve been really interested in the style of my friend
&lt;a href="http://www.zeolitefuhrman.com/category/visualization/"&gt;Zeolite Fuhrman&lt;/a&gt;
and the various projects going around based on
&lt;a href="http://libcinder.org/"&gt;libcinder&lt;/a&gt;. The other big design style is
&lt;a href="http://mbostock.github.com/d3"&gt;d3&amp;rsquo;s&lt;/a&gt; &amp;ndash; white background, Helvetica'ed,
&lt;a href="http://colorbrewer2.org/"&gt;ColorBrewer'ed&lt;/a&gt; information. Somewhere between the two
seems about right &amp;ndash; there&amp;rsquo;s a certain beauty to infographics that are made
to be puzzling for a few seconds before the understanding strikes.&lt;/p&gt;

&lt;p&gt;Tracking nearly anything you do is alarming
and humbling. The aggregates of our actions are lost on us: we can
watch hundreds of hours of television and write it off as a small time commitment.
How much is too much? It&amp;rsquo;s hard to make pretty charts without learning something
and thinking about what they &lt;em&gt;should&lt;/em&gt; look like.&lt;/p&gt;
&lt;img src="http://feeds.feedburner.com/~r/tommacwright/odWX/~4/T5TqtFe__W0" height="1" width="1"/&gt;</content>
    <author>
      <name>Tom MacWright</name>
      <uri>http://macwright.org/about/</uri>
    </author>
  <feedburner:origLink>http://macwright.org/2012/02/15/minute.html</feedburner:origLink></entry>
  
  <entry>
    <title>Recently</title>
    <link href="http://feedproxy.google.com/~r/tommacwright/odWX/~3/3U_QX1scZPc/recently.html" />
    <updated>2012-02-09T10:00:00Z</updated>
    <id>http://macwright.org/2012/02/09/recently</id>
    <content type="html">&lt;p&gt;&lt;img src='http://farm8.staticflickr.com/7065/6844371477_ecaf998991_o.png' height='1928' width='640' title='Everyman By Philip Roth, Liars and Outliers by Bruce Schneider, The Banjo Players Handbook by Tim Jumper, a Visit from the Goon Squad by Jennifer Egan, photos from a recent Philadelphia trip, and output of a keylogger' /&gt;&lt;/p&gt;
&lt;img src="http://feeds.feedburner.com/~r/tommacwright/odWX/~4/3U_QX1scZPc" height="1" width="1"/&gt;</content>
    <author>
      <name>Tom MacWright</name>
      <uri>http://macwright.org/about/</uri>
    </author>
  <feedburner:origLink>http://macwright.org/2012/02/09/recently.html</feedburner:origLink></entry>
  
  <entry>
    <title>Shadowplay</title>
    <link href="http://feedproxy.google.com/~r/tommacwright/odWX/~3/LIc_4kJNpW8/shadowplay.html" />
    <updated>2012-02-05T10:00:00Z</updated>
    <id>http://macwright.org/2012/02/05/shadowplay</id>
    <content type="html">&lt;iframe width='640' height='360' frameBorder='0' src='http://a.tiles.mapbox.com/v3/tmcw.shadowplay.html#2/0/0.000'&gt;&lt;/iframe&gt;


&lt;p&gt;&lt;img src='/graphics/shadowplay.gif' width='640' height='540' /&gt;&lt;/p&gt;

&lt;p&gt;Inspired by &lt;a href="http://en.wikipedia.org/wiki/Unknown_Pleasures"&gt;Unknown Pleasures&lt;/a&gt;
by &lt;a href="http://en.wikipedia.org/wiki/Joy_Division"&gt;Joy Division&lt;/a&gt;,
&lt;a href="http://adamcap.com/2011/05/history-of-joy-division-unknown-pleasures-album-art/"&gt;inspired by the radio transmissions of a pulsar&lt;/a&gt;,
rendered with &lt;a href="http://tilemill.com/"&gt;TileMill&lt;/a&gt; and served by &lt;a href="http://mapbox.com/hosting/"&gt;MapBox Hosting&lt;/a&gt;.
Perturbed by &lt;a href="http://pitchfork.com/news/45193-disney-is-selling-a-joy-division-mickey-mouse-shirt/"&gt;the Mickey Mouse Waves shirt&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;src: &lt;a href='https://gist.github.com/1746328'&gt;shadowplay.py&lt;/a&gt;. The GIF above
triggers a variety of amusing browser bugs.&lt;/p&gt;
&lt;img src="http://feeds.feedburner.com/~r/tommacwright/odWX/~4/LIc_4kJNpW8" height="1" width="1"/&gt;</content>
    <author>
      <name>Tom MacWright</name>
      <uri>http://macwright.org/about/</uri>
    </author>
  <feedburner:origLink>http://macwright.org/2012/02/05/shadowplay.html</feedburner:origLink></entry>
  
  <entry>
    <title>Rhumb Lines and Great Circles</title>
    <link href="http://feedproxy.google.com/~r/tommacwright/odWX/~3/8A42RKEGhcM/rhumb-lines-great-circles.html" />
    <updated>2012-02-02T10:00:00Z</updated>
    <id>http://macwright.org/2012/02/02/rhumb-lines-great-circles</id>
    <content type="html">&lt;p&gt;&lt;img src="http://farm8.staticflickr.com/7033/6785847925_6528fa1fd5_z.jpg" alt="Rhumb Lines and Great Circles" /&gt;&lt;/p&gt;

&lt;p&gt;&lt;img src="http://farm8.staticflickr.com/7035/6785847071_6bccc4b9fd_z.jpg" alt="Rhumb Angle" /&gt;&lt;/p&gt;

&lt;p&gt;&lt;img src="http://farm8.staticflickr.com/7001/6785845707_8d2d0e3856_z.jpg" alt="Spirals instead of Circles" /&gt;&lt;/p&gt;

&lt;p&gt;&lt;img src="http://farm8.staticflickr.com/7150/6785844645_34ffb9fdcb_z.jpg" alt="Easy to Find North" /&gt;&lt;/p&gt;

&lt;p&gt;&lt;img src="http://farm8.staticflickr.com/7148/6785843017_8599af8481_z.jpg" alt="Great Circle" /&gt;&lt;/p&gt;

&lt;p&gt;&lt;img src="http://farm8.staticflickr.com/7161/6785841859_4a00e614c1_z.jpg" alt="Splits the World" /&gt;&lt;/p&gt;

&lt;p&gt;&lt;img src="http://farm8.staticflickr.com/7034/6785840809_2c70633dcd_z.jpg" alt="The End" /&gt;&lt;/p&gt;

&lt;p&gt;This post is &lt;a href="http://www.flickr.com/photos/tmcw/sets/72157629090641837/with/6785845707/"&gt;also available as a photoset on Flickr&lt;/a&gt;.&lt;/p&gt;
&lt;img src="http://feeds.feedburner.com/~r/tommacwright/odWX/~4/8A42RKEGhcM" height="1" width="1"/&gt;</content>
    <author>
      <name>Tom MacWright</name>
      <uri>http://macwright.org/about/</uri>
    </author>
  <feedburner:origLink>http://macwright.org/2012/02/02/rhumb-lines-great-circles.html</feedburner:origLink></entry>
  
  <entry>
    <title>Understanding Map Projections</title>
    <link href="http://feedproxy.google.com/~r/tommacwright/odWX/~3/nHUo1O3vWYg/projections-understanding.html" />
    <updated>2012-01-27T10:00:00Z</updated>
    <id>http://macwright.org/2012/01/27/projections-understanding</id>
    <content type="html">&lt;p&gt;&lt;em&gt;Beware: this is a post about opinions and concepts, rather than
about &lt;a href="http://macwright.org/2011/10/28/big.html"&gt;releasing software&lt;/a&gt;
or &lt;a href="http://macwright.org/2011/10/06/javascript.html"&gt;learning about things&lt;/a&gt;.&lt;/em&gt;
And, while I am a &amp;lsquo;professional&amp;rsquo;, I&amp;rsquo;m a software developer first
and a &lt;a href="http://en.wikipedia.org/wiki/Neogeography"&gt;neogeographer&lt;/a&gt;
second, and have yet to print out a map.&lt;/p&gt;

&lt;h2&gt;What are Map Projections?&lt;/h2&gt;

&lt;blockquote&gt;&lt;p&gt;Chastising the Spanish artist for painting unrepresentative
cubistic abstractions, a layman withdrew a photograph of his wife
from his pocket and held it up to Picasso with the
admonition, &amp;ldquo;Why can’t you paint realistically, like that?&amp;rdquo;
&amp;ldquo;Is that what your wife really looks like?&amp;rdquo;
Picasso asked. &amp;ldquo;Yes,&amp;rdquo; replied the man.
&amp;ldquo;Well, she’s very small, and quite flat.&amp;rdquo;&lt;/p&gt;&lt;/blockquote&gt;

&lt;p&gt;&lt;span class='image-credit'&gt;
  &lt;a href='http://www.amazon.com/dp/B005VDX0HQ/ref=r_soa_w_d'&gt;Dorion Sagan,
in Dazzle Gradually&lt;/a&gt;
&lt;/span&gt;&lt;/p&gt;

&lt;p&gt;Map projections are _creative ways to represent a three-dimensional
world as a differently-shaped thing, usually something flat &amp;ndash; so you can
print or pan out your map. They&amp;rsquo;re compromises between different sorts
of accuracy and usefulness.&lt;/p&gt;

&lt;p&gt;Even if one were to reject projections entirely and go into space to
take a gander at the real thing, they could only see one side of the world
at a time &amp;ndash; a disadvantage relative to your common world map.&lt;/p&gt;

&lt;p&gt;So you always lose something in abstractions. Projections are a
&lt;strong&gt;trade between distortion, accuracy, and aesthetics&lt;/strong&gt;. Some projections
wildly distort all paths except for one, like
&lt;a href="http://en.wikipedia.org/wiki/Craig_retroazimuthal_projection"&gt;Craig retroazimuthal&lt;/a&gt;.
Others only show part of the globe, like &lt;a href="http://ds.io/uAlbZ8"&gt;the orthographic&lt;/a&gt;
or &lt;a href="http://en.wikipedia.org/wiki/General_Perspective_projection"&gt;general perspective&lt;/a&gt;.
And still others will wildly distort the size of things on the earth,
like &lt;a href="http://en.wikipedia.org/wiki/Mercator_projection"&gt;mercator&lt;/a&gt;, the familiar
face of &lt;a href="http://mapbox.com/"&gt;MapBox&lt;/a&gt; and &lt;a href="http://maps.google.com/"&gt;Google Maps&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;You can&amp;rsquo;t get it all: thanks to the &lt;a href="http://en.wikipedia.org/wiki/Theorema_Egregium"&gt;Theorema Egregium&lt;/a&gt;,
we know that projections from a sphere to a 2D surface will always distort
either directionality or area.&lt;/p&gt;

&lt;h2&gt;Projections are Old&lt;/h2&gt;

&lt;p&gt;&lt;img src="http://farm8.staticflickr.com/7143/6770797541_8a9f131e26_z.jpg" alt="mercator old" /&gt;&lt;/p&gt;

&lt;p&gt;&lt;span class='image-credit'&gt;
  &lt;a href='http://en.wikipedia.org/wiki/File:Mercator_1569.png'&gt;1569 Mercator World Map&lt;/a&gt;
&lt;/span&gt;&lt;/p&gt;

&lt;p&gt;Map projections are about as old as paper maps, though the modern
&amp;lsquo;science of cartographic projections&amp;rsquo; is a work in progress.&lt;/p&gt;

&lt;p&gt;This matters: the &amp;lsquo;Mercator projection&amp;rsquo;, invented by
&lt;a href="http://en.wikipedia.org/wiki/Gerardus_Mercator"&gt;Gerardus Mercator&lt;/a&gt;
around 1569, was a hit because it&amp;rsquo;s useful for sailing: it preserves
angles, a property known as &lt;a href="http://en.wikipedia.org/wiki/Conformality"&gt;conformality&lt;/a&gt;.
Sea voyaging was a big deal, and having a map with which you could
draw a line from one place to another and sail &lt;em&gt;that path&lt;/em&gt; without
hitting a continent was pretty useful.&lt;/p&gt;

&lt;h2&gt;Projections are New&lt;/h2&gt;

&lt;p&gt;It turned out that a variant of the Mercator projection, what we call
&lt;a href="http://docs.openlayers.org/library/spherical_mercator.html"&gt;spherical mercator&lt;/a&gt;,
not only had this property, but also is really easy to calculate:
here&amp;rsquo;s an implementation in Javascript:&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre&gt;&lt;code class="js"&gt;&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nx"&gt;lonlat_to_meters&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;ll&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;var&lt;/span&gt; &lt;span class="nx"&gt;A&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;6378137&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;D2R&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;Math&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;PI&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt; &lt;span class="mi"&gt;180&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
        &lt;span class="nx"&gt;A&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="nx"&gt;ll&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="nx"&gt;D2R&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="nx"&gt;A&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="nb"&gt;Math&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;Math&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;tan&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nb"&gt;Math&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;PI&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="mf"&gt;0.25&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mf"&gt;0.5&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="nx"&gt;ll&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="nx"&gt;D2R&lt;/span&gt;&lt;span class="p"&gt;)))&lt;/span&gt;
    &lt;span class="p"&gt;];&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;


&lt;p&gt;Sure, this loses critical aspects of traditional cartography: not only
does it distort scale, it treats the Earth as a sphere, when it&amp;rsquo;s more the shape
of a squashed, dimpled ball.&lt;/p&gt;

&lt;p&gt;But technology is a result of its environment and requirements, not any absolute
value: spherical mercator fits the role of a simple, fast, &lt;strong&gt;pannable, and zoomable&lt;/strong&gt; projection
like no other common projection.&lt;/p&gt;

&lt;p&gt;Much like how the original mercator projection was developed for sea voyages,
the projection that we now use is developed for web maps, and carries the marks
of that purpose. In a future where dynamic morphing of data is cheap and 3D is
the standard, it might seem outdated &amp;ndash; but it will still be no more or less
right than any other choice.&lt;/p&gt;

&lt;p&gt;So maps need to be &lt;strong&gt;zoomable&lt;/strong&gt;: this would be nonsense twenty years ago,
but is vital today. The value of Google Maps is not in its whole-earth view,
but when it&amp;rsquo;s zoomed up to street or province level, where it looks pretty darn
good. And maps that don&amp;rsquo;t zoom on the internet are considered &lt;strong&gt;broken&lt;/strong&gt;: user
expectations are set hard by our constant scroll-wheeling and pinching to think
that anything that could get closer should. This forces modern cartographers
to re-weight the importance of global views versus local, and rethink styling.&lt;/p&gt;

&lt;p&gt;&lt;img src="http://farm8.staticflickr.com/7163/6770797463_02d30be1d7_o.png" alt="Paper ends" /&gt;&lt;/p&gt;

&lt;p&gt;And they&amp;rsquo;re typically &lt;strong&gt;pannable&lt;/strong&gt;. There are beautiful projections, like
&lt;a href="http://en.wikipedia.org/wiki/Albers_projection"&gt;the Albers projection&lt;/a&gt;,
with beautiful implementations, like the one above from
&lt;a href="http://mbostock.github.com/d3/ex/choropleth.html"&gt;d3, an incredible visualization library&lt;/a&gt;.
But one can feel the influence of paper: what happens at the edges? Where
is the context? Of course, in the age of posters in offices and printouts
for GIS class, it doesn&amp;rsquo;t matter if the world ends at the corners of the US
or New Jersey.&lt;/p&gt;

&lt;p&gt;And projections like Albers do indeed continue,
but &lt;a href="http://en.wikipedia.org/wiki/Albers_projection"&gt;not quite like you&amp;rsquo;d expect&lt;/a&gt;:
sometimes sweeping up the edges of the page instead of continuing horizontally
as you scroll.&lt;/p&gt;

&lt;p&gt;The sum of this change is that currently conformality, that aspect of
preserving direction that spherical mercator handles deftly, is possibly
the highest priority for the majority of web maps.&lt;/p&gt;

&lt;p&gt;But these requirements are based on the current state of technology: that
square tiles, of size 256x256, are the way that people get maps. And that
the map one person sees is the the one everyone else does. These restrictions
are based on technological hurdles that are likely to fade:
&lt;a href="http://googleblog.blogspot.com/2011/10/step-inside-map-with-google-mapsgl.html"&gt;MapsGL&lt;/a&gt; is
the first &amp;lsquo;production&amp;rsquo; vector web map, and Apple is rumored to be working
on &lt;a href="http://ds.io/zBBsOi"&gt;&amp;lsquo;napkin maps&amp;rsquo;&lt;/a&gt; that are tailored to one specific
route. It&amp;rsquo;s likely that driving directions will no longer show
extraneous roads, or that the projection you see zoomed-out, looking at
the entire world, is the same one as you see close-up.&lt;/p&gt;

&lt;p&gt;This is the first quick bit I&amp;rsquo;m going to write on projections. Hopefully
the rest will follow &lt;a href="http://bl.ocks.org/1653763"&gt;with this little projection toy&lt;/a&gt; &amp;ndash;
trying to make this subject area more approachable in a creative way.&lt;/p&gt;
&lt;img src="http://feeds.feedburner.com/~r/tommacwright/odWX/~4/nHUo1O3vWYg" height="1" width="1"/&gt;</content>
    <author>
      <name>Tom MacWright</name>
      <uri>http://macwright.org/about/</uri>
    </author>
  <feedburner:origLink>http://macwright.org/2012/01/27/projections-understanding.html</feedburner:origLink></entry>
  
  <entry>
    <title>Yell, a Yelp Exporter, and TOSes</title>
    <link href="http://feedproxy.google.com/~r/tommacwright/odWX/~3/VAlJwan-8qY/yell-tos.html" />
    <updated>2012-01-24T10:00:00Z</updated>
    <id>http://macwright.org/2012/01/24/yell-tos</id>
    <content type="html">&lt;p&gt;I&amp;rsquo;m releasing some code that could get you in some mild trouble if you use it. It&amp;rsquo;s
nothing groundbreaking &amp;ndash; just a run-of-the-mill &lt;a href="http://en.wikipedia.org/wiki/Web_scraping"&gt;scraper&lt;/a&gt;
written with &lt;a href="http://nodejs.org/"&gt;nodejs&lt;/a&gt;
that grabs your data from &lt;a href="http://yelp.com"&gt;Yelp&lt;/a&gt; and gives it to you either
as &lt;a href="http://json.org"&gt;JSON&lt;/a&gt; and
HTML formatted with &lt;a href="http://microformats.org/wiki/hreview"&gt;hReview&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;&lt;img src='http://farm8.staticflickr.com/7165/6746558927_1d1fe1547b_z.jpg' width='640' height='350' /&gt;&lt;/p&gt;

&lt;p&gt;It&amp;rsquo;s &lt;a href="http://github.com/tmcw/yell"&gt;open source on GitHub &amp;ndash; the yell project&lt;/a&gt;.&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre&gt;&lt;code class="sh"&gt;~/⇾ npm install yell

~/⇾ yell YOUR_USER_ID
fetching articles starting with 0
fetching articles starting with 10
fetching articles starting with 20
fetching articles starting with 30
fetching articles starting with 40

Finished! Find in this directory:
- yelp.html, a hreview-formatted HTML version
- yelp.json: raw JSON data.
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;


&lt;p&gt;&lt;em&gt;Dear Yelp: it only fetches one user&amp;rsquo;s data &amp;ndash; not everyone&amp;rsquo;s. No need to worry
about evil people stealing data, if you really tried to use this tool to that, it&amp;rsquo;d
do a terrible and incomplete job. It&amp;rsquo;s for users who want their data.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Yelp has an API. It&amp;rsquo;s &lt;a href="http://www.yelp.com/developers"&gt;right here&lt;/a&gt;, but,
in the words of a Yelp employee, it&amp;rsquo;s made for businesses &amp;ndash; it doesn&amp;rsquo;t
have a method to get &lt;strong&gt;your&lt;/strong&gt; data.&lt;/p&gt;

&lt;h2&gt;The Terms of Service&lt;/h2&gt;

&lt;p&gt;The problem is the difference between what lawyers write about technology
and what they write about copyright.&lt;/p&gt;

&lt;blockquote&gt;&lt;p&gt;As between you and Yelp, you own Your Content.
  &lt;em&gt;(5C: Content Ownership)&lt;/em&gt;&lt;/p&gt;&lt;/blockquote&gt;

&lt;p&gt;Yelp is reasonable about copyright; like many other services, they
claim perpetual rights to use your content pretty much however they like,
and the aggregates of your star rating with everyone elses isn&amp;rsquo;t
&amp;ldquo;everyone&amp;rsquo;s&amp;rdquo; &amp;ndash; it&amp;rsquo;s owned by Yelp. Fair: aggregation is what they
do.&lt;/p&gt;

&lt;p&gt;But you own the &amp;copy; on your data &amp;ndash; what if you want it?&lt;/p&gt;

&lt;blockquote&gt;&lt;p&gt;You also agree not to, and will not assist, encourage, or enable others to:
  use any robot, spider, site search/retrieval application,
  or other automated device, process or means to
  access, retrieve, scrape, or index any portion of
  the Site or any Site Content;
  &lt;em&gt;(6B, part iii)&lt;/em&gt;&lt;/p&gt;&lt;/blockquote&gt;

&lt;p&gt;All credit to &lt;a href="http://www.lessig.org/"&gt;Lawrence Lessig&lt;/a&gt; for popularizing
the notion of &lt;a href="http://www.code-is-law.org/"&gt;code is law&lt;/a&gt;: this is that.&lt;/p&gt;

&lt;p&gt;You can write your reviews and post them on Yelp, but there is no way &amp;ndash;
API or scraping &amp;ndash; that you can &lt;em&gt;legally&lt;/em&gt; copy them from Yelp, except by visiting
each page and copy &amp;amp; pasting. For me, this is a deterrent to contributing to
Yelp, even if it&amp;rsquo;s tepid reviews of coffeeshops. And since I&amp;rsquo;ve found
&lt;a href="http://qualiacoffee.wordpress.com/"&gt;DC&amp;rsquo;s best&lt;/a&gt;, there&amp;rsquo;s not much to say there.&lt;/p&gt;

&lt;p&gt;So I get it: companies see user-generated data as their competitive advantage.
If anyone could get a MySQL dump of Yelp, there&amp;rsquo;d be lots of competitors who
are &amp;lsquo;unfairly&amp;rsquo; advantaged by having the work done for them. Yelp has competition,
like &lt;a href="http://www.google.com/places/"&gt;Google Places&lt;/a&gt;, &lt;a href="http://foursquare.com/"&gt;Foursquare&lt;/a&gt;
and the like, and needs to manage how they reuse and its content.&lt;/p&gt;

&lt;p&gt;But that&amp;rsquo;s not the point: a website inviting contributions but lacking an
export API isn&amp;rsquo;t good enough for conscientious or creative users. In this case,
over-eager legal terms really limit the potential of site.&lt;/p&gt;

&lt;h2&gt;Scrapers and Exporters&lt;/h2&gt;

&lt;p&gt;The first iteration was in &lt;a href="http://node.io"&gt;node.io&lt;/a&gt;
and &lt;a href="http://coffeescript.org/"&gt;CoffeeScript&lt;/a&gt;, but I rebuilt it with
&lt;a href="https://github.com/MatthewMueller/cheerio"&gt;cheerio&lt;/a&gt;, a great implementation
of jQuery&amp;rsquo;s essentials along with a relaxed parser. And instead of request,
I used the library that I wrote, and that still powers &lt;a href="http://mapbox.com/tilemill/"&gt;TileMill&lt;/a&gt;
and some other work projects &amp;ndash; &lt;a href="https://github.com/developmentseed/node-get"&gt;node-get&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;This really isn&amp;rsquo;t a significant amount of code: maybe 50 LOC total, and an
hour less time to build.&lt;/p&gt;

&lt;p&gt;Scrapers are odd like that: I wrote a quick one
&lt;a href="https://gist.github.com/1098861"&gt;for Garmin&amp;rsquo;s website to get running data&lt;/a&gt;
for &lt;a href="http://macwright.org/running/"&gt;my running map&lt;/a&gt; and it got a decent amount
of usage &amp;ndash; and even &lt;a href="https://gist.github.com/1232102"&gt;a meaningful improvement in a fork&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Scrapers rarely work on more than one site, and abstracting the process
rarely yields results. This makes them a nice to do every once in a while:
it tends to help out a lot of less-technical people to give them the
ability to export the data that &lt;em&gt;they own&lt;/em&gt;, but is hard to pull out.&lt;/p&gt;
&lt;img src="http://feeds.feedburner.com/~r/tommacwright/odWX/~4/VAlJwan-8qY" height="1" width="1"/&gt;</content>
    <author>
      <name>Tom MacWright</name>
      <uri>http://macwright.org/about/</uri>
    </author>
  <feedburner:origLink>http://macwright.org/2012/01/24/yell-tos.html</feedburner:origLink></entry>
  
  <entry>
    <title>The Wary Guide to OpenLayers</title>
    <link href="http://feedproxy.google.com/~r/tommacwright/odWX/~3/lSoQqLBcfnY/openlayers.html" />
    <updated>2012-01-12T10:00:00Z</updated>
    <id>http://macwright.org/2012/01/12/openlayers</id>
    <content type="html">&lt;p&gt;&lt;a href="http://openlayers.org/"&gt;OpenLayers&lt;/a&gt; is a very popular Javascript API for
web mapping. It&amp;rsquo;s &lt;a href="http://www.whitehouse.gov/change/"&gt;deployed on the White House&lt;/a&gt;,
used as the basis for &lt;a href="http://geoext.org/"&gt;a bunch&lt;/a&gt; of &lt;a href="https://github.com/opengeo/gxp"&gt;other&lt;/a&gt; projects.
In a past life, I maintained &lt;a href="http://drupal.org/project/openlayers"&gt;one of those projects, the Drupal module&lt;/a&gt; and
got a lot of experience using OpenLayers. MapBox launched Hosting
with OpenLayers and kept it that way for quite a while &lt;a href="http://developmentseed.org/blog/2011/jun/29/fast-maps-tilestream-launches-compositing-modest-maps-and-new-mobile-support/"&gt;before switching to Modest Maps&lt;/a&gt;. So I&amp;rsquo;ve had quite
a bit of experience using, debugging, and occasionally patching
OpenLayers.&lt;/p&gt;

&lt;p&gt;Though I recommend you take a long, hard look at &lt;a href="http://leaflet.cloudmade.com/"&gt;Leaflet&lt;/a&gt;,
&lt;a href="https://github.com/stamen/modestmaps-js"&gt;Modest Maps&lt;/a&gt;, or &lt;a href="http://polymaps.org/"&gt;polymaps&lt;/a&gt;
for new projects, there are lots of people who are going to use OpenLayers anyway,
for whatever reason (please add reasons to the comments). So here are some collected
words of wisdom about common pitfalls with the library. Hopefully this
saves new users some time and head-scratching.&lt;/p&gt;

&lt;div class='shutter-300'&gt;
  &lt;a href='http://www.flickr.com/photos/tmcw/6746635/'&gt;&lt;img src='http://farm1.staticflickr.com/5/6746635_a40adac65f_z.jpg?zz=1'/&gt;&lt;/a&gt;
&lt;/div&gt;


&lt;p&gt;For new users, OpenLayers is a scary, scary place to be. You&amp;rsquo;ll find many
things breaking in unexpected ways for weird reasons. This post is a quick summary
of vital understandings to have.&lt;/p&gt;

&lt;h2&gt;LonLat is not Longitude Latitude &lt;a href="https://github.com/openlayers/openlayers/issues/83"&gt;(i)&lt;/a&gt;&lt;/h2&gt;

&lt;p&gt;You would think that LonLat is asking for longitude and latitude
values: it reads Lon(gitude)Lat(itude), right?&lt;/p&gt;

&lt;p&gt;Nope, &lt;code&gt;OpenLayers.LonLat&lt;/code&gt; is a dumb container for any sort of coordinates,
whether they&amp;rsquo;re in degrees, meters, feet, or cubits. It doesn&amp;rsquo;t take on
any responsibility for projecting those coordinates into anything usable
by your map. If you do want something usable, you&amp;rsquo;ll need to do something like&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre&gt;&lt;code class="js"&gt;&lt;span class="kd"&gt;var&lt;/span&gt; &lt;span class="nx"&gt;pt&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nx"&gt;OpenLayers&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;LonLat&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;20&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;20&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="nx"&gt;pt&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;transform&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="c1"&gt;// degrees are degrees&lt;/span&gt;
    &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nx"&gt;OpenLayers&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;Projection&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;EPSG:4326&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
    &lt;span class="c1"&gt;// but your map is in meters (probably)&lt;/span&gt;
    &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nx"&gt;OpenLayers&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;Projection&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;EPSG:900913&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;


&lt;p&gt;There&amp;rsquo;s another gotcha here, did you notice it? Yep, &lt;code&gt;.transform&lt;/code&gt; does changes
in-place. It doesn&amp;rsquo;t return a reprojected &lt;code&gt;pt&lt;/code&gt;, it reprojects &lt;code&gt;pt&lt;/code&gt;. If you
aren&amp;rsquo;t aware of this, you&amp;rsquo;ll probably get burned &amp;ndash; especially since the API
&lt;em&gt;returns the changed point&lt;/em&gt; as well.&lt;/p&gt;

&lt;h2&gt;projection and displayProjection &lt;a href="https://github.com/openlayers/openlayers/issues/118"&gt;(i)&lt;/a&gt;&lt;/h2&gt;

&lt;p&gt;Much like &lt;code&gt;OpenLayers.LonLat&lt;/code&gt;, &lt;code&gt;OpenLayers.Map.displayProjection&lt;/code&gt; seems to
introduce itself: that&amp;rsquo;s the projection in which the map will display.&lt;/p&gt;

&lt;p&gt;Nope: &lt;code&gt;displayProjection&lt;/code&gt; is used in a handful of places. If you add a
&lt;code&gt;OpenLayers.Control.MousePosition&lt;/code&gt; to the map, or a permalink, it&amp;rsquo;ll get used
there: the permalink will link to something using that projection, and your
mouse&amp;rsquo;s position will show degrees or meters or whatnot. But if you don&amp;rsquo;t
have those controls, it doensn&amp;rsquo;t matter one bit. The setting could be
called &amp;lsquo;textDisplayOfPositions&amp;rsquo; or such, and it&amp;rsquo;d be more accurate.&lt;/p&gt;

&lt;h2&gt;Your Raster Projections Aren&amp;rsquo;t Going to Work &lt;a href="https://github.com/openlayers/openlayers/issues/112"&gt;(i)&lt;/a&gt;&lt;/h2&gt;

&lt;p&gt;Do you have one map that&amp;rsquo;s in &lt;code&gt;EPSG:4326&lt;/code&gt; and one that&amp;rsquo;s in &lt;code&gt;EPSG:900913&lt;/code&gt;?
Or one that&amp;rsquo;s in some &lt;a href="http://en.wikipedia.org/wiki/Lambert_conformal_conic_projection"&gt;lambert conic local thing&lt;/a&gt;
and you want to put it on top of a &lt;a href="http://tiles.mapbox.com/"&gt;MapBox&lt;/a&gt; map?&lt;/p&gt;

&lt;p&gt;I hate to break it to you, but this isn&amp;rsquo;t going to work.
You see, projections are baked into images: the images are skewed and
sized, and their tile sizes changed, in order to fit your very specific
mapping of earth-places to screen-places. And at this point,
there is no javascript API that can reproject images from one to the other.&lt;/p&gt;

&lt;p&gt;If in this situation, there are a few options:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Get your tile server to work in the proper projection for the map&lt;/li&gt;
&lt;li&gt;If you don&amp;rsquo;t have control over the server, it&amp;rsquo;s going to be hard. There
are bleeding-edge solutions like &lt;a href="http://mapproxy.org/"&gt;MapProxy&lt;/a&gt; that
can reproject upstream sources, but the task is difficult.&lt;/li&gt;
&lt;li&gt;Use vector data, if your data and visualization needs are extremely light&lt;/li&gt;
&lt;/ul&gt;


&lt;p&gt;Re: the first one. If you&amp;rsquo;ve got some map in a bizarre projection just because
that&amp;rsquo;s the standard for the unit of company or government you work for, figure
out whether you can change that standard. It&amp;rsquo;s unlikely that Google Maps and
co will be supporting boutique projections soon, and having incompatible maps
means that many fewer people will be using your data, and you&amp;rsquo;ll have more
limited software options.&lt;/p&gt;

&lt;p&gt;Not to say that you should switch entirely to spherical mercator: it&amp;rsquo;s not the
ideal projection for static thematic maps or for local maps of certain places.
But &lt;em&gt;not providing&lt;/em&gt; tiles in it is unwise: the point of the internet is to
combine things, and your odd-projection maps will be orphans otherwise.&lt;/p&gt;

&lt;h2&gt;When in doubt, put settings on Layers&lt;/h2&gt;

&lt;p&gt;OpenLayers lets you put lots of settings everywhere. The weirdest place
is the Map versus the Layer. This is a simple one: the Map is a fallback
for Layers. Put your geographic stuff on Layers. That means extents,
projections, resolutions, what-have-you. Don&amp;rsquo;t repeat yourself and put
these settings in two places &amp;ndash; that&amp;rsquo;ll only make things more complicated.&lt;/p&gt;

&lt;p&gt;If you&amp;rsquo;ve got lots and lots of layers in handwritten Javascript and you
need to move settings to the map, you&amp;rsquo;ll have other problems anyway.&lt;/p&gt;

&lt;h2&gt;maxExtent does not mean what you think it means&lt;/h2&gt;

&lt;p&gt;No: maxExtent doesn&amp;rsquo;t keep people from moving the map. You&amp;rsquo;re looking for
&lt;code&gt;restrictedExtent&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;maxExtent configures how much of the world is rendered on the map. Actually,
it does something more complicated than that, because it&amp;rsquo;s not thinking
about the typical &amp;lsquo;XYZ layer with only a country rendered&amp;rsquo; it&amp;rsquo;s more like
&amp;lsquo;renderer thinks that this country is the world and rendered that&amp;rsquo;. I&amp;rsquo;ve
never been able to get maxExtent to work doing anything but setting it
to the maximum Mercator extent.&lt;/p&gt;

&lt;h2&gt;Your imgPath (and themePath) is broken&lt;/h2&gt;

&lt;p&gt;Ah, imgPath. The best way to use OpenLayers controls is to not use them,
but unfortunately a lot of users are deathly scared of writing their own code,
even if that just means hooking up zoom in &amp;amp; out buttons.&lt;/p&gt;

&lt;p&gt;But, if you must: imgPath. If you don&amp;rsquo;t provide it, OpenLayers tries to figure
it out. So provide it, because the system will guess wrong. One day you&amp;rsquo;ll
be chillin with a great map and your code is like:&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre&gt;&lt;code class="sh"&gt;/js/OpenLayers.js
looks &lt;span class="k"&gt;for&lt;/span&gt;
/js/theme/*
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;


&lt;p&gt;Then someone runs &lt;a href="http://developer.yahoo.com/yslow/"&gt;YSlow&lt;/a&gt; or something and
gets the bright idea of combining your javascript resources. So, the urls
become&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre&gt;&lt;code class="sh"&gt;/OpenLayers.js
looks &lt;span class="k"&gt;for&lt;/span&gt;
/theme/*
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;


&lt;p&gt;And all of your images break. Moral of the story: specify your
imgPath and themePath.
And download the images for OpenLayers if you plan on using them.&lt;/p&gt;

&lt;h2&gt;Don&amp;rsquo;t hotlink your OpenLayers&lt;/h2&gt;

&lt;p&gt;Too many sites pull from &lt;a href="http://openlayers.org/"&gt;openlayers.org&lt;/a&gt;
for OpenLayers.js. &lt;em&gt;Don&amp;rsquo;t do this, unless you&amp;rsquo;re just putting a page up
for testing&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;The OpenLayers.org version of OpenLayers.js is a &lt;em&gt;full build&lt;/em&gt; &amp;ndash; which means that
it&amp;rsquo;s big. It&amp;rsquo;s 957K un-gzipped and 220K gzipped. For reference, 220K gzipped
is around 7 &lt;a href="http://jquery.com/"&gt;jQueries&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;OpenLayers.org is not always online, and when it goes offline, your maps
will break. All of them. And depending on how you include the script tag,
your site will take a lot longer to load, because it&amp;rsquo;s trying desperately
to get the code.&lt;/p&gt;

&lt;p&gt;Plus, if you use the library on the front page,
&lt;code&gt;http://openlayers.org/api/OpenLayers.js&lt;/code&gt;,
you&amp;rsquo;ll get the latest API version of OpenLayers. Meaning you build your
site against 2.11, and when 2.12 is released, your site breaks.&lt;/p&gt;

&lt;p&gt;Hopefully this is enough to convince you: download OpenLayers for yourself,
and put it on your own server.&lt;/p&gt;

&lt;h2&gt;OpenLayers Controls Are Ugly&lt;/h2&gt;

&lt;p&gt;It&amp;rsquo;s not too hard to make OpenLayer&amp;rsquo;s default controls look nicer:
they simply haven&amp;rsquo;t been updated for years. &lt;a href="https://github.com/developmentseed/openlayers_themes"&gt;Development Seed&amp;rsquo;s OpenLayers Theme&lt;/a&gt;
is one example &amp;ndash; try it, and use the source SVG images to make
your own theme.&lt;/p&gt;

&lt;p&gt;Note that the OpenLayers theme system falls apart at certain points:
popups are one part of the library that are near-impossible to style
nicely.&lt;/p&gt;

&lt;h2&gt;Go and Conquer&lt;/h2&gt;

&lt;p&gt;If you&amp;rsquo;re really looking to level up with OpenLayers, do a custom build:
look in the &lt;code&gt;build/&lt;/code&gt; directory, and you&amp;rsquo;ll find a &lt;code&gt;build.py&lt;/code&gt; script
you can use to make slimmer builds of the library that only include parts
that you use. A dated example of how to do this is
&lt;a href="https://github.com/developmentseed/openlayers_slim"&gt;openlayers slim&lt;/a&gt;,
which we used at &lt;a href="http://developmentseed.org/"&gt;Development Seed&lt;/a&gt; before
switching off of OpenLayers to &lt;a href="http://github.com/stamen/modestmaps-js"&gt;Modest Maps&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;If you&amp;rsquo;re using OpenLayers with &lt;a href="http://tiles.mapbox.com/"&gt;MapBox Hosting&lt;/a&gt;
maps (as I&amp;rsquo;d recommend you do), try the &lt;a href="http://mapbox.com/wax/connector-ol.html"&gt;connector provided by the Wax library&lt;/a&gt;.
With the magic of &lt;a href="https://github.com/mapbox/tilejson"&gt;TileJSON&lt;/a&gt;, it
removes a lot of the potential configuration fail in using OpenLayers.&lt;/p&gt;
&lt;img src="http://feeds.feedburner.com/~r/tommacwright/odWX/~4/lSoQqLBcfnY" height="1" width="1"/&gt;</content>
    <author>
      <name>Tom MacWright</name>
      <uri>http://macwright.org/about/</uri>
    </author>
  <feedburner:origLink>http://macwright.org/2012/01/12/openlayers.html</feedburner:origLink></entry>
  
  <entry>
    <title>JS Security With Untrusted Code</title>
    <link href="http://feedproxy.google.com/~r/tommacwright/odWX/~3/l0m-NSWtSWc/iframes.html" />
    <updated>2012-01-10T10:00:00Z</updated>
    <id>http://macwright.org/2012/01/10/iframes</id>
    <content type="html">&lt;p&gt;&lt;img src='http://farm8.staticflickr.com/7156/6654707231_e52f8287fd_o.jpg' height='257' width='640' alt='Lock' /&gt;&lt;/p&gt;

&lt;p&gt;Combining security and flexibility is a difficult task. This is just one
tiny corner of the problem that I&amp;rsquo;ve experienced in depth, in an effort
to make &lt;a href="http://mapbox.com/tilemill/"&gt;TileMill&lt;/a&gt;&amp;rsquo;s
&lt;a href="http://github.com/mapbox/utfgrid-spec"&gt;interactivity language&lt;/a&gt; more secure.&lt;/p&gt;

&lt;p&gt;At the start of the day we had a problem: maps have an idea of &amp;lsquo;formatters&amp;rsquo;
similar to &lt;a href="http://wiki.apache.org/couchdb/HTTP_view_API"&gt;CouchDB views&lt;/a&gt;, which
are Javascript. And while the vast majority of formatters are generated by friendly
tools like TileMill to take objects and return formatted strings, the technical
definition of a formatter was extremely broad: it was any Javascript.&lt;/p&gt;

&lt;p&gt;This was a problem: &lt;em&gt;any Javascript means evil Javascript&lt;/em&gt;, and, like
any other company that provides embeds, like YouTube or Disqus, we don&amp;rsquo;t want
to be a vector.&lt;/p&gt;

&lt;h2&gt;Sanitizing Javascript&lt;/h2&gt;

&lt;p&gt;The first thought was detecting malicious code, or even whitelisting only
certain constructs. Unfortunately, Javascript&amp;rsquo;s flexibility makes it possible
to write hacks in novel ways &amp;ndash; with unusual characters, with odd references
to &lt;code&gt;this['win'+'dow']&lt;/code&gt;, and much, much more. There are &lt;a href="http://utf-8.jp/public/jjencode.html"&gt;tools to write javascript encoded into just a few characters&lt;/a&gt;. It&amp;rsquo;s a losing battle trying to blacklist. You aren&amp;rsquo;t going
to get real protection without a full-fledged parser and generator.&lt;/p&gt;

&lt;p&gt;&lt;a href='http://code.google.com/p/google-caja/'&gt;&lt;img class='white-on-white' src='http://farm8.staticflickr.com/7153/6672966105_9bd8a4e687_o.png' /&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;And that&amp;rsquo;s &lt;a href="http://code.google.com/p/google-caja/"&gt;Google Caja&lt;/a&gt;: a fiendishly
complex, Java-based Javascript-cleaning server. Given no way to slot Java
into our stack, this was a nogo &amp;ndash; and the architecture is difficult to manage
without a central service: our security model needed to work with arbitrary
&lt;a href="http://mapbox.com/tilemill/"&gt;TileMill&lt;/a&gt; users not only using &lt;a href="http://mapbox.com/hosting"&gt;MapBox Hosting&lt;/a&gt;,
but also alternative servers like &lt;a href="http://github.com/mapbox/tilestream"&gt;TileStream&lt;/a&gt;
and &lt;a href="http://tilestache.org/"&gt;TileStache&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;The Caja security model is also difficult to summarize: we need something that,
at the end of the day, is predictable enough that you can write code and not
notice that it&amp;rsquo;s running in a secure environment.&lt;/p&gt;

&lt;p&gt;That said, Caja is an incredible resource that came in handy at the end of this journey,
and its &lt;a href="http://code.google.com/p/google-caja/wiki/AttackVectors"&gt;wiki is a goldmine&lt;/a&gt;
of attack vectors and
&lt;a href="http://code.google.com/p/google-caja/wiki/SourcesOfNonDeterminism"&gt;design decisions&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Caja is also a little sketchy with deployment: it looks like it was mainly built to
work with &lt;a href="http://en.wikipedia.org/wiki/OpenSocial"&gt;the OpenSocial spec&lt;/a&gt;, which
looks to be entirely abandoned: Caja still lists MySpace as a big implementor.&lt;/p&gt;

&lt;h2&gt;&lt;code&gt;&amp;lt;iframes&amp;gt;&lt;/code&gt;&lt;/h2&gt;

&lt;p&gt;Five years ago, Dean Edwards posted
&lt;a href="http://dean.edwards.name/weblog/2006/11/sandbox/"&gt;Sandboxing Javascript using iframes&lt;/a&gt;
and the state of the art hasn&amp;rsquo;t moved very far from there.
Still I insisted on sinking a few days into trying to run JavaScript
in some kind of idyllic sandboxed environment.
&lt;a href="https://github.com/premasagar/sandie"&gt;Sandie&lt;/a&gt;
and &lt;a href="https://github.com/TooTallNate/SandboxJS"&gt;SandboxJS&lt;/a&gt; seemed promising.
At the end of the day, there weren&amp;rsquo;t any iframe-based projects
with any testing or compatibility research, and most treat security
in a pretty simplistic &lt;code&gt;var window = {}&lt;/code&gt; fashion.&lt;/p&gt;

&lt;p&gt;After that &lt;a href="http://ds.io/wgOp4s"&gt;LightingJS&lt;/a&gt;
came out, which is great for trusted code, but &amp;lsquo;safe&amp;rsquo; in this context is a
matter of preventing conflicts, rather than containing security problems;
a malicious third-party script can always &lt;code&gt;window.parent&lt;/code&gt; out of their
context and wreak havoc. Hence the trusted-code paradigm.&lt;/p&gt;

&lt;p&gt;And &lt;a href="https://github.com/ternarylabs/porthole"&gt;Porthole&lt;/a&gt; promised to communicate
with &lt;code&gt;&amp;lt;iframe&amp;gt;&lt;/code&gt;s. But, with how much data? In IE, it uses location hashes, which
are limited in length, and uses &lt;code&gt;onresize&lt;/code&gt; events to trigger the frame to
read the hash. Clever, but scary: I&amp;rsquo;m working on this stuff to deploy
to thousands of sites, not &lt;em&gt;entirely&lt;/em&gt; for kicks. It all sounds like a hack,
that doesn&amp;rsquo;t even start to
properly guard against common hacks.
How real is this security? Not much &amp;ndash; at least SandBoxJS admits to
this fact by quoting the epic &lt;a href="http://foohack.com/"&gt;Isaac Schlueter&lt;/a&gt;&lt;/p&gt;

&lt;blockquote&gt;&lt;p&gt;Prisons are designed to keep dangerous criminals. Sandboxes are
for children to not get lost or hurt while playing. There are
several ways to break out of the sandbox&amp;hellip; DON&amp;rsquo;T!&lt;/p&gt;&lt;/blockquote&gt;

&lt;h2&gt;Giving up and Templating&lt;/h2&gt;

&lt;p&gt;After struggling against Javascript sandboxing for two days, I decided that it
was futile to build a fake security model on something that doesn&amp;rsquo;t have a
security model, and at the end of the day restrict the functionality of
Javascript to a template language.&lt;/p&gt;

&lt;div style='text-align:center;font-size:230px;-webkit-transform: rotate(-90deg);-moz-transform: rotate(-90deg);'&gt;}&lt;/div&gt;


&lt;p&gt;&lt;a href="http://mustache.github.com/"&gt;Mustache&lt;/a&gt; is the clear pick for
cross-platform templates &amp;ndash; the Objective-C implementation,
&lt;a href="https://github.com/groue/GRMustache"&gt;GRMoustache&lt;/a&gt;, let us have
compatibility with &lt;a href="http://mapbox.com/ipad/"&gt;the iPad app&lt;/a&gt; on day two.
While the language has its faults, they tend to be syntax details rather
than the awesome concept and intentions of the language.&lt;/p&gt;

&lt;p&gt;Mustache is logic-free: meaning that users can&amp;rsquo;t call arbitrary functions
from the template language, much unlike &lt;a href="http://ds.io/zclNTE"&gt;underscore templates&lt;/a&gt;
or &lt;a href="http://jade-lang.com/"&gt;jade&lt;/a&gt;. While this can be frustrating in
other contexts, it shouldn&amp;rsquo;t be here: the data input is simple and
relatively flat.&lt;/p&gt;

&lt;h2&gt;Sanitizing HTML&lt;/h2&gt;

&lt;p&gt;So, with pure Javascript a distant memory and templates in the future,
we have a new enemy: HTML output. Read
&lt;a href="http://html5sec.org/"&gt;html5sec.org&lt;/a&gt; and you&amp;rsquo;ll lose your mind learning
about how the most innocent-looking spec additions can be security holes
in your code.&lt;/p&gt;

&lt;p&gt;Mustache is output-agnostic, so it doesn&amp;rsquo;t really know that it&amp;rsquo;s outputting
HTML, or try to do anything special because it is: which means that it&amp;rsquo;s
far out of scope for Mustache itself to do HTML sanitization.&lt;/p&gt;

&lt;p&gt;Most of the users of &lt;a href="http://liquidmarkup.org/"&gt;liquid&lt;/a&gt;, the Ruby language
that inspired Mustache, use the &lt;a href="https://github.com/rgrove/sanitize/"&gt;Sanitize&lt;/a&gt;
gem, which uses a whitelist to eliminate a wide swatch of XSS potentials. But
that&amp;rsquo;s in Ruby, so quite far away from anything we could use.&lt;/p&gt;

&lt;p&gt;Via &lt;a href="http://ds.io/sxyUsN"&gt;a lucky link&lt;/a&gt;
from Stack Overflow I happened upon a corner of the Google Caja project that
works in the browser and sanitizes HTML, called
&lt;a href="http://code.google.com/p/google-caja/wiki/JsHtmlSanitizer"&gt;JsHtmlSanitizer&lt;/a&gt;.
It&amp;rsquo;s a heavyweight solution: it&amp;rsquo;s a full-fledged
&lt;a href="http://en.wikipedia.org/wiki/Simple_API_for_XML"&gt;SAX parser&lt;/a&gt; and whitelist.
And, given that this is part of Caja, you need to
check out the project with SVN and build it with ant to even get the file
&lt;code&gt;html-sanitizer-bundle.js&lt;/code&gt;
(you can see it in Google Code&amp;rsquo;s SVN repo, but it has dependencies).&lt;/p&gt;

&lt;p&gt;And it adds a good 12K to the codebase &amp;ndash; but, this is an area where you need
to do things right, and should really, really avoid reinventing the wheel.&lt;/p&gt;

&lt;p&gt;So the process is&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre&gt;&lt;code class="js"&gt;&lt;span class="c1"&gt;// data &amp;amp; options -&amp;gt; mustache.js -&amp;gt; html_sanitize&lt;/span&gt;
&lt;span class="nx"&gt;html_sanitize&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;Mustache&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;to_html&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;x&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;view&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="nx"&gt;urlX&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;idX&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;


&lt;p&gt;&lt;code&gt;html_sanitize&lt;/code&gt; is reasonably fast for its task, and it&amp;rsquo;s
incredibly well-tested and well-written.&lt;/p&gt;

&lt;h2&gt;Sanitizing CSS&lt;/h2&gt;

&lt;p&gt;This works pretty well, though making yourself aware of the full world of
potential vulnerabilities is rough:
&lt;a href="http://html5sec.org/#css"&gt;even CSS can be dangerous&lt;/a&gt;, because of the silly,
regrettable, stupid decision to add Javascript support to CSS. This is
something that we may be able to add back by restricting CSS tag content,
but will forever be burned into my mind as yet another example of how the
&lt;a href="http://www.w3.org/"&gt;w3c&lt;/a&gt;
has foolishly supported IE-additions to specs that only degrade it and
mix concerns.&lt;/p&gt;

&lt;p&gt;As Google Caja lays out &lt;a href="http://ds.io/w2HVeW"&gt;CSS allows arbitrary code execution&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;So, for the time being, we&amp;rsquo;re doing some very simple validation of CSS,
and relaxing &lt;code&gt;html_sanitize&lt;/code&gt; restrictions for some of the most intense cuts:
like allowing &lt;code&gt;data-uri&lt;/code&gt;-based images via a URL whitelist.
Luckily, the architecture of &lt;code&gt;html_sanitize&lt;/code&gt; lets you set your own
rules &lt;a href="http://ds.io/yozBTX"&gt;in a separate file&lt;/a&gt;,
so you don&amp;rsquo;t have to hack the library.
In the vast
majority of cases, the HTML that users type is the HTML that they get on
the page.&lt;/p&gt;

&lt;p&gt;We did also put maps in &lt;code&gt;&amp;lt;iframe&amp;gt;&lt;/code&gt;s &amp;ndash; though not for security purposes.
It turned out to be the only way to keep CSS from clobbering embed
content.&lt;/p&gt;

&lt;h2&gt;Post-Notes&lt;/h2&gt;

&lt;p&gt;I should have specified originally: this is focusing on client-side code
that runs on A-level browsers: which unfortunately includes later versions
of IE. So the solution needed to be basically vanilla Javascript of some sort,
which luckily the Caja HTML sanitizer supports.&lt;/p&gt;

&lt;p&gt;If this had been on more modern browsers,
&lt;a href="https://gist.github.com/1597914"&gt;CrabDude&amp;rsquo;s example of Harmony Proxies&lt;/a&gt;
is simple and awesome. It&amp;rsquo;s good to see that Javascript is gaining features that fit
this use case.&lt;/p&gt;

&lt;p&gt;If this was running in &lt;a href="http://nodejs.org"&gt;node.js&lt;/a&gt;, &lt;a href="https://github.com/darobin"&gt;Robin&amp;rsquo;s&lt;/a&gt;
&lt;a href="https://github.com/darobin/html-sanitiser"&gt;html-sanitizer&lt;/a&gt; is a simpler,
more understandable implementation than Caja&amp;rsquo;s for sanitization.
Since you also have cutting-edge Javascript features in node and lots
of control over processes, there are sandboxes you can use there,
like &lt;a href="https://github.com/gf3"&gt;Gianni&amp;rsquo;s&lt;/a&gt; &lt;a href="http://gf3.github.com/sandbox/"&gt;sandbox&lt;/a&gt;.&lt;/p&gt;
&lt;img src="http://feeds.feedburner.com/~r/tommacwright/odWX/~4/l0m-NSWtSWc" height="1" width="1"/&gt;</content>
    <author>
      <name>Tom MacWright</name>
      <uri>http://macwright.org/about/</uri>
    </author>
  <feedburner:origLink>http://macwright.org/2012/01/10/iframes.html</feedburner:origLink></entry>
  
  <entry>
    <title>Longitude Over Time - The End of 2011</title>
    <link href="http://feedproxy.google.com/~r/tommacwright/odWX/~3/IKbFLR5TM9Y/longitude-over-time.html" />
    <updated>2012-01-02T10:00:00Z</updated>
    <id>http://macwright.org/2012/01/02/longitude-over-time</id>
    <content type="html">&lt;p&gt;&lt;small&gt;(if the visualization below fails to load, try a modern browser
like Chrome, Firefox, or Safari)&lt;/small&gt;&lt;/p&gt;

&lt;iframe frameBorder='0' width='640' height='620' src='http://macwright.org/demo/up/'&gt;&lt;/iframe&gt;


&lt;p&gt;&lt;strong&gt;Longitude over time is a travel map that replaces latitude with
time.&lt;/strong&gt; Here I&amp;rsquo;m using it with
my own travel data in order to see where I&amp;rsquo;ve been traveling,
at what frequency and for how long.&lt;/p&gt;

&lt;p&gt;It&amp;rsquo;s been
a continuing fascination to experiment with the few dimensions
we have in order to represent hidden information
in a natural way. Travel maps are typically disconnected with
the experience of traveling because positions are equally weighted &amp;ndash;
I spent a long time in Colorado, but it&amp;rsquo;s just another dot on a typical
map.&lt;/p&gt;

&lt;p&gt;I first tried an &amp;lsquo;orthographic 3D time cube&amp;rsquo;,
but realized that it was
rather hard to understand, since the line extending out in space had no
good reference point and was only geographically understandable from one position:
looking straight down.&lt;/p&gt;

&lt;p&gt;With a few months of data collected by
&lt;a href="http://itunes.apple.com/us/app/trackme/id454704336?mt=8"&gt;Track Me&lt;/a&gt; and
converted into GeoJSON with  &lt;a href="http://www.gdal.org/ogr2ogr.html"&gt;ogr2ogr&lt;/a&gt;,
there was plenty of raw material. The graphic came together quickly
with a dash of &lt;a href="http://mbostock.github.com/d3"&gt;d3&lt;/a&gt;,
the visualization library to rule them all.&lt;/p&gt;

&lt;p&gt;From there, a bit of &lt;a href="http://github.com/stamen/modestmaps-js"&gt;Modest Maps&lt;/a&gt;,
&lt;a href="http://mapbox.com/wax/"&gt;Wax&lt;/a&gt; and &lt;a href="http://mapbox.com/easey"&gt;Easey&lt;/a&gt;
with the beautiful &lt;a href="http://tiles.mapbox.com/mapbox/map/world-bright"&gt;World Bright&lt;/a&gt;
tileset from MapBox do the trick for showing where, geographically,
I was.&lt;/p&gt;
&lt;img src="http://feeds.feedburner.com/~r/tommacwright/odWX/~4/IKbFLR5TM9Y" height="1" width="1"/&gt;</content>
    <author>
      <name>Tom MacWright</name>
      <uri>http://macwright.org/about/</uri>
    </author>
  <feedburner:origLink>http://macwright.org/2012/01/02/longitude-over-time.html</feedburner:origLink></entry>
  
  <entry>
    <title>November 2011</title>
    <link href="http://feedproxy.google.com/~r/tommacwright/odWX/~3/AgMgbaVrxrc/november.html" />
    <updated>2011-11-29T10:00:00Z</updated>
    <id>http://macwright.org/2011/11/29/november</id>
    <content type="html">&lt;div class='shutter-300'&gt;
  &lt;img src='http://farm7.static.flickr.com/6094/6326269350_c710b65cda_z.jpg'&gt;
&lt;/div&gt;


&lt;p&gt;&lt;span class='image-credit'&gt;&lt;a href='http://www.flickr.com/photos/developmentseed/6326269350/'&gt;from the Development Seed Flickr&lt;/a&gt;&lt;/span&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="http://developmentseed.org"&gt;Development Seed&lt;/a&gt; hosted a &lt;a href="http://developmentseed.org/blog/2011/nov/08/recapping-dc-tech-foosball-shootout/"&gt;foosball
tournament for DCWeek&lt;/a&gt;,
and my team &amp;lsquo;Foolsball&amp;rsquo; &amp;ndash; came in approximately
third to fourth. Congratulations to the winners, &amp;ldquo;Backalley FC&amp;rdquo;.&lt;/p&gt;

&lt;p&gt;My band &lt;a href="http://teenmomdc.bandcamp.com/"&gt;Teen Mom&lt;/a&gt; got a spot playing
the opening party for &lt;a href="http://digitalcapitalweek.org/"&gt;DCWeek&lt;/a&gt;,
and thus got to grab (one half) of the
huge stage at the &lt;a href="http://930.com/"&gt;9:30 Club&lt;/a&gt; (for 15 minutes).&lt;/p&gt;

&lt;p&gt;&lt;img style='width:640px;' src='http://farm7.static.flickr.com/6237/6313563647_6126196cc9_z.jpg'&gt;
&lt;span class='image-credit'&gt;&lt;a href='http://www.flickr.com/photos/somewhatfrank/6313563647/'&gt;CC photo by Frank Gruber&lt;/a&gt;&lt;/span&gt;&lt;/p&gt;

&lt;p&gt;This merited our first, albeit unnamed photos in &lt;a href="http://www.brightestyoungthings.com/articles/photos-dcweek-kick-off-party-930-club.htm"&gt;Brightest Young Things&lt;/a&gt;.
I did an extremely rough compression of our first single
(which is being perfected at &lt;a href="http://thebastillestudio.com/"&gt;The Bastille&lt;/a&gt;) &amp;ndash;
so there&amp;rsquo;s some online evidence of our existence in audio form.&lt;/p&gt;

&lt;iframe width="400" height="100" style="position: relative; display: block; width: 400px; height: 100px;" src="http://bandcamp.com/EmbeddedPlayer/v=2/track=3911609991/size=venti/bgcol=31356F/linkcol=f60aff/transparent=true/" allowtransparency="true" frameborder="0"&gt;&lt;a href="http://teenmomdc.com/track/you-and-me"&gt;You and Me by Teen Mom&lt;/a&gt;&lt;/iframe&gt;


&lt;p&gt;&lt;a href="http://www.flickr.com/photos/tmcw/6436822079/" title="IMG_0655 by macwright, on Flickr"&gt;&lt;img src="http://farm8.staticflickr.com/7029/6436822079_091f392fd8_z.jpg" width="640" height="360" alt="IMG_0655"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;I swung a quick trip up to Troy, NY for &lt;a href="http://www.photocentertroy.org/exhibits-calls/exhibits.html"&gt;Elusive Persona&lt;/a&gt;,
an opening by &lt;a href="http://sarahmacwright.com/"&gt;my sister&lt;/a&gt; and &lt;a href="http://www.carriewill.com/"&gt;Carrie Will&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;Consumption&lt;/h2&gt;

&lt;p&gt;There&amp;rsquo;s been quite a bit flowing in and out of my &lt;a href="http://instapaper.com/"&gt;Instapaper&lt;/a&gt;
and Kindle.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="http://www.scroogle.org/doctorow.html"&gt;Cory Doctorow&amp;rsquo;s Scroogled&lt;/a&gt; is a
rather dramatic but pretty effective piece. I think I might read a bit more,
since he has a unique ability to write about technology without
butchering the details.&lt;/li&gt;
&lt;li&gt;&lt;a href="http://andywoodruff.com/blog/value-by-alpha-maps/"&gt;Andy Woodruff&amp;rsquo;s Value by Alpha&lt;/a&gt;
is awesome. Now that maps and visualizations are hip, there are a lot
of opinions floating around, and kind of odd tangents like dymaxion maps
and cartograms gain traction. But, for people who really actually make
things daily, like Andy &amp;ndash; there&amp;rsquo;s real value to having things be understandable,
rather than just flashy.&lt;/li&gt;
&lt;li&gt;&lt;a href="http://www.youtube.com/watch?v=b8xqu_TlQPU"&gt;This inverview series with Lynn Margulis&lt;/a&gt;
is touching, inspiring, and really gripping for a million reasons. I
adore &lt;a href="http://youtu.be/KOjKZdW8HSY?t=1m20s"&gt;this one bit in the second episode where she rephrases a question&lt;/a&gt;.
She certainly wasn&amp;rsquo;t a spotless character &amp;ndash; Google will pull up enough evidence
for judgmental types to dismiss her &amp;ndash; but the way that she handled science,
with the attitude that sharing is the end result of research, and understanding
isn&amp;rsquo;t just about publishing dry scientific articles, is a model for all
disciplines. Sadly she died on the 22nd.&lt;/li&gt;
&lt;li&gt;&lt;a href="http://greenland.bandcamp.com/"&gt;Greenland&lt;/a&gt; is the latest happy
realization that DC produces some good music. They&amp;rsquo;ve got a lot of albums
online for free: get them.&lt;/li&gt;
&lt;/ul&gt;

&lt;img src="http://feeds.feedburner.com/~r/tommacwright/odWX/~4/AgMgbaVrxrc" height="1" width="1"/&gt;</content>
    <author>
      <name>Tom MacWright</name>
      <uri>http://macwright.org/about/</uri>
    </author>
  <feedburner:origLink>http://macwright.org/2011/11/29/november.html</feedburner:origLink></entry>
  
</feed>

