<?php
function nicemap_menu() {
$items = array();
$items['admin/settings/nicemap'] = array(
'title' => 'Nicemap Configuration',
'description' => 'Test WMS servers with the Nicemap module.',
'page callback' => 'drupal_get_form',
'page arguments' => array('nicemap_settings'),
'access arguments' => array('administer site configuration'),
'file' => 'nicemap_admin.inc',
'type' => MENU_NORMAL_ITEM,
);
$items['admin/settings/nicemap/settings'] = array(
'type' => MENU_DEFAULT_LOCAL_TASK,
'title' => 'Settings',
'weight' => -1,
);
$items['admin/settings/nicemap/cache'] = array(
'type' => MENU_LOCAL_TASK,
'title' => 'Clear cache',
'page callback' => 'drupal_get_form',
'page arguments' => array('nicemap_cache_clear'),
'access arguments' => array('administer site configuration'),
'file' => 'nicemap_admin.inc',
);
return $items;
}
function nicemap_theme($existing, $type, $theme, $path) {
return array(
'nicemap_map' => array(
'file' => 'nicemap.theme.inc',
'arguments' => array('points' => array(), 'map' => array(), 'width' => 200, 'height' => 200),
),
'nicemap_point' => array(
'file' => 'nicemap.theme.inc',
'arguments' => array('point' => array()),
),
'nicemap_content' => array(
'file' => 'nicemap.theme.inc',
'arguments' => array('point' => array()),
),
'nicemap_settings_layers' => array(
'file' => 'nicemap_admin.inc',
'arguments' => array('form' => array()),
),
);
}
function nicemap_views_api() {
return array(
'api' => 2,
'path' => drupal_get_path('module', 'nicemap') . '/views',
);
}
function nicemap_capabilities($base_url) {
$capabilities = $base_url .'?request=GetCapabilities&service=WMS';
$cxml = @simplexml_load_file($capabilities);
if (!$cxml) {
drupal_set_message('The WMS server could not be reached.');
return array();
}
foreach ($cxml->Capability->Request->GetMap->Format as $f) {
$file_types[] = (String) $f;
}
$c['info'] = array(
'name' => (String) $cxml->Service->Name,
'title' => (String) $cxml->Service->Title,
'abstract' => (String) $cxml->Service->Abstract,
'filetypes' => (String) $file_types);
if ($layers = $cxml->Capability->Layer->Layer) {
if (isset($cxml->Capability->Layer->CRS)) {
$c['crs'][] = (String) $cxml->Capability->Layer->CRS;
}
foreach ($layers as $l) {
$c['layers'][(String) $l->Name] = array(
'title' => (String) $l->Title,
'bounds' =>
array(
'minx' => (float) $l->LatLonBoundingBox['minx'],
'miny' => (float) $l->LatLonBoundingBox['miny'],
'maxx' => (float) $l->LatLonBoundingBox['maxx'],
'maxy' => (float) $l->LatLonBoundingBox['maxy']),
);
if ((String) $l->SRS) {
$c['layers'][(String) $l->Name]['srs'] = (String) $l->SRS;
}
if ($l->Style) {
foreach ($l->Style as $style) {
$c['layers'][(String) $l->Name]['styles'][(String) $style->Name] = (String) $style->Title;
}
ksort($c['layers'][(String) $l->Name]['styles']);
}
}
}
return $c;
}
function nicemap_capabilities_cache($base_url = NULL, $reset = false) {
$base_url = $base_url ? $base_url : variable_get('nicemap_wms_url', '');
$cache = variable_get('nicemap_cache', array());
if (!isset($cache[$base_url]) || $reset) {
$cache[$base_url] = nicemap_capabilities($base_url);
variable_set('nicemap_cache', $cache);
}
return $cache[$base_url];
}
function _nicemap_get_layers($spec = NULL) {
$layers = array();
if ($spec) {
if (count($spec['layers'])) {
$layers = $spec['layers'];
$weights = variable_get('nicemap_wms_weights', array());
foreach ($weights as $layer => $weight) {
if (isset($layers[$layer])) {
$layers[$layer]['#weight'] = $weight;
}
}
}
}
else {
$styles = variable_get('nicemap_wms_styles', array());
$weights = variable_get('nicemap_wms_weights', array());
foreach (variable_get('nicemap_wms_layers', array()) as $layer => $enabled) {
if ($enabled) {
$layers[$layer] = array(
'style' => $styles[$layer],
'#weight' => isset($weights[$layer]) ? $weights[$layer] : 0,
);
}
}
}
uasort($layers, 'element_sort');
return $layers;
}
function nicemap_map_projection($type) {
switch ($type) {
case 'equirectangular':
$projection = new nicemap_equirectangular_projection();
return $projection;
case 'mercator':
$projection = new nicemap_mercator_projection();
return $projection;
}
return false;
}
function nicemap_get_projection() {
$projections = nicemap_projections();
switch (variable_get('nicemap_mode', '')) {
case 'wms':
$p = variable_get('nicemap_wms_crs', false);
break;
case 'file':
$p = variable_get('nicemap_file_projection', false);
break;
}
if ($p && isset($projections[$p])) {
return new $projections[$p]['class']();
}
return false;
}
function nicemap_projections() {
return array(
'EPSG:3395' => array(
'mercator' => t('Mercator'),
'class' => 'nicemap_mercator_projection',
),
'EPSG:4326' => array(
'name' => t('Equirectangular'),
'class' => 'nicemap_equirectangular_projection',
),
'EPSG:900913' => array(
'mercator' => t('Google Mercator'),
'class' => 'nicemap_mercator_projection', ),
);
}
class nicemap_map {
public $server;
public $bgcolor;
public $layers = array();
public $styles = array();
public $bounds = array();
public $projection;
function __construct($load_layers = true) {
$this->bgcolor = variable_get('nicemap_wms_bgcolor', '');
$this->server = variable_get('nicemap_wms_url', '');
$this->projection = nicemap_get_projection();
if ($load_layers) {
foreach (_nicemap_get_layers() as $layer => $info) {
$this->layers[] = $layer;
$this->styles[] = $info['style'];
}
}
}
function process($items, $target = array()) {
$orig_map = $this->bounds;
$this->bounds = $this->projection->getmap($this->bounds, $target);
$points = array();
foreach ($items as $item) {
if (
$item['lat'] > $orig_map['miny'] &&
$item['lat'] < $orig_map['maxy'] &&
$item['lon'] > $orig_map['minx'] &&
$item['lon'] < $orig_map['maxx']
) {
list($x, $y) = $this->projection->getpoint($this->bounds, $item);
$ratio['y'] = $y / $this->bounds['h'];
$ratio['x'] = $x / $this->bounds['w'];
$y = 100 - (100 * $ratio['y']);
$x = 100 * $ratio['x'];
$item['x'] = $x;
$item['y'] = $y;
$points[] = $item;
}
}
return $points;
}
function url($options = array()) {
if ($this->server) {
if ($this->styles) {
$options['styles'] = implode(',', $this->styles);
}
if ($this->bgcolor) {
$options['bgcolor'] = '0x'. $this->bgcolor;
}
$options['request'] = 'GetMap';
$options['version'] = '1.1.1';
$options['format'] = 'image/png';
$options['layers'] = implode(',', $this->layers);
$options['srs'] = variable_get('nicemap_wms_crs', 'EPSG:900913');
$options['EXCEPTIONS'] = 'application/vnd.ogc.se_inimage';
$options['bbox'] = $this->bounds['minx'].','.$this->bounds['miny'].','.$this->bounds['maxx'].','.$this->bounds['maxy'];
$url = array();
foreach ($options as $flag => $val) {
$url[] = $flag ."=". $val;
}
$url = implode('&', $url);
return url($this->server, array('query' => $url, 'fragment' => null, 'absolute' => TRUE));
}
else {
return;
}
}
}
interface nicemap_projection {
public function getmap($map, $target);
public function getpoint($map, $item);
}
class nicemap_mercator_projection implements nicemap_projection {
public function getmap($map, $target) {
$map['w'] = deg2rad($map['maxx']) - deg2rad($map['minx']);
$map['h'] = asinh(tan(deg2rad($map['maxy']))) - asinh(tan(deg2rad($map['miny'])));
$map['o'] = asinh(tan(deg2rad($map['miny'])));
$map['ratio'] = $map['w'] / $map['h'];
if (count($target)) {
$target['ratio'] = $target['width'] / $target['height'];
if ($target['ratio'] >= $map['ratio']) {
$new_w = $map['h'] * $target['ratio'];
$map['minx'] = deg2rad($map['minx']) - ($new_w - $map['w']) * .5;
$map['maxx'] = deg2rad($map['maxx']) + ($new_w - $map['w']) * .5;
if (($map['minx'] < (M_PI * -1)) && ($map['maxx'] > M_PI)) {
$map['minx'] = M_PI * -1;
$map['maxx'] = M_PI;
}
else if ($map['minx'] < (M_PI * -1)) {
$diff = $map['minx'] - (M_PI * -1);
$map['minx'] = $map['minx'] - $diff;
$map['maxx'] = $map['maxx'] - $diff;
}
else if ($map['maxx'] > M_PI) {
$diff = ($map['maxx'] - M_PI);
$map['maxx'] = $map['maxx'] - $diff;
$map['minx'] = $map['minx'] - $diff;
}
$map['miny'] = rad2deg($map['miny']);
$map['maxy'] = rad2deg($map['maxy']);
$map['w'] = $new_w;
$map['ratio'] = $target['ratio'];
}
else {
$midpoint = asinh(tan(deg2rad($map['maxy']))) - ($map['h']*.5);
$map['h'] = $map['w'] / $target['ratio'];
$map['o'] = $midpoint - ($map['h']*.5);
$map['maxy'] = rad2deg(atan(sinh($midpoint + ($map['h']*.5))));
$map['miny'] = rad2deg(atan(sinh($midpoint - ($map['h']*.5))));
}
}
$map['ratio'] = $map['w'] / $map['h'];
return $map;
}
public function getpoint($map, $item) {
$y = asinh(tan(deg2rad($item['lat']))) - $map['o'];
$x = deg2rad($item['lon']) - deg2rad($map['minx']);
return array($x, $y);
}
}
class nicemap_equirectangular_projection implements nicemap_projection {
public function getmap($map, $target) {
$map['w'] = deg2rad($map['maxx']) - deg2rad($map['minx']);
$map['h'] = deg2rad($map['maxy']) - deg2rad($map['miny']);
$map['o'] = deg2rad($map['miny']);
$map['ratio'] = $map['w'] / $map['h'];
if (count($target)) {
$target['ratio'] = $target['width'] / $target['height'];
if ($target['ratio'] >= $map['ratio']) {
$new_w = $map['h'] * $target['ratio'];
$map['minx'] = $map['minx'] - rad2deg(($new_w - $map['w']) * .5);
$map['maxx'] = $map['maxx'] + rad2deg(($new_w - $map['w']) * .5);
$map['minx'] = ($map['minx'] < -180) ? $map['minx'] = -179.99 : $map['minx'];
$map['maxx'] = ($map['maxx'] > 180) ? $map['maxx'] = 179.99 : $map['maxx'];
$map['w'] = $new_w;
$map['ratio'] = $target['ratio'];
}
else {
$midpoint = $map['maxy'] - (rad2deg($map['h'])*.5);
$map['h'] = $map['w'] / $target['ratio'];
$map['o'] = deg2rad($midpoint) - ($map['h']*.5);
$map['maxy'] = $midpoint + rad2deg($map['h']*.5);
$map['miny'] = $midpoint - rad2deg($map['h']*.5);
}
}
$map['ratio'] = $map['w'] / $map['h'];
return $map;
}
public function getpoint($map, $item) {
$x = deg2rad($item['lon']) - deg2rad($map['minx']);
$y = deg2rad($item['lat']) - $map['o'];
return array($x, $y);
}
}