Browse Source

wxGUI animation: allow to use saved region for animation instead of comp region (#656)

Anna Petrasova 4 years ago
parent
commit
dc3c4c7228

+ 4 - 6
gui/wxpython/animation/controller.py

@@ -355,8 +355,7 @@ class AnimationController(wx.EvtHandler):
                     continue
                 anim = [anim for anim in self.animationData
                         if anim.windowIndex == i][0]
-                w, h = self.mapwindows[i].GetClientSize()
-                regions = anim.GetRegions(w, h)
+                regions = anim.GetRegions()
                 self.animations[i].SetFrames(
                     [HashCmds(cmdList, region) for cmdList,
                      region in zip(anim.cmdMatrix, regions)])
@@ -368,8 +367,7 @@ class AnimationController(wx.EvtHandler):
                     continue
                 anim = [anim for anim in self.animationData
                         if anim.windowIndex == i][0]
-                w, h = self.mapwindows[i].GetClientSize()
-                regions = anim.GetRegions(w, h)
+                regions = anim.GetRegions()
                 identifiers = sampleCmdMatrixAndCreateNames(
                     anim.cmdMatrix, mapNamesDict[
                         anim.firstStdsNameType[0]], regions)
@@ -413,8 +411,8 @@ class AnimationController(wx.EvtHandler):
         opacities = [
             layer.opacity for layer in animationData.layerList
             if layer.active]
-        w, h = self.mapwindows[animationData.GetWindowIndex()].GetClientSize()
-        regions = animationData.GetRegions(w, h)
+        #w, h = self.mapwindows[animationData.GetWindowIndex()].GetClientSize()
+        regions = animationData.GetRegions()
         self.bitmapProvider.SetCmds(
             animationData.cmdMatrix, opacities, regions)
 

+ 21 - 25
gui/wxpython/animation/data.py

@@ -213,33 +213,35 @@ class AnimationData(object):
         fset=SetZoomRegionValue,
         fget=GetZoomRegionValue)
 
-    def GetRegions(self, width, height):
-        self._computeRegions(width, height, self._mapCount, self._startRegion,
+    def GetRegions(self):
+        self._computeRegions(self._mapCount, self._startRegion,
                              self._endRegion, self._zoomRegionValue)
         return self._regions
 
     def _computeRegions(
-            self, width, height, count, startRegion, endRegion=None,
+            self, count, startRegion, endRegion=None,
             zoomValue=None):
         """Computes regions based on start region and end region or zoom value
         for each of the animation frames."""
-        currRegion = dict(
-            gcore.region())  # cast to dict, otherwise deepcopy error
-        del currRegion['cells']
-        del currRegion['cols']
-        del currRegion['rows']
-        if 'projection' in currRegion:
-            del currRegion['projection']
-        if 'zone' in currRegion:
-            del currRegion['zone']
+        region = dict(gcore.region())  # cast to dict, otherwise deepcopy error
+        if startRegion:
+            region = dict(parse_key_val(gcore.read_command('g.region',
+                                                           flags='gu',
+                                                           region=startRegion),
+                                        val_type=float))
+
+        del region['cells']
+        del region['cols']
+        del region['rows']
+        if 'projection' in region:
+            del region['projection']
+        if 'zone' in region:
+            del region['zone']
         regions = []
         for i in range(self._mapCount):
-            if endRegion or zoomValue:
-                regions.append(copy.copy(currRegion))
-            else:
-                regions.append(None)
-        if not startRegion:
-            self._regions = regions
+            regions.append(copy.copy(region))
+        self._regions = regions
+        if not (endRegion or zoomValue):
             return
 
         startRegionDict = parse_key_val(
@@ -255,7 +257,7 @@ class AnimationData(object):
                     flags='gu',
                     region=endRegion),
                 val_type=float)
