Example #1
0
function maps_images_for_dots(&$bag_of_dots, $more = array())
{
    $defaults = array('width' => 1024, 'height' => 768, 'draw_dots' => 1, 'dot_size' => 25);
    $template = $GLOBALS['cfg']['maptiles_template_url'];
    # This really needs to happen in modestmaps/Providers.php
    # but we'll do it here for now (20110112/straup)
    $hosts = $GLOBALS['cfg']['maptiles_template_hosts'];
    shuffle($hosts);
    $defaults['template'] = str_replace("{S}", $hosts[0], $template);
    $more = array_merge($defaults, $more);
    # If $GLOBALS['cfg']['enable_feature_wscompose'] is true then the drawing of
    # actual raster maps will be delegated to a wscompose server running on the
    # host and port of your choosing. The advantage of doing it this way is that
    # the PHP port of ModestMaps fetches tiles (for a map image) one at a time
    # while the Python version fetches them in a thread. If you're going to use
    # the wscompose stuff you should probably run the WSGIComposeServer under a
    # not-single-threaded server like gunicorn. Note that we still use ModestMaps.php
    # to draw dots. For now. (20110726/straup)
    # See the $queue array, below? We're going to iterate over all the dots and for
    # each one create an array of ModestMap.php objects and wscompose argument hashes.
    # The first foreach loop is used to figure out the bounds of the map and zoom
    # levels. The second loop is what will actually draw the maps. If wscompose is
    # in the house then the code will see whether it should try to fetch all the maps
    # using a multiget, using wscompose sequentially or ModestMaps.php sequentially.
    # The third and final loop will iterate over $queue and $bag_of_dots in parallel
    # and use the latter to draw dots on the corresponding index (image) in the former.
    # (20110727/straup)
    $queue = array();
    foreach ($bag_of_dots as $dots) {
        # null island
        if (count($dots) == 0) {
            $template = 'http://acetate.geoiq.com/tiles/acetate-hillshading/{Z}/{X}/{Y}.png';
            $provider = new MMaps_Templated_Spherical_Mercator_Provider($template);
            $centroid = new MMaps_Location(0, 0);
            $dims = new MMaps_Point($more['width'], $more['height']);
            $map = MMaps_mapByCenterZoom($provider, $centroid, 18, $dims);
            $wscompose_args = array('provider' => $template, 'method' => 'center', 'latitude' => 0, 'longitude' => 0, 'zoom' => 18, 'height' => $more['height'], 'width' => $more['width']);
            $queue[] = array($map, $wscompose_args);
        } else {
            if (count($dots) == 1) {
                $dot = $dots[0];
                $provider = new MMaps_Templated_Spherical_Mercator_Provider($template);
                $centroid = new MMaps_Location($dot['latitude'], $dot['longitude']);
                $dims = new MMaps_Point($more['width'], $more['height']);
                $map = MMaps_mapByCenterZoom($provider, $centroid, 17, $dims);
                $wscompose_args = array('provider' => $template, 'method' => 'center', 'latitude' => $dot['latitude'], 'longitude' => $dot['longitude'], 'zoom' => 17, 'height' => $more['height'], 'width' => $more['width']);
                $queue[] = array($map, $wscompose_args);
            } else {
                $swlat = null;
                $swlon = null;
                $nelat = null;
                $nelon = null;
                foreach ($dots as $dot) {
                    $swlat = !isset($swlat) ? $dot['latitude'] : min($swlat, $dot['latitude']);
                    $swlon = !isset($swlon) ? $dot['longitude'] : min($swlon, $dot['longitude']);
                    $nelat = !isset($nelat) ? $dot['latitude'] : max($nelat, $dot['latitude']);
                    $nelon = !isset($nelon) ? $dot['longitude'] : max($nelon, $dot['longitude']);
                }
                $provider = new MMaps_Templated_Spherical_Mercator_Provider($template);
                $sw = new MMaps_Location($swlat, $swlon);
                $ne = new MMaps_Location($nelat, $nelon);
                $dims = new MMaps_Point($more['width'], $more['height']);
                $wscompose_args = array('provider' => $template, 'height' => $more['height'], 'width' => $more['width']);
                if ($swlat == $nelat && $swlon == $nelon) {
                    $map = MMaps_mapByCenterZoom($provider, $sw, 17, $dims);
                    $wscompose_args['method'] = 'center';
                    $wscompose_args['latitude'] = $swlat;
                    $wscompose_args['longitude'] = $swlon;
                    $wscompose_args['zoom'] = 17;
                } else {
                    $map = MMaps_mapByExtent($provider, $sw, $ne, $dims);
                    $wscompose_args['method'] = 'extent';
                    $wscompose_args['bbox'] = implode(",", array($swlat, $swlon, $nelat, $nelon));
                }
                $queue[] = array($map, $wscompose_args);
            }
        }
    }
    # now we actually draw the images
    $count_queue = count($queue);
    # use wscompose and plow through all the images using a series of
    # batched multiget request (the multiget stuff happens in lib_http)
    if ($GLOBALS['cfg']['enable_feature_wscompose'] && $GLOBALS['cfg']['wscompose_enable_multigets']) {
        $wscompose_args = array();
        foreach ($queue as $stuff) {
            list($mm, $ws_args) = $stuff;
            $wscompose_args[] = $ws_args;
        }
        $rsp = array();
        $batch_size = 25;
        while (count($wscompose_args)) {
            $slice = array_slice($wscompose_args, 0, $batch_size);
            $wscompose_args = array_slice($wscompose_args, $batch_size);
            $_rsp = wscompose_get_many($slice);
            $rsp = array_merge($rsp, $_rsp);
        }
        # merge the results back in to $queue
        for ($i = 0; $i < $count_queue; $i++) {
            list($mm, $ignore) = $queue[$i];
            $_rsp = $rsp[$i];
            $img = $_rsp['ok'] ? $_rsp['image'] : null;
            $queue[$i] = array($mm, $img);
        }
    } else {
        if ($GLOBALS['cfg']['enable_feature_wscompose']) {
            for ($i = 0; $i < $count_queue; $i++) {
                list($mm, $ws_args) = $queue[$i];
                $rsp = wscompose_get($ws_args);
                $img = $rsp['ok'] ? $rsp['image'] : null;
                $queue[$i] = array($mm, $img);
            }
        } else {
            for ($i = 0; $i < $count_queue; $i++) {
                list($mm, $ignore) = $queue[$i];
                $img = $mm->draw();
                $queue[$i] = array($mm, $img);
            }
        }
    }
    # Not dots! Just return here and save ourselves the
    # very special Hell of another if/else block...
    if (!$more['draw_dots']) {
        return $queue;
    }
    # Carry on and draw the dots using ModestMaps.php - at some point this
    # may be functionality that is also delegated to wscompose/pinwin but
    # for now it is not. (20110726/straup)
    $rsp = array();
    $fill = imagecolorallocatealpha($img, 11, 189, 255, 96);
    $stroke = imagecolorallocate($img, 255, 255, 255);
    if (isset($GLOBALS['cfg']['dot_color_scheme'])) {
        $red_fill_val = isset($GLOBALS['cfg']['dot_color_scheme']['fill'][0]) ? $GLOBALS['cfg']['dot_color_scheme']['fill'][0] : 11;
        $green_fill_val = isset($GLOBALS['cfg']['dot_color_scheme']['fill'][1]) ? $GLOBALS['cfg']['dot_color_scheme']['fill'][1] : 189;
        $blue_fill_val = isset($GLOBALS['cfg']['dot_color_scheme']['fill'][2]) ? $GLOBALS['cfg']['dot_color_scheme']['fill'][2] : 255;
        # alpha value: convert alpha scale from 0,1 to 127,0
        $alpha_fill_val = isset($GLOBALS['cfg']['dot_color_scheme']['fill'][3]) ? floor(abs($GLOBALS['cfg']['dot_color_scheme']['fill'][3] * 127 - 127)) : 96;
        $red_stroke_val = isset($GLOBALS['cfg']['dot_color_scheme']['stroke'][0]) ? $GLOBALS['cfg']['dot_color_scheme']['stroke'][0] : 255;
        $green_stroke_val = isset($GLOBALS['cfg']['dot_color_scheme']['stroke'][1]) ? $GLOBALS['cfg']['dot_color_scheme']['stroke'][1] : 255;
        $blue_stroke_val = isset($GLOBALS['cfg']['dot_color_scheme']['stroke'][2]) ? $GLOBALS['cfg']['dot_color_scheme']['stroke'][2] : 255;
        $fill = imagecolorallocatealpha($img, $red_fill_val, $green_fill_val, $blue_fill_val, $alpha_fill_val);
        $stroke = imagecolorallocate($img, $red_stroke_val, $green_stroke_val, $blue_stroke_val);
    }
    for ($i = 0; $i < $count_queue; $i++) {
        list($mm, $img) = $queue[$i];
        $_dots = $bag_of_dots[$i];
        # because GD images get passed around as 'null' values...
        if ($img) {
            foreach ($_dots as $dot) {
                $loc = new MMaps_Location($dot['latitude'], $dot['longitude']);
                $pt = $mm->locationPoint($loc);
                imagefilledellipse($img, $pt->x, $pt->y, $more['dot_size'], $more['dot_size'], $fill);
                imagesetthickness($img, 3);
                imagearc($img, $pt->x, $pt->y, $more['dot_size'], $more['dot_size'], 0, 359.9, $stroke);
            }
        }
        $rsp[] = array($mm, $img);
    }
    return $rsp;
}
Example #2
0
/**
 * Convert a string of GeoJSON data to an atlas composition and queue it up.
 */
function compose_from_geojson(&$dbh, $data)
{
    $json = json_decode($data, true);
    if (!is_geojson($json)) {
        return null;
    }
    //
    // Move on to the actual business of converting GeoJSON to an atlas.
    // Start with a global paper size and orientation for the full document.
    //
    $p = $json['properties'];
    $paper_size = is_array($p) && isset($p['paper_size']) ? $p['paper_size'] : 'letter';
    $orientation = is_array($p) && isset($p['orientation']) ? $p['orientation'] : 'portrait';
    $layout = is_array($p) && isset($p['layout']) ? $p['layout'] : 'full-page';
    //
    // "orientation" above refers to the *map*, so if we want half-size
    // we'll need to flip the orientation of the overall printed sheet
    // to accommodate it.
    //
    if ($orientation == 'landscape' && $layout == 'half-page') {
        $orientation = 'portrait';
    } elseif ($orientation == 'portrait' && $layout == 'half-page') {
        $orientation = 'landscape';
    }
    list($printed_width, $printed_height) = get_printed_dimensions($paper_size, $orientation, $layout);
    $printed_aspect = $printed_width / $printed_height;
    $paper_type = "{$orientation}, {$paper_size}";
    $message = array('action' => 'compose', 'paper_size' => $paper_size, 'orientation' => $orientation, 'layout' => $layout, 'pages' => array());
    //
    // Iterate over each feature and determine an appropriate extent and zoom.
    // Each feature in the GeoJSON becomes a single page in the atlas.
    //
    foreach ($json['features'] as $f => $feature) {
        $number = $f + 1;
        //
        // Check the properties for a provider and explicit zoom.
        //
        $p = $feature['properties'];
        $provider = is_array($p) && isset($p['provider']) ? new MMaps_Templated_Spherical_Mercator_Provider($p['provider']) : new MMaps_OpenStreetMap_Provider();
        $explicit_zoom = is_array($p) && is_numeric($p['zoom']);
        $zoom = $explicit_zoom ? intval($p['zoom']) : 16;
        $mark = is_array($p['mark']) ? $p['mark'] : null;
        $fuzzy = is_array($p['fuzzy']) ? $p['fuzzy'] : null;
        $text = isset($p['text']) ? $p['text'] : null;
        //
        // Determine extent based on geometry type and zoom level.
        //
        $extent = null;
        if ($feature['geometry']['type'] == 'Point') {
            $extent = geojson_point_extent($feature['geometry'], $zoom);
        } elseif ($feature['geometry']['type'] == 'Polygon') {
            $extent = geojson_polygon_extent($feature['geometry']);
        } else {
            die_with_code(500, "I don't know how to do this yet, sorry.");
        }
        //
        // If we got this far, we know we have a meaningful zoom and extent
        // for this page, now adjust it to the known aspect ratio of the page.
        //
        $_mmap = MMaps_mapByExtentZoom($provider, $extent[0], $extent[1], $zoom);
        $dim = $_mmap->dimensions;
        $_mmap_center = $_mmap->pointLocation(new MMaps_Point($dim->x / 2, $dim->y / 2));
        $_mmap_aspect = $dim->x / $dim->y;
        if ($printed_aspect > $_mmap_aspect) {
            // paper is wider than the map
            $dim->x *= $printed_aspect / $_mmap_aspect;
        } else {
            // paper is taller than the map
            $dim->y *= $_mmap_aspect / $printed_aspect;
        }
        $mmap = MMaps_mapByCenterZoom($provider, $_mmap_center, $zoom, $dim);
        $provider = join(',', $mmap->provider->templates);
        $northwest = $mmap->pointLocation(new MMaps_Point(0, 0));
        $southeast = $mmap->pointLocation($mmap->dimensions);
        $bounds = array($northwest->lat, $northwest->lon, $southeast->lat, $southeast->lon);
        $message['pages'][] = compact('number', 'provider', 'bounds', 'zoom', 'text', 'mark', 'fuzzy');
    }
    //
    // Make room in the database for the new print and all its pages.
    //
    $print = add_print($dbh, 'nobody');
    $print['paper_size'] = $message['paper_size'];
    $print['orientation'] = $message['orientation'];
    $print['layout'] = $message['layout'];
    $print['north'] = $message['pages'][0]['bounds'][0];
    $print['south'] = $message['pages'][0]['bounds'][2];
    $print['west'] = $message['pages'][0]['bounds'][1];
    $print['east'] = $message['pages'][0]['bounds'][3];
    foreach ($message['pages'] as $_page) {
        $page = add_print_page($dbh, $print['id'], $_page['number']);
        $page['text'] = $_page['text'];
        $page['provider'] = $_page['provider'];
        $page['zoom'] = $_page['zoom'];
        $page['north'] = $_page['bounds'][0];
        $page['south'] = $_page['bounds'][2];
        $page['west'] = $_page['bounds'][1];
        $page['east'] = $_page['bounds'][3];
        set_print_page($dbh, $page);
        $print['north'] = max($print['north'], $page['north']);
        $print['south'] = min($print['south'], $page['south']);
        $print['west'] = min($print['west'], $page['west']);
        $print['east'] = max($print['east'], $page['east']);
    }
    $print['progress'] = 0.1;
    // the first 10% is getting it queued
    set_print($dbh, $print);
    $message['print_id'] = $print['id'];
    // queue the task
    queue_task("tasks.composePrint", array("http://" . SERVER_NAME, API_PASSWORD), $message);
    return $print;
}
Example #3
0
 function test_map_by_center_zoom()
 {
     $c = new MMaps_Location(37.804274, -122.26294);
     $z = 12;
     $d = new MMaps_Point(800, 600);
     $m = MMaps_mapByCenterZoom(new MMaps_OpenStreetMap_Provider(), $c, $z, $d);
     $this->assertEquals('(800.000, 600.000)', $m->dimensions->toString(), 'Map dimensions');
     $this->assertEquals('(1582.000, 656.000 @12.000)', $m->coordinate->toString(), 'Map coordinate');
     $this->assertEquals('(-235.000, -196.000)', $m->offset->toString(), 'Map offset');
 }
Example #4
0
<?php

require_once 'ModestMaps.php';
$p = new MMaps_Templated_Spherical_Mercator_Provider('http://tile.openstreetmap.org/{Z}/{X}/{Y}.png,http://osm.stamen.com/gridtile/tilecache.cgi/1.0/mgrs/{Z}/{X}/{Y}.png');
$m = MMaps_mapByCenterZoom($p, new MMaps_Location(37.804969, -122.257662), 14, new MMaps_Point(500, 500));
$i = $m->draw();
imagepng($i, '/tmp/out.png');