2 @package nviz.mapwindow
4 @brief wxGUI 3D view mode (map canvas)
6 This module implements 3D visualization mode for map display.
9 - mapwindow::NvizThread
12 (C) 2008-2011 by the GRASS Development Team
14 This program is free software under the GNU General Public License
15 (>=v2). Read the file COPYING that comes with GRASS for details.
17 @author Martin Landa <landa.martin gmail.com> (Google SoC 2008/2010)
18 @author Anna Kratochvilova <kratochanna gmail.com> (Google SoC 2011)
29 from threading
import Thread
32 from wx.lib.newevent
import NewEvent
33 from wx
import glcanvas
34 from wx.glcanvas
import WX_GL_DEPTH_SIZE
38 from core.gcmd import GMessage, GException, GError
45 from nviz
import wxnviz
48 wxUpdateProperties, EVT_UPDATE_PROP = NewEvent()
49 wxUpdateView, EVT_UPDATE_VIEW = NewEvent()
50 wxUpdateLight, EVT_UPDATE_LIGHT = NewEvent()
51 wxUpdateCPlane, EVT_UPDATE_CPLANE = NewEvent()
56 Debug.msg(5,
"NvizThread.__init__():")
69 """!Get display instance"""
73 """!OpenGL canvas for Map Display Window"""
74 def __init__(self, parent, id = wx.ID_ANY,
75 Map =
None, tree =
None, lmgr =
None):
82 sys.platform
not in (
'win32',
'darwin'):
83 depthBuffer = int(UserSettings.Get(group=
'display', key=
'nvizDepthBuffer', subkey=
'value'))
84 attribs=[WX_GL_DEPTH_SIZE, depthBuffer, 0]
85 glcanvas.GLCanvas.__init__(self, parent, id, attribList=attribs)
87 glcanvas.GLCanvas.__init__(self, parent, id)
90 MapWindow.__init__(self, parent, id,
107 'default' : wx.StockCursor(wx.CURSOR_ARROW),
108 'cross' : wx.StockCursor(wx.CURSOR_CROSS),
137 self.
log = self.lmgr.goutput
138 logerr = self.lmgr.goutput.GetLog(err =
True)
139 logmsg = self.lmgr.goutput.GetLog()
141 self.
log = logmsg = sys.stdout
145 os.environ[
'GRASS_REGION'] = self.Map.SetRegion(windres =
True)
148 self.parent.GetProgressBar(),
150 self.nvizThread.start()
152 self.
_display = self.nvizThread.GetDisplay()
155 del os.environ[
'GRASS_REGION']
157 self.
img = wx.Image(self.Map.mapfile, wx.BITMAP_TYPE_ANY)
164 self.
view = copy.deepcopy(UserSettings.Get(group =
'nviz', key =
'view'))
165 self.
iview = UserSettings.Get(group =
'nviz', key =
'view', internal =
True)
166 self.
light = copy.deepcopy(UserSettings.Get(group =
'nviz', key =
'light'))
167 self.
decoration = self.nvizDefault.SetDecorDefaultProp(type =
'arrow')
179 self.Bind(wx.EVT_SIZE, self.
OnSize)
180 self.Bind(wx.EVT_PAINT, self.
OnPaint)
190 self.Bind(wx.EVT_KEY_DOWN, self.
OnKeyDown)
191 self.Bind(wx.EVT_KEY_UP, self.
OnKeyUp)
193 self.Bind(wx.EVT_CLOSE, self.
OnClose)
196 sys.platform
not in (
'win32',
'darwin'):
202 def _warningDepthBuffer(self):
204 message=_(
"Opening 3D view was not successful. "
205 "Please try to change the value of depth buffer "
206 "in GUI Settings dialog > tab Map Display > Advanced "
211 """!Initialize fly through dictionary"""
212 fly = {
'interval' : 10,
216 'move' : UserSettings.Get(group =
'nviz', key =
'fly', subkey = [
'exag',
'move']),
217 'turn' : UserSettings.Get(group =
'nviz', key =
'fly', subkey = [
'exag',
'turn'])},
218 'exagMultiplier' : 3,
220 'mouseControl' :
None,
221 'pos' : {
'x' : 0,
'y' : 0},
229 """!Fly event was emitted, move the scene"""
230 if self.
mouse[
'use'] !=
'fly':
233 if self.
fly[
'mouseControl']:
239 self._display.FlyThrough(flyInfo = self.
fly[
'value'], mode = self.
fly[
'mode'],
240 exagInfo = self.
fly[
'exag'])
242 self.
render[
'quick'] =
True
246 """!Compute values for flythrough navigation
247 (ComputeFlyValues should follow).
249 Based on visualization/nviz/src/togl_flythrough.c.
250 @param x,y screen coordinates
252 sx, sy = self.GetClientSizeTuple()
255 mx = 2 * (float(x) / sx) - 1
256 my = 2 * (float(y) / sy) - 1
281 """!Compute parameters for fly-through navigation
283 @params mx,my results from ComputeMxMy method
285 self.
fly[
'value'] = [0, 0, 0]
287 if self.
fly[
'mode'] == 0:
288 self.
fly[
'value'][0] = self.
fly[
'flySpeed'] * self.
fly[
'interval'] / 1000.
289 self.
fly[
'value'][1] = mx * 0.1 * self.
fly[
'interval'] / 1000.
290 self.
fly[
'value'][2] = my * 0.1 * self.
fly[
'interval'] / 1000.
292 self.
fly[
'value'][0] = mx * 100.0 * self.
fly[
'interval'] /1000.
293 self.
fly[
'value'][2] = - my * 100.0 * self.
fly[
'interval'] /1000.
296 """!Increase/decrease flight spped"""
298 self.
fly[
'flySpeed'] += self.
fly[
'flySpeedStep']
300 self.
fly[
'flySpeed'] -= self.
fly[
'flySpeedStep']
303 """!Stop timers if running, unload data"""
309 """!Stop timer if running"""
310 if timer.IsRunning():
313 def _bindMouseEvents(self):
315 self.Bind(wx.EVT_MOTION, self.
OnMotion)
318 """!Initialize cutting planes list"""
319 for i
in range(self._display.GetCPlanesCount()):
320 cplane = copy.deepcopy(UserSettings.Get(group =
'nviz', key =
'cplane'))
322 self.cplanes.append(cplane)
325 """!Sets reference to nviz toolwindow in layer manager"""
329 """!Returns reference to nviz toolwindow in layer manager"""
342 size = self.GetClientSize()
343 if self.
size != size \
344 and self.GetContext():
345 Debug.msg(3,
"GLCanvas.OnSize(): w = %d, h = %d" % \
346 (size.width, size.height))
348 self._display.ResizeWindow(size.width,
352 self.parent.StatusbarReposition()
355 self.parent.StatusbarUpdate()
362 Debug.msg(1,
"GLCanvas.OnPaint()")
364 self.
render[
'overlays'] =
True
365 dc = wx.PaintDC(self)
373 self._display.InitView()
382 if hasattr(self.
lmgr,
"nviz"):
383 self.lmgr.nviz.UpdatePage(
'view')
384 self.lmgr.nviz.UpdatePage(
'light')
385 self.lmgr.nviz.UpdatePage(
'cplane')
386 self.lmgr.nviz.UpdatePage(
'decoration')
387 self.lmgr.nviz.UpdatePage(
'animation')
390 if layer.type ==
'raster':
391 self.lmgr.nviz.UpdatePage(
'surface')
392 self.lmgr.nviz.UpdatePage(
'fringe')
393 elif layer.type ==
'vector':
394 self.lmgr.nviz.UpdatePage(
'vector')
396 self.lmgr.nviz.UpdateSettings()
399 win = self.lmgr.nviz.FindWindowById( \
400 self.lmgr.nviz.win[
'vector'][
'lines'][
'surface'])
408 """!Draw overlay image"""
410 if texture.IsActive():
414 """!Estimates legend size for dragging"""
417 for param
in self.
overlays[1].cmd[1:]:
418 if param.startswith(
"at="):
419 size = map(int, param.split(
"=")[-1].
split(
','))
422 wSize = self.GetClientSizeTuple()
423 x, y = size[2]/100. * wSize[0], wSize[1] - (size[1]/100. * wSize[1])
426 w = (size[3] - size[2])/100. * wSize[0]
427 h = (size[1] - size[0])/100. * wSize[1]
429 rect = wx.Rect(x, y, w, h)
435 """!Draw overlay text"""
436 bmp = wx.EmptyBitmap(textDict[
'bbox'][2], textDict[
'bbox'][3])
437 memDC = wx.MemoryDC()
438 memDC.SelectObject(bmp)
440 mask = self.
view[
'background'][
'color']
441 if mask == textDict[
'color']:
443 memDC.SetBackground(wx.Brush(mask))
445 memDC.SetFont(textDict[
'font'])
446 memDC.SetTextForeground(textDict[
'color'])
447 if textDict[
'rotation'] == 0:
448 memDC.DrawText(textDict[
'text'], 0, 0)
450 memDC.DrawRotatedText(textDict[
'text'], relCoords[0], relCoords[1],
451 textDict[
'rotation'])
452 bmp.SetMaskColour(mask)
453 memDC.DrawBitmap(bmp, 0, 0, 1)
455 filename = tempfile.mktemp() +
'.png'
456 bmp.SaveFile(filename, wx.BITMAP_TYPE_PNG)
457 memDC.SelectObject(wx.NullBitmap)
462 """!Converts rendered overlay files and text labels to wx.Image
463 and then to textures so that they can be rendered by OpenGL.
464 Updates self.imagelist"""
465 self.Map.ChangeMapSize(self.GetClientSize())
466 self.Map.RenderOverlays(force =
True)
471 if texture.GetId() < 100:
472 if not self.
overlays[texture.GetId()].IsShown():
473 texture.SetActive(
False)
475 texture.SetActive(
True)
477 if texture.GetId()
not in self.
textdict:
478 self.imagelist.remove(texture)
481 for oid, overlay
in self.overlays.iteritems():
482 if not overlay.IsShown()
or oid == 0:
484 if oid
not in [t.GetId()
for t
in self.
imagelist]:
489 if not t.Corresponds(overlay):
490 self.imagelist.remove(t)
493 t.SetCoords(overlay.coords)
497 for textId
in self.textdict.keys():
498 if textId
not in [t.GetId()
for t
in self.
imagelist]:
502 if t.GetId() == textId:
503 self.
textdict[textId][
'bbox'] = t.textDict[
'bbox']
504 if not t.Corresponds(self.
textdict[textId]):
505 self.imagelist.remove(t)
508 t.SetCoords(self.
textdict[textId][
'coords'])
511 """!Create texture from overlay image or from textdict"""
514 coords = list(self.
overlays[overlay.id].coords),
515 cmd = overlay.GetCmd())
520 self.
textdict[textId][
'coords'] = coords
521 self.
textdict[textId][
'bbox'] = bbox
524 coords = coords, textDict = self.
textdict[textId])
525 bbox.OffsetXY(*relCoords)
526 texture.SetBounds(bbox)
528 if not texture.textureId:
529 GMessage(parent = self, message =
530 _(
"Image is too large, your OpenGL implementation "
531 "supports maximum texture size %d px.") % texture.maxSize)
534 self.imagelist.append(texture)
539 """Find object which was clicked on"""
541 if texture.HitTest(mouseX, mouseY, radius):
546 self.animation.Update()
554 Used for fly-through mode.
556 if not self.
mouse[
'use'] ==
'fly':
559 key = event.GetKeyCode()
560 if key == wx.WXK_CONTROL:
563 elif key == wx.WXK_SHIFT:
564 self.
fly[
'exag'][
'move'] *= self.
fly[
'exagMultiplier']
565 self.
fly[
'exag'][
'turn'] *= self.
fly[
'exagMultiplier']
567 elif key == wx.WXK_ESCAPE
and self.timerFly.IsRunning()
and not self.
fly[
'mouseControl']:
569 self.
fly[
'mouseControl'] =
None
570 self.
render[
'quick'] =
False
573 elif key
in (wx.WXK_UP, wx.WXK_DOWN, wx.WXK_LEFT, wx.WXK_RIGHT):
574 if not self.
fly[
'mouseControl']:
575 if not self.timerFly.IsRunning():
576 sx, sy = self.GetClientSizeTuple()
577 self.
fly[
'pos'][
'x'] = sx / 2
578 self.
fly[
'pos'][
'y'] = sy / 2
579 self.
fly[
'mouseControl'] =
False
580 self.timerFly.Start(self.
fly[
'interval'])
588 elif key == wx.WXK_DOWN:
591 elif key
in (wx.WXK_HOME, wx.WXK_PAGEUP)
and self.timerFly.IsRunning():
593 elif key
in (wx.WXK_END, wx.WXK_PAGEDOWN)
and self.timerFly.IsRunning():
599 """!Process arrow key during fly-through"""
600 step = self.
fly[
'arrowStep']
601 if keyCode == wx.WXK_UP:
602 self.
fly[
'pos'][
'y'] -= step
603 elif keyCode == wx.WXK_DOWN:
604 self.
fly[
'pos'][
'y'] += step
605 elif keyCode == wx.WXK_LEFT:
606 self.
fly[
'pos'][
'x'] -= step
607 elif keyCode == wx.WXK_RIGHT:
608 self.
fly[
'pos'][
'x'] += step
611 """!Key was released.
613 Used for fly-through mode.
615 if not self.
mouse[
'use'] ==
'fly':
618 key = event.GetKeyCode()
619 if key == wx.WXK_CONTROL:
621 elif key == wx.WXK_SHIFT:
622 self.
fly[
'exag'][
'move'] = math.floor(self.
fly[
'exag'][
'move'] / self.
fly[
'exagMultiplier'])
623 self.
fly[
'exag'][
'turn'] = math.floor(self.
fly[
'exag'][
'turn'] / self.
fly[
'exagMultiplier'])
628 """!Handle mouse events"""
630 if event.GetWheelRotation() != 0:
634 elif event.LeftDown():
642 elif event.Dragging():
646 elif event.ButtonDClick():
652 """!Change perspective"""
653 if UserSettings.Get(group =
'display',
654 key =
'mouseWheelZoom',
655 subkey =
'selection') == 2:
659 wheel = event.GetWheelRotation()
660 Debug.msg (5,
"GLWindow.OnMouseMotion(): wheel = %d" % wheel)
661 if self.timerFly.IsRunning()
and self.
fly[
'mouseControl']:
667 if UserSettings.Get(group =
'display',
668 key =
'scrollDirection',
669 subkey =
'selection'):
671 self.
DoZoom(zoomtype = wheel, pos = event.GetPositionTuple())
677 """!On left mouse down"""
678 self.
mouse[
'begin'] = event.GetPositionTuple()
679 self.
mouse[
'tmp'] = event.GetPositionTuple()
680 if self.
mouse[
'use'] ==
"lookHere":
681 size = self.GetClientSize()
682 self._display.LookHere(self.
mouse[
'begin'][0], size[1] - self.
mouse[
'begin'][1])
683 focus = self._display.GetFocus()
684 for i, coord
in enumerate((
'x',
'y',
'z')):
685 self.
iview[
'focus'][coord] = focus[i]
688 toggle = self.lmgr.nviz.FindWindowByName(
'here')
689 toggle.SetValue(
False)
690 self.
mouse[
'use'] =
'pointer'
691 self.SetCursor(self.
cursors[
'default'])
693 if self.
mouse[
'use'] ==
'arrow':
694 pos = event.GetPosition()
695 size = self.GetClientSize()
698 if self.
mouse[
'use'] ==
'scalebar':
699 pos = event.GetPosition()
700 size = self.GetClientSize()
703 if self.
mouse[
'use'] ==
'pointer':
708 if self.
mouse[
'use'] ==
'fly':
709 if not self.timerFly.IsRunning():
710 self.timerFly.Start(self.
fly[
'interval'])
711 self.
fly[
'mouseControl'] =
True
716 if self.
mouse[
'use'] ==
'pointer':
721 if self.
mouse[
'use'] ==
'rotate':
722 dx, dy = event.GetX() - self.
mouse[
'tmp'][0], event.GetY() - self.
mouse[
'tmp'][1]
724 angle, x, y, z = self._display.GetRotationParameters(dx, dy)
725 self._display.Rotate(angle, x, y, z)
727 self.
render[
'quick'] =
True
730 if self.
mouse[
'use'] ==
'pan':
733 self.
mouse[
'tmp'] = event.GetPositionTuple()
738 """!Convert image coordinates to real word coordinates
740 @param x, y image coordinates
742 @return easting, northing
743 @return None on error
745 size = self.GetClientSize()
747 sid, x, y, z = self._display.GetPointOnSurface(x, size[1] - y)
755 """!Change perspective and focus"""
757 prev_value = self.
view[
'persp'][
'value']
759 value = -1 * self.
view[
'persp'][
'step']
761 value = self.
view[
'persp'][
'step']
762 self.
view[
'persp'][
'value'] += value
763 if self.
view[
'persp'][
'value'] < 1:
764 self.
view[
'persp'][
'value'] = 1
765 elif self.
view[
'persp'][
'value'] > 180:
766 self.
view[
'persp'][
'value'] = 180
768 if prev_value != self.
view[
'persp'][
'value']:
769 if hasattr(self.
lmgr,
"nviz"):
770 self.lmgr.nviz.UpdateSettings()
771 x, y = pos[0], self.GetClientSize()[1] - pos[1]
772 result = self._display.GetPointOnSurface(x, y)
774 self._display.LookHere(x, y)
775 focus = self._display.GetFocus()
776 for i, coord
in enumerate((
'x',
'y',
'z')):
777 self.
iview[
'focus'][coord] = focus[i]
778 self._display.SetView(self.
view[
'position'][
'x'], self.
view[
'position'][
'y'],
779 self.
iview[
'height'][
'value'],
780 self.
view[
'persp'][
'value'],
781 self.
view[
'twist'][
'value'])
787 self.
mouse[
'end'] = event.GetPositionTuple()
788 if self.
mouse[
"use"] ==
"query":
790 if self.parent.IsStandalone():
791 GMessage(parent = self.
parent,
792 message = _(
"Querying is not implemented in standalone mode of Map Display"))
797 self.parent.Query(self.
mouse[
'begin'][0],self.
mouse[
'begin'][1], layers)
799 elif self.
mouse[
"use"]
in (
'arrow',
'scalebar'):
800 self.lmgr.nviz.FindWindowById(
801 self.lmgr.nviz.win[
'decoration'][self.
mouse[
"use"]][
'place']).
SetValue(
False)
802 self.
mouse[
'use'] =
'pointer'
803 self.SetCursor(self.
cursors[
'default'])
804 elif self.
mouse[
'use'] ==
'pointer':
806 dx = self.
mouse[
'end'][0] - self.
mouse[
'begin'][0]
807 dy = self.
mouse[
'end'][1] - self.
mouse[
'begin'][1]
810 self.
overlays[self.
dragid].coords = [coords[0] + dx, coords[1] + dy]
813 self.
textdict[self.
dragid][
'coords'] = [coords[0] + dx, coords[1] + dy]
815 self.
render[
'quick'] =
False
818 elif self.
mouse[
'use'] ==
'rotate':
819 self._display.UnsetRotation()
820 self.
iview[
'rotation'] = self._display.GetRotationMatrix()
822 self.
render[
'quick'] =
False
825 elif self.
mouse[
'use'] ==
'pan':
827 self.
render[
'quick'] =
False
830 elif self.
mouse[
'use'] ==
'fly':
831 if self.
fly[
'mouseControl']:
833 self.
fly[
'mouseControl'] =
None
840 self.
render[
'quick'] =
False
843 elif self.
mouse[
'use'] ==
'zoom':
844 self.
DoZoom(zoomtype = self.zoomtype, pos = self.
mouse[
'end'])
848 """!On mouse double click"""
849 if self.
mouse[
'use'] !=
'pointer':
return
850 pos = event.GetPositionTuple()
854 self.parent.AddLegend()
856 self.parent.OnAddText(
None)
861 """!Simulation of panning using focus"""
862 size = self.GetClientSizeTuple()
863 id1, x1, y1, z1 = self._display.GetPointOnSurface(
864 self.
mouse[
'tmp'][0], size[1] - self.
mouse[
'tmp'][1])
865 id2, x2, y2, z2 = self._display.GetPointOnSurface(
866 event.GetX(), size[1] - event.GetY())
867 if id1
and id1 == id2:
868 dx, dy, dz = x2 - x1, y2 - y1, z2 - z1
869 focus = self.
iview[
'focus']
870 focus[
'x'], focus[
'y'], focus[
'z'] = self._display.GetFocus()
878 self.
mouse[
'tmp'] = event.GetPositionTuple()
879 self.
render[
'quick'] =
True
883 """!Move all layers in horizontal (x, y) direction.
886 size = self.GetClientSizeTuple()
887 id1, x1, y1, z1 = self._display.GetPointOnSurface(
888 self.
mouse[
'tmp'][0], size[1] - self.
mouse[
'tmp'][1])
889 id2, x2, y2, z2 = self._display.GetPointOnSurface(
890 event.GetX(), size[1] - event.GetY())
892 if id1
and id1 == id2:
893 dx, dy = x2 - x1, y2 - y1
896 mapLayer = self.tree.GetPyData(item)[0][
'maplayer']
898 data = self.tree.GetPyData(item)[0][
'nviz']
899 if mapLayer.GetType() ==
'raster':
900 data[
'surface'][
'position'][
'x'] += dx
901 data[
'surface'][
'position'][
'y'] += dy
902 data[
'surface'][
'position'][
'update'] =
None
905 evt = wxUpdateProperties(data = data)
906 wx.PostEvent(self, evt)
908 if event.CmdDown()
and id1 == data[
'surface'][
'object'][
'id']:
911 elif mapLayer.GetType() ==
'3d-raster':
912 if 'x' not in data[
'volume'][
'position']:
913 data[
'volume'][
'position'][
'x'] = 0
914 data[
'volume'][
'position'][
'y'] = 0
915 data[
'volume'][
'position'][
'z'] = 0
916 data[
'volume'][
'position'][
'x'] += dx
917 data[
'volume'][
'position'][
'y'] += dy
918 data[
'volume'][
'position'][
'update'] =
None
921 evt = wxUpdateProperties(data = data)
922 wx.PostEvent(self, evt)
924 self.
mouse[
'tmp'] = event.GetPositionTuple()
925 self.
render[
'quick'] =
True
929 """!Drag an overlay decoration item
932 Debug.msg (5,
"GLWindow.DragItem(): id=%d" % id)
933 x, y = self.
mouse[
'tmp']
934 dx = event.GetX() - x
935 dy = event.GetY() - y
938 texture.MoveTexture(dx, dy)
941 self.
render[
'quick'] =
True
944 self.
mouse[
'tmp'] = (event.GetX(), event.GetY())
947 """!Set previous view in history list
951 self.viewhistory.pop()
956 toolbar = self.parent.GetMapToolbar()
957 toolbar.Enable(
'zoomback', enable =
False)
960 self.lmgr.nviz.UpdateState(view = view[0], iview = view[1])
961 self.lmgr.nviz.UpdatePage(
'view')
966 """!Manages a list of last 10 views
968 @param view view dictionary
969 @param iview view dictionary (internal)
971 @return removed history item if exists (or None)
974 hview = copy.deepcopy(view)
975 hiview = copy.deepcopy(iview)
978 self.viewhistory.append((hview, hiview))
981 removed = self.viewhistory.pop(0)
984 Debug.msg(4,
"GLWindow.ViewHistory(): hist=%s, removed=%s" %
987 Debug.msg(4,
"GLWindow.ViewHistory(): hist=%s" %
996 toolbar = self.parent.GetMapToolbar()
997 toolbar.Enable(
'zoomback', enable)
1002 """!Reset view history"""
1006 """!Focus on given point"""
1007 w = self.Map.region[
'w']
1008 s = self.Map.region[
's']
1011 focus = self.
iview[
'focus']
1012 focus[
'x'], focus[
'y'] = e, n
1017 self.
render[
'quick'] =
False
1021 """!Query surface on given position"""
1022 size = self.GetClientSizeTuple()
1023 result = self._display.QueryMap(x, size[1] - y)
1025 self.qpoints.append((result[
'x'], result[
'y'], result[
'z']))
1026 self.log.WriteLog(
"%-30s: %.3f" % (_(
"Easting"), result[
'x']))
1027 self.log.WriteLog(
"%-30s: %.3f" % (_(
"Northing"), result[
'y']))
1028 self.log.WriteLog(
"%-30s: %.3f" % (_(
"Elevation"), result[
'z']))
1031 self.tree.GetPyData(item)[0][
'nviz']
1032 if self.tree.GetPyData(item)[0][
'maplayer'].type ==
'raster' and\
1033 self.tree.GetPyData(item)[0][
'nviz'][
'surface'][
'object'][
'id'] == result[
'id']:
1034 name = self.tree.GetPyData(item)[0][
'maplayer'].name
1035 self.log.WriteLog(
"%-30s: %s" % (_(
"Surface map name"), name))
1036 self.log.WriteLog(
"%-30s: %s" % (_(
"Surface map elevation"), result[
'elevation']))
1037 self.log.WriteLog(
"%-30s: %s" % (_(
"Surface map color"), result[
'color']))
1041 dxy = math.sqrt(pow(prev[0]-curr[0], 2) +
1042 pow(prev[1]-curr[1], 2))
1043 dxyz = math.sqrt(pow(prev[0]-curr[0], 2) +
1044 pow(prev[1]-curr[1], 2) +
1045 pow(prev[2]-curr[2], 2))
1046 self.log.WriteLog(
"%-30s: %.3f" % (_(
"XY distance from previous"), dxy))
1047 self.log.WriteLog(
"%-30s: %.3f" % (_(
"XYZ distance from previous"), dxyz))
1048 self.log.WriteLog(
"%-30s: %.3f" % (_(
"Distance along surface"),
1049 self._display.GetDistanceAlongSurface(result[
'id'],
1053 self.log.WriteLog(
"%-30s: %.3f" % (_(
"Distance along exag. surface"),
1054 self._display.GetDistanceAlongSurface(result[
'id'],
1058 self.log.WriteCmdLog(
'-' * 80)
1060 self.log.WriteLog(_(
"No point on surface"))
1061 self.log.WriteCmdLog(
'-' * 80)
1064 """!Change view settings"""
1065 event = wxUpdateView(zExag = zExag)
1066 wx.PostEvent(self, event)
1069 """!Query vector on given position"""
1070 self.parent.QueryVector(*event.GetPosition())
1073 """!Get current viewdir and viewpoint and set view"""
1076 (view[
'position'][
'x'], view[
'position'][
'y'],
1077 iview[
'height'][
'value']) = self._display.GetViewpointPosition()
1078 for key, val
in zip((
'x',
'y',
'z'), self._display.GetViewdir()):
1079 iview[
'dir'][key] = val
1081 iview[
'dir'][
'use'] =
True
1084 """!Change view settings"""
1094 """!Change view settings"""
1097 if zexag
and 'value' in view[
'z-exag']:
1098 self._display.SetZExag(view[
'z-exag'][
'value'] / iview[
'z-exag'][
'llRatio'])
1100 self._display.SetView(view[
'position'][
'x'], view[
'position'][
'y'],
1101 iview[
'height'][
'value'],
1102 view[
'persp'][
'value'],
1103 view[
'twist'][
'value'])
1105 if iview[
'dir'][
'use']:
1106 self._display.SetViewdir(iview[
'dir'][
'x'], iview[
'dir'][
'y'], iview[
'dir'][
'z'])
1108 elif iview[
'focus'][
'x'] != -1:
1109 self._display.SetFocus(self.
iview[
'focus'][
'x'], self.
iview[
'focus'][
'y'],
1110 self.
iview[
'focus'][
'z'])
1112 if 'rotation' in iview:
1113 if iview[
'rotation']:
1114 self._display.SetRotationMatrix(iview[
'rotation'])
1116 self._display.ResetRotation()
1119 """!Change light settings"""
1121 self._display.SetLight(x = data[
'position'][
'x'], y = data[
'position'][
'y'],
1122 z = data[
'position'][
'z'] / 100., color = data[
'color'],
1123 bright = data[
'bright'] / 100.,
1124 ambient = data[
'ambient'] / 100.)
1125 self._display.DrawLightingModel()
1130 """!Updates the canvas anytime there is a change to the
1131 underlaying images or to the geometry of the canvas.
1133 @param render re-render map composition
1135 start = time.clock()
1139 if self.
render[
'quick']
is False:
1140 self.parent.GetProgressBar().Show()
1141 self.parent.GetProgressBar().
SetRange(2)
1142 self.parent.GetProgressBar().
SetValue(0)
1144 if self.
render[
'quick']
is False:
1145 self.parent.GetProgressBar().
SetValue(1)
1146 self._display.Draw(
False, -1)
1150 elif self.
render[
'quick']
is True:
1152 mode = wxnviz.DRAW_QUICK_SURFACE | wxnviz.DRAW_QUICK_VOLUME
1153 if self.
render[
'vlines']:
1154 mode |= wxnviz.DRAW_QUICK_VLINES
1155 if self.
render[
'vpoints']:
1156 mode |= wxnviz.DRAW_QUICK_VPOINTS
1157 self._display.Draw(
True, mode)
1164 if self.
render[
'quick']
is False:
1165 self._display.DrawFringe()
1167 self._display.DrawArrow()
1169 self._display.DrawScalebar()
1173 self._display.Start2D()
1180 if self.
render[
'quick']
is False:
1181 self.parent.GetProgressBar().
SetValue(2)
1183 self.parent.GetProgressBar().Hide()
1185 Debug.msg(3,
"GLWindow.UpdateMap(): quick = %d, -> time = %g" % \
1186 (self.
render[
'quick'], (stop-start)))
1189 """!Erase the canvas
1191 self._display.EraseMap()
1194 def _getDecorationSize(self):
1195 """!Get initial size of north arrow/scalebar"""
1196 size = self._display.GetLongDim() / 8.
1200 return int(size * coef)/coef
1204 if self._display.SetArrow(pos[0], pos[1],
1207 self._display.DrawArrow()
1210 self.
decoration[
'arrow'][
'position'][
'x'] = pos[0]
1211 self.
decoration[
'arrow'][
'position'][
'y'] = pos[1]
1215 """!Add scale bar, sets properties and draw"""
1218 self.nvizDefault.SetDecorDefaultProp(type =
'scalebar')[
'scalebar'])
1224 ret = self._display.SetScalebar(self.
decoration[
'scalebar'][-1][
'id'], pos[0], pos[1],
1228 self._display.DrawScalebar()
1230 self.
decoration[
'scalebar'][-1][
'position'][
'x'] = pos[0]
1231 self.
decoration[
'scalebar'][-1][
'position'][
'y'] = pos[1]
1235 """!Check if layer (item) is already loaded
1237 @param item layer item
1239 layer = self.tree.GetPyData(item)[0][
'maplayer']
1240 data = self.tree.GetPyData(item)[0][
'nviz']
1245 if layer.type ==
'raster':
1246 if 'object' not in data[
'surface']:
1248 elif layer.type ==
'vector':
1249 if 'object' not in data[
'vlines']
and \
1250 'object' not in data[
'points']:
1255 def _GetDataLayers(self, item, litems):
1256 """!Return get list of enabled map layers"""
1258 while item
and item.IsOk():
1259 type = self.tree.GetPyData(item)[0][
'type']
1261 subItem = self.tree.GetFirstChild(item)[0]
1263 item = self.tree.GetNextSibling(item)
1265 if not item.IsChecked()
or \
1266 type
not in (
'raster',
'vector',
'3d-raster'):
1267 item = self.tree.GetNextSibling(item)
1272 item = self.tree.GetNextSibling(item)
1275 """!Load raster/vector from current layer tree
1283 item = self.tree.GetFirstChild(self.tree.root)[0]
1288 while(len(listOfItems) > 0):
1289 item = listOfItems.pop()
1290 type = self.tree.GetPyData(item)[0][
'type']
1295 if ' ' in self.tree.GetPyData(item)[0][
'maplayer'].name:
1298 if type ==
'raster':
1300 elif type ==
'3d-raster':
1302 elif type ==
'vector':
1303 layer = self.tree.GetPyData(item)[0][
'maplayer']
1304 vInfo = grass.vector_info_topo(layer.GetName())
1305 if (vInfo[
'points']) > 0:
1308 if (vInfo[
'lines'] + vInfo[
'boundaries']) > 0
or vInfo[
'map3d']:
1311 except GException, e:
1312 GError(parent = self,
1317 Debug.msg(1,
"GLWindow.LoadDataLayers(): time = %f" % (stop-start))
1320 """!Unload any layers that have been deleted from layer tree
1322 @param force True to unload all data layers
1329 item = self.tree.GetFirstChild(self.tree.root)[0]
1335 layersTmp = self.
layers[:]
1336 for layer
in layersTmp:
1337 if layer
in listOfItems:
1339 ltype = self.tree.GetPyData(layer)[0][
'type']
1341 if ltype ==
'raster':
1343 elif ltype ==
'3d-raster':
1345 elif ltype ==
'vector':
1346 maplayer = self.tree.GetPyData(layer)[0][
'maplayer']
1347 vInfo = grass.vector_info_topo(maplayer.GetName())
1348 if (vInfo[
'points'] + vInfo[
'centroids']) > 0:
1350 if (vInfo[
'lines'] + vInfo[
'boundaries']) > 0
or vInfo[
'map3d']:
1353 except GException, e:
1354 GError(parent = self,
1357 if force
and self.
baseId > 0:
1358 ret = self._display.UnloadSurface(self.
baseId)
1361 self.lmgr.nviz.UpdateSettings()
1366 Debug.msg(1,
"GLWindow.UnloadDataLayers(): time = %f" % (stop-start))
1369 """!Set reference surfaces of vector"""
1370 data[
'mode'][
'surface'] = {}
1371 data[
'mode'][
'surface'][
'value'] = list()
1372 data[
'mode'][
'surface'][
'show'] = list()
1374 data[
'mode'][
'surface'][
'value'].append(name)
1375 data[
'mode'][
'surface'][
'show'].append(
True)
1378 """!Set 3D view properties from cmd (d.vect)
1380 @param item Layer Tree item
1383 cmd = self.tree.GetPyData(item)[0][
'cmd']
1384 if cmd[0] !=
'd.vect':
1388 key, value = opt.split(
'=')
1392 data[
'lines'][
'color'][
'value'] = value
1393 data[
'points'][
'color'][
'value'] = value
1396 """!Set map object properties
1398 Properties must be afterwards updated by
1399 UpdateMapObjProperties().
1401 @param item layer item
1402 @param id nviz layer id (or -1)
1403 @param nvizType nviz data type (surface, points, vector)
1405 if nvizType !=
'constant':
1406 mapType = self.tree.GetPyData(item)[0][
'maplayer'].type
1408 data = self.tree.GetPyData(item)[0][
'nviz']
1415 if nvizType !=
'constant':
1416 self.tree.GetPyData(item)[0][
'nviz'] = {}
1417 data = self.tree.GetPyData(item)[0][
'nviz']
1419 if mapType ==
'raster':
1421 data[nvizType] = self.nvizDefault.SetSurfaceDefaultProp()
1423 elif mapType ==
'vector':
1425 data[
'vector'] = self.nvizDefault.SetVectorDefaultProp()
1430 elif mapType ==
'3d-raster':
1432 data[nvizType] = self.nvizDefault.SetVolumeDefaultProp()
1434 elif mapType ==
'constant':
1435 data[
'constant'] = self.nvizDefault.SetConstantDefaultProp()
1439 if mapType ==
'raster':
1440 if not data[
'surface']:
1441 data[
'surface'] = self.nvizDefault.SetSurfaceDefaultProp()
1442 if mapType ==
'vector':
1443 if not data[
'vector'][
'lines']:
1444 self.nvizDefault.SetVectorLinesDefaultProp(data[
'vector'][
'lines'])
1445 if not data[
'vector'][
'points']:
1446 self.nvizDefault.SetVectorPointsDefaultProp(data[
'vector'][
'points'])
1448 for sec
in data.keys():
1449 for sec1
in data[sec].keys():
1450 if sec1 ==
'position':
1451 data[sec][sec1][
'update'] =
None
1453 if type(data[sec][sec1]) == types.DictType:
1454 for sec2
in data[sec][sec1].keys():
1455 if sec2
not in (
'all',
'init',
'id'):
1456 data[sec][sec1][sec2][
'update'] =
None
1457 elif type(data[sec][sec1]) == types.ListType:
1458 for i
in range(len(data[sec][sec1])):
1459 for sec2
in data[sec][sec1][i].keys():
1460 data[sec][sec1][i][sec2][
'update'] =
None
1461 event = wxUpdateProperties(data = data)
1462 wx.PostEvent(self, event)
1466 if mapType
in (
'raster',
'3d-raster'):
1467 data[nvizType][
'object'] = {
'id' : id,
1469 elif mapType ==
'vector':
1470 data[
'vector'][nvizType][
'object'] = {
'id' : id,
1472 elif mapType ==
'constant':
1473 data[nvizType][
'object'] = {
'id' : id,
1479 """!Load 2d raster map and set surface attributes
1486 """!Load 3d raster map and set surface attributes
1492 def _loadRaster(self, item):
1493 """!Load 2d/3d raster map and set its attributes
1497 layer = self.tree.GetPyData(item)[0][
'maplayer']
1499 if layer.type
not in (
'raster',
'3d-raster'):
1502 if layer.type ==
'raster':
1503 id = self._display.LoadSurface(str(layer.name),
None,
None)
1504 nvizType =
'surface'
1505 errorMsg = _(
"Loading raster map")
1506 elif layer.type ==
'3d-raster':
1507 id = self._display.LoadVolume(str(layer.name),
None,
None)
1509 errorMsg = _(
"Loading 3d raster map")
1514 if layer.type
in (
'raster',
'3d-raster'):
1515 self.log.WriteError(
"%s <%s> %s" % (errorMsg, layer.name, _(
"failed")))
1517 self.log.WriteError(_(
"Unsupported layer type '%s'") % layer.type)
1519 self.layers.append(item)
1525 event = wxUpdateProperties(data = data)
1526 wx.PostEvent(self, event)
1529 if hasattr(self.
lmgr,
"nviz")
and \
1531 toolWin = self.lmgr.nviz
1532 if layer.type ==
'raster':
1533 win = toolWin.FindWindowById( \
1534 toolWin.win[
'vector'][
'lines'][
'surface'])
1543 """!Create new constant"""
1546 name = self.
constants[-1][
'constant'][
'object'][
'name'] + 1
1550 self.constants.append(data)
1556 """!Add new constant"""
1557 id = self._display.AddConstant(value = data[
'constant'][
'value'], color = data[
'constant'][
'color'])
1558 self._display.SetSurfaceRes(id, data[
'constant'][
'resolution'], data[
'constant'][
'resolution'])
1559 data[
'constant'][
'object'] = {
'id' : id,
1564 """!Delete constant layer"""
1565 id = self.
constants[index][
'constant'][
'object'][
'id']
1566 self._display.UnloadSurface(id)
1570 """!Select cutting plane"""
1571 for plane
in range (self._display.GetCPlanesCount()):
1573 self._display.SelectCPlane(plane)
1574 self.
cplanes[plane][
'on'] =
True
1575 self._display.SetFenceColor(self.
cplanes[plane][
'shading'])
1577 self._display.UnselectCPlane(plane)
1579 self.
cplanes[plane][
'on'] =
False
1584 """!Change cutting plane settings"""
1588 """!Change cutting plane settings"""
1589 for each
in changes:
1590 if each ==
'rotation':
1591 self._display.SetCPlaneRotation(0, self.
cplanes[index][
'rotation'][
'tilt'],
1592 self.
cplanes[index][
'rotation'][
'rot'])
1593 if each ==
'position':
1594 self._display.SetCPlaneTranslation(self.
cplanes[index][
'position'][
'x'],
1595 self.
cplanes[index][
'position'][
'y'],
1596 self.
cplanes[index][
'position'][
'z'])
1597 if each ==
'shading':
1598 self._display.SetFenceColor(self.
cplanes[index][
'shading'])
1601 """!Unload 2d raster map
1608 """!Unload 3d raster map
1614 def _unloadRaster(self, item):
1615 """!Unload 2d/3d raster map
1617 @param item layer item
1619 layer = self.tree.GetPyData(item)[0][
'maplayer']
1621 if layer.type
not in (
'raster',
'3d-raster'):
1624 data = self.tree.GetPyData(item)[0][
'nviz']
1626 if layer.type ==
'raster':
1627 nvizType =
'surface'
1628 unloadFn = self._display.UnloadSurface
1629 errorMsg = _(
"Unable to unload raster map")
1630 successMsg = _(
"Raster map")
1633 unloadFn = self._display.UnloadVolume
1634 errorMsg = _(
"Unable to unload 3d raster map")
1635 successMsg = _(
"3d raster map")
1638 id = data[nvizType][
'object'][
'id']
1642 if unloadFn(id) == 0:
1643 self.log.WriteError(
"%s <%s>" % (errorMsg, layer.name))
1645 self.log.WriteLog(
"%s <%s> %s" % (successMsg, layer.name, _(
"unloaded successfully")))
1647 data[nvizType].pop(
'object')
1649 self.layers.remove(item)
1652 if hasattr(self.
lmgr,
"nviz"):
1653 toolWin = self.lmgr.nviz
1654 if layer.type ==
'raster':
1655 win = toolWin.FindWindowById(toolWin.win[
'vector'][
'lines'][
'surface'])
1657 win = toolWin.FindWindowById(toolWin.win[
'surface'][
'map'])
1659 if layer.type ==
'3d-raster':
1660 win = toolWin.FindWindowById(toolWin.win[
'volume'][
'map'])
1662 if layer.type ==
'vector':
1663 win = toolWin.FindWindowById(toolWin.win[
'vector'][
'map'])
1667 """!Load 2D or 3D vector map overlay
1669 @param item layer item
1670 @param points True to load points, False to load lines, None
1672 @param append append vector to layer list
1674 layer = self.tree.GetPyData(item)[0][
'maplayer']
1675 if layer.type !=
'vector':
1682 vecTypes = (
'points',
'lines')
1685 vecTypes = (
'points', )
1688 vecTypes = (
'lines', )
1691 for vecType
in vecTypes:
1692 if vecType ==
'lines':
1693 id, baseId = self._display.LoadVector(str(layer.GetName()),
False)
1695 id, baseId = self._display.LoadVector(str(layer.GetName()),
True)
1697 self.log.WriteError(_(
"Loading vector map <%(name)s> (%(type)s) failed") % \
1698 {
'name' : layer.name,
'type' : vecType })
1704 self.layers.append(item)
1707 data = self.tree.GetPyData(item)[0][
'nviz']
1708 event = wxUpdateProperties(data = data)
1709 wx.PostEvent(self, event)
1712 if hasattr(self.
lmgr,
"nviz")
and \
1714 toolWin = self.lmgr.nviz
1716 toolWin.UpdatePage(
'vector')
1722 """!Unload vector map overlay
1724 @param item layer item
1725 @param points,lines True to unload given feature type
1726 @param remove remove layer from list
1728 layer = self.tree.GetPyData(item)[0][
'maplayer']
1729 data = self.tree.GetPyData(item)[0][
'nviz'][
'vector']
1739 vecTypes = (
'points',
'lines')
1741 vecTypes = (
'points', )
1743 vecTypes = (
'lines', )
1745 for vecType
in vecTypes:
1746 if 'object' not in data[vecType]:
1749 id = data[vecType][
'object'][
'id']
1751 if vecType ==
'lines':
1752 ret = self._display.UnloadVector(id,
False)
1754 ret = self._display.UnloadVector(id,
True)
1756 self.log.WriteError(_(
"Unable to unload vector map <%(name)s> (%(type)s)") % \
1757 {
'name': layer.name,
'type' : vecType })
1759 self.log.WriteLog(_(
"Vector map <%(name)s> (%(type)s) unloaded successfully") % \
1760 {
'name' : layer.name,
'type' : vecType })
1762 data[vecType].pop(
'object')
1764 if remove
and item
in self.
layers:
1765 self.layers.remove(item)
1768 """!Reset to default view"""
1770 self.
iview[
'height'][
'value'], \
1771 self.
iview[
'height'][
'min'], \
1772 self.
iview[
'height'][
'max'] = self._display.SetViewDefault()
1776 self.
iview[
'z-exag'][
'llRatio'] = 1
1777 if grass.locn_is_latlong():
1778 self.
iview[
'z-exag'][
'llRatio'] = \
1779 math.pi / 180 * 6371000 * math.cos((grass.region()[
'n'] + grass.region()[
's']) / 2)
1781 self.
view[
'z-exag'][
'value'] =
round(zexagOriginal * self.
iview[
'z-exag'][
'llRatio'])
1782 self.
view[
'z-exag'][
'min'] = UserSettings.Get(group =
'nviz', key =
'view',
1783 subkey = (
'z-exag',
'min'))
1784 zexagMax = UserSettings.Get(group =
'nviz', key =
'view',
1785 subkey = (
'z-exag',
'max'))
1786 if zexagMax <= self.
view[
'z-exag'][
'value']:
1787 self.
view[
'z-exag'][
'max'] = self.
view[
'z-exag'][
'value'] * 2
1788 elif self.
view[
'z-exag'][
'value'] < 1:
1789 if self.
view[
'z-exag'][
'value'] == 0:
1790 self.
view[
'z-exag'][
'value'] = 1
1791 self.
view[
'z-exag'][
'max'] = 10 * self.
view[
'z-exag'][
'value']
1793 self.
view[
'z-exag'][
'max'] = zexagMax
1795 self.
view[
'position'][
'x'] = UserSettings.Get(group =
'nviz', key =
'view',
1796 subkey = (
'position',
'x'))
1797 self.
view[
'position'][
'y'] = UserSettings.Get(group =
'nviz', key =
'view',
1798 subkey = (
'position',
'y'))
1799 self.
view[
'persp'][
'value'] = UserSettings.Get(group =
'nviz', key =
'view',
1800 subkey = (
'persp',
'value'))
1802 self.
view[
'twist'][
'value'] = UserSettings.Get(group =
'nviz', key =
'view',
1803 subkey = (
'twist',
'value'))
1804 self._display.ResetRotation()
1805 self.
iview[
'rotation'] =
None
1806 self._display.LookAtCenter()
1807 focus = self.
iview[
'focus']
1808 focus[
'x'], focus[
'y'], focus[
'z'] = self._display.GetFocus()
1813 """!Generic method to update data layer properties"""
1816 if 'surface' in data:
1818 id = data[
'surface'][
'object'][
'id']
1823 data[
'surface'][
'object'][
'init'] =
True
1825 elif 'constant' in data:
1826 id = data[
'constant'][
'object'][
'id']
1829 data[
'constant'][
'object'][
'init'] =
True
1831 elif 'volume' in data:
1832 id = data[
'volume'][
'object'][
'id']
1835 data[
'volume'][
'object'][
'init'] =
True
1837 elif 'vector' in data:
1838 for type
in (
'lines',
'points'):
1839 if 'object' in data[
'vector'][type]:
1840 id = data[
'vector'][type][
'object'][
'id']
1843 data[
'vector'][type][
'object'][
'init'] =
True
1846 """!Update surface map object properties"""
1847 self._display.SetSurfaceColor(id = id, map =
False, value = data[
'color'])
1848 self._display.SetSurfaceTopo(id = id, map =
False, value = data[
'value'])
1849 self._display.SetSurfaceRes(id, data[
'resolution'], data[
'resolution'])
1850 if data[
'transp'] == 0:
1851 self._display.UnsetSurfaceTransp(id)
1853 self._display.SetSurfaceTransp(id, map =
False, value = data[
'transp'])
1856 """!Update surface map object properties"""
1858 for attrb
in (
'color',
'mask',
1860 if attrb
not in data[
'attribute']
or \
1861 'update' not in data[
'attribute'][attrb]:
1864 map = data[
'attribute'][attrb][
'map']
1865 value = data[
'attribute'][attrb][
'value']
1872 self._display.UnsetSurfaceMask(id)
1873 elif attrb ==
'transp':
1874 self._display.UnsetSurfaceTransp(id)
1876 if type(value) == types.StringType
and \
1879 if attrb ==
'color':
1880 self._display.SetSurfaceColor(id, map, str(value))
1881 elif attrb ==
'mask':
1884 self._display.SetSurfaceMask(id,
False, str(value))
1885 elif attrb ==
'transp':
1886 self._display.SetSurfaceTransp(id, map, str(value))
1887 elif attrb ==
'shine':
1888 self._display.SetSurfaceShine(id, map, str(value))
1889 data[
'attribute'][attrb].pop(
'update')
1892 if 'update' in data[
'draw'][
'resolution']:
1893 coarse = data[
'draw'][
'resolution'][
'coarse']
1894 fine = data[
'draw'][
'resolution'][
'fine']
1896 if data[
'draw'][
'all']:
1897 self._display.SetSurfaceRes(-1, fine, coarse)
1899 self._display.SetSurfaceRes(id, fine, coarse)
1900 data[
'draw'][
'resolution'].pop(
'update')
1903 if 'update' in data[
'draw'][
'mode']:
1904 if data[
'draw'][
'mode'][
'value'] < 0:
1905 data[
'draw'][
'mode'][
'value'] = \
1906 self.nvizDefault.GetDrawMode(mode = data[
'draw'][
'mode'][
'desc'][
'mode'],
1907 style = data[
'draw'][
'mode'][
'desc'][
'style'],
1908 shade = data[
'draw'][
'mode'][
'desc'][
'shading'],
1910 style = data[
'draw'][
'mode'][
'value']
1911 if data[
'draw'][
'all']:
1912 self._display.SetSurfaceStyle(-1, style)
1914 self._display.SetSurfaceStyle(id, style)
1915 data[
'draw'][
'mode'].pop(
'update')
1918 if 'update' in data[
'draw'][
'wire-color']:
1919 color = data[
'draw'][
'wire-color'][
'value']
1920 if data[
'draw'][
'all']:
1921 self._display.SetWireColor(-1, str(color))
1923 self._display.SetWireColor(id, str(color))
1924 data[
'draw'][
'wire-color'].pop(
'update')
1927 if 'update' in data[
'position']:
1928 x = data[
'position'][
'x']
1929 y = data[
'position'][
'y']
1930 z = data[
'position'][
'z']
1931 self._display.SetSurfacePosition(id, x, y, z)
1932 data[
'position'].pop(
'update')
1933 data[
'draw'][
'all'] =
False
1936 """!Update volume (isosurface/slice) map object properties"""
1937 if 'update' in data[
'draw'][
'resolution']:
1938 if data[
'draw'][
'mode'][
'value'] == 0:
1939 self._display.SetIsosurfaceRes(id, data[
'draw'][
'resolution'][
'isosurface'][
'value'])
1941 self._display.SetSliceRes(id, data[
'draw'][
'resolution'][
'slice'][
'value'])
1942 data[
'draw'][
'resolution'].pop(
'update')
1944 if 'update' in data[
'draw'][
'shading']:
1945 if data[
'draw'][
'mode'][
'value'] == 0:
1946 if data[
'draw'][
'shading'][
'isosurface'][
'value'] < 0:
1947 mode = data[
'draw'][
'shading'][
'isosurface'][
'value'] = \
1948 self.nvizDefault.GetDrawMode(shade = data[
'draw'][
'shading'][
'isosurface'],
1950 self._display.SetIsosurfaceMode(id, mode)
1952 if data[
'draw'][
'shading'][
'slice'][
'value'] < 0:
1953 mode = data[
'draw'][
'shading'][
'slice'][
'value'] = \
1954 self.nvizDefault.GetDrawMode(shade = data[
'draw'][
'shading'][
'slice'],
1956 self._display.SetSliceMode(id, mode)
1957 data[
'draw'][
'shading'].pop(
'update')
1963 for isosurf
in data[
'isosurface']:
1964 self._display.AddIsosurface(id, 0, isosurf_id = isosurfId)
1965 for attrb
in (
'topo',
'color',
'mask',
1967 if attrb
not in isosurf
or \
1968 'update' not in isosurf[attrb]:
1970 map = isosurf[attrb][
'map']
1971 value = isosurf[attrb][
'value']
1975 if attrb ==
'topo' :
1976 self._display.SetIsosurfaceTopo(id, isosurfId, map, str(value))
1977 elif attrb ==
'mask':
1980 self._display.UnsetIsosurfaceMask(id, isosurfId)
1981 elif attrb ==
'transp':
1982 self._display.UnsetIsosurfaceTransp(id, isosurfId)
1984 if type(value) == types.StringType
and \
1987 elif attrb ==
'color':
1988 self._display.SetIsosurfaceColor(id, isosurfId, map, str(value))
1989 elif attrb ==
'mask':
1992 self._display.SetIsosurfaceMask(id, isosurfId,
False, str(value))
1993 elif attrb ==
'transp':
1994 self._display.SetIsosurfaceTransp(id, isosurfId, map, str(value))
1995 elif attrb ==
'shine':
1996 self._display.SetIsosurfaceShine(id, isosurfId, map, str(value))
1997 isosurf[attrb].pop(
'update')
2003 for slice
in data[
'slice']:
2004 ret = self._display.AddSlice(id, slice_id = sliceId)
2005 if 'update' in slice[
'position']:
2006 pos = slice[
'position']
2007 ret = self._display.SetSlicePosition(id, sliceId, pos[
'x1'], pos[
'x2'],
2008 pos[
'y1'], pos[
'y2'], pos[
'z1'], pos[
'z2'], pos[
'axis'])
2010 slice[
'position'].pop(
'update')
2011 if 'update' in slice[
'transp']:
2012 tr = slice[
'transp'][
'value']
2013 self._display.SetSliceTransp(id, sliceId, tr)
2017 if 'update' in data[
'position']
and 'x' in data[
'position']:
2018 x = data[
'position'][
'x']
2019 y = data[
'position'][
'y']
2020 z = data[
'position'][
'z']
2021 self._display.SetVolumePosition(id, x, y, z)
2022 data[
'position'].pop(
'update')
2025 """!Update vector layer properties
2028 @param data properties
2029 @param type lines/points
2031 if type ==
'points':
2037 """!Update vector line map object properties"""
2039 if 'update' in data[
'color']
or \
2040 'update' in data[
'width']
or \
2041 'update' in data[
'mode']:
2042 width = data[
'width'][
'value']
2043 color = data[
'color'][
'value']
2044 if data[
'mode'][
'type'] ==
'flat':
2046 if 'surface' in data[
'mode']:
2047 data[
'mode'].pop(
'surface')
2051 self._display.SetVectorLineMode(id, color,
2054 if 'update' in data[
'color']:
2055 data[
'color'].pop(
'update')
2056 if 'update' in data[
'width']:
2057 data[
'width'].pop(
'update')
2060 if 'update' in data[
'height']:
2061 self._display.SetVectorLineHeight(id,
2062 data[
'height'][
'value'])
2063 data[
'height'].pop(
'update')
2066 if 'surface' in data[
'mode']
and 'update' in data[
'mode']:
2067 for item
in range(len(data[
'mode'][
'surface'][
'value'])):
2068 for type
in (
'raster',
'constant'):
2070 name = data[
'mode'][
'surface'][
'value'][item])
2072 if data[
'mode'][
'surface'][
'show'][item]:
2073 self._display.SetVectorLineSurface(id, sid)
2075 self._display.UnsetVectorLineSurface(id, sid)
2078 if 'update' in data[
'mode']:
2079 data[
'mode'].pop(
'update')
2082 """!Update vector point map object properties"""
2083 if 'update' in data[
'size']
or \
2084 'update' in data[
'width']
or \
2085 'update' in data[
'marker']
or \
2086 'update' in data[
'color']:
2088 ret = self._display.SetVectorPointMode(id, data[
'color'][
'value'],
2089 data[
'width'][
'value'], float(data[
'size'][
'value']),
2090 data[
'marker'][
'value'] + 1)
2094 error = _(
"Vector point layer not found (id = %d)") % id
2096 error = _(
"Unable to set data layer properties (id = %d)") % id
2099 raise GException(_(
"Setting data layer properties failed.\n\n%s") % error)
2101 for prop
in (
'size',
'width',
'marker',
'color'):
2102 if 'update' in data[prop]:
2103 data[prop].pop(
'update')
2106 if 'update' in data[
'height']:
2107 self._display.SetVectorPointHeight(id,
2108 data[
'height'][
'value'])
2109 data[
'height'].pop(
'update')
2112 if 'update' in data[
'mode']
and 'surface' in data[
'mode']:
2113 for item
in range(len(data[
'mode'][
'surface'][
'value'])):
2114 for type
in (
'raster',
'constant'):
2116 name = data[
'mode'][
'surface'][
'value'][item])
2118 if data[
'mode'][
'surface'][
'show'][item]:
2119 self._display.SetVectorPointSurface(id, sid)
2121 self._display.UnsetVectorPointSurface(id, sid)
2123 data[
'mode'].pop(
'update')
2126 """!Return list of map layer names of given type"""
2129 if type ==
'constant':
2131 layerName.append(_(
"constant#") + str(item[
'constant'][
'object'][
'name']))
2134 mapLayer = self.tree.GetPyData(item)[0][
'maplayer']
2135 if type != mapLayer.GetType():
2138 layerName.append(mapLayer.GetName())
2143 """!Get layer object id or -1"""
2147 if type ==
'constant':
2149 if _(
"constant#") + str(item[
'constant'][
'object'][
'name']) == name:
2150 return item[
'constant'][
'object'][
'id']
2154 mapLayer = self.tree.GetPyData(item)[0][
'maplayer']
2155 if type != mapLayer.GetType()
or \
2156 name != mapLayer.GetName():
2159 data = self.tree.GetPyData(item)[0][
'nviz']
2162 if type ==
'raster':
2163 return data[
'surface'][
'object'][
'id']
2164 elif type ==
'vector':
2165 if vsubtyp ==
'vpoint':
2166 return data[
'vector'][
'points'][
'object'][
'id']
2167 elif vsubtyp ==
'vline':
2168 return data[
'vector'][
'lines'][
'object'][
'id']
2169 elif type ==
'3d-raster':
2170 return data[
'volume'][
'object'][
'id']
2176 """!Delete nviz data of all loaded layers and reload them from current settings"""
2178 type = self.tree.GetPyData(item)[0][
'type']
2179 layer = self.tree.GetPyData(item)[0][
'maplayer']
2180 data = self.tree.GetPyData(item)[0][
'nviz']
2182 if type ==
'raster':
2183 self.nvizDefault.SetSurfaceDefaultProp(data[
'surface'])
2184 if type ==
'vector':
2185 vInfo = grass.vector_info_topo(layer.GetName())
2186 if (vInfo[
'points'] + vInfo[
'centroids']) > 0:
2187 self.nvizDefault.SetVectorPointsDefaultProp(data[
'vector'][
'points'])
2188 if (vInfo[
'lines'] + vInfo[
'boundaries']) > 0:
2189 self.nvizDefault.SetVectorLinesDefaultProp(data[
'vector'][
'lines'])
2192 """!Generate command for m.nviz.image according to current state"""
2193 cmd =
'm.nviz.image '
2199 if self.tree.GetPyData(item)[0][
'type'] ==
'raster':
2200 rasters.append(item)
2201 elif self.tree.GetPyData(item)[0][
'type'] ==
'3d-raster':
2202 volumes.append(item)
2203 elif self.tree.GetPyData(item)[0][
'type'] ==
'vector':
2204 vectors.append(item)
2206 return _(
"At least one raster map required")
2209 subcmd =
"elevation_value="
2211 subcmd +=
"%d," % constant[
'constant'][
'value']
2212 subcmd = subcmd.strip(
', ') +
' '
2215 subcmd =
"elevation_map="
2216 for item
in rasters:
2217 subcmd +=
"%s," % self.tree.GetPyData(item)[0][
'maplayer'].GetName()
2218 subcmd = subcmd.strip(
', ') +
' '
2224 cmdFine =
"resolution_fine="
2225 cmdCoarse =
"resolution_coarse="
2226 cmdShading =
"shading="
2228 cmdWire =
"wire_color="
2231 nvizDataFirst = self.tree.GetPyData(rasters[0])[0][
'nviz'][
'surface'][
'draw']
2232 for item
in rasters:
2233 nvizData = self.tree.GetPyData(item)[0][
'nviz'][
'surface'][
'draw']
2234 if nvizDataFirst != nvizData:
2237 for item
in rasters:
2238 nvizData = self.tree.GetPyData(item)[0][
'nviz'][
'surface'][
'draw']
2240 cmdMode +=
"%s," % nvizData[
'mode'][
'desc'][
'mode']
2241 cmdFine +=
"%s," % nvizData[
'resolution'][
'fine']
2242 cmdCoarse +=
"%s," % nvizData[
'resolution'][
'coarse']
2243 cmdShading +=
"%s," % nvizData[
'mode'][
'desc'][
'shading']
2244 cmdStyle +=
"%s," % nvizData[
'mode'][
'desc'][
'style']
2245 cmdWire +=
"%s," % nvizData[
'wire-color'][
'value']
2248 cmdFine +=
"%s," % item[
'constant'][
'resolution']
2249 cmdCoarse +=
"%s," % item[
'constant'][
'resolution']
2250 cmdShading +=
"gouraud,"
2251 cmdStyle +=
"surface,"
2254 for subcmd
in (cmdMode, cmdFine, cmdCoarse, cmdShading, cmdStyle, cmdWire):
2256 mode.append(subcmd.split(
',')[0] +
' ')
2258 subcmd = subcmd.strip(
', ') +
' '
2262 if 'fine' in mode[0]:
2264 elif 'coarse' in mode[0]:
2266 elif 'both' in mode[0]:
2269 if 'flat' in mode[3]:
2271 if 'wire' in mode[4]:
2273 if 'coarse' in mode[0]
or 'both' in mode[0]
and 'wire' in mode[3]:
2278 cmdColorMap =
"color_map="
2279 cmdColorVal =
"color="
2280 for item
in rasters:
2281 nvizData = self.tree.GetPyData(item)[0][
'nviz'][
'surface'][
'attribute']
2282 if 'color' not in nvizData:
2283 cmdColorMap +=
"%s," % self.tree.GetPyData(item)[0][
'maplayer'].GetName()
2285 if nvizData[
'color'][
'map']:
2286 cmdColorMap +=
"%s," % nvizData[
'color'][
'value']
2288 cmdColorVal +=
"%s," % nvizData[
'color'][
'value']
2292 cmdColorVal +=
"%s," % item[
'constant'][
'color']
2293 if cmdColorMap.split(
"=")[1]:
2294 cmd += cmdColorMap.strip(
', ') +
' '
2295 if cmdColorVal.split(
"=")[1]:
2296 cmd += cmdColorVal.strip(
', ') +
' '
2302 cmdLines = cmdLWidth = cmdLHeight = cmdLColor = cmdLMode = cmdLPos = \
2303 cmdPoints = cmdPWidth = cmdPSize = cmdPColor = cmdPMarker = cmdPPos = cmdPLayer =
""
2304 markers = [
'x',
'box',
'sphere',
'cube',
'diamond',
2305 'dec_tree',
'con_tree',
'aster',
'gyro',
'histogram']
2306 for vector
in vectors:
2307 layerName = self.tree.GetPyData(vector)[0][
'maplayer'].GetName()
2308 vInfo = grass.vector_info_topo(layerName)
2309 nvizData = self.tree.GetPyData(vector)[0][
'nviz'][
'vector']
2310 if (vInfo[
'lines'] + vInfo[
'boundaries']) > 0:
2311 cmdLines +=
"%s," % self.tree.GetPyData(vector)[0][
'maplayer'].GetName()
2312 cmdLWidth +=
"%d," % nvizData[
'lines'][
'width'][
'value']
2313 cmdLHeight +=
"%d," % nvizData[
'lines'][
'height'][
'value']
2314 cmdLColor +=
"%s," % nvizData[
'lines'][
'color'][
'value']
2315 cmdLMode +=
"%s," % nvizData[
'lines'][
'mode'][
'type']
2316 cmdLPos +=
"0,0,%d," % nvizData[
'lines'][
'height'][
'value']
2317 if (vInfo[
'points'] + vInfo[
'centroids']) > 0:
2318 cmdPoints +=
"%s," % self.tree.GetPyData(vector)[0][
'maplayer'].GetName()
2319 cmdPWidth +=
"%d," % nvizData[
'points'][
'width'][
'value']
2320 cmdPSize +=
"%d," % nvizData[
'points'][
'size'][
'value']
2321 cmdPColor +=
"%s," % nvizData[
'points'][
'color'][
'value']
2322 cmdPMarker +=
"%s," % markers[nvizData[
'points'][
'marker'][
'value']]
2323 cmdPPos +=
"0,0,%d," % nvizData[
'points'][
'height'][
'value']
2326 cmd +=
"vline=" + cmdLines.strip(
',') +
' '
2327 cmd +=
"vline_width=" + cmdLWidth.strip(
',') +
' '
2328 cmd +=
"vline_color=" + cmdLColor.strip(
',') +
' '
2329 cmd +=
"vline_height=" + cmdLHeight.strip(
',') +
' '
2330 cmd +=
"vline_mode=" + cmdLMode.strip(
',') +
' '
2331 cmd +=
"vline_position=" + cmdLPos.strip(
',') +
' '
2333 cmd +=
"vpoint=" + cmdPoints.strip(
',') +
' '
2334 cmd +=
"vpoint_width=" + cmdPWidth.strip(
',') +
' '
2335 cmd +=
"vpoint_color=" + cmdPColor.strip(
',') +
' '
2336 cmd +=
"vpoint_size=" + cmdPSize.strip(
',') +
' '
2337 cmd +=
"vpoint_marker=" + cmdPMarker.strip(
',') +
' '
2338 cmd +=
"vpoint_position=" + cmdPPos.strip(
',') +
' '
2345 cmdName = cmdShade = cmdRes = cmdPos = cmdIso =
""
2346 cmdIsoColorMap = cmdIsoColorVal = cmdIsoTrMap = cmdIsoTrVal =
""
2347 cmdSlice = cmdSliceTransp = cmdSlicePos =
""
2348 for i, volume
in enumerate(volumes):
2349 nvizData = self.tree.GetPyData(volume)[0][
'nviz'][
'volume']
2350 cmdName +=
"%s," % self.tree.GetPyData(volume)[0][
'maplayer'].GetName()
2351 cmdShade +=
"%s," % nvizData[
'draw'][
'shading'][
'isosurface'][
'desc']
2352 cmdRes +=
"%d," % nvizData[
'draw'][
'resolution'][
'isosurface'][
'value']
2353 if nvizData[
'position']:
2354 cmdPos +=
"%d,%d,%d," % (nvizData[
'position'][
'x'], nvizData[
'position'][
'y'],
2355 nvizData[
'position'][
'z'])
2356 for iso
in nvizData[
'isosurface']:
2357 level = iso[
'topo'][
'value']
2358 cmdIso +=
"%d:%s," % (i + 1, level)
2359 if iso[
'color'][
'map']:
2360 cmdIsoColorMap +=
"%s," % iso[
'color'][
'value']
2362 cmdIsoColorVal +=
"%s," % iso[
'color'][
'value']
2364 if iso[
'transp'][
'map']:
2365 cmdIsoTrMap +=
"%s," % iso[
'transp'][
'value']
2367 cmdIsoTrVal +=
"%s," % iso[
'transp'][
'value']
2369 for slice
in nvizData[
'slice']:
2370 axis = (
'x',
'y',
'z')[slice[
'position'][
'axis']]
2371 cmdSlice +=
"%d:%s," % (i + 1, axis)
2372 for coord
in (
'x1',
'x2',
'y1',
'y2',
'z1',
'z2'):
2373 cmdSlicePos +=
"%f," % slice[
'position'][coord]
2374 cmdSliceTransp +=
"%s," % slice[
'transp'][
'value']
2376 cmd +=
"volume=" + cmdName.strip(
',') +
' '
2377 cmd +=
"volume_shading=" + cmdShade.strip(
',') +
' '
2378 cmd +=
"volume_resolution=" + cmdRes.strip(
',') +
' '
2379 if nvizData[
'position']:
2380 cmd +=
"volume_position=" + cmdPos.strip(
',') +
' '
2382 cmd +=
"isosurf_level=" + cmdIso.strip(
',') +
' '
2384 cmd +=
"isosurf_color_map=" + cmdIsoColorMap.strip(
',') +
' '
2386 cmd +=
"isosurf_color_value=" + cmdIsoColorVal.strip(
',') +
' '
2388 cmd +=
"isosurf_transparency_map=" + cmdIsoTrMap.strip(
',') +
' '
2390 cmd +=
"isosurf_transparency_value=" + cmdIsoTrVal.strip(
',') +
' '
2392 cmd +=
"slice=" + cmdSlice.strip(
',') +
' '
2393 cmd +=
"slice_position=" + cmdSlicePos.strip(
',') +
' '
2394 cmd +=
"slice_transparency=" + cmdSliceTransp.strip(
',') +
' '
2399 cplane = self.lmgr.nviz.FindWindowById(self.lmgr.nviz.win[
'cplane'][
'planes']).GetStringSelection()
2401 planeIndex = int(cplane.split()[-1]) - 1
2402 except (IndexError, ValueError):
2404 if planeIndex
is not None:
2405 shading = [
'clear',
'top',
'bottom',
'blend',
'shaded']
2406 cmd +=
"cplane=%d " % planeIndex
2407 cmd +=
"cplane_rotation=%d " % self.
cplanes[planeIndex][
'rotation'][
'rot']
2408 cmd +=
"cplane_tilt=%d " % self.
cplanes[planeIndex][
'rotation'][
'tilt']
2409 cmd +=
"cplane_position=%d,%d,%d " % (self.
cplanes[planeIndex][
'position'][
'x'],
2410 self.
cplanes[planeIndex][
'position'][
'y'],
2411 self.
cplanes[planeIndex][
'position'][
'z'])
2412 cmd +=
"cplane_shading=%s " % shading[self.
cplanes[planeIndex][
'shading']]
2417 subcmd =
"position=%.2f,%.2f " % (self.
view[
'position'][
'x'], self.
view[
'position'][
'y'])
2418 subcmd +=
"height=%d " % (self.
iview[
'height'][
'value'])
2419 subcmd +=
"perspective=%d " % (self.
view[
'persp'][
'value'])
2420 subcmd +=
"twist=%d " % (self.
view[
'twist'][
'value'])
2421 subcmd +=
"zexag=%f " % (self.
view[
'z-exag'][
'value'] / self.
iview[
'z-exag'][
'llRatio'])
2422 subcmd +=
"focus=%d,%d,%d " % (self.
iview[
'focus'][
'x'],self.
iview[
'focus'][
'y'],self.
iview[
'focus'][
'z'])
2426 subcmd =
"bgcolor=%d:%d:%d " % (self.
view[
'background'][
'color'][:3])
2427 if self.
view[
'background'][
'color'] != (255, 255, 255):
2431 subcmd =
"light_position=%.2f,%.2f,%.2f " % (self.
light[
'position'][
'x'],
2432 self.
light[
'position'][
'y'],
2433 self.
light[
'position'][
'z']/100.)
2434 subcmd +=
"light_brightness=%d " % (self.
light[
'bright'])
2435 subcmd +=
"light_ambient=%d " % (self.
light[
'ambient'])
2436 subcmd +=
"light_color=%d:%d:%d " % (self.
light[
'color'][:3])
2440 toolWindow = self.lmgr.nviz
2442 for dir
in (
'nw',
'ne',
'sw',
'se'):
2443 if toolWindow.FindWindowById(toolWindow.win[
'fringe'][dir]).IsChecked():
2444 direction +=
"%s," % dir
2446 subcmd =
"fringe=%s " % (direction.strip(
','))
2447 color = toolWindow.FindWindowById(toolWindow.win[
'fringe'][
'color']).
GetValue()
2448 subcmd +=
"fringe_color=%d:%d:%d " % (color[0], color[1], color[2])
2449 subcmd +=
"fringe_elevation=%d " % (toolWindow.FindWindowById(toolWindow.win[
'fringe'][
'elev']).
GetValue())
2454 subcmd =
"arrow_position=%d,%d " % (self.
decoration[
'arrow'][
'position'][
'x'],
2456 subcmd +=
"arrow_color=%s " % self.
decoration[
'arrow'][
'color']
2457 subcmd +=
"arrow_size=%d " % self.
decoration[
'arrow'][
'size']
2461 subcmd =
'output=nviz_output '
2462 subcmd +=
'format=ppm '
2463 subcmd +=
'size=%d,%d ' % self.GetClientSizeTuple()
2469 """!Generate and write command to command output"""
2473 """!This draws the DC to a buffer that can be saved to a file.
2475 @todo fix BufferedPaintDC
2477 @param FileName file name
2478 @param FileType type of bitmap
2479 @param width image width
2480 @param height image height
2482 self._display.SaveToFile(FileName, width, height, FileType)
2493 """!Get display instance"""
2499 self.lmgr.nviz.OnResetView(
None)
2502 """!Return text boundary data
2504 @param textinfo text metadata (text, font, color, rotation)
2506 return self.parent.MapWindow2D.TextBounds(textinfo, relcoords =
True)