/[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 2154 - (show annotations)
Sat Apr 10 19:07:59 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: 10774 byte(s)
Incorporate WMSCapabilities from capabilities.py and parser.py.
Implement priority list for supported graphics formats, take care of
  wbmp != bmp.  PNG, TIFF and GIF are supported here, but not yet by
  main Thuban.  Hence, support for them may be removed later.
Special contribution to usability: get wxWidgets to change the cursor
    when we're waiting for data from the network so the user won't
    start to worry.  This causes a redrawing error/warning, though.

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