2 @package mapdisp_window.py
4 @brief Map display canvas - buffered window.
10 (C) 2006-2011 by the GRASS Development Team
11 This program is free software under the GNU General Public
12 License (>=v2). Read the file COPYING that comes with GRASS
15 @author Martin Landa <landa.martin gmail.com>
16 @author Michael Barton
17 @author Jachym Cepicky
37 from debug
import Debug
38 from preferences
import globalSettings
as UserSettings
39 from units
import ConvertValue
as UnitsConvertValue
48 """!Abstract map display window class
50 Superclass for BufferedWindow class (2D display mode), and GLWindow
53 def __init__(self, parent, id = wx.ID_ANY,
54 Map =
None, tree =
None, lmgr =
None, **kwargs):
70 """!Track mouse motion and update statusbar
72 if self.parent.statusbarWin[
'toggle'].GetSelection() == 0:
73 precision = int(UserSettings.Get(group =
'projection', key =
'format',
74 subkey =
'precision'))
75 format = UserSettings.Get(group =
'projection', key =
'format',
78 e, n = self.Pixel2Cell(event.GetPositionTuple())
79 except (TypeError, ValueError):
80 self.parent.statusbar.SetStatusText(
"", 0)
84 if hasattr(self,
"digit"):
85 updated = self._onMotion((e, n), precision)
88 if self.parent.statusbarWin[
'projection'].IsChecked():
89 if not UserSettings.Get(group =
'projection', key =
'statusbar', subkey =
'proj4'):
90 self.parent.statusbar.SetStatusText(_(
"Projection not defined (check the settings)"), 0)
92 proj, coord = utils.ReprojectCoordinates(coord = (e, n),
93 projOut = UserSettings.Get(group =
'projection',
100 if proj
in (
'll',
'latlong',
'longlat')
and format ==
'DMS':
101 self.parent.statusbar.SetStatusText(utils.Deg2DMS(e, n, precision = precision),
104 self.parent.statusbar.SetStatusText(
"%.*f; %.*f" % \
105 (precision, e, precision, n), 0)
107 self.parent.statusbar.SetStatusText(_(
"Error in projection (check the settings)"), 0)
109 if self.parent.Map.projinfo[
'proj'] ==
'll' and format ==
'DMS':
110 self.parent.statusbar.SetStatusText(utils.Deg2DMS(e, n, precision = precision),
113 self.parent.statusbar.SetStatusText(
"%.*f; %.*f" % \
114 (precision, e, precision, n), 0)
119 """!Get layer from layer tree by nam
121 @param name layer name
122 @param type 'item' / 'layer' / 'nviz'
124 @return layer / map layer properties / nviz properties
131 mapLayer = self.Map.GetListOfLayers(l_type = mapType, l_name = name)[0]
135 if dataType ==
'layer':
137 item = self.tree.FindItemByData(
'maplayer', mapLayer)
140 if dataType ==
'nviz':
141 return self.tree.GetPyData(item)[0][
'nviz']
146 """!Get selected layer from layer tree
148 @param type 'item' / 'layer' / 'nviz'
149 @param multi return first selected layer or all
151 @return layer / map layer properties / nviz properties
152 @return None / [] on failure
155 if not self.
tree or \
156 not self.tree.GetSelection():
164 return self.tree.GetSelections()
166 for item
in self.tree.GetSelections():
167 if not item.IsChecked():
178 layer = self.tree.GetPyData(item)[0][
'nviz']
180 layer = self.tree.GetPyData(item)[0][
'maplayer']
192 """!A Buffered window class (2D view mode)
194 Superclass for VDigitWindow (vector digitizer).
196 When the drawing needs to change, you app needs to call the
197 UpdateMap() method. Since the drawing is stored in a bitmap, you
198 can also save the drawing to file by calling the
201 def __init__(self, parent, id = wx.ID_ANY,
202 Map =
None, tree =
None, lmgr =
None,
203 style = wx.NO_FULL_REPAINT_ON_RESIZE, **kwargs):
204 MapWindow.__init__(self, parent, id, Map, tree, lmgr, **kwargs)
205 wx.Window.__init__(self, parent, id, style = style, **kwargs)
222 self.Bind(wx.EVT_PAINT, self.
OnPaint)
223 self.Bind(wx.EVT_SIZE, self.
OnSize)
224 self.Bind(wx.EVT_IDLE, self.
OnIdle)
226 self.Bind(wx.EVT_MOTION, self.
OnMotion)
260 self.Bind(wx.EVT_ERASE_BACKGROUND,
lambda x:
None)
266 def _definePseudoDC(self):
267 """!Define PseudoDC objects to use
278 def Draw(self, pdc, img = None, drawid = None, pdctype = 'image', coords = [0, 0, 0, 0]):
279 """!Draws map and overlay decorations
282 if pdctype ==
'image' and img:
284 elif pdctype ==
'clear':
289 if img
and pdctype ==
'image':
296 bg = wx.TRANSPARENT_BRUSH
298 bg = wx.Brush(self.GetBackgroundColour())
300 pdc.SetBackground(bg)
302 Debug.msg (5,
"BufferedWindow.Draw(): id=%s, pdctype = %s, coord=%s" % \
303 (drawid, pdctype, coords))
306 if drawid
is not None:
309 if pdctype ==
'clear':
312 pdc.SetBackground(bg)
320 if pdctype ==
'image':
321 bitmap = wx.BitmapFromImage(img)
322 w,h = bitmap.GetSize()
323 pdc.DrawBitmap(bitmap, coords[0], coords[1],
True)
324 pdc.SetIdBounds(drawid, wx.Rect(coords[0],coords[1], w, h))
326 elif pdctype ==
'box':
328 pdc.SetBrush(wx.Brush(wx.CYAN, wx.TRANSPARENT))
330 x2 =
max(coords[0],coords[2])
331 x1 =
min(coords[0],coords[2])
332 y2 =
max(coords[1],coords[3])
333 y1 =
min(coords[1],coords[3])
336 rect = wx.Rect(x1, y1, rwidth, rheight)
337 pdc.DrawRectangleRect(rect)
338 pdc.SetIdBounds(drawid, rect)
340 elif pdctype ==
'line':
342 pdc.SetBrush(wx.Brush(wx.CYAN, wx.TRANSPARENT))
344 pdc.DrawLinePoint(wx.Point(coords[0], coords[1]),wx.Point(coords[2], coords[3]))
345 pdc.SetIdBounds(drawid, wx.Rect(coords[0], coords[1], coords[2], coords[3]))
347 elif pdctype ==
'polyline':
349 pdc.SetBrush(wx.Brush(wx.CYAN, wx.TRANSPARENT))
351 if (len(coords) < 2):
354 while i < len(coords):
355 pdc.DrawLinePoint(wx.Point(coords[i-1][0], coords[i-1][1]),
356 wx.Point(coords[i][0], coords[i][1]))
371 pdc.SetIdBounds(drawid, wx.Rect(x1,y1,x2,y2))
374 elif pdctype ==
'point':
377 pdc.DrawPoint(coords[0], coords[1])
378 coordsBound = (coords[0] - 5,
382 pdc.SetIdBounds(drawid, wx.Rect(coordsBound))
384 elif pdctype ==
'text':
385 if not img[
'active']:
387 if 'rotation' in img:
388 rotation = float(img[
'rotation'])
391 w, h = self.GetFullTextExtent(img[
'text'])[0:2]
392 pdc.SetFont(img[
'font'])
393 pdc.SetTextForeground(img[
'color'])
396 pdc.DrawText(img[
'text'], coords[0], coords[1])
398 pdc.DrawRotatedText(img[
'text'], coords[0], coords[1], rotation)
399 pdc.SetIdBounds(drawid, wx.Rect(coords[0], coords[1], w, h))
408 """!Return text boundary data
410 @param textinfo text metadata (text, font, color, rotation)
411 @param coords reference point
413 if 'rotation' in textinfo:
414 rotation = float(textinfo[
'rotation'])
418 coords = textinfo[
'coords']
420 Debug.msg (4,
"BufferedWindow.TextBounds(): text=%s, rotation=%f" % \
421 (textinfo[
'text'], rotation))
425 self.SetFont(textinfo[
'font'])
427 w, h = self.GetTextExtent(textinfo[
'text'])
430 coords[2], coords[3] = coords[0] + w, coords[1] + h
433 boxh = math.fabs(math.sin(math.radians(rotation)) * w) + h
434 boxw = math.fabs(math.cos(math.radians(rotation)) * w) + h
435 coords[2] = coords[0] + boxw
436 coords[3] = coords[1] + boxh
438 return coords, boxw, boxh
441 """!Draw PseudoDC's to buffered paint DC
443 If self.redrawAll is False on self.pdcTmp content is re-drawn
445 Debug.msg(4,
"BufferedWindow.OnPaint(): redrawAll=%s" % self.
redrawAll)
447 dc = wx.BufferedPaintDC(self, self.
buffer)
455 rgn = self.GetUpdateRegion().GetBox()
456 dc.SetClippingRect(rgn)
465 self.pdc.DrawToDCClipped(dc, rgn)
468 if hasattr(self,
"digit"):
472 self.pdcVector.DrawToDCClipped(gcdc, rgn)
473 except NotImplementedError, e:
474 print >> sys.stderr, e
475 self.pdcVector.DrawToDCClipped(dc, rgn)
481 self.pdc.DrawToDC(dc)
483 if hasattr(self,
"digit"):
487 self.pdcVector.DrawToDC(gcdc)
488 except NotImplementedError, e:
489 print >> sys.stderr, e
490 self.pdcVector.DrawToDC(dc)
494 self.
bufferLast = dc.GetAsBitmap(wx.Rect(0, 0, self.Map.width, self.Map.height))
496 self.pdc.DrawBitmap(self.
bufferLast, 0, 0,
False)
497 self.pdc.DrawToDC(dc)
502 self.pdcDec.DrawToDC(gcdc)
503 except NotImplementedError, e:
504 print >> sys.stderr, e
505 self.pdcDec.DrawToDC(dc)
509 self.pdcTmp.DrawToDC(dc)
515 """!Scale map image so that it is the same size as the Window
517 Debug.msg(3,
"BufferedWindow.OnSize():")
520 self.Map.ChangeMapSize(self.GetClientSize())
528 self.
buffer = wx.EmptyBitmap(
max(1, self.Map.width),
max(1, self.Map.height))
534 if self.
img and self.Map.width + self.Map.height > 0:
535 self.
img = self.img.Scale(self.Map.width, self.Map.height)
536 if len(self.Map.GetListOfLayers()) > 0:
543 self.parent.StatusbarReposition()
546 self.parent.StatusbarUpdate()
549 """!Only re-render a composite map image from GRASS during
550 idle time instead of multiple times during resizing.
558 """!This draws the pseudo DC to a buffer that can be saved to
561 @param FileName file name
562 @param FileType type of bitmap
563 @param width image width
564 @param height image height
566 busy = wx.BusyInfo(message = _(
"Please wait, exporting image..."),
570 self.Map.ChangeMapSize((width, height))
571 ibuffer = wx.EmptyBitmap(
max(1, width),
max(1, height))
572 self.Map.Render(force =
True, windres =
True)
574 self.
Draw(self.
pdc, img, drawid = 99)
575 dc = wx.BufferedPaintDC(self, ibuffer)
578 self.pdc.DrawToDC(dc)
580 self.pdcVector.DrawToDC(dc)
581 ibuffer.SaveFile(FileName, FileType)
589 """!Converts rendered overlay files to wx.Image
591 Updates self.imagedict
593 @return list of images
596 for overlay
in self.Map.GetListOfLayers(l_type =
"overlay", l_active =
True):
597 if os.path.isfile(overlay.mapfile)
and os.path.getsize(overlay.mapfile):
598 img = wx.Image(overlay.mapfile, wx.BITMAP_TYPE_ANY)
599 self.
imagedict[img] = {
'id' : overlay.id,
606 """!Converts redered map files to wx.Image
608 Updates self.imagedict (id=99)
610 @return wx.Image instance (map composition)
613 if self.
mapfile and self.Map.mapfile
and os.path.isfile(self.Map.mapfile)
and \
614 os.path.getsize(self.Map.mapfile):
615 img = wx.Image(self.Map.mapfile, wx.BITMAP_TYPE_ANY)
623 def UpdateMap(self, render = True, renderVector = True):
624 """!Updates the canvas anytime there is a change to the
625 underlaying images or to the geometry of the canvas.
627 @param render re-render map composition
628 @param renderVector re-render vector map layer enabled for editing (used for digitizer)
640 if render
or renderVector:
641 self.parent.statusbarWin[
'progress'].Show()
642 if self.parent.statusbarWin[
'progress'].GetRange() > 0:
643 self.parent.statusbarWin[
'progress'].SetValue(1)
649 if self.
tree and self.tree.reorder:
650 self.tree.ReorderLayers()
654 self.tree.rerender =
False
659 self.Map.ChangeMapSize(self.GetClientSize())
660 if self.parent.statusbarWin[
'resolution'].IsChecked():
665 self.
mapfile = self.Map.Render(force =
True, mapWindow = self.
parent,
668 self.
mapfile = self.Map.Render(force =
False, mapWindow = self.
parent)
678 for pdc
in (self.
pdc,
688 self.
Draw(self.
pdc, pdctype =
'clear')
700 if renderVector
and hasattr(self,
"digit"):
707 if self.
imagedict[img][
'layer'].IsActive():
709 self.
Draw(self.
pdc, img = img, drawid = id,
710 pdctype = self.
overlays[id][
'pdcType'], coords = self.
overlays[id][
'coords'])
712 for id
in self.textdict.keys():
714 pdctype =
'text', coords = [10, 10, 10, 10])
725 if not self.parent.IsStandalone()
and \
726 self.parent.GetLayerManager().georectifying:
728 if self.parent.toolbars[
'georect']:
729 coordtype =
'gcpcoord'
731 coordtype =
'mapcoord'
732 self.parent.GetLayerManager().georectifying.DrawGCP(coordtype)
734 if not self.parent.IsStandalone()
and \
735 self.parent.GetLayerManager().gcpmanagement:
737 if self.parent.toolbars[
'gcpdisp']:
738 if self == self.parent.TgtMapWindow:
743 self.parent.DrawGCP(coordtype)
748 if self.
mouse[
"use"] ==
"measure":
751 self.
mouse[
'use'] =
'pointer'
752 self.
mouse[
'box'] =
'point'
753 self.
mouse[
'end'] = [0, 0]
754 self.SetCursor(self.parent.cursors[
"default"])
761 self.parent.statusbarWin[
'progress'].Hide()
767 self.parent.StatusbarUpdate()
768 if grass.find_file(name =
'MASK', element =
'cell')[
'name']:
770 self.parent.statusbarWin[
'mask'].SetLabel(_(
'MASK'))
772 self.parent.statusbarWin[
'mask'].SetLabel(
'')
774 Debug.msg (1,
"BufferedWindow.UpdateMap(): render=%s, renderVector=%s -> time=%g" % \
775 (render, renderVector, (stop-start)))
780 """!Draw computational region extent in the display
782 Display region is drawn as a blue box inside the computational region,
783 computational region inside a display region as a red box).
785 if hasattr(self,
"regionCoords"):
786 compReg = self.Map.GetRegion()
787 dispReg = self.Map.GetCurrentRegion()
790 self.
polypen = wx.Pen(colour = wx.Colour(0, 0, 255, 128), width = 3, style = wx.SOLID)
793 self.
polypen = wx.Pen(colour = wx.Colour(255, 0, 0, 128),
794 width = 3, style = wx.SOLID)
798 self.regionCoords.append((reg[
'w'], reg[
'n']))
799 self.regionCoords.append((reg[
'e'], reg[
'n']))
800 self.regionCoords.append((reg[
'e'], reg[
's']))
801 self.regionCoords.append((reg[
'w'], reg[
's']))
802 self.regionCoords.append((reg[
'w'], reg[
'n']))
808 Test if 'region' is inside of 'refRegion'
810 @param region input region
811 @param refRegion reference region (e.g. computational region)
813 @return True if region is inside of refRegion
816 if region[
's'] >= refRegion[
's']
and \
817 region[
'n'] <= refRegion[
'n']
and \
818 region[
'w'] >= refRegion[
'w']
and \
819 region[
'e'] <= refRegion[
'e']:
827 self.
Draw(self.
pdc, pdctype =
'clear')
829 if hasattr(self,
"digit"):
836 """!Drag the entire map image for panning.
840 dc = wx.BufferedDC(wx.ClientDC(self))
841 dc.SetBackground(wx.Brush(
"White"))
845 self.dragimg.BeginDrag((0, 0), self)
846 self.dragimg.GetImageRect(moveto)
847 self.dragimg.Move(moveto)
849 self.dragimg.DoDrawImage(dc, moveto)
850 self.dragimg.EndDrag()
853 """!Drag an overlay decoration item
855 if id == 99
or id ==
'' or id ==
None:
return
856 Debug.msg (5,
"BufferedWindow.DragItem(): id=%d" % id)
858 dx = event.GetX() - x
859 dy = event.GetY() - y
860 self.pdc.SetBackground(wx.Brush(self.GetBackgroundColour()))
861 r = self.pdc.GetIdBounds(id)
863 r = wx.Rect(r[0], r[1], r[2], r[3])
865 rtop = (r[0],r[1]-r[3],r[2],r[3])
867 rleft = (r[0]-r[2],r[1],r[2],r[3])
869 self.pdc.TranslateId(id, dx, dy)
871 r2 = self.pdc.GetIdBounds(id)
873 r2 = wx.Rect(r[0], r[1], r[2], r[3])
878 self.RefreshRect(r,
False)
879 self.
lastpos = (event.GetX(), event.GetY())
881 def MouseDraw(self, pdc = None, begin = None, end = None):
882 """!Mouse box or line from 'begin' to 'end'
884 If not given from self.mouse['begin'] to self.mouse['end'].
890 begin = self.
mouse[
'begin']
892 end = self.
mouse[
'end']
894 Debug.msg (5,
"BufferedWindow.MouseDraw(): use=%s, box=%s, begin=%f,%f, end=%f,%f" % \
896 begin[0], begin[1], end[0], end[1]))
898 if self.
mouse[
'box'] ==
"box":
900 mousecoords = [begin[0], begin[1],
902 r = pdc.GetIdBounds(boxid)
904 r = wx.Rect(r[0], r[1], r[2], r[3])
910 self.RefreshRect(r,
False)
912 self.
Draw(pdc, drawid = boxid, pdctype =
'box', coords = mousecoords)
914 elif self.
mouse[
'box'] ==
"line":
916 mousecoords = [begin[0], begin[1], \
918 x1 =
min(begin[0],end[0])
919 x2 =
max(begin[0],end[0])
920 y1 =
min(begin[1],end[1])
921 y2 =
max(begin[1],end[1])
922 r = wx.Rect(x1,y1,x2-x1,y2-y1)
928 self.RefreshRect(r,
False)
930 self.
Draw(pdc, drawid = self.
lineid, pdctype =
'line', coords = mousecoords)
933 """!Draw polyline in PseudoDC
935 Set self.pline to wx.NEW_ID + 1
937 polycoords - list of polyline vertices, geographical coordinates
938 (if not given, self.polycoords is used)
946 if len(polycoords) > 0:
953 self.
Draw(pdc, drawid = self.
plineid, pdctype =
'polyline', coords = coords)
955 Debug.msg (4,
"BufferedWindow.DrawLines(): coords=%s, id=%s" % \
962 def DrawCross(self, pdc, coords, size, rotation = 0,
963 text =
None, textAlign =
'lr', textOffset = (5, 5)):
964 """!Draw cross in PseudoDC
966 @todo implement rotation
969 @param coord center coordinates
970 @param rotation rotate symbol
971 @param text draw also text (text, font, color, rotation)
972 @param textAlign alignment (default 'lower-right')
973 @textOffset offset for text (from center point)
975 Debug.msg(4,
"BufferedWindow.DrawCross(): pdc=%s, coords=%s, size=%d" % \
977 coordsCross = ((coords[0] - size, coords[1], coords[0] + size, coords[1]),
978 (coords[0], coords[1] - size, coords[0], coords[1] + size))
981 for lineCoords
in coordsCross:
982 self.
Draw(pdc, drawid = self.
lineid, pdctype =
'line', coords = lineCoords)
987 if textAlign ==
'ul':
988 coord = [coords[0] - textOffset[0], coords[1] - textOffset[1], 0, 0]
989 elif textAlign ==
'ur':
990 coord = [coords[0] + textOffset[0], coords[1] - textOffset[1], 0, 0]
991 elif textAlign ==
'lr':
992 coord = [coords[0] + textOffset[0], coords[1] + textOffset[1], 0, 0]
994 coord = [coords[0] - textOffset[0], coords[1] + textOffset[1], 0, 0]
996 self.
Draw(pdc, img = text,
997 pdctype =
'text', coords = coord)
1002 """!Mouse motion and button click notifier
1008 if event.GetWheelRotation() != 0:
1012 elif event.LeftDown():
1016 elif event.LeftUp():
1020 elif event.Dragging():
1024 elif event.ButtonDClick():
1028 elif event.MiddleDown():
1032 elif event.MiddleUp():
1036 elif event.RightDown():
1040 elif event.RightUp():
1043 elif event.Entering():
1046 elif event.Moving():
1050 """!Mouse wheel moved
1053 current = event.GetPositionTuple()[:]
1054 wheel = event.GetWheelRotation()
1055 Debug.msg (5,
"BufferedWindow.MouseAction(): wheel=%d" % wheel)
1057 begin = (current[0] - self.Map.width / 4,
1058 current[1] - self.Map.height / 4)
1059 end = (current[0] + self.Map.width / 4,
1060 current[1] + self.Map.height / 4)
1068 self.
Zoom(begin, end, zoomtype)
1074 self.parent.StatusbarUpdate()
1082 Debug.msg (5,
"BufferedWindow.MouseAction(): Dragging")
1083 current = event.GetPositionTuple()[:]
1084 previous = self.
mouse[
'begin']
1085 move = (current[0] - previous[0],
1086 current[1] - previous[1])
1088 if hasattr(self,
"digit"):
1089 digitToolbar = self.toolbar
1094 if self.
mouse[
'use'] ==
'pan' or \
1095 event.MiddleIsDown():
1099 elif (self.
mouse[
'use'] ==
'pointer' and
1100 not digitToolbar
and
1106 if (self.
mouse[
'use'] ==
'pointer' and
1110 self.
mouse[
'end'] = event.GetPositionTuple()[:]
1111 if (event.LeftIsDown()
and
1112 not (digitToolbar
and
1113 digitToolbar.GetAction()
in (
"moveLine",)
and
1114 self.digit.GetDisplay().GetSelected() > 0)):
1118 """!Left mouse button pressed
1120 Debug.msg (5,
"BufferedWindow.OnLeftDown(): use=%s" % \
1123 self.
mouse[
'begin'] = event.GetPositionTuple()[:]
1125 if self.
mouse[
"use"]
in [
"measure",
"profile"]:
1134 elif self.
mouse[
'use'] ==
'zoom':
1138 elif self.
mouse[
"use"] ==
"pointer" and \
1139 hasattr(self,
"digit"):
1140 if event.ControlDown():
1141 self.OnLeftDownUndo(event)
1143 self._onLeftDown(event)
1145 elif self.
mouse[
'use'] ==
'pointer':
1162 """!Left mouse button released
1164 Debug.msg (5,
"BufferedWindow.OnLeftUp(): use=%s" % \
1167 self.
mouse[
'end'] = event.GetPositionTuple()[:]
1169 if self.
mouse[
'use']
in [
"zoom",
"pan"]:
1171 begin = self.
mouse[
'begin']
1172 end = self.
mouse[
'end']
1174 if self.
mouse[
'use'] ==
'zoom':
1176 if begin[0] - end[0] == 0
or \
1177 begin[1] - end[1] == 0:
1179 begin = (end[0] - self.Map.width / 4,
1180 end[1] - self.Map.height / 4)
1181 end = (end[0] + self.Map.width / 4,
1182 end[1] + self.Map.height / 4)
1190 self.parent.StatusbarUpdate()
1192 elif self.
mouse[
"use"] ==
"query":
1198 if l.GetType() ==
'raster':
1201 if l.GetType() ==
'vector':
1204 if isRaster
or nVectors > 1:
1205 self.parent.QueryMap(self.
mouse[
'begin'][0],self.
mouse[
'begin'][1])
1207 self.parent.QueryVector(self.
mouse[
'begin'][0], self.
mouse[
'begin'][1])
1209 self.
UpdateMap(render =
False, renderVector =
False)
1211 elif self.
mouse[
"use"] ==
"queryVector":
1213 self.parent.QueryVector(self.
mouse[
'begin'][0], self.
mouse[
'begin'][1])
1216 self.
UpdateMap(render =
False, renderVector =
False)
1218 elif self.
mouse[
"use"]
in [
"measure",
"profile"]:
1220 if self.
mouse[
"use"] ==
"measure":
1221 self.parent.MeasureDist(self.
mouse[
'begin'], self.
mouse[
'end'])
1227 elif self.
mouse[
"use"] ==
"pointer" and \
1228 self.parent.GetLayerManager().gcpmanagement:
1230 if self.parent.toolbars[
'gcpdisp']:
1232 if self.parent.MapWindow == self.parent.SrcMapWindow:
1233 coordtype =
'source'
1235 coordtype =
'target'
1237 self.parent.GetLayerManager().gcpmanagement.SetGCPData(coordtype, coord, self, confirm =
True)
1238 self.
UpdateMap(render =
False, renderVector =
False)
1240 elif self.
mouse[
"use"] ==
"pointer" and \
1241 self.parent.GetLayerManager().georectifying:
1244 if self.parent.toolbars[
'georect']:
1245 coordtype =
'gcpcoord'
1247 coordtype =
'mapcoord'
1249 self.parent.GetLayerManager().georectifying.SetGCPData(coordtype, coord, self)
1250 self.
UpdateMap(render =
False, renderVector =
False)
1252 elif self.
mouse[
"use"] ==
"pointer" and \
1253 hasattr(self,
"digit"):
1254 self._onLeftUp(event)
1256 elif (self.
mouse[
'use'] ==
'pointer' and
1270 """!Mouse button double click
1272 Debug.msg (5,
"BufferedWindow.OnButtonDClick(): use=%s" % \
1275 if self.
mouse[
"use"] ==
"measure":
1279 self.
mouse[
'use'] =
'pointer'
1280 self.
mouse[
'box'] =
'point'
1281 self.
mouse[
'end'] = [0, 0]
1283 self.SetCursor(self.parent.cursors[
"default"])
1285 elif self.
mouse[
"use"] !=
"profile" or \
1286 (self.
mouse[
'use'] !=
'pointer' and \
1287 hasattr(self,
"digit")):
1289 clickposition = event.GetPositionTuple()[:]
1290 idlist = self.pdc.FindObjects(clickposition[0], clickposition[1], self.
hitradius)
1298 self.parent.OnAddText(
None)
1300 self.parent.OnAddBarscale(
None)
1302 self.parent.OnAddLegend(
None)
1305 """!Right mouse button pressed
1307 Debug.msg (5,
"BufferedWindow.OnRightDown(): use=%s" % \
1310 if hasattr(self,
"digit"):
1311 self._onRightDown(event)
1316 """!Right mouse button released
1318 Debug.msg (5,
"BufferedWindow.OnRightUp(): use=%s" % \
1321 if hasattr(self,
"digit"):
1322 self._onRightUp(event)
1330 """!Middle mouse button pressed
1335 self.
mouse[
'begin'] = event.GetPositionTuple()[:]
1338 """!Middle mouse button released
1340 self.
mouse[
'end'] = event.GetPositionTuple()[:]
1343 begin = self.
mouse[
'begin']
1344 end = self.
mouse[
'end']
1346 self.
Zoom(begin, end, 0)
1352 self.parent.StatusbarUpdate()
1355 """!Mouse entered window and no mouse buttons were pressed
1357 if self.parent.GetLayerManager().gcpmanagement:
1358 if self.parent.toolbars[
'gcpdisp']:
1359 if not self.parent.MapWindow == self:
1360 self.parent.MapWindow = self
1361 self.parent.Map = self.
Map
1362 self.parent.UpdateActive(self)
1369 """!Motion event and no mouse buttons were pressed
1371 if self.
mouse[
"use"] ==
"pointer" and \
1372 hasattr(self,
"digit"):
1373 self._onMouseMoving(event)
1378 """!Clears temporary drawn lines from PseudoDC
1384 pdc.RemoveId(self.
lineid)
1394 Debug.msg(4,
"BufferedWindow.ClearLines(): lineid=%s, plineid=%s" %
1400 """!Convert image coordinates to real word coordinates
1402 @param x, y image coordinates
1404 @return easting, northing
1405 @return None on error
1413 if self.Map.region[
"ewres"] > self.Map.region[
"nsres"]:
1414 res = self.Map.region[
"ewres"]
1416 res = self.Map.region[
"nsres"]
1418 w = self.Map.region[
"center_easting"] - (self.Map.width / 2) * res
1419 n = self.Map.region[
"center_northing"] + (self.Map.height / 2) * res
1424 return (east, north)
1427 """!Convert real word coordinates to image coordinates
1431 north = float(north)
1435 if self.Map.region[
"ewres"] > self.Map.region[
"nsres"]:
1436 res = self.Map.region[
"ewres"]
1438 res = self.Map.region[
"nsres"]
1440 w = self.Map.region[
"center_easting"] - (self.Map.width / 2) * res
1441 n = self.Map.region[
"center_northing"] + (self.Map.height / 2) * res
1443 x = (east - w) / res
1444 y = (n - north) / res
1448 def Zoom(self, begin, end, zoomtype):
1450 Calculates new region while (un)zoom/pan-ing
1458 if abs(x2-x1) > 5
and abs(y2-y1) > 5
and zoomtype != 0:
1466 newreg[
'w'], newreg[
'n'] = self.
Pixel2Cell((x1, y1))
1467 newreg[
'e'], newreg[
's'] = self.
Pixel2Cell((x2, y2))
1471 newreg[
'w'], newreg[
'n'] = self.
Pixel2Cell((-x1 * 2, -y1 * 2))
1472 newreg[
'e'], newreg[
's'] = self.
Pixel2Cell((self.Map.width + 2 * \
1473 (self.Map.width - x2),
1474 self.Map.height + 2 * \
1475 (self.Map.height - y2)))
1480 if dx == 0
and dy == 0:
1481 dx = x1 - self.Map.width / 2
1482 dy = y1 - self.Map.height / 2
1483 newreg[
'w'], newreg[
'n'] = self.
Pixel2Cell((dx, dy))
1484 newreg[
'e'], newreg[
's'] = self.
Pixel2Cell((self.Map.width + dx,
1485 self.Map.height + dy))
1490 if self.parent.Map.projinfo[
'proj'] ==
'll':
1491 if newreg[
'n'] > 90.0:
1493 if newreg[
's'] < -90.0:
1496 ce = newreg[
'w'] + (newreg[
'e'] - newreg[
'w']) / 2
1497 cn = newreg[
's'] + (newreg[
'n'] - newreg[
's']) / 2
1500 self.Map.region[
'center_easting'] = ce
1501 self.Map.region[
'center_northing'] = cn
1502 self.Map.region[
"ewres"] = (newreg[
'e'] - newreg[
'w']) / self.Map.width
1503 self.Map.region[
"nsres"] = (newreg[
'n'] - newreg[
's']) / self.Map.height
1504 self.Map.AlignExtentFromDisplay()
1506 if hasattr(self,
"digit")
and \
1507 hasattr(self,
"moveInfo"):
1510 self.
ZoomHistory(self.Map.region[
'n'], self.Map.region[
's'],
1511 self.Map.region[
'e'], self.Map.region[
'w'])
1517 """!Zoom to previous extents in zoomhistory list
1522 self.zoomhistory.pop()
1527 if self.parent.GetName() ==
'MapWindow':
1528 toolbar = self.parent.toolbars[
'map']
1529 elif self.parent.GetName() ==
'GRMapWindow':
1530 toolbar = self.parent.toolbars[
'georect']
1531 elif self.parent.GetName() ==
'GCPMapWindow':
1532 toolbar = self.parent.toolbars[
'gcpdisp']
1534 toolbar.Enable(
'zoomback', enable =
False)
1537 self.Map.GetRegion(n = zoom[0], s = zoom[1],
1538 e = zoom[2], w = zoom[3],
1544 self.parent.StatusbarUpdate()
1547 """!Manages a list of last 10 zoom extents
1549 @param n,s,e,w north, south, east, west
1551 @return removed history item if exists (or None)
1554 self.zoomhistory.append((n,s,e,w))
1557 removed = self.zoomhistory.pop(0)
1560 Debug.msg(4,
"BufferedWindow.ZoomHistory(): hist=%s, removed=%s" %
1563 Debug.msg(4,
"BufferedWindow.ZoomHistory(): hist=%s" %
1572 if self.parent.GetName() ==
'MapWindow':
1573 toolbar = self.parent.toolbars[
'map']
1574 elif self.parent.GetName() ==
'GRMapWindow':
1575 toolbar = self.parent.toolbars[
'georect']
1576 elif self.parent.GetName() ==
'GCPMapWindow':
1577 toolbar = self.parent.toolbars[
'gcpdisp']
1579 toolbar.Enable(
'zoomback', enable)
1584 """!Reset zoom history"""
1587 def ZoomToMap(self, layers = None, ignoreNulls = False, render = True):
1588 """!Set display extents to match selected raster
1591 @param layers list of layers to be zoom to
1592 @param ignoreNulls True to ignore null-values (valid only for rasters)
1593 @param render True to re-render display
1608 if l.type ==
'raster':
1609 rast.append(l.GetName())
1610 elif l.type ==
'vector':
1611 if hasattr(self,
"digit")
and \
1612 self.toolbar.GetLayer() == l:
1613 w, s, b, e, n, t = self.digit.GetDisplay().GetMapBoundingBox()
1614 self.Map.GetRegion(n = n, s = s, w = w, e = e,
1619 elif l.type ==
'rgb':
1620 for rname
in l.GetName().splitlines():
1624 self.Map.GetRegion(rast = rast,
1628 self.
ZoomHistory(self.Map.region[
'n'], self.Map.region[
's'],
1629 self.Map.region[
'e'], self.Map.region[
'w'])
1634 self.parent.StatusbarUpdate()
1637 """!Set display geometry to match computational region
1638 settings (set with g.region)
1640 self.Map.region = self.Map.GetRegion()
1642 self.
ZoomHistory(self.Map.region[
'n'], self.Map.region[
's'],
1643 self.Map.region[
'e'], self.Map.region[
'w'])
1647 self.parent.StatusbarUpdate()
1650 """!Set display geometry to match default region settings
1652 self.Map.region = self.Map.GetRegion(default =
True)
1653 self.Map.AdjustRegion()
1655 self.
ZoomHistory(self.Map.region[
'n'], self.Map.region[
's'],
1656 self.Map.region[
'e'], self.Map.region[
'w'])
1660 self.parent.StatusbarUpdate()
1663 """!Set computational region (WIND file) to match display
1666 tmpreg = os.getenv(
"GRASS_REGION")
1668 del os.environ[
"GRASS_REGION"]
1672 new = self.Map.AlignResolution()
1673 gcmd.RunCommand(
'g.region',
1680 rows = int(new[
'rows']),
1681 cols = int(new[
'cols']))
1684 os.environ[
"GRASS_REGION"] = tmpreg
1687 """!Set display geometry to match extents in
1691 title = _(
"Zoom to saved region extents"),
1694 if dlg.ShowModal() == wx.ID_CANCEL
or not dlg.wind:
1698 if not grass.find_file(name = dlg.wind, element =
'windows')[
'name']:
1699 wx.MessageBox(parent = self,
1700 message = _(
"Region <%s> not found. Operation canceled.") % dlg.wind,
1701 caption = _(
"Error"), style = wx.ICON_ERROR | wx.OK | wx.CENTRE)
1705 self.Map.GetRegion(regionName = dlg.wind,
1711 self.Map.region[
's'],
1712 self.Map.region[
'e'],
1713 self.Map.region[
'w'])
1718 """!Save display extents to named region file.
1721 title = _(
"Save display extents to region file"),
1724 if dlg.ShowModal() == wx.ID_CANCEL
or not dlg.wind:
1729 if grass.find_file(name = dlg.wind, element =
'windows')[
'name']:
1730 overwrite = wx.MessageBox(parent = self,
1731 message = _(
"Region file <%s> already exists. "
1732 "Do you want to overwrite it?") % (dlg.wind),
1733 caption = _(
"Warning"), style = wx.YES_NO | wx.CENTRE)
1734 if (overwrite == wx.YES):
1742 """!Save region settings
1744 @param wind region name
1746 new = self.Map.GetCurrentRegion()
1748 tmpreg = os.getenv(
"GRASS_REGION")
1750 del os.environ[
"GRASS_REGION"]
1752 gcmd.RunCommand(
'g.region',
1760 rows = int(new[
'rows']),
1761 cols = int(new[
'cols']),
1765 os.environ[
"GRASS_REGION"] = tmpreg
1768 """!Calculete distance
1770 Ctypes required for LL-locations
1772 @param beginpt first point
1773 @param endpt second point
1774 @param screen True for screen coordinates otherwise EN
1786 if self.parent.Map.projinfo[
'proj'] ==
'll' and haveCtypes:
1787 dist = gislib.G_distance(e1, n1, e2, n2)
1789 dist = math.sqrt(math.pow((dEast), 2) + math.pow((dNorth), 2))
1791 return (dist, (dEast, dNorth))