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; }
function test_map_by_extent() { $sw = new MMaps_Location(36.893326, -123.533554); $ne = new MMaps_Location(38.864246, -121.208153); $d = new MMaps_Point(800, 600); $m = MMaps_mapByExtent(new MMaps_OpenStreetMap_Provider(), $sw, $ne, $d); $this->assertEquals('(800.000, 600.000)', $m->dimensions->toString(), 'Map dimensions'); $this->assertEquals('(98.000, 40.000 @8.000)', $m->coordinate->toString(), 'Map coordinate'); $this->assertEquals('(-251.000, -218.000)', $m->offset->toString(), 'Map offset'); $se = new MMaps_Location(36.893326, -121.208153); $nw = new MMaps_Location(38.864246, -123.533554); $d = new MMaps_Point(1600, 1200); $m = MMaps_mapByExtent(new MMaps_OpenStreetMap_Provider(), $se, $nw, $d); $this->assertEquals('(1600.000, 1200.000)', $m->dimensions->toString(), 'Map dimensions'); $this->assertEquals('(197.000, 81.000 @9.000)', $m->coordinate->toString(), 'Map coordinate'); $this->assertEquals('(-246.000, -179.000)', $m->offset->toString(), 'Map offset'); }