|
@@ -24,7 +24,6 @@ This program is free software under the GNU General Public License
|
|
|
|
|
|
import os
|
|
import os
|
|
import sys
|
|
import sys
|
|
-import math
|
|
|
|
import copy
|
|
import copy
|
|
|
|
|
|
from core import globalvar
|
|
from core import globalvar
|
|
@@ -37,7 +36,6 @@ if os.path.join(globalvar.ETCDIR, "python") not in sys.path:
|
|
sys.path.append(os.path.join(globalvar.ETCDIR, "python"))
|
|
sys.path.append(os.path.join(globalvar.ETCDIR, "python"))
|
|
|
|
|
|
from core import globalvar
|
|
from core import globalvar
|
|
-import core.units as units
|
|
|
|
from core.render import Map
|
|
from core.render import Map
|
|
from vdigit.toolbars import VDigitToolbar
|
|
from vdigit.toolbars import VDigitToolbar
|
|
from mapdisp.toolbars import MapToolbar, NvizIcons
|
|
from mapdisp.toolbars import MapToolbar, NvizIcons
|
|
@@ -58,6 +56,7 @@ from modules.histogram import HistogramFrame
|
|
from wxplot.histogram import HistogramPlotFrame
|
|
from wxplot.histogram import HistogramPlotFrame
|
|
from wxplot.profile import ProfileFrame
|
|
from wxplot.profile import ProfileFrame
|
|
from wxplot.scatter import ScatterFrame
|
|
from wxplot.scatter import ScatterFrame
|
|
|
|
+from mapdisp.analysis import ProfileController, MeasureDistanceController
|
|
|
|
|
|
from mapdisp import statusbar as sb
|
|
from mapdisp import statusbar as sb
|
|
|
|
|
|
@@ -218,7 +217,7 @@ class MapFrame(SingleMapFrame):
|
|
|
|
|
|
self.decorationDialog = None # decoration/overlays
|
|
self.decorationDialog = None # decoration/overlays
|
|
|
|
|
|
- self.measureController = None
|
|
|
|
|
|
+ self.measureDistController = None
|
|
|
|
|
|
def GetMapWindow(self):
|
|
def GetMapWindow(self):
|
|
return self.MapWindow
|
|
return self.MapWindow
|
|
@@ -489,12 +488,6 @@ class MapFrame(SingleMapFrame):
|
|
"""
|
|
"""
|
|
self.RemoveQueryLayer()
|
|
self.RemoveQueryLayer()
|
|
|
|
|
|
- # delete tmp lines
|
|
|
|
- if self.MapWindow.mouse["use"] in ("measure",
|
|
|
|
- "profile"):
|
|
|
|
- self.MapWindow.polycoords = []
|
|
|
|
- self.MapWindow.ClearLines()
|
|
|
|
-
|
|
|
|
# deselect features in vdigit
|
|
# deselect features in vdigit
|
|
if self.GetToolbar('vdigit'):
|
|
if self.GetToolbar('vdigit'):
|
|
if self.MapWindow.digit:
|
|
if self.MapWindow.digit:
|
|
@@ -865,20 +858,23 @@ class MapFrame(SingleMapFrame):
|
|
return cmd
|
|
return cmd
|
|
|
|
|
|
def OnMeasure(self, event):
|
|
def OnMeasure(self, event):
|
|
- if not self.measureController:
|
|
|
|
- self.measureController = MeasureController(self._giface)
|
|
|
|
- self.measureController.StartMeasurement()
|
|
|
|
|
|
+ if not self.measureDistController:
|
|
|
|
+ self.measureDistController = MeasureDistanceController(self._giface,
|
|
|
|
+ mapWindow=self.GetMapWindow())
|
|
|
|
+ self.measureDistController.Start()
|
|
|
|
|
|
def OnProfile(self, event):
|
|
def OnProfile(self, event):
|
|
"""!Launch profile tool
|
|
"""!Launch profile tool
|
|
"""
|
|
"""
|
|
|
|
+ self.profileController = ProfileController(self._giface, mapWindow=self.GetMapWindow())
|
|
rasters = []
|
|
rasters = []
|
|
layers = self._giface.GetLayerList().GetSelectedLayers()
|
|
layers = self._giface.GetLayerList().GetSelectedLayers()
|
|
for layer in layers:
|
|
for layer in layers:
|
|
if layer.type == 'raster':
|
|
if layer.type == 'raster':
|
|
rasters.append(layer.maplayer.name)
|
|
rasters.append(layer.maplayer.name)
|
|
|
|
|
|
- win = ProfileFrame(parent = self, mapwindow = self.GetMapWindow(), rasterList = rasters)
|
|
|
|
|
|
+ win = ProfileFrame(parent=self, rasterList=rasters,
|
|
|
|
+ controller=self.profileController)
|
|
|
|
|
|
win.CentreOnParent()
|
|
win.CentreOnParent()
|
|
win.Show()
|
|
win.Show()
|
|
@@ -1202,8 +1198,8 @@ class MapFrame(SingleMapFrame):
|
|
if btn.GetValue():
|
|
if btn.GetValue():
|
|
btn.SetValue(0)
|
|
btn.SetValue(0)
|
|
self.dialogs['legend'].DisconnectResizing()
|
|
self.dialogs['legend'].DisconnectResizing()
|
|
- if self.measureController and self.measureController.IsMeasuring():
|
|
|
|
- self.measureController.StopMeasurement(restore=False)
|
|
|
|
|
|
+ if self.measureDistController and self.measureDistController.IsActive():
|
|
|
|
+ self.measureDistController.Stop(restore=False)
|
|
|
|
|
|
def ResetPointer(self):
|
|
def ResetPointer(self):
|
|
"""Sets pointer mode.
|
|
"""Sets pointer mode.
|
|
@@ -1217,166 +1213,3 @@ class MapFrame(SingleMapFrame):
|
|
toolbar.action['id'] = vars(toolbar)["pointer"]
|
|
toolbar.action['id'] = vars(toolbar)["pointer"]
|
|
toolbar.OnTool(None)
|
|
toolbar.OnTool(None)
|
|
self.OnPointer(event=None)
|
|
self.OnPointer(event=None)
|
|
-
|
|
|
|
-
|
|
|
|
-class MeasureController:
|
|
|
|
- """!Class controls measuring in map display."""
|
|
|
|
- def __init__(self, giface):
|
|
|
|
- self._giface = giface
|
|
|
|
- self._mapWindow = self._giface.GetMapWindow()
|
|
|
|
- self._projInfo = self._mapWindow.Map.projinfo
|
|
|
|
- self._measureGraphics = None
|
|
|
|
-
|
|
|
|
- self._totaldist = 0.0 # total measured distance
|
|
|
|
-
|
|
|
|
- self._oldMouseUse = None
|
|
|
|
- self._oldCursor = None
|
|
|
|
-
|
|
|
|
- self._useCtypes = False
|
|
|
|
-
|
|
|
|
- def IsMeasuring(self):
|
|
|
|
- """!Returns True if measuring mode is enabled, otherwise False"""
|
|
|
|
- return bool(self._measureGraphics)
|
|
|
|
-
|
|
|
|
- def _startMeasurement(self, x, y):
|
|
|
|
- """!Handles the actual start of measuring
|
|
|
|
- and adding each new point.
|
|
|
|
-
|
|
|
|
- @param x,y east north coordinates
|
|
|
|
- """
|
|
|
|
- if not self._measureGraphics.GetAllItems():
|
|
|
|
- item = self._measureGraphics.AddItem(coords=[[x, y]])
|
|
|
|
- item.SetPropertyVal('penName', 'measure')
|
|
|
|
- else:
|
|
|
|
- # needed to switch mouse begin and end to draw intermediate line properly
|
|
|
|
- coords = self._measureGraphics.GetItem(0).GetCoords()[-1]
|
|
|
|
- self._mapWindow.mouse['begin'] = self._mapWindow.Cell2Pixel(coords)
|
|
|
|
-
|
|
|
|
- def _addMeasurement(self, x, y):
|
|
|
|
- """!New point added.
|
|
|
|
-
|
|
|
|
- @param x,y east north coordinates
|
|
|
|
- """
|
|
|
|
- # add new point and calculate distance
|
|
|
|
- item = self._measureGraphics.GetItem(0)
|
|
|
|
- coords = item.GetCoords() + [[x, y]]
|
|
|
|
- item.SetCoords(coords)
|
|
|
|
- self.MeasureDist(coords[-2], coords[-1])
|
|
|
|
- # draw
|
|
|
|
- self._mapWindow.ClearLines()
|
|
|
|
- self._measureGraphics.Draw(pdc=self._mapWindow.pdcTmp)
|
|
|
|
-
|
|
|
|
- def StopMeasurement(self, restore=True):
|
|
|
|
- """!Measure mode is stopped."""
|
|
|
|
- self._mapWindow.ClearLines(pdc=self._mapWindow.pdcTmp)
|
|
|
|
- self._mapWindow.mouse['end'] = self._mapWindow.mouse['begin']
|
|
|
|
- # disconnect mouse events
|
|
|
|
- self._mapWindow.mouseLeftUp.disconnect(self._addMeasurement)
|
|
|
|
- self._mapWindow.mouseDClick.disconnect(self.StopMeasurement)
|
|
|
|
- self._mapWindow.mouseLeftDown.disconnect(self._startMeasurement)
|
|
|
|
- # unregister
|
|
|
|
- self._mapWindow.UnregisterGraphicsToDraw(self._measureGraphics)
|
|
|
|
- self._measureGraphics = None
|
|
|
|
- self._mapWindow.Refresh()
|
|
|
|
-
|
|
|
|
- if restore:
|
|
|
|
- # restore mouse['use'] and cursor to the state before measuring starts
|
|
|
|
- self._mapWindow.SetNamedCursor(self._oldCursor)
|
|
|
|
- self._mapWindow.mouse['use'] = self._oldMouseUse
|
|
|
|
-
|
|
|
|
- self._giface.WriteCmdLog(_('Measuring finished'))
|
|
|
|
-
|
|
|
|
- def StartMeasurement(self):
|
|
|
|
- """!Init measurement routine that calculates map distance
|
|
|
|
- along transect drawn on map display
|
|
|
|
- """
|
|
|
|
- self._totaldist = 0.0 # total measured distance
|
|
|
|
-
|
|
|
|
- self._oldMouseUse = self._mapWindow.mouse['use']
|
|
|
|
- self._oldCursor = self._mapWindow.GetNamedCursor()
|
|
|
|
-
|
|
|
|
- self._measureGraphics = self._mapWindow.RegisterGraphicsToDraw(graphicsType='line')
|
|
|
|
-
|
|
|
|
- self._mapWindow.mouseLeftDown.connect(self._startMeasurement)
|
|
|
|
- self._mapWindow.mouseDClick.connect(self.StopMeasurement)
|
|
|
|
- self._mapWindow.mouseLeftUp.connect(self._addMeasurement)
|
|
|
|
-
|
|
|
|
- # change mouse['box'] and pen to draw line during dragging
|
|
|
|
- # TODO: better soluyion for drawing this line
|
|
|
|
- self._mapWindow.mouse['use'] = None
|
|
|
|
- self._mapWindow.mouse['box'] = "line"
|
|
|
|
- self._mapWindow.pen = wx.Pen(colour='red', width=2, style=wx.SHORT_DASH)
|
|
|
|
-
|
|
|
|
- self._measureGraphics.AddPen('measure', wx.Pen(colour='green', width=2, style=wx.SHORT_DASH) )
|
|
|
|
-
|
|
|
|
- # change the cursor
|
|
|
|
- self._mapWindow.SetNamedCursor('pencil')
|
|
|
|
-
|
|
|
|
- # initiating output (and write a message)
|
|
|
|
- # e.g., in Layer Manager switch to output console
|
|
|
|
- # TODO: this should be something like: write important message or write tip
|
|
|
|
- # TODO: mixed 'switching' and message? no, measuring handles 'swithing' on its own
|
|
|
|
- self._giface.WriteWarning(_('Click and drag with left mouse button '
|
|
|
|
- 'to measure.%s'
|
|
|
|
- 'Double click with left button to clear.') % \
|
|
|
|
- (os.linesep))
|
|
|
|
- if self._projInfo['proj'] != 'xy':
|
|
|
|
- mapunits = self._projInfo['units']
|
|
|
|
- self._giface.WriteCmdLog(_('Measuring distance') + ' ('
|
|
|
|
- + mapunits + '):')
|
|
|
|
- else:
|
|
|
|
- self._giface.WriteCmdLog(_('Measuring distance:'))
|
|
|
|
-
|
|
|
|
- if self._projInfo['proj'] == 'll':
|
|
|
|
- try:
|
|
|
|
- import grass.lib.gis as gislib
|
|
|
|
- gislib.G_begin_distance_calculations()
|
|
|
|
- self._useCtypes = True
|
|
|
|
- except ImportError, e:
|
|
|
|
- self._giface.WriteWarning(_('Geodesic distance calculation '
|
|
|
|
- 'is not available.\n'
|
|
|
|
- 'Reason: %s' % e))
|
|
|
|
-
|
|
|
|
- def MeasureDist(self, beginpt, endpt):
|
|
|
|
- """!Calculate distance and print to output window.
|
|
|
|
-
|
|
|
|
- @param beginpt,endpt EN coordinates
|
|
|
|
- """
|
|
|
|
- # move also Distance method?
|
|
|
|
- dist, (north, east) = self._mapWindow.Distance(beginpt, endpt, screen=False)
|
|
|
|
-
|
|
|
|
- dist = round(dist, 3)
|
|
|
|
- mapunits = self._projInfo['units']
|
|
|
|
- if mapunits == 'degrees' and self._useCtypes:
|
|
|
|
- mapunits = 'meters'
|
|
|
|
- d, dunits = units.formatDist(dist, mapunits)
|
|
|
|
-
|
|
|
|
- self._totaldist += dist
|
|
|
|
- td, tdunits = units.formatDist(self._totaldist,
|
|
|
|
- mapunits)
|
|
|
|
-
|
|
|
|
- strdist = str(d)
|
|
|
|
- strtotdist = str(td)
|
|
|
|
-
|
|
|
|
- if self._projInfo['proj'] == 'xy' or 'degree' not in self._projInfo['unit']:
|
|
|
|
- angle = int(math.degrees(math.atan2(north,east)) + 0.5)
|
|
|
|
- # uncomment below (or flip order of atan2(y,x) above) to use
|
|
|
|
- # the mathematical theta convention (CCW from +x axis)
|
|
|
|
- #angle = 90 - angle
|
|
|
|
- if angle < 0:
|
|
|
|
- angle = 360 + angle
|
|
|
|
-
|
|
|
|
- mstring = '%s = %s %s\n%s = %s %s\n%s = %d %s\n%s' \
|
|
|
|
- % (_('segment'), strdist, dunits,
|
|
|
|
- _('total distance'), strtotdist, tdunits,
|
|
|
|
- _('bearing'), angle, _('degrees (clockwise from grid-north)'),
|
|
|
|
- '-' * 60)
|
|
|
|
- else:
|
|
|
|
- mstring = '%s = %s %s\n%s = %s %s\n%s' \
|
|
|
|
- % (_('segment'), strdist, dunits,
|
|
|
|
- _('total distance'), strtotdist, tdunits,
|
|
|
|
- '-' * 60)
|
|
|
|
-
|
|
|
|
- self._giface.WriteLog(mstring, priority=2)
|
|
|
|
-
|
|
|
|
- return dist
|
|
|