1 |
# Copyright (C) 2003 by Intevation GmbH |
# Copyright (C) 2003, 2004 by Intevation GmbH |
2 |
# Authors: |
# Authors: |
3 |
# Jan-Oliver Wagner <[email protected]> |
# Jan-Oliver Wagner <[email protected]> |
4 |
# |
# |
13 |
layer into Thuban via an extension. |
layer into Thuban via an extension. |
14 |
Some things are not wired, so be prepared for Exceptions |
Some things are not wired, so be prepared for Exceptions |
15 |
everywhere. |
everywhere. |
|
|
|
|
You will need PyOGCLib 0.1.0, see |
|
|
http://pyogclib.sourceforge.net/ |
|
|
Set the PYTHONPATH to the PyOGCLib directory before |
|
|
starting Thuban. |
|
16 |
""" |
""" |
17 |
|
|
18 |
__version__ = "$Revision$" |
__version__ = "$Revision$" |
19 |
|
# $Source$ |
20 |
|
# $Id$ |
21 |
|
|
22 |
import os, sys |
import os, sys |
23 |
import xml.dom.minidom |
import xml.dom.minidom |
25 |
|
|
26 |
from wxPython.wx import * |
from wxPython.wx import * |
27 |
|
|
|
from ogclib.WMSClient import WMSClient |
|
|
|
|
|
from Thuban.Model.layer import BaseLayer |
|
28 |
from Thuban.Model.proj import Projection |
from Thuban.Model.proj import Projection |
29 |
from Thuban.Model.extension import Extension |
from Thuban.Model.extension import Extension |
|
from Thuban.Model.resource import read_proj_file |
|
30 |
from Thuban.UI.command import registry, Command |
from Thuban.UI.command import registry, Command |
31 |
import Thuban.UI.mainwindow |
from Thuban.UI.mainwindow import main_menu, layer_properties_dialogs |
32 |
from Thuban import _ |
from Thuban import _ |
33 |
import Thuban.UI.baserenderer |
import Thuban.UI.baserenderer |
34 |
|
from Thuban.UI.extensionregistry import ExtensionDesc, ext_registry |
35 |
|
|
36 |
|
from layer import WMSLayer |
37 |
|
|
38 |
def epsg_code_to_projection(epsg): |
ext_registry.add(ExtensionDesc( |
39 |
"""Find the projection for the given epsg code. |
name = 'WMS', |
40 |
|
version = '0.1.0', |
41 |
|
authors= [ 'Jan-Oliver Wagner' ], |
42 |
|
copyright = '2003, 2004 Intevation GmbH', |
43 |
|
desc = _("Provide layers via OGC WMS."))) |
44 |
|
|
|
epsg -- EPSG code as string |
|
|
""" |
|
|
proj_file, warnings = read_proj_file("Resources/Projections/epsg.proj") |
|
|
for proj in proj_file.GetProjections(): |
|
|
if proj.EPSGCode() == epsg: |
|
|
return proj |
|
|
proj_file, warnings = read_proj_file("Resources/Projections/epsg-deprecated.proj") |
|
|
for proj in proj_file.GetProjections(): |
|
|
if proj.EPSGCode() == epsg: |
|
|
return proj |
|
|
return None |
|
45 |
|
|
46 |
class WMSExtension(Extension): |
class WMSExtension(Extension): |
47 |
def TreeInfo(self): |
def TreeInfo(self): |
48 |
return (_("Extension: %s") % self.title, |
return (_("Extension: %s") % self.title, |
49 |
[ object.TreeInfo() for object in self.objects ]) |
[ object.TreeInfo() for object in self.objects ]) |
50 |
|
|
|
class WMSLayer(BaseLayer, WMSClient): |
|
|
|
|
|
def __init__(self, title, url): |
|
|
"""Initializes the WMSLayer. |
|
|
|
|
|
title -- Title of this layer. |
|
|
url -- URL of the WMS-Server wich must contain '?' |
|
|
|
|
|
If an error occured, self.error_msg is a string describing |
|
|
the problem(s). Else, self.error_msg is None. |
|
|
""" |
|
|
BaseLayer.__init__(self, title, visible = True, projection = None) |
|
|
self.url = url |
|
|
self.bbox = None |
|
|
self.latlonbbox = None |
|
|
self.error_msg = None |
|
|
self.layer_name = None |
|
|
|
|
|
wms_response = self.getCapabilities(self.url, '1.0') |
|
|
self._capa_dom = xml.dom.minidom.parseString(wms_response) |
|
|
|
|
|
root = self._capa_dom.documentElement |
|
|
cap = root.getElementsByTagName('Capability')[0] |
|
|
layer = cap.getElementsByTagName('Layer')[0] |
|
|
|
|
|
# get projected bounding box and latlon bounding box |
|
|
for node in layer.childNodes: |
|
|
if node.nodeName == 'BoundingBox': |
|
|
minx = node.attributes.get('minx').nodeValue |
|
|
miny = node.attributes.get('miny').nodeValue |
|
|
maxx = node.attributes.get('maxx').nodeValue |
|
|
maxy = node.attributes.get('maxy').nodeValue |
|
|
self.bbox = (float(minx), float(miny), float(maxx), float(maxy)) |
|
|
bbox = layer.getElementsByTagName('LatLonBoundingBox')[0] |
|
|
self.layer_name = layer.getElementsByTagName('Name')[0].childNodes[0].data |
|
|
minx = bbox.attributes.get('minx').nodeValue |
|
|
miny = bbox.attributes.get('miny').nodeValue |
|
|
maxx = bbox.attributes.get('maxx').nodeValue |
|
|
maxy = bbox.attributes.get('maxy').nodeValue |
|
|
self.latlonbbox = (float(minx), float(miny), float(maxx), float(maxy)) |
|
|
|
|
|
# get projection |
|
|
srs = layer.getElementsByTagName('SRS')[0].childNodes[0].data |
|
|
if len(srs.split(':')) == 1: |
|
|
epsg_id = srs |
|
|
else: |
|
|
epsg_id = srs.split(':')[1] |
|
|
|
|
|
p = epsg_code_to_projection(epsg_id) |
|
|
self.SetProjection(p) |
|
|
|
|
|
if p is None: |
|
|
self.error_msg = _('EPSG projection code %s not found!\n'\ |
|
|
'Setting projection to "None".\n'\ |
|
|
'Please set an appropriate projection yourself.'\ |
|
|
% epsg_id) |
|
|
|
|
|
# get title |
|
|
title = layer.getElementsByTagName('Title')[0].childNodes[0].data |
|
|
self.SetTitle(title.encode('latin1', 'replace')) |
|
|
|
|
|
self._capa_dom.unlink() |
|
|
|
|
|
def LatLongBoundingBox(self): |
|
|
"""Return the layer's bounding box in lat-lon. |
|
|
""" |
|
|
return self.latlonbbox |
|
|
|
|
|
def BoundingBox(self): |
|
|
"""Return the layer's bounding box in the intrinsic coordinate system. |
|
|
""" |
|
|
return self.bbox |
|
|
|
|
|
def GetMapImg(self, width, height, bbox): |
|
|
bbox_dict = { 'minx': bbox[0], 'miny': bbox[1], |
|
|
'maxx': bbox[2], 'maxy': bbox[3] } |
|
|
epsg_id = int(self.GetProjection().EPSGCode()) |
|
|
wms_response = self.getMap(self.url, 'JPEG', width, height, |
|
|
epsg_id, bbox_dict, |
|
|
[self.layer_name], version = '1.0') |
|
|
return wms_response |
|
|
|
|
|
|
|
51 |
|
|
52 |
def render_wms_layer(renderer, layer): |
def render_wms_layer(renderer, layer): |
53 |
offx, offy = renderer.offset |
offx, offy = renderer.offset |
59 |
xmax = (width - offx) / scale |
xmax = (width - offx) / scale |
60 |
ymax = (offy - 0) / scale |
ymax = (offy - 0) / scale |
61 |
|
|
62 |
img = layer.GetMapImg(width, height, (xmin, ymin, xmax, ymax)) |
img, format = layer.GetMapImg(width, height, (xmin, ymin, xmax, ymax)) |
63 |
renderer.draw_raster_data(img, "JPEG") |
renderer.draw_raster_data(img, format) |
64 |
|
|
65 |
return () |
return () |
66 |
|
|
67 |
Thuban.UI.baserenderer.add_renderer_extension(WMSLayer, render_wms_layer) |
Thuban.UI.baserenderer.add_renderer_extension(WMSLayer, render_wms_layer) |
68 |
|
from properties import wmsProperties |
69 |
|
layer_properties_dialogs.add(WMSLayer, wmsProperties) |
70 |
|
|
71 |
|
|
72 |
class SelectWMSServer(wxDialog): |
class SelectWMSServer(wxDialog): |
124 |
|
|
125 |
if dialog.ShowModal() == wxID_OK: |
if dialog.ShowModal() == wxID_OK: |
126 |
url = dialog.url |
url = dialog.url |
127 |
|
if len(url) == 0: |
128 |
|
url = None |
129 |
else: |
else: |
130 |
url = None |
url = None |
131 |
dialog.Destroy() |
dialog.Destroy() |
155 |
helptext = _('Add a WMS Layer'))) |
helptext = _('Add a WMS Layer'))) |
156 |
|
|
157 |
# find the experimental menu (create it anew if not found) |
# find the experimental menu (create it anew if not found) |
158 |
main_menu = Thuban.UI.mainwindow.main_menu |
experimental_menu = main_menu.FindOrInsertMenu('experimental', |
159 |
experimental_menu = main_menu.find_menu('experimental') |
_('Experimenta&l')) |
|
if experimental_menu is None: |
|
|
experimental_menu = main_menu.InsertMenu('experimental', _('Experimenta&l')) |
|
160 |
|
|
161 |
# finally add the new entry to the experimental menu |
# finally add the new entry to the experimental menu |
162 |
experimental_menu.InsertItem('wms') |
experimental_menu.InsertItem('wms') |