-            for key in ('n', 's', 'e', 'w'):
+            for key in ('n', 's', 'e', 'w', 'nsres', 'ewres'):
                 values = interpolate(
                     startRegionDict[key],
                     endRegionDict[key],
@@ -275,12 +277,6 @@ class AnimationData(object):
                    regions[i]['e'] < regions[i]['w']:
                     regions[i] = regions[i - 1]
 
-        for region in regions:
-            mapwidth = abs(region['e'] - region['w'])
-            mapheight = abs(region['n'] - region['s'])
-            region['nsres'] = mapheight / height
-            region['ewres'] = mapwidth / width
-
         self._regions = regions
 
     def __repr__(self):

+ 43 - 18
gui/wxpython/animation/dialogs.py

@@ -558,11 +558,12 @@ class InputDialog(wx.Dialog):
         mainSizer = wx.BoxSizer(wx.VERTICAL)
         box = StaticBox(
             parent=panel, label=" %s " %
-            _("Animate region change (2D view only)"))
+            _("Set spatial extent in 2D view"))
         sizer = wx.StaticBoxSizer(box, wx.VERTICAL)
 
         gridSizer = wx.GridBagSizer(hgap=3, vgap=3)
-        gridSizer.Add(StaticText(panel, label=_("Start region:")),
+        self.stRegionLabel = StaticText(panel, label=_("Use saved region:"))
+        gridSizer.Add(self.stRegionLabel,
                       pos=(0, 0), flag=wx.ALIGN_CENTER_VERTICAL)
         self.stRegion = Select(parent=panel, type='region', size=(200, -1))
         if self.animationData.startRegion:
@@ -571,17 +572,22 @@ class InputDialog(wx.Dialog):
             self.stRegion, pos=(0, 1),
             flag=wx.ALIGN_CENTER_VERTICAL | wx.EXPAND)
 
+        self.animateRegionCheckbox = CheckBox(panel, label=_("Animate region change"))
+        self.animateRegionCheckbox.SetValue(False)
+        gridSizer.Add(self.animateRegionCheckbox, pos=(1, 0), span=(1, 2), flag=wx.EXPAND)
+        self.animateRegionCheckbox.Bind(wx.EVT_CHECKBOX, lambda evt: self._onAnimateExtent())
+
         self.endRegRadio = RadioButton(
             panel, label=_("End region:"), style=wx.RB_GROUP)
-        gridSizer.Add(self.endRegRadio, pos=(1, 0), flag=wx.EXPAND)
+        gridSizer.Add(self.endRegRadio, pos=(2, 0),  border=10, flag=wx.EXPAND | wx.LEFT)
         self.endRegion = Select(parent=panel, type='region', size=(200, -1))
         gridSizer.Add(
-            self.endRegion, pos=(1, 1),
+            self.endRegion, pos=(2, 1),
             flag=wx.ALIGN_CENTER_VERTICAL | wx.EXPAND)
         self.zoomRadio = RadioButton(panel, label=_("Zoom value:"))
         self.zoomRadio.SetToolTip(_("N-S/E-W distances in map units used to "
                                     "gradually reduce region."))
-        gridSizer.Add(self.zoomRadio, pos=(2, 0), flag=wx.EXPAND)
+        gridSizer.Add(self.zoomRadio, pos=(3, 0), border=10, flag=wx.EXPAND | wx.LEFT)
 
         zoomSizer = wx.BoxSizer(wx.HORIZONTAL)
         self.zoomNS = TextCtrl(panel, validator=FloatValidator())
@@ -593,13 +599,15 @@ class InputDialog(wx.Dialog):
                       flag=wx.ALIGN_CENTER_VERTICAL | wx.LEFT, border=3)
         zoomSizer.Add(self.zoomEW, proportion=1, flag=wx.LEFT, border=3)
         gridSizer.Add(
-            zoomSizer, pos=(2, 1),
+            zoomSizer, pos=(3, 1),
             flag=wx.ALIGN_CENTER_VERTICAL | wx.EXPAND)
         if self.animationData.endRegion:
+            self.animateRegionCheckbox.SetValue(True)
             self.endRegRadio.SetValue(True)
             self.zoomRadio.SetValue(False)
             self.endRegion.SetValue(self.animationData.endRegion)
         if self.animationData.zoomRegionValue:
+            self.animateRegionCheckbox.SetValue(True)
             self.endRegRadio.SetValue(False)
             self.zoomRadio.SetValue(True)
             zoom = self.animationData.zoomRegionValue
@@ -612,7 +620,7 @@ class InputDialog(wx.Dialog):
         self.zoomRadio.Bind(
             wx.EVT_RADIOBUTTON,
             lambda evt: self._enableRegionWidgets())
-        self._enableRegionWidgets()
+        self._onAnimateExtent()
 
         gridSizer.AddGrowableCol(1)
         sizer.Add(gridSizer, proportion=0, flag=wx.EXPAND | wx.ALL, border=3)
@@ -623,6 +631,16 @@ class InputDialog(wx.Dialog):
 
         return panel
 
+    def _onAnimateExtent(self):
+        checked = self.animateRegionCheckbox.IsChecked()
+        self.endRegion.Enable(checked)
+        self.zoomNS.Enable(checked)
+        self.zoomEW.Enable(checked)
+        self.zoomRadio.Enable(checked)
+        self.endRegRadio.Enable(checked)
+        if checked:
+            self._enableRegionWidgets()
+
     def _enableRegionWidgets(self):
         """Enables/disables region widgets
         according to which radiobutton is active."""
@@ -645,7 +663,8 @@ class InputDialog(wx.Dialog):
                     child_.GetWindow().Enable(mode != 1)
             elif child.IsWindow():
                 child.GetWindow().Enable(mode != 1)
-        self._enableRegionWidgets()
+        if mode == 0:
+            self._onAnimateExtent()
 
         # update layout
         sizer = self.threeDPanel.GetContainingSizer()
@@ -721,23 +740,29 @@ class InputDialog(wx.Dialog):
         isEnd = self.endRegRadio.GetValue() and self.endRegion.GetValue()
         isZoom = self.zoomRadio.GetValue() and self.zoomNS.GetValue() and self.zoomEW.GetValue()
         isStart = self.stRegion.GetValue()
-        condition = bool(isStart) + bool(isZoom) + bool(isEnd)
-        if condition == 1:
-            raise GException(_("Region information is not complete"))
-        elif condition == 2:
-            self.animationData.startRegion = isStart
+        useAnim = self.animateRegionCheckbox.GetValue()
+
+        self.animationData.startRegion = None
+        self.animationData.endRegion = None
+        self.animationData.zoomRegionValue = None
+        if not useAnim:
+            if isStart:
+                self.animationData.startRegion = isStart
+        else:
+            if isStart:
+                self.animationData.startRegion = isStart
+            else:
+                raise GException(_("Region information is not complete"))
             if isEnd:
                 self.animationData.endRegion = self.endRegion.GetValue()
                 self.animationData.zoomRegionValue = None
-            else:
+            elif isZoom:
                 self.animationData.zoomRegionValue = (
                     float(self.zoomNS.GetValue()),
                     float(self.zoomEW.GetValue()))
                 self.animationData.endRegion = None
-        else:
-            self.animationData.startRegion = None
-            self.animationData.endRegion = None
-            self.animationData.zoomRegionValue = None
+            else:
+                raise GException(_("Region information is not complete"))
 
     def UnInit(self):
         self.simpleLmgr.UnInit()

+ 4 - 1
gui/wxpython/animation/utils.py

@@ -384,9 +384,12 @@ def interpolate(start, end, count):
         while start < end:
             values.append(start)
             start += step
-    else:
+    elif end < start:
         while end < start:
             values.append(start)
             start += step
+    else:
+        values = [start] * (count - 1)
     values.append(end)
+
     return values