Aaron Straup Cope
and 1 contributors

NAME

Net::Flickr::Geo::ModestMaps - tools for working with geotagged Flickr photos and Modest Maps

SYNOPSIS

 my %opts = ();
 getopts('c:s:', \%opts);

 #
 # Defaults
 #

 my $cfg = Config::Simple->new($opts{'c'});

 #
 # Atkinson dithering is hawt but takes a really long
 # time...
 #

 $cfg->param("modestmaps.filter", "atkinson");
 $cfg->param("modestmaps.timeout", (45 * 60));

 #
 # Let's say all but one of your photos are in the center of
 # Paris and the last one is at the airport. If you try to render
 # a 'poster style' (that is all the tiles for the bounding box
 # containing those points at street level) map you will make 
 # your computer cry...
 #

 $cfg->param("pinwin.skip_photos", [506934069]);

 #
 # I CAN HAS MAPZ?
 #

 my $fl = Net::Flickr::Geo::ModestMaps->new($cfg);
 $fl->log()->add(Log::Dispatch::Screen->new('name' => 'scr', min_level => 'info'));

 my $map_data = $fl->mk_poster_map_for_photoset($opts{'s'});

 #
 # returns stuff like :
 #
 # {
 #  'url' => 'http://127.0.0.1:9999/?provider=YAHOO_AERIAL&marker=yadda yadda yadda',
 #  'image-height' => '8528',
 #  'marker-484080715' => '5076,5606,4919,5072,500,375',
 #  'marker-506435771' => '5256,4768,5099,542,500,375',
 #  'path' => '/tmp/dkl0o7uxjY.jpg',
 #  'image-width' => '6656',
 # }
 #

 my $results = $fl->upload_poster_map($map_data->{'path'});

 #
 # returns stuff like :
 #
 # [
 #   ['/tmp/GGsf4552h.jpg', '99999992'],
 #   ['/tmp/kosfGgsfdh.jpg', '99999254'],
 #   ['/tmp/h354jF590.jpg', '999984643'],
 #   [ and so on... ] 
 # ];
 #

DESCRIPTION

Tools for working with geotagged Flickr photos and the Modest Maps ws-pinwin HTTP service.

OPTIONS

Options are passed to Net::Flickr::Backup using a Config::Simple object or a valid Config::Simple config file. Options are grouped by "block".

flickr

  • api_key

    String. required

    A valid Flickr API key.

  • api_secret

    String. required

    A valid Flickr Auth API secret key.

  • auth_token

    String. required

    A valid Flickr Auth API token.

    The api_handler defines which XML/XPath handler to use to process API responses.

    • LibXML

      Use XML::LibXML.

    • XPath

      Use XML::XPath.

pinwin

  • map_height

    The height of the background map on which the pinwin/thumbnail will be placed.

    Default is 1024.

  • map_width

    The width of the background map on which the pinwin/thumbnail will be placed.

    Default is 1024.

  • upload

    Boolean.

    Automatically upload newly create map images to Flickr. Photos will be tagged with the following machine tags :

    • flickr:photo=photo_id

      Where photo_id is the photo that has been added to the map image.

    • flickr:map=pinwin

    Default is false.

  • upload_public

    Boolean.

    Mark pinwin uploads to Flickr as viewable by anyone.

    Default is false.

  • upload_friend

    Boolean.

    Mark pinwin uploads to Flickr as viewable only by friends.

    Default is false.

  • upload_family

    Boolean.

    Mark pinwin uploads to Flickr as viewable only by family.

    Default is false.

  • photo_size

    String.

    The string label for the photo size to display, as defined by the flickr.photos.getSizes API method :

     http://www.flickr.com/services/api/flickr.photos.getSizes.html

    Default is Medium

  • zoom

    Int.

    By default, the object will try to map the (Flickr) accuracy to the corresponding zoom level of the Modest Maps provider you have chosen. If this option is defined then it will be used as the zoom level regardless of what Flickr says.

  • crop_width

    Int.

    Used by the crop_poster_map (and by extension upload_poster_map) object methods to define the width of each slice taken from a poster map.

    Default is 1771

  • crop_height

    Int.

    Used by the crop_poster_map (and by extension upload_poster_map) object methods to define the height of each slice taken from a poster map.

    Default is 1239

  • skip_photos

    Int (or array reference of ints)

    Used by photoset related object methods, a list of photos to exclude from the list returned by the Flickr API.

  • skip_tags

    String (or array reference of strings)

    Used by photoset related object methods, a list of tags that all photos must not have if they are to be included in the final output.

  • ensure_tags

    String (or array reference of strings)

    Used by photoset related object methods, a list of tags that all photos must have if they are to be included in the final output.

