<?xml version="1.0" encoding="UTF-8"?>
<essay xml:lang="en" version="5.0" xmlns="http://docbook.org/ns/docbook">
  <info>
    <title>More mapping hacks</title>
    <biblioid class="uri">http://norman.walsh.name/2008/03/31/moreMapping</biblioid>
    <volumenum>11</volumenum>
    <issuenum>34</issuenum>
    <pubdate>2008-03-31T13:44:35-04:00</pubdate>
    <author>
      <personname>
        <firstname>Norman</firstname>
        <surname>Walsh</surname>
      </personname>
    </author>
    <copyright>
      <year>2008</year>
      <holder>Norman Walsh</holder>
    </copyright>
    <abstract>
      <para>Mapping photographs is one of those fun little projects that grows
      everytime I think about it.</para>
    </abstract>
<releaseinfo role="gmapkey">ABQIAAAAO1qAaQsvBqLxt1nDHmVdXRS4k_Slk4HpyYNJokS65uiFGyHI9RQnDJVG7YhIt2uKxaEup9yE1lDNtA</releaseinfo>
<dc:subject rdf:resource="http://norman.walsh.name/knows/taxonomy#Entertainment" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"/>
<dc:subject rdf:resource="http://norman.walsh.name/knows/taxonomy#SelfReference" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"/>
<dc:subject rdf:resource="http://norman.walsh.name/knows/taxonomy#TheWeb" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"/>
</info>

<para xml:id="p1">Over the weekend, I realized there were three things
I really wanted to add to my
<link xlink:href="/2008/03/26/mappingPhotographs" xmlns:xlink="http://www.w3.org/1999/xlink">mapping hacks</link>:
</para>

<orderedlist spacing="compact">
<listitem>
  <simpara xml:id="p2">Map all the photos on a given map, not just those with
in 0.1 degrees of latitude/longitude from the center. As you zoom out, you
should be able to see more images.</simpara>
</listitem>
<listitem>
  <simpara xml:id="p3">Provide more control over the number of images mapped.
Just because there are 600 images on the map doesn't mean you really want
your browser to add 600 markers all at once.</simpara>
</listitem>
<listitem>
  <simpara xml:id="p4">Figure out what places are most interesting, from a
mapped photographs perspective.</simpara>
</listitem>
</orderedlist>

<para xml:id="p5">And Dave's <link xlink:href="#comment0002" xmlns:xlink="http://www.w3.org/1999/xlink">comment</link> gave
me another idea:</para>

<orderedlist spacing="compact" continuation="continues">
<listitem>
      <simpara xml:id="p6">Handle multiple photographs with the same latitude
and longitude. This turns out to be more common than I would have expected
because, I think, Flickr makes it easy to tag a batch of photos.
<wikipedia page="Small_matter_of_programming">SMOP</wikipedia>.
</simpara>
</listitem>
</orderedlist>

<para xml:id="p7">Fixing the first two items was just a simple matter of programming.
Along the way, I also improved the color coding so that its more consistent.
My photos are still the only ones that get red pins.</para>

<para xml:id="p8">The third was harder, but I can now produce a map and a list of
places.</para>

<para xml:id="map" xlink:show="embed" xlink:actuate="onLoad" xlink:href="moreMapping.map" xmlns:xlink="http://www.w3.org/1999/xlink"/>

<para xml:id="p9">The line just below the map gives you more control
over the markers. The following list of places includes everywhere
that has at least one photograph.
(This list will change over time as new geotagged
photographs are added to <link xlink:href="http://www.flickr.com/" xmlns:xlink="http://www.w3.org/1999/xlink">Flickr</link>.)</para>

<?include virtual="/2008/03/31/places.html"?>

<para xml:id="p10">If you click on places in that list, the center of the map will
move, showing you a selection of photographs near that place. The
actual number of photographs shown depends on the zoom factor of the
map.</para>

<para xml:id="p11">Mapping a point on the earth to its closest landmark must be a well
solved problem. I can imagine a variety of hierarchical data structures
that would provide fast, accurate answers.</para>

<para xml:id="p12">In my case, all of the computations are done “off line”. I don't have
very significant performance constraints, so I went for the simplest thing
that would work. The simplest thing, brute force, really won't work.
Calculating great circle distances is computationally expensive, relatively
speaking, and comparing each known point to all 84,000+ points in the list
isn't practical. (I got the list by taking the
<wikipedia>GeoNames</wikipedia> data and extracting all cities with a population
greater than 1000.)</para>

<para xml:id="p13">To make the searching practical, I divide the world into a grid
of squares, each two degrees of longitude by two degrees of latitude.
Into each square, I place all the cities with a latitude and longitude
that falls within that square or within one degree of latitude or
longitude in each direction. (So a 4x4 square centered on the 2x2
square.) This extra “sloppiness” solves the boundary problem well
enough, at least, for my purposes.</para>

<para xml:id="p14">Given a random coordinate, I can quickly find the relevant
square. I then do a brute-force search of all the cities in that
square. If there aren't any cities in the starting square, I search
outward, building a larger and larger square until I find one
big enough to contain at least one city.</para>

<para xml:id="p15">Then it's just a simple matter of collation. Just for fun, I'll
see if I can make a simple web service out if this bit of code.</para>

</essay>

