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

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

Parent Directory Parent Directory | Revision Log Revision Log


Revision 2154 - (hide 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 bh 2086 # Copyright (C) 2003, 2004 by Intevation GmbH
2 jan 1944 # 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 bh 2086 from Thuban.Model.resource import get_system_proj_file, EPSG_PROJ_FILE, \
37     EPSG_DEPRECATED_PROJ_FILE
38 jan 1944 from Thuban.UI.command import registry, Command
39     import Thuban.UI.mainwindow
40     from Thuban import _
41     import Thuban.UI.baserenderer
42    
43 joey 2154 from capabilities import WMSCapabilities
44 jan 1944
45     def epsg_code_to_projection(epsg):
46     """Find the projection for the given epsg code.
47    
48 bh 2086 epsg -- EPSG code as string
49 jan 1944 """
50 bh 2086 proj_file, warnings = get_system_proj_file(EPSG_PROJ_FILE)
51    
52 jan 1944 for proj in proj_file.GetProjections():
53     if proj.EPSGCode() == epsg:
54     return proj
55 bh 2086 proj_file, warnings = get_system_proj_file(EPSG_DEPRECATED_PROJ_FILE)
56 jan 1944 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 joey 2154 class WMSLayer(BaseLayer):
67 jan 1944
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 joey 2154 self.capabilities = None
84 jan 1944
85 joey 2154 # Change the cursor to demonstrate that we're busy but working
86     wxBeginBusyCursor()
87     self.capabilities = WMSCapabilities(url)
88     wxEndBusyCursor()
89 jan 1944
90 joey 2154 # 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 jan 1944
99 joey 2154 # 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 jan 1944
107 joey 2154 # 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 jan 1944 # get projection
126 joey 2154 p = epsg_code_to_projection(top_srs)
127 jan 1944 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 joey 2154 # 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 jan 1944
143 joey 2154 # get and set the title
144     self.SetTitle(self.capabilities.getTitle().encode('latin1', 'replace'))
145 jan 1944
146 joey 2154
147 jan 1944 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 joey 2154
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 jan 1944 def GetMapImg(self, width, height, bbox):
213     bbox_dict = { 'minx': bbox[0], 'miny': bbox[1],
214     'maxx': bbox[2], 'maxy': bbox[3] }
215 joey 2154
216     # Change the cursor to demonstrate that we're busy but working
217     wxBeginBusyCursor()
218    
219     wmsclient = WMSClient()
220    
221 jan 1944 epsg_id = int(self.GetProjection().EPSGCode())
222 joey 2154
223     wms_response = wmsclient.getMap(self.url, self.wmsformat, width, height,
224 jan 1944 epsg_id, bbox_dict,
225 joey 2154 [self.layer_name], version = self.capabilities.getVersion())
226     wxEndBusyCursor()
227     return wms_response, self.format
228 jan 1944
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 joey 2154 img, format = layer.GetMapImg(width, height, (xmin, ymin, xmax, ymax))
241     renderer.draw_raster_data(img, format)
242 jan 1944
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