/[thuban]/branches/WIP-pyshapelib-bramz/Extensions/wms/wms.py
ViewVC logotype

Contents of /branches/WIP-pyshapelib-bramz/Extensions/wms/wms.py

Parent Directory Parent Directory | Revision Log Revision Log


Revision 2159 - (show annotations)
Sun Apr 11 17:39:30 2004 UTC (20 years, 10 months ago) by joey
Original Path: trunk/thuban/Extensions/wms/wms.py
File MIME type: text/x-python
File size: 10862 byte(s)
The epsg_id variable is named top_srs now.

1 # Copyright (C) 2003, 2004 by Intevation GmbH
2 # Authors:
3 # Jan-Oliver Wagner <[email protected]>
4 #
5 # This program is free software under the GPL (>=v2)
6 # Read the file COPYING coming with Thuban for details.
7
8 """
9 Provide layers via OGC WMS.
10
11 This extension is in a very experimental stage!
12 It just demonstrates how to add a special
13 layer into Thuban via an extension.
14 Some things are not wired, so be prepared for Exceptions
15 everywhere.
16
17 You will need PyOGCLib 0.1.0, see
18 http://pyogclib.sourceforge.net/
19 Set the PYTHONPATH to the PyOGCLib directory before
20 starting Thuban.
21 """
22
23 __version__ = "$Revision$"
24
25 import os, sys
26 import xml.dom.minidom
27 import tempfile
28
29 from wxPython.wx import *
30
31 from ogclib.WMSClient import WMSClient
32
33 from Thuban.Model.layer import BaseLayer
34 from Thuban.Model.proj import Projection
35 from Thuban.Model.extension import Extension
36 from Thuban.Model.resource import get_system_proj_file, EPSG_PROJ_FILE, \
37 EPSG_DEPRECATED_PROJ_FILE
38 from Thuban.UI.command import registry, Command
39 import Thuban.UI.mainwindow
40 from Thuban.UI.common import ThubanBeginBusyCursor, ThubanEndBusyCursor
41 from Thuban import _
42 import Thuban.UI.baserenderer
43
44 from capabilities import WMSCapabilities
45
46 def epsg_code_to_projection(epsg):
47 """Find the projection for the given epsg code.
48
49 epsg -- EPSG code as string
50 """
51 proj_file, warnings = get_system_proj_file(EPSG_PROJ_FILE)
52
53 for proj in proj_file.GetProjections():
54 if proj.EPSGCode() == epsg:
55 return proj
56 proj_file, warnings = get_system_proj_file(EPSG_DEPRECATED_PROJ_FILE)
57 for proj in proj_file.GetProjections():
58 if proj.EPSGCode() == epsg:
59 return proj
60 return None
61
62 class WMSExtension(Extension):
63 def TreeInfo(self):
64 return (_("Extension: %s") % self.title,
65 [ object.TreeInfo() for object in self.objects ])
66
67 class WMSLayer(BaseLayer):
68
69 def __init__(self, title, url):
70 """Initializes the WMSLayer.
71
72 title -- Title of this layer.
73 url -- URL of the WMS-Server wich must contain '?'
74
75 If an error occured, self.error_msg is a string describing
76 the problem(s). Else, self.error_msg is None.
77 """
78 BaseLayer.__init__(self, title, visible = True, projection = None)
79 self.url = url
80 self.bbox = None
81 self.latlonbbox = None
82 self.error_msg = None
83 self.layer_name = None
84 self.capabilities = None
85
86 # Change the cursor to demonstrate that we're busy but working
87 ThubanBeginBusyCursor()
88 self.capabilities = WMSCapabilities(url)
89 ThubanEndBusyCursor()
90
91 # name of the top layer of the remote map
92 foo = self.capabilities.getLayers()
93 if len(foo) == 0:
94 self.error_msg = _('No layers found in remote resource:\n'\
95 '%s') % url
96 return
97 top_layer = foo[0]
98 self.layer_name = top_layer
99
100 # first projection of the top layer
101 foo = self.capabilities.getLayerSRS(top_layer)
102 if len(foo) == 0:
103 self.error_msg = _('No LatLonBoundingBox found for top layer %s')\
104 % top_layer
105 return
106 top_srs = foo[0]
107
108 # BoundingBox of the top layer
109 bbox = self.capabilities.getLayerBBox(top_layer, top_srs)
110 if len(bbox) == 0:
111 self.error_msg = _('No BoundingBox found for layer %s and EPSG:')\
112 % (top_layer, top_srs)
113 return
114 self.bbox = (float(bbox['minx']),
115 float(bbox['miny']),
116 float(bbox['maxx']),
117 float(bbox['maxy']))
118
119 # LatLonBox of the top layer
120 bbox = self.capabilities.getLayerLatLonBBox(top_layer)
121 self.latlonbbox = (float(bbox['minx']),
122 float(bbox['miny']),
123 float(bbox['maxx']),
124 float(bbox['maxy']))
125
126 # get projection
127 p = epsg_code_to_projection(top_srs)
128 self.SetProjection(p)
129
130 if p is None:
131 self.error_msg = _('EPSG projection code %s not found!\n'\
132 'Setting projection to "None".\n'\
133 'Please set an appropriate projection yourself.'\
134 % top_srs)
135
136 # pre-determine the used format
137 self.wmsformat, self.format = \
138 self.calcFormat(self.capabilities.getFormats())
139 if self.wmsformat is None:
140 self.error_msg = \
141 _('No supported image format found in remote resource')
142 return
143
144 # get and set the title
145 self.SetTitle(self.capabilities.getTitle().encode('latin1', 'replace'))
146
147
148 def LatLongBoundingBox(self):
149 """Return the layer's bounding box in lat-lon.
150 """
151 return self.latlonbbox
152
153 def BoundingBox(self):
154 """Return the layer's bounding box in the intrinsic coordinate system.
155 """
156 return self.bbox
157
158
159 def getFormat(self, format):
160 """
161 Return the image format for the render engine
162
163 format -- format as returned by the WMS server
164
165 If no mapping was found, None is returned
166
167 An exception rule is implemented in order to not accept
168 image/wbmp or WBMP which refers to WAP bitmap format and is
169 not supported by the included render engine.
170 """
171 fmap = {'png' : "PNG",
172 'jpeg': "JPEG",
173 'jpg' : "JPEG",
174 'tif' : "TIFF",
175 'gif' : "GIF",
176 'wbmp': None,
177 'bmp' : "BMP"}
178
179 for f in fmap.keys():
180 if format.lower().find(f) > -1:
181 return fmap[f]
182 return None
183
184
185 def calcFormat(self, formats):
186 """
187 Calculate the preferred image format
188
189 formats -- list of formates as returned by the WMS server
190
191 The following priority is used:
192 - PNG
193 - JPEG
194 - TIFF
195 - GIF
196 - BMP
197
198 If no matching format was found, None, None will be returned.
199
200 An exception rule is implemented in order to not accept
201 image/wbmp or WBMP which refers to WAP bitmap format and is
202 not supported by the included render engine.
203 """
204 prio = ['png', 'jpeg', 'jpg', 'tif', 'gif', 'bmp']
205 for p in prio:
206 for f in formats:
207 if f.lower().find(p) > -1:
208 if f.lower().find('wbmp') == -1:
209 return f, self.getFormat(f)
210 return None, None
211
212
213 def GetMapImg(self, width, height, bbox):
214 bbox_dict = { 'minx': bbox[0], 'miny': bbox[1],
215 'maxx': bbox[2], 'maxy': bbox[3] }
216
217 # Change the cursor to demonstrate that we're busy but working
218 ThubanBeginBusyCursor()
219
220 wmsclient = WMSClient()
221
222 epsg_id = int(self.GetProjection().EPSGCode())
223
224 wms_response = wmsclient.getMap(self.url, self.wmsformat, width, height,
225 epsg_id, bbox_dict,
226 [self.layer_name], version = self.capabilities.getVersion())
227 ThubanEndBusyCursor()
228 return wms_response, self.format
229
230
231 def render_wms_layer(renderer, layer):
232 offx, offy = renderer.offset
233 width, height = renderer.dc.GetSizeTuple()
234
235 scale = renderer.scale
236 xmin = (0 - offx) / scale
237 ymin = (offy - height) / scale
238 xmax = (width - offx) / scale
239 ymax = (offy - 0) / scale
240
241 img, format = layer.GetMapImg(width, height, (xmin, ymin, xmax, ymax))
242 renderer.draw_raster_data(img, format)
243
244 return ()
245
246 Thuban.UI.baserenderer.add_renderer_extension(WMSLayer, render_wms_layer)
247
248
249 class SelectWMSServer(wxDialog):
250
251 ID_COMBOVALUE = 4003
252
253 def __init__(self, parent):
254 wxDialog.__init__(self, parent, -1, _("Select WMS Server"),
255 style = wxDEFAULT_DIALOG_STYLE
256 | wxSYSTEM_MENU
257 | wxRESIZE_BORDER)
258
259 self.combo_value = wxComboBox(self, self.ID_COMBOVALUE, size=(500,-1))
260 self.combo_value.Append("")
261 self.combo_value.Append('http://frida.intevation.org/cgi-bin/frida_wms?')
262 #self.combo_value.Append('http://wms.jpl.nasa.gov/wms.cgi?')
263 #self.combo_value.Append('http://eukrante.hq:9089/cgi-bin/wms_shg?')
264 #self.combo_value.Append('http://131.220.106.112:8080/deegree0.7/wms?')
265 #self.combo_value.Append('http://demo.cubewerx.com/demo/cubeserv/cubeserv.cgi?CONFIG=gita&')
266 self.combo_value.SetSelection(0)
267
268 button_ok = wxButton(self, wxID_OK, _("OK"))
269 button_ok.SetDefault()
270 button_close = wxButton(self, wxID_CANCEL, _("Close"))
271
272 vbox = wxBoxSizer(wxVERTICAL)
273 vbox.Add(self.combo_value, 1, wxEXPAND|wxALL|wxCB_SORT, 10)
274 hbox = wxBoxSizer(wxHORIZONTAL)
275 hbox.Add(button_ok, 0, wxALL, 10)
276 hbox.Add(button_close, 0, wxALL, 10)
277 vbox.Add(hbox, 0, 10)
278
279 self.SetAutoLayout(True)
280 self.SetSizer(vbox)
281 vbox.Fit(self)
282 vbox.SetSizeHints(self)
283 self.Layout()
284
285 EVT_BUTTON(self, wxID_OK, self.OnOK)
286 EVT_BUTTON(self, wxID_CANCEL, self.OnCancel)
287
288 def OnOK(self, event):
289 self.url = self.combo_value.GetValue()
290 self.EndModal(wxID_OK)
291
292 def OnCancel(self, event):
293 self.EndModal(wxID_CANCEL)
294
295 def wms_dialog(context):
296 """Request URL from user and add WMS Layer.
297
298 context -- The Thuban context.
299 """
300 dialog = SelectWMSServer(context.mainwindow)
301
302 if dialog.ShowModal() == wxID_OK:
303 url = dialog.url
304 else:
305 url = None
306 dialog.Destroy()
307
308 if url is None:
309 return
310
311 wms_layer = WMSLayer('A WMS Layer', url)
312 if wms_layer.error_msg is not None:
313 context.mainwindow.RunMessageBox(_('WMS'), wms_layer.error_msg)
314
315 map = context.mainwindow.canvas.Map()
316 if map.projection is None:
317 map.SetProjection(wms_layer.projection)
318 has_layers = map.HasLayers()
319 map.AddLayer(wms_layer)
320 if not has_layers:
321 # if we're adding a layer to an empty map, fit the
322 # new map to the window
323 context.mainwindow.canvas.FitMapToWindow()
324
325 wxInitAllImageHandlers()
326 wms_extension = WMSExtension('WMS')
327
328 # register the new command
329 registry.Add(Command('wms', _('Add WMS layer ...'), wms_dialog,
330 helptext = _('Add a WMS Layer')))
331
332 # find the experimental menu (create it anew if not found)
333 main_menu = Thuban.UI.mainwindow.main_menu
334 experimental_menu = main_menu.find_menu('experimental')
335 if experimental_menu is None:
336 experimental_menu = main_menu.InsertMenu('experimental', _('Experimenta&l'))
337
338 # finally add the new entry to the experimental menu
339 experimental_menu.InsertItem('wms')

Properties

Name Value
svn:eol-style native
svn:keywords Author Date Id Revision

[email protected]
ViewVC Help
Powered by ViewVC 1.1.26