modestmaps

  • server

    The URL to a server running the ws-pinwin.py HTTP interface to the ModestMaps tile-creation service.

    This requires Modest Maps 1.0 release or higher.

  • provider

    A map provider and tile format for generating map images.

    As of this writing, current providers are :

    • MICROSOFT_ROAD

    • MICROSOFT_AERIAL

    • MICROSOFT_HYBRID

    • GOOGLE_ROAD

    • GOOGLE_AERIAL

    • GOOGLE_HYBRID

    • YAHOO_ROAD

    • YAHOO_AERIAL

    • YAHOO_HYBRID

  • method

    Used only when creating poster maps, the method parameter defines how the underlying map is generated. Valid options are :

    • extent

      Render map tiles at a suitable zoom level in order to fit the bounding box (for all the images in a photoset) in an image with specific dimensions (pinwin.map_height and pinwin.map_width).

    • bbox

      Render all the map tiles necessary to display the bounding box (for all the images in a photoset) at a specific zoom level.

    Default is bbox.

  • bleed

    If true then extra white space will be added the underlying image in order to fit any markers that may extend beyond the original dimensions of the map.

    Boolean.

    Default is true.

  • adjust

    Used only when creating poster maps, the adjust parameter tells the modest maps server to extend bbox passed by n kilometers. This is mostly for esthetics so that there is a little extra map love near pinwin located at the borders of a map.

    Boolean.

    Default is .25

  • filter

    Tell the Modest Maps server to filter the rendered map image before applying an markers. Valid options are :

    • atkinson

      Apply the Atkinson dithering filter to the map image.

      This is brutally slow. Especially for poster maps. That's life.

  • timeout

    Int.

    The number of seconds the object's HTTP handler will wait when requesting data from the Modest Maps server.

    Default is 300 seconds.

PACKAGE METHODS

__PACKAGE__->new($cfg)

Returns a Net::Flickr::Geo object.

PINWIN MAPS

$obj->mk_pinwin_map_for_photo($photo_id)

Fetch a map using the Modest Maps ws-pinwin API for a geotagged Flickr photo and place a "pinwin" style thumbnail of the photo over the map's marker.

Returns an array of arrays (kind of pointless really, but at least consistent).

The first element of the (second-level) array will be the path to the newly created map image. If uploads are enabled the newly created Flickr photo ID will be passed as the second element.

$obj->mk_pinwin_maps_for_photoset($photoset_id)

For each geotagged photo in a set, fetch a map using the Modest Maps ws-pinwin API for a geotagged Flickr photo and place a "pinwin" style thumbnail of the photo over the map's marker.

If uploads are enabled then each map for a given photo will be added such that it appears before the photo it references.

Returns an array of arrays.

The first element of each (second-level) array reference will be the path to the newly created map image. If uploads are enabled the newly created Flickr photo ID will be passed as the second element.

POSTER MAPS

$obj->mk_poster_map_for_photoset($set_id)

For each geotagged photo in a set, plot the latitude and longitude and create a bounding box for the collection. Then fetch a map for that box using the Modest Maps ws-pinwin API for a geotagged Flickr photo and place a "pinwin" style thumbnail for each photo in the set.

Automatic uploads are not available for this method since the resultant images will almost always be too big.

Returns a hash reference containing the URL that was used to request the map image, the path to the data that was sent back as well as all of the Modest Maps specific headers sent back.

$obj->upload_poster_map($poster_map)

Take a file created by the mk_poster_map_for_photoset and chop it up in "postcard-sized" pieces and upload each to Flickr.

Returns an array of arrays.

The first element of the (second-level) array will be the path to the newly created map image. If uploads are enabled the newly created Flickr photo ID will be passed as the second element.

$obj->crop_poster_map($poster_map)

Take a file created by the mk_poster_map_for_photoset and chop it up in "postcard-sized" pieces.

The height and width of each piece are defined by the pinwin.crop_width and pinwin.crop_height config options.

Any image whose cropping creates a file smaller than either dimension will be padded with extra (white) space.

Returns a list of files.

CLUSTER MAPS

$obj->mk_cluster_maps_for_photo($photo_id)

Like poster maps, cluster maps plot many photos in multiple pinwins on a single background map image. Unlike poster maps, where you explicitly list all the photos to display (by specifying a photo set) cluster maps renders a single photo as its principal focus with all the photos with in an (n) kilometer radius of the subject photo.

Multiple photos sharing the same latitude and longitude are also clustered together and rendered in a single pinwin, whose size and shape is relative to the square root of the number of total photos. This helps, in densely photographed areas, to prevent cascading pinwins from rocketing off the map canvas trying to find a suitably empty space to avoid overlapping other nearby pinwins.

As of this writing, all the surrounding photos are rendered using their 75x75 pixel square thumbnail though this will be a user-configurable option in future releases. The principal photo size can still be set by assigning the pinwin.photo_size config variable (the default is Medium).

Cluster maps are not a general purpose interface to the Flickr photos.search method (yet) although there are some flags to limit search results to the principal photo's owner or by one or more copyright licenses.

All (except method, discussed below) the usual config options may be set for cluster maps. In addition, you may also define the following options :

  • clustermap.radius

    Float.

    The number of kilometers from $photo_id's lat/lon in which to perform a radial query for other geotagged photos.

    Default is 1

  • clustermap.offset

    Int.

    The number of days on either side of $photo_id's "date taken" value with which to limit the scope of the query.

    Default is 0

  • clustermap.only_photo_owner

    Boolean.

    Limit all queries to include only photos uploaded by $photo_id's owner.

    Default is true

  • clustermap.force_photo_owner

    Boolean.

    Typically used when setting the photo_license to ensure that nearby photos uploaded by $photo_ids owner are included. If true, this will cause the code to execute the same search twice. The second query will remove any licensing restrictions and enforce that only photos owned by $photo_id's owner be returned. The two result sets will then be merged and sorted by distance from the center point.

    (Ignored if the clustermap.only_photo_owner is true.)

    Default is false

  • photo_license

    String.

    A comma-separated list of Flickr license IDs to limit the list of photos returned by the photos.search API method.

    Default is none.

  • clustermap.geo_perms

    String.

    Post search, ensure that all the photos have a minimum set of geo permissions.

    Valid options are : "public", "contact", "friend", "family", "friend or family" and "all".

    Default is all

  • clustermap.max_photos

    Int.

    Although the clustering of photos sharing the same latitude and longitude helps cut down on number of pinwins the Modest Maps needs to figure out how to layout on the background map, there is still an upper limit after which it (Modest Maps) will simply give up.

    The exact number is a little hard to say as it is usually a function of how closely grouped any number of pinwins (clustered or not) are to each other. Anecdotally, anything less than 100 is fine; less than 200 is a toss up; anything after that usually wakes the baby.

    Default is 100

  • clustermap.max_photos_per_group

    Int.

    All of the clusters are grouped by their lat/lon position rounded off to three decimal points. You can change this option to set the maximum number of photos that can be contained in a single group.

    Default is half the value of the clustermap.max_photos parameter.

If either the max_photos or max_photos_per_group is exceeded then another search query is initiated, where the radial days offset from $photo_id's taken date is reduced by 10%. If no offset value was set by the user then an initial value of 365 is set (meaning that if there are still too many photos after the second query it will be reset to 328 days and so on.)

Finally, all cluster maps assume the Modest Maps bbox method. The bounding box itself is calcluated using the photos further from the center and is adjusted (in size) relative to distance between the south-west and north-east corners.

If the distance is less that 1km, the bounding box will be expanded by .25km; If the distance is less than 1.5km, the bounding box will be expanded by .1km; If the bounding is less than 2km, the bounding box will be expanded by .1km.

Returns a hash reference containing the URL that was used to request the map image, the path to the data that was sent back as well as all of the Modest Maps specific headers sent back.

Attribution for the photos is returned in a hash refernce whose key is labeled attribution and whose contents are a series of nested hashes mapping marker IDs to owners and a list of photos for that marker. For example :

 $response = {
        # lots of other stuff
        'marker-2561168539' => '1455,4189,1427,2065,75,75',
        'attribution' => {
                '2366199422' => {
                        'foobar' => ['http://www.flickr.com/photos/foobar/999999'],
                 }
         }
 }

$obj->mk_historical_cluster_map_for_photo($photo_id)

Historical cluster maps are similar to plain old cluster in nature, but not in execution. Rather than doing a single query and showing whatever happens to be closest to $photo_id historical cluster maps rely on the code making two calls to the photos.search each explicitly constrained by a date range.

The first query will ask for photos within (n) days of when the photo was taken; the second query will ask for photos within (n) days of today.

The two result sets are then smushed together, sorted by distance to $photo_id and clustered in to groups. If the number of photos, or grouped photos, is too high then each date range is reduced (the value of offset days is multiplied by 90% and rounded down) and the process is repeated until everything fits.

Or something breaks.

Then we make a map!

All the same rules and options that apply for plain old cluster maps are valid for historical cluster maps.

VERSION

0.72

DATE

$Date: 2008/08/03 17:08:39 $

AUTHOR

Aaron Straup Cope <ascope@cpan.org>

EXAMPLES

http://flickr.com/photos/straup/tags/modestmaps/

REQUIREMENTS

Modest Maps 1.0 or higher.

http://modestmaps.com/

NOTES

All uploads to Flickr are marked with a content-type of "other".

SEE ALSO

Net::Flickr::Geo

Net::ModestMaps

http://modestmaps.com/

http://mike.teczno.com/notes/oakland-crime-maps/IX.html

http://www.aaronland.info/weblog/2008/02/05/fox/#ws-modestmaps

BUGS

Sure, why not.

Please report all bugs via http://rt.cpan.org

LICENSE

Copyright (c) 2007-2008 Aaron Straup Cope. All Rights Reserved.

This is free software. You may redistribute it and/or modify it under the same terms as Perl itself.

2 POD Errors

The following errors were encountered while parsing the POD:

Around line 129:

'=item' outside of any '=over'

Around line 243:

You forgot a '=back' before '=head2'