[GRASS-SVN] r50840 - in grass/branches/develbranch_6/gui/wxpython:
. docs psmap
svn_grass at osgeo.org
svn_grass at osgeo.org
Fri Feb 17 01:45:00 EST 2012
Author: annakrat
Date: 2012-02-16 22:45:00 -0800 (Thu, 16 Feb 2012)
New Revision: 50840
Added:
grass/branches/develbranch_6/gui/wxpython/psmap/instructions.py
grass/branches/develbranch_6/gui/wxpython/psmap/utils.py
Modified:
grass/branches/develbranch_6/gui/wxpython/docs/wxGUI.PsMap.html
grass/branches/develbranch_6/gui/wxpython/psmap/dialogs.py
grass/branches/develbranch_6/gui/wxpython/psmap/frame.py
grass/branches/develbranch_6/gui/wxpython/psmap/toolbars.py
grass/branches/develbranch_6/gui/wxpython/wxpythonlib.dox
Log:
wxGUI/wxpsmap: backport of recent changes from trunk (r50797, r50798, r50829, r50836)
Modified: grass/branches/develbranch_6/gui/wxpython/docs/wxGUI.PsMap.html
===================================================================
--- grass/branches/develbranch_6/gui/wxpython/docs/wxGUI.PsMap.html 2012-02-17 00:41:01 UTC (rev 50839)
+++ grass/branches/develbranch_6/gui/wxpython/docs/wxGUI.PsMap.html 2012-02-17 06:45:00 UTC (rev 50840)
@@ -43,6 +43,9 @@
<li> text
<li> scalebar
<li> mapinfo
+ <li> point
+ <li> line
+ <li> rectangle
</ul>
Modified: grass/branches/develbranch_6/gui/wxpython/psmap/dialogs.py
===================================================================
--- grass/branches/develbranch_6/gui/wxpython/psmap/dialogs.py 2012-02-17 00:41:01 UTC (rev 50839)
+++ grass/branches/develbranch_6/gui/wxpython/psmap/dialogs.py 2012-02-17 06:45:00 UTC (rev 50840)
@@ -1,28 +1,12 @@
"""!
@package psmap.dialogs
- at brief Map feature objects and dialogs for wxPsMap
+ at brief dialogs for wxPsMap
Classes:
- - dialogs::UnitConversion
- dialogs::TCValidator
- dialogs::PenStyleComboBox
- dialogs::CheckListCtrl
- - dialogs::Instruction
- - dialogs::InstructionObject
- - dialogs::InitMap
- - dialogs::MapFrame
- - dialogs::PageSetup
- - dialogs::Mapinfo
- - dialogs::Text
- - dialogs::Image
- - dialogs::NorthArrow
- - dialogs::Scalebar
- - dialogs::RasterLegend
- - dialogs::VectorLegend
- - dialogs::Raster
- - dialogs::Vector
- - dialogs::VProperties
- dialogs::PsmapDialog
- dialogs::PageSetupDialog
- dialogs::MapDialog
@@ -38,8 +22,10 @@
- dialogs::TextDialog
- dialogs::ImageDialog
- dialogs::NorthArrowDialog
+ - dialogs::PointDialog
+ - dialogs::RectangleDialog
-(C) 2011 by Anna Kratochvilova, and the GRASS Development Team
+(C) 2011-2012 by Anna Kratochvilova, and the GRASS Development Team
This program is free software under the GNU General Public License
(>=v2). Read the file COPYING that comes with GRASS for details.
@@ -51,14 +37,7 @@
import os
import sys
import string
-from math import ceil, floor, sin, cos, pi
from copy import deepcopy
-from time import strftime, localtime
-try:
- import Image as PILImage
- havePILImage = True
-except ImportError:
- havePILImage = False
import wx
import wx.lib.scrolledpanel as scrolled
@@ -72,71 +51,20 @@
import grass.script as grass
-from core import globalvar
-from dbmgr.vinfo import VectorDBInfo
-from core.utils import CmdToTuple, GetCmdString
-from gui_core.gselect import Select
-from core.gcmd import RunCommand, GError, GMessage, GWarning
-from gui_core.dialogs import SymbolDialog
+from core import globalvar
+from dbmgr.vinfo import VectorDBInfo
+from gui_core.gselect import Select
+from core.gcmd import RunCommand, GError, GMessage
+from gui_core.dialogs import SymbolDialog
+from psmap.utils import *
+from psmap.instructions import *
# grass.set_raise_on_error(True)
PSMAP_COLORS = ['aqua', 'black', 'blue', 'brown', 'cyan', 'gray', 'grey', 'green', 'indigo',
'magenta','orange', 'purple', 'red', 'violet', 'white', 'yellow']
-class UnitConversion:
- """! Class for converting units"""
- def __init__(self, parent = None):
- self.parent = parent
- if self.parent:
- ppi = wx.ClientDC(self.parent).GetPPI()
- else:
- ppi = (72, 72)
- self._unitsPage = { 'inch' : {'val': 1.0, 'tr' : _("inch")},
- 'point' : {'val': 72.0, 'tr' : _("point")},
- 'centimeter' : {'val': 2.54, 'tr' : _("centimeter")},
- 'millimeter' : {'val': 25.4, 'tr' : _("millimeter")}}
- self._unitsMap = { 'meters' : {'val': 0.0254, 'tr' : _("meters")},
- 'kilometers' : {'val': 2.54e-5, 'tr' : _("kilometers")},
- 'feet' : {'val': 1./12, 'tr' : _("feet")},
- 'miles' : {'val': 1./63360, 'tr' : _("miles")},
- 'nautical miles': {'val': 1/72913.386, 'tr' : _("nautical miles")}}
-
- self._units = { 'pixel' : {'val': ppi[0], 'tr' : _("pixel")},
- 'meter' : {'val': 0.0254, 'tr' : _("meter")},
- 'nautmiles' : {'val': 1/72913.386, 'tr' :_("nautical miles")},
- 'degrees' : {'val': 0.0254 , 'tr' : _("degree")} #like 1 meter, incorrect
- }
- self._units.update(self._unitsPage)
- self._units.update(self._unitsMap)
-
- def getPageUnitsNames(self):
- return sorted(self._unitsPage[unit]['tr'] for unit in self._unitsPage.keys())
- def getMapUnitsNames(self):
- return sorted(self._unitsMap[unit]['tr'] for unit in self._unitsMap.keys())
-
- def getAllUnits(self):
- return sorted(self._units.keys())
-
- def findUnit(self, name):
- """!Returns unit by its tr. string"""
- for unit in self._units.keys():
- if self._units[unit]['tr'] == name:
- return unit
- return None
-
- def findName(self, unit):
- """!Returns tr. string of a unit"""
- try:
- return self._units[unit]['tr']
- except KeyError:
- return None
-
- def convert(self, value, fromUnit = None, toUnit = None):
- return float(value)/self._units[fromUnit]['val']*self._units[toUnit]['val']
-
-
class TCValidator(wx.PyValidator):
"""!validates input in textctrls, combobox, taken from wxpython demo"""
def __init__(self, flag = None):
@@ -163,7 +91,7 @@
if key < wx.WXK_SPACE or key == wx.WXK_DELETE or key > 255:
event.Skip()
return
- if self.flag == 'DIGIT_ONLY' and chr(key) in string.digits + '.':
+ if self.flag == 'DIGIT_ONLY' and chr(key) in string.digits + '.-':
event.Skip()
return
## if self.flag == 'SCALE' and chr(key) in string.digits + ':':
@@ -246,1579 +174,7 @@
CheckListCtrlMixin.__init__(self)
ListCtrlAutoWidthMixin.__init__(self)
-class Instruction:
- """!Class which represents instruction file"""
- def __init__(self, parent, objectsToDraw):
-
- self.parent = parent
- self.objectsToDraw = objectsToDraw
- #here are kept objects like mapinfo, rasterlegend, etc.
- self.instruction = list()
-
- def __str__(self):
- """!Returns text for instruction file"""
- comment = "# timestamp: " + strftime("%Y-%m-%d %H:%M", localtime()) + '\n'
- env = grass.gisenv()
- comment += "# location: %s\n" % env['LOCATION_NAME']
- comment += "# mapset: %s\n" % env['MAPSET']
- comment += "# page orientation: %s\n" % self.FindInstructionByType('page')['Orientation']
- border = ''
- if not self.FindInstructionByType('map'):
- border = 'border n\n'
- text = [str(each) for each in self.instruction]
- return comment + border + '\n'.join(text) + '\nend'
-
- def __getitem__(self, id):
- for each in self.instruction:
- if each.id == id:
- return each
- return None
- def __contains__(self, id):
- """!Test if instruction is included"""
- for each in self.instruction:
- if each.id == id:
- return True
- return False
-
- def __delitem__(self, id):
- """!Delete instruction"""
- for each in self.instruction:
- if each.id == id:
- if each.type == 'map':
- #must remove raster, vector layers too
- vektor = self.FindInstructionByType('vector', list = True)
- vProperties = self.FindInstructionByType('vProperties', list = True)
- raster = self.FindInstructionByType('raster', list = True)
- for item in vektor + vProperties + raster:
- if item in self.instruction:
- self.instruction.remove(item)
-
- self.instruction.remove(each)
- if id in self.objectsToDraw:
- self.objectsToDraw.remove(id)
- return
-
- def AddInstruction(self, instruction):
- """!Add instruction"""
- # add to instructions
- if instruction.type == 'map':
- self.instruction.insert(0, instruction)
- else:
- self.instruction.append(instruction)
- # add to drawable objects
- if instruction.type not in ('page', 'raster', 'vector', 'vProperties', 'initMap'):
- if instruction.type == 'map':
- self.objectsToDraw.insert(0, instruction.id)
- else:
- self.objectsToDraw.append(instruction.id)
-
-
- def FindInstructionByType(self, type, list = False):
- """!Find instruction(s) with the given type"""
- inst = []
- for each in self.instruction:
- if each.type == type:
- inst.append(each)
- if len(inst) == 1 and not list:
- return inst[0]
- return inst
-
- def Read(self, filename):
- """!Reads instruction file and creates instruction objects"""
- self.filename = filename
- # open file
- try:
- file = open(filename, 'r')
- except IOError:
- GError(message = _("Unable to open file\n%s") % filename)
- return
- # first read file to get information about region and scaletype
- isRegionComment = False
- orientation = 'Portrait'
- for line in file:
- if '# g.region' in line:
- self.SetRegion(regionInstruction = line)
- isRegionComment = True
- break
- if '# page orientation' in line:
- orientation = line.split(':')[-1].strip()
-
- if not isRegionComment:
- self.SetRegion(regionInstruction = None)
- # then run ps.map -b to get information for maploc
- # compute scale and center
- map = self.FindInstructionByType('map')
- region = grass.region()
- map['center'] = (region['n'] + region['s']) / 2, (region['w'] + region['e']) / 2
- mapRect = GetMapBounds(self.filename, portrait = (orientation == 'Portrait'))
- map['rect'] = mapRect
- proj = projInfo()
- toM = 1.0
- if proj['units']:
- toM = float(proj['meters'])
- units = UnitConversion(self.parent)
- w = units.convert(value = mapRect.Get()[2], fromUnit = 'inch', toUnit = 'meter') / toM
- map['scale'] = w / abs((region['w'] - region['e']))
-
- SetResolution(dpi = 300, width = map['rect'].width, height = map['rect'].height)
-
- # read file again, now with information about map bounds
- isBuffer = False
- buffer = []
- instruction = None
- vectorMapNumber = 1
- file.seek(0)
- for line in file:
- if not line.strip():
- continue
- line = line.strip()
- if isBuffer:
- buffer.append(line)
- if 'end' in line:
- isBuffer = False
- kwargs = {}
- if instruction == 'scalebar':
- kwargs['scale'] = map['scale']
- elif instruction in ('text', 'eps'):
- kwargs['mapInstruction'] = map
- elif instruction in ('vpoints', 'vlines', 'vareas'):
- kwargs['id'] = wx.NewId()
- kwargs['vectorMapNumber'] = vectorMapNumber
- vectorMapNumber += 1
- elif instruction == 'paper':
- kwargs['Orientation'] = orientation
-
- ok = self.SendToRead(instruction, buffer, **kwargs)
- if not ok: return False
- buffer = []
- continue
-
- elif line.startswith('paper'):
- instruction = 'paper'
- isBuffer = True
- buffer.append(line)
-
- elif line.startswith('border'):
- if line.split()[1].lower() in ('n', 'no', 'none'):
- ok = self.SendToRead('border', [line])
- if not ok: return False
- elif line.split()[1].lower() in ('y', 'yes'):
- instruction = 'border'
- isBuffer = True
- buffer.append(line)
-
- elif line.startswith('scale '):
- if isBuffer:
- continue
- ok = self.SendToRead('scale', line, isRegionComment = isRegionComment)
- if not ok: return False
-
- elif line.startswith('maploc'):
- ok = self.SendToRead(instruction = 'maploc', text = line)
- if not ok: return False
-
- elif line.startswith('raster'):
- ok = self.SendToRead(instruction = 'raster', text = line)
- if not ok: return False
-
- elif line.startswith('mapinfo'):
- instruction = 'mapinfo'
- isBuffer = True
- buffer.append(line)
-
-
- elif line.startswith('scalebar'):
- instruction = 'scalebar'
- isBuffer = True
- buffer.append(line)
-
- elif line.startswith('text'):
- instruction = 'text'
- isBuffer = True
- buffer.append(line)
-
- elif line.startswith('eps'):
- instruction = 'eps'
- isBuffer = True
- buffer.append(line)
-
- elif line.startswith('colortable'):
- if len(line.split()) == 2 and line.split()[1].lower() in ('n', 'no', 'none'):
- break
- instruction = 'colortable'
- isBuffer = True
- buffer.append(line)
-
- elif line.startswith('vlegend'):
- instruction = 'vlegend'
- isBuffer = True
- buffer.append(line)
-
- elif line.startswith('vpoints'):
- instruction = 'vpoints'
- isBuffer = True
- buffer.append(line)
-
- elif line.startswith('vlines'):
- instruction = 'vlines'
- isBuffer = True
- buffer.append(line)
-
- elif line.startswith('vareas'):
- instruction = 'vareas'
- isBuffer = True
- buffer.append(line)
-
-
-
- rasterLegend = self.FindInstructionByType('rasterLegend')
- raster = self.FindInstructionByType('raster')
- page = self.FindInstructionByType('page')
- vector = self.FindInstructionByType('vector')
- vectorLegend = self.FindInstructionByType('vectorLegend')
- vectorMaps = self.FindInstructionByType('vProperties', list = True)
-
- # check (in case of scaletype 0) if map is drawn also
- map['drawMap'] = False
- if map['scaleType'] == 0:
- mapForRegion = map['map']
- if map['mapType'] == 'raster' and raster:
- if mapForRegion == raster['raster']:
- map['drawMap'] = True
- elif map['mapType'] == 'vector' and vector:
- for vmap in vector['list']:
- if mapForRegion == vmap[0]:
- map['drawMap'] = True
-
- # rasterLegend
- if rasterLegend:
- if rasterLegend['rasterDefault'] and raster:
- rasterLegend['raster'] = raster['raster']
- if not rasterLegend['discrete']:
- rasterType = getRasterType(map = rasterLegend['raster'])
- if rasterType == 'CELL':
- rasterLegend['discrete'] = 'y'
- else:
- rasterLegend['discrete'] = 'n'
-
- #estimate size
- height = rasterLegend.EstimateHeight(raster = rasterLegend['raster'], discrete = rasterLegend['discrete'],
- fontsize = rasterLegend['fontsize'],
- cols = rasterLegend['cols'],
- height = rasterLegend['height'])
- width = rasterLegend.EstimateWidth(raster = rasterLegend['raster'], discrete = rasterLegend['discrete'],
- fontsize = rasterLegend['fontsize'],
- cols = rasterLegend['cols'] ,
- width = rasterLegend['width'],
- paperInstr = page)
- rasterLegend['rect'] = wx.Rect2D(x = float(rasterLegend['where'][0]), y = float(rasterLegend['where'][1]),
- w = width, h = height)
-
- # vectors, vlegend
-
- if vector:
- for vmap in vectorMaps:
- for i, each in enumerate(vector['list']):
- if each[2] == vmap.id:
-
- vector['list'][i][4] = vmap['label']
- vector['list'][i][3] = vmap['lpos']
- if vectorLegend:
- size = vectorLegend.EstimateSize(vectorInstr = vector, fontsize = vectorLegend['fontsize'],
- width = vectorLegend['width'], cols = vectorLegend['cols'])
- vectorLegend['rect'] = wx.Rect2D(x = float(vectorLegend['where'][0]), y = float(vectorLegend['where'][1]),
- w = size[0], h = size[1])
-
-
- page = self.FindInstructionByType('page')
- if not page:
- page = PageSetup(wx.NewId())
- self.AddInstruction(page)
- else:
- page['Orientation'] = orientation
-
-
- #
- return True
-
- def SendToRead(self, instruction, text, **kwargs):
- psmapInstrDict = dict(paper = ['page'],
- maploc = ['map'],
- scale = ['map'],
- border = ['map'],
- raster = ['raster'],
- mapinfo = ['mapinfo'],
- scalebar = ['scalebar'],
- text = ['text'],
- eps = ['image', 'northArrow'],
- vpoints = ['vector', 'vProperties'],
- vlines = ['vector', 'vProperties'],
- vareas = ['vector', 'vProperties'],
- colortable = ['rasterLegend'],
- vlegend = ['vectorLegend']
- )
-
- myInstrDict = dict(page = PageSetup,
- map = MapFrame,
- raster = Raster,
- mapinfo = Mapinfo,
- scalebar = Scalebar,
- text = Text,
- image = Image,
- northArrow = NorthArrow,
- rasterLegend = RasterLegend,
- vectorLegend = VectorLegend,
- vector = Vector,
- vProperties = VProperties
- )
-
- myInstruction = psmapInstrDict[instruction]
-
- for i in myInstruction:
- instr = self.FindInstructionByType(i)
- if i in ('text', 'vProperties', 'image', 'northArrow') or not instr:
-
- id = wx.NewId() #!vProperties expect subtype
- if i == 'vProperties':
- id = kwargs['id']
- newInstr = myInstrDict[i](id, subType = instruction[1:])
- elif i in ('image', 'northArrow'):
- commentFound = False
- for line in text:
- if line.find("# north arrow") >= 0:
- commentFound = True
- if i == 'image' and commentFound or \
- i == 'northArrow' and not commentFound:
- continue
- newInstr = myInstrDict[i](id, settings = self)
- else:
- newInstr = myInstrDict[i](id)
- ok = newInstr.Read(instruction, text, **kwargs)
- if ok:
- self.AddInstruction(newInstr)
- else:
- return False
-
- else:
- ok = instr.Read(instruction, text, **kwargs)
-
- if not ok:
- return False
- return True
-
- def SetRegion(self, regionInstruction):
- """!Sets region from file comment or sets current region in case of no comment"""
- map = MapFrame(wx.NewId())
- self.AddInstruction(map)
- if regionInstruction:
- cmd = CmdToTuple(regionInstruction.strip('# ').split())
-
- # define scaleType
- if len(cmd[1]) <= 3:
- if 'rast' in cmd[1]:
- map['scaleType'] = 0
- map['mapType'] = 'raster'
- map['map'] = cmd[1]['rast']
- elif 'vect' in cmd[1]:
- map['scaleType'] = 0
- map['mapType'] = 'vector'
- map['map'] = cmd[1]['vect']
- elif 'region' in cmd[1]:
- map['scaleType'] = 1
- map['region'] = cmd[1]['region']
-
- else:
- map['scaleType'] = 2
- else:
- map['scaleType'] = 2
- grass.del_temp_region()
- region = grass.region()
- grass.use_temp_region()
- cmd = ['g.region', region]
- cmdString = GetCmdString(cmd).replace('g.region', '')
- GMessage(_("Instruction file will be loaded with following region: %s\n") % cmdString)
- try:
- RunCommand(cmd[0], **cmd[1])
-
- except grass.ScriptError, e:
- GError(_("Region cannot be set\n%s") % e)
- return False
-
-
-class InstructionObject:
- """!Abtract class representing single instruction"""
- def __init__(self, id):
- self.id = id
-
- # default values
- self.defaultInstruction = dict()
- # current values
- self.instruction = self.defaultInstruction
- # converting units
- self.unitConv = UnitConversion()
-
- def __str__(self):
- """!Returns particular part of text instruction"""
- return ''
-
- def __getitem__(self, key):
- for each in self.instruction.keys():
- if each == key:
- return self.instruction[key]
- return None
-
- def __setitem__(self, key, value):
- self.instruction[key] = value
-
- def GetInstruction(self):
- """!Get current values"""
- return self.instruction
-
- def SetInstruction(self, instruction):
- """!Set default values"""
- self.instruction = instruction
-
- def Read(self, instruction, text, **kwargs):
- """!Read instruction and save them"""
- pass
-
-class InitMap(InstructionObject):
- """!Class representing virtual map"""
- def __init__(self, id):
- InstructionObject.__init__(self, id = id)
- self.type = 'initMap'
-
- # default values
- self.defaultInstruction = dict(rect = None, scale = None)
- # current values
- self.instruction = dict(self.defaultInstruction)
-
-
-class MapFrame(InstructionObject):
- """!Class representing map (instructions maploc, scale, border)"""
- def __init__(self, id):
- InstructionObject.__init__(self, id = id)
- self.type = 'map'
- # default values
- self.defaultInstruction = dict(map = None, mapType = None, drawMap = True, region = None,
- rect = wx.Rect2D(), scaleType = 0, scale = None, center = None,
- resolution = 300, border = 'y', width = 1, color = '0:0:0')
- # current values
- self.instruction = dict(self.defaultInstruction)
-
- def __str__(self):
- instr = ''
- comment = ''
-
- #region settings
- region = grass.region()
- if self.instruction['scaleType'] == 0: #match map
- map = self.instruction['map']
- if self.instruction['mapType'] == 'raster':
- comment = "# g.region rast=%s nsres=%s ewres=%s\n" % (map, region['nsres'], region['ewres'])
- else:
- comment = "# g.region vect=%s\n" % (map)
- elif self.instruction['scaleType'] == 1:# saved region
- region = self.instruction['region']
- comment = "# g.region region=%s\n" % region
- elif self.instruction['scaleType'] in (2, 3): #current region, fixed scale
- comment = string.Template("# g.region n=$n s=$s e=$e w=$w rows=$rows cols=$cols \n").substitute(**region)
-
- instr += comment
- instr += '\n'
- # maploc
- maplocInstruction = "maploc %.3f %.3f" % (self.instruction['rect'].x, self.instruction['rect'].y)
- if self.instruction['scaleType'] != 3:
- maplocInstruction += " %.3f %.3f"% (self.instruction['rect'].width, self.instruction['rect'].height)
- instr += maplocInstruction
- instr += '\n'
-
- # scale
- if self.instruction['scaleType'] == 3: #fixed scale
- scaleInstruction = "scale 1:%.0f" % (1/self.instruction['scale'])
- instr += scaleInstruction
- instr += '\n'
- # border
- borderInstruction = ''
- if self.instruction['border'] == 'n':
- borderInstruction = "border n"
- else:
- borderInstruction = "border y\n"
- borderInstruction += string.Template(" width $width\n color $color\n").substitute(self.instruction)
- borderInstruction += " end"
- instr += borderInstruction
- instr += '\n'
-
- return instr
-
- def Read(self, instruction, text, **kwargs):
- """!Read instruction and save information"""
- if 'isRegionComment' in kwargs:
- isRegionComment = kwargs['isRegionComment']
- instr = {}
-
- if instruction == 'border':
- for line in text:
- if line.startswith('end'):
- break
- try:
- if line.split()[1].lower() in ('n', 'no', 'none'):
- instr['border'] = 'n'
- break
- elif line.split()[1].lower() in ('y', 'yes'):
- instr['border'] = 'y'
- elif line.startswith('width'):
- instr['width'] = line.split()[1]
- elif line.startswith('color'):
- instr['color'] = line.split()[1]
- except IndexError:
- GError(_("Failed to read instruction %s") % instruction)
- return False
-
- elif instruction == 'scale':
- try:
- scaleText = text.strip('scale ').split(':')[1]
- # when scale instruction given and region comment also, then scaletype is fixed scale
- if not isRegionComment:
- instr['scaleType'] = 2
- else:
- instr['scaleType'] = 3
-
- scale = 1/float(scaleText)
- if abs(scale - self.instruction['scale']) > (0.01 * scale):
- GWarning(_("Scale has changed, old value: %(old)s\nnew value: %(new)s") % \
- { 'old' : scale, 'new' : self.instruction['scale'] })
- except (ValueError, IndexError):
- GError(_("Failed to read instruction %s.\nUse 1:25000 notation.") % instruction)
- return False
-
- elif instruction == 'maploc':
- maploc = text.strip('maploc ').split()
- if len(maploc) >= 2:
- if abs(self.instruction['rect'].Get()[0] - float(maploc[0])) > 0.5 or \
- abs(self.instruction['rect'].Get()[1] - float(maploc[1])) > 0.5:
- GWarning(_("Map frame position changed, old value: %(old1)s %(old2)s\nnew value: %(new1)s %(new2)s") % \
- { 'old1' : maploc[0], 'old2' : maploc[1],
- 'new1' : self.instruction['rect'].Get()[0], 'new2' : self.instruction['rect'].Get()[1] })
-
- #instr['rect'] = wx.Rect2D(float(maploc[0]), float(maploc[1]), self.instruction['rect'][2], self.instruction['rect'][3])
- if len(maploc) == 4:
- if abs(self.instruction['rect'].Get()[2] - float(maploc[2])) > 0.5 or \
- abs(self.instruction['rect'].Get()[3] - float(maploc[3])) > 0.5:
- GWarning(_("Map frame size changed, old value: %(old1)s %(old2)s\nnew value: %(new1)s %(new2)s") % \
- { 'old1' : maploc[2], 'old2' : maploc[3],
- 'new1' : self.instruction['rect'].Get()[2], 'new2' : self.instruction['rect'].Get()[3] })
- #instr['rect'] = wx.Rect2D(*map(float, maploc))
- self.instruction.update(instr)
- return True
-
-class PageSetup(InstructionObject):
- """!Class representing page instruction"""
- def __init__(self, id):
- InstructionObject.__init__(self, id = id)
- self.type = 'page'
- # default values
- self.defaultInstruction = dict(Units = 'inch', Format = 'a4', Orientation = 'Portrait',
- Width = 8.268, Height = 11.693, Left = 0.5, Right = 0.5, Top = 1, Bottom = 1)
- # current values
- self.instruction = dict(self.defaultInstruction)
-
- def __str__(self):
- if self.instruction['Format'] == 'custom':
- instr = string.Template("paper\n width $Width\n height $Height\n").substitute(self.instruction)
- else:
- instr = string.Template("paper $Format\n").substitute(self.instruction)
- instr += string.Template(" left $Left\n right $Right\n bottom $Bottom\n top $Top\n end").substitute(self.instruction)
-
- return instr
-
- def Read(self, instruction, text, **kwargs):
- """!Read instruction and save information"""
- instr = {}
- self.cats = ['Width', 'Height', 'Left', 'Right', 'Top', 'Bottom']
- self.subInstr = dict(zip(['width', 'height', 'left', 'right', 'top', 'bottom'], self.cats))
-
- if instruction == 'paper': # just for sure
- for line in text:
- if line.startswith('paper'):
- if len(line.split()) > 1:
- pformat = line.split()[1]
- availableFormats = self._toDict(grass.read_command('ps.map', flags = 'p',
- quiet = True))
- # e.g. paper a3
- try:
- instr['Format'] = pformat
- for key, value in availableFormats[pformat].iteritems():
- instr[key] = float(value)
- break
- except KeyError:
- GError(_("Failed to read instruction %(file)s.\nUnknown format %(for)s") % \
- { 'file' : instruction, 'for' : format })
- return False
- else:
- # paper
- # width ...
- instr['Format'] = 'custom'
- # read subinstructions
- elif instr['Format'] == 'custom' and not line.startswith('end'):
- text = line.split()
- try:
- instr[self.subInstr[text[0]]] = float(text[1])
- except (IndexError, KeyError):
- GError(_("Failed to read instruction %s.") % instruction)
- return False
-
- if 'Orientation' in kwargs and kwargs['Orientation'] == 'Landscape':
- instr['Width'], instr['Height'] = instr['Height'], instr['Width']
-
- self.instruction.update(instr)
- return True
-
- def _toDict(self, paperStr):
- sizeDict = dict()
-# cats = self.subInstr[ 'Width', 'Height', 'Left', 'Right', 'Top', 'Bottom']
- for line in paperStr.strip().split('\n'):
- d = dict(zip(self.cats, line.split()[1:]))
- sizeDict[line.split()[0]] = d
-
- return sizeDict
-
-class Mapinfo(InstructionObject):
- """!Class representing mapinfo instruction"""
- def __init__(self, id):
- InstructionObject.__init__(self, id = id)
- self.type = 'mapinfo'
- # default values
- self.defaultInstruction = dict(unit = 'inch', where = (0, 0),
- font = 'Helvetica', fontsize = 10, color = '0:0:0', background = 'none',
- border = 'none', rect = None)
- # current values
- self.instruction = dict(self.defaultInstruction)
-
- def __str__(self):
- instr = "mapinfo\n"
- instr += " where %.3f %.3f\n" % (self.instruction['where'][0], self.instruction['where'][1])
- instr += string.Template(" font $font\n fontsize $fontsize\n color $color\n").substitute(self.instruction)
- instr += string.Template(" background $background\n border $border\n").substitute(self.instruction)
- instr += " end"
- return instr
-
- def Read(self, instruction, text):
- """!Read instruction and save information"""
- instr = {}
- try:
- for line in text:
- sub = line.split(None,1)
- if sub[0] == 'font':
- instr['font'] = sub[1]
- elif sub[0] == 'fontsize':
- instr['fontsize'] = int(sub[1])
- elif sub[0] == 'color':
- instr['color'] = sub[1]
- elif sub[0] == 'background':
- instr['background'] = sub[1]
- elif sub[0] == 'border':
- instr['border'] = sub[1]
- elif sub[0] == 'where':
- instr['where'] = float(sub[1].split()[0]), float(sub[1].split()[1])
- except (ValueError, IndexError):
- GError(_("Failed to read instruction %s") % instruction)
- return False
- self.instruction.update(instr)
- self.instruction['rect'] = self.EstimateRect(mapinfoDict = self.instruction)
- return True
-
- def EstimateRect(self, mapinfoDict):
- """!Estimate size to draw mapinfo"""
- w = mapinfoDict['fontsize'] * 20 # any better estimation?
- h = mapinfoDict['fontsize'] * 7
- width = self.unitConv.convert(value = w, fromUnit = 'point', toUnit = 'inch')
- height = self.unitConv.convert(value = h, fromUnit = 'point', toUnit = 'inch')
- return wx.Rect2D(x = float(mapinfoDict['where'][0]), y = float(mapinfoDict['where'][1]), w = width, h = height)
-
-class Text(InstructionObject):
- """!Class representing text instruction"""
- def __init__(self, id):
- InstructionObject.__init__(self, id = id)
- self.type = 'text'
- # default values
- self.defaultInstruction = dict(text = "", font = "Helvetica", fontsize = 10, color = 'black', background = 'none',
- hcolor = 'none', hwidth = 1, border = 'none', width = '1', XY = True,
- where = (0,0), unit = 'inch', rotate = None,
- ref = "center center", xoffset = 0, yoffset = 0, east = None, north = None)
- # current values
- self.instruction = dict(self.defaultInstruction)
-
- def __str__(self):
- text = self.instruction['text'].replace('\n','\\n')
- instr = u"text %s %s" % (self.instruction['east'], self.instruction['north'])
- instr += " %s\n" % text
- instr += (string.Template(" font $font\n fontsize $fontsize\n color $color\n").
- substitute(self.instruction))
- instr += string.Template(" hcolor $hcolor\n").substitute(self.instruction)
- if self.instruction['hcolor'] != 'none':
- instr += string.Template(" hwidth $hwidth\n").substitute(self.instruction)
- instr += string.Template(" border $border\n").substitute(self.instruction)
- if self.instruction['border'] != 'none':
- instr += string.Template(" width $width\n").substitute(self.instruction)
- instr += string.Template(" background $background\n").substitute(self.instruction)
- if self.instruction["ref"] != '0':
- instr += string.Template(" ref $ref\n").substitute(self.instruction)
- if self.instruction["rotate"]:
- instr += string.Template(" rotate $rotate\n").substitute(self.instruction)
- if float(self.instruction["xoffset"]) or float(self.instruction["yoffset"]):
- instr += (string.Template(" xoffset $xoffset\n yoffset $yoffset\n").
- substitute(self.instruction))
- instr += " end"
- try:
- instr = instr.encode('latin1')
- except UnicodeEncodeError, err:
- try:
- print err
- pos = str(err).split('position')[1].split(':')[0].strip()
- except IndexError:
- pos = ''
- if pos:
- message = _("Characters on position %s are not supported "
- "by ISO-8859-1 (Latin 1) encoding "
- "which is required by module ps.map.") % pos
- else:
- message = _("Not all characters are supported "
- "by ISO-8859-1 (Latin 1) encoding "
- "which is required by module ps.map.")
- GMessage(message = message)
- return ''
-
- return instr
-
- def Read(self, instruction, text, **kwargs):
- """!Read instruction and save information"""
- map = kwargs['mapInstruction']
- instr = {}
- for line in text:
- try:
- sub = line.split(None, 1)[0]
- if sub == 'text':
- e, n = line.split(None, 3)[1:3]
- if '%' in e and '%' in n:
- instr['XY'] = True
- instr['east'], instr['north'] = self.PercentToReal(e, n)
- else:
- instr['XY'] = False
- instr['east'], instr['north'] = float(e), float(n)
-
- instr['text'] = line.split(None, 3)[3].decode('latin_1')
-
- elif sub == 'font':
- instr['font'] = line.split(None, 1)[1]
- elif sub == 'fontsize':
- instr['fontsize'] = float(line.split(None, 1)[1])
- elif sub == 'color':
- instr['color'] = line.split(None, 1)[1]
- elif sub == 'width':
- instr['width'] = line.split(None, 1)[1]
- elif sub == 'hcolor':
- instr['hcolor'] = line.split(None, 1)[1]
- elif sub == 'hwidth':
- instr['hwidth'] = line.split(None, 1)[1]
- elif sub == 'background':
- instr['background'] = line.split(None, 1)[1]
- elif sub == 'border':
- instr['border'] = line.split(None, 1)[1]
- elif sub == 'ref':
- instr['ref'] = line.split(None, 1)[1]
- elif sub == 'rotate':
- instr['rotate'] = float(line.split(None, 1)[1])
- elif sub == 'xoffset':
- instr['xoffset'] = int(line.split(None, 1)[1])
- elif sub == 'yoffset':
- instr['yoffset'] = int(line.split(None, 1)[1])
- elif sub == 'opaque':
- if line.split(None, 1)[1].lower() in ('n', 'none'):
- instr['background'] = 'none'
-
- except(IndexError, ValueError):
- GError(_("Failed to read instruction %s") % instruction)
- return False
- instr['where'] = PaperMapCoordinates(map = map, x = instr['east'], y = instr['north'], paperToMap = False)
- self.instruction.update(instr)
-
- return True
-
- def PercentToReal(self, e, n):
- """!Converts text coordinates from percent of region to map coordinates"""
- e, n = float(e.strip('%')), float(n.strip('%'))
- region = grass.region()
- N = region['s'] + (region['n'] - region['s']) / 100 * n
- E = region['w'] + (region['e'] - region['w']) / 100 * e
- return E, N
-
-class Image(InstructionObject):
- """!Class representing eps instruction - image"""
- def __init__(self, id, settings):
- InstructionObject.__init__(self, id = id)
- self.settings = settings
- self.type = 'image'
- # default values
- self.defaultInstruction = dict(epsfile = "", XY = True, where = (0,0), unit = 'inch',
- east = None, north = None,
- rotate = None, scale = 1)
- # current values
- self.instruction = dict(self.defaultInstruction)
-
- def __str__(self):
- self.ChangeRefPoint(toCenter = True)
-
- instr = "eps %s %s\n" % (self.instruction['east'], self.instruction['north'])
- instr += string.Template(" epsfile $epsfile\n").substitute(self.instruction)
- if self.instruction["rotate"]:
- instr += string.Template(" rotate $rotate\n").substitute(self.instruction)
- if self.instruction["scale"]:
- instr += string.Template(" scale $scale\n").substitute(self.instruction)
- instr += " end"
- return instr
-
- def Read(self, instruction, text, **kwargs):
- """!Read instruction and save information"""
- mapInstr = kwargs['mapInstruction']
- instr = {}
- for line in text:
- try:
- sub = line.split(None, 1)[0]
- if sub == 'eps':
- e, n = line.split(None, 3)[1:3]
- if '%' in e and '%' in n:
- instr['XY'] = True
- instr['east'], instr['north'] = self.PercentToReal(e, n)
- else:
- instr['XY'] = False
- instr['east'], instr['north'] = float(e), float(n)
-
- elif sub == 'epsfile':
- instr['epsfile'] = line.split(None, 1)[1]
- elif sub == 'rotate':
- instr['rotate'] = float(line.split(None, 1)[1])
- elif sub == 'scale':
- instr['scale'] = float(line.split(None, 1)[1])
-
- except(IndexError, ValueError):
- GError(_("Failed to read instruction %s") % instruction)
- return False
- if not os.path.exists(instr['epsfile']):
- GError(_("Failed to read instruction %(inst)s: "
- "file %(file)s not found.") % { 'inst' : instruction,
- 'file' : instr['epsfile'] })
- return False
-
- instr['epsfile'] = os.path.abspath(instr['epsfile'])
- instr['size'] = self.GetImageOrigSize(instr['epsfile'])
- if 'rotate' in instr:
- instr['size'] = BBoxAfterRotation(instr['size'][0], instr['size'][1], instr['rotate'])
- self.instruction.update(instr)
- self.ChangeRefPoint(toCenter = False)
- instr['where'] = PaperMapCoordinates(map = mapInstr, x = self.instruction['east'],
- y = self.instruction['north'], paperToMap = False)
- w = self.unitConv.convert(value = instr['size'][0], fromUnit = 'point', toUnit = 'inch')
- h = self.unitConv.convert(value = instr['size'][1], fromUnit = 'point', toUnit = 'inch')
- instr['rect'] = wx.Rect2D(x = float(instr['where'][0]), y = float(instr['where'][1]),
- w = w * self.instruction['scale'], h = h * self.instruction['scale'])
- self.instruction.update(instr)
-
- return True
-
- def PercentToReal(self, e, n):
- """!Converts eps coordinates from percent of region to map coordinates"""
- e, n = float(e.strip('%')), float(n.strip('%'))
- region = grass.region()
- N = region['s'] + (region['n'] - region['s']) / 100 * n
- E = region['w'] + (region['e'] - region['w']) / 100 * e
- return E, N
-
- def ChangeRefPoint(self, toCenter):
- """!Change reference point (left top x center)"""
- mapInstr = self.settings.FindInstructionByType('map')
- if not mapInstr:
- mapInstr = self.settings.FindInstructionByType('initMap')
- mapId = mapInstr.id
- if toCenter:
- center = self.instruction['rect'].GetCentre()
- ENCenter = PaperMapCoordinates(map = self.settings[mapId],
- x = center[0], y = center[1], paperToMap = True)
-
- self.instruction['east'], self.instruction['north'] = ENCenter
- else:
- x, y = PaperMapCoordinates(map = self.settings[mapId], x = self.instruction['east'],
- y = self.instruction['north'], paperToMap = False)
- w = self.unitConv.convert(value = self.instruction['size'][0], fromUnit = 'point', toUnit = 'inch')
- h = self.unitConv.convert(value = self.instruction['size'][1], fromUnit = 'point', toUnit = 'inch')
- x -= w * self.instruction['scale'] / 2
- y -= h * self.instruction['scale'] / 2
- e, n = PaperMapCoordinates(map = self.settings[mapId], x = x, y = y, paperToMap = True)
- self.instruction['east'], self.instruction['north'] = e, n
-
- def GetImageOrigSize(self, imagePath):
- """!Get image size.
-
- If eps, size is read from image header.
- """
- fileName = os.path.split(imagePath)[1]
- # if eps, read info from header
- if os.path.splitext(fileName)[1].lower() == '.eps':
- bbInfo = "%%BoundingBox"
- file = open(imagePath,"r")
- w = h = 0
- while file:
- line = file.readline()
- if line.find(bbInfo) == 0:
- w, h = line.split()[3:5]
- break
- file.close()
- return float(w), float(h)
- else: # we can use wx.Image
- img = wx.Image(fileName, type=wx.BITMAP_TYPE_ANY)
- return img.GetWidth(), img.GetHeight()
-
-class NorthArrow(Image):
- """!Class representing eps instruction -- North Arrow"""
- def __init__(self, id, settings):
- Image.__init__(self, id = id, settings = settings)
- self.type = 'northArrow'
-
- def __str__(self):
- self.ChangeRefPoint(toCenter = True)
-
- instr = "eps %s %s\n" % (self.instruction['east'], self.instruction['north'])
- instr += "# north arrow\n"
- instr += string.Template(" epsfile $epsfile\n").substitute(self.instruction)
- if self.instruction["rotate"]:
- instr += string.Template(" rotate $rotate\n").substitute(self.instruction)
- if self.instruction["scale"]:
- instr += string.Template(" scale $scale\n").substitute(self.instruction)
- instr += " end"
- return instr
-
-class Scalebar(InstructionObject):
- """!Class representing scalebar instruction"""
- def __init__(self, id):
- InstructionObject.__init__(self, id = id)
- self.type = 'scalebar'
- # default values
- self.defaultInstruction = dict(unit = 'inch', where = (1,1),
- unitsLength = 'auto', unitsHeight = 'inch',
- length = None, height = 0.1, rect = None,
- fontsize = 10, background = 'y',
- scalebar = 'f', segment = 4, numbers = 1)
- # current values
- self.instruction = dict(self.defaultInstruction)
-
- def __str__(self):
- instr = string.Template("scalebar $scalebar\n").substitute(self.instruction)
- instr += " where %.3f %.3f\n" % (self.instruction['where'][0], self.instruction['where'][1])
- instr += string.Template(" length $length\n units $unitsLength\n").substitute(self.instruction)
- instr += string.Template(" height $height\n").substitute(self.instruction)
- instr += string.Template(" segment $segment\n numbers $numbers\n").substitute(self.instruction)
- instr += string.Template(" fontsize $fontsize\n background $background\n").substitute(self.instruction)
- instr += " end"
- return instr
-
- def Read(self, instruction, text, **kwargs):
- """!Read instruction and save information"""
- scale = kwargs['scale']
- instr = {}
- for line in text:
- try:
- if line.startswith('scalebar'):
- if 'scalebar s' in line:
- instr['scalebar'] = 's'
- else:
- instr['scalebar'] = 'f'
- elif line.startswith('where'):
- instr['where'] = map(float, line.split()[1:3])
- elif line.startswith('length'):
- instr['length'] = float(line.split()[1])
- elif line.startswith('units'):
- if line.split()[1] in ['auto', 'meters', 'kilometers', 'feet', 'miles', 'nautmiles']:
- instr['unitsLength'] = line.split()[1]
- elif line.startswith('height'):
- instr['height'] = float(line.split()[1])
- elif line.startswith('fontsize'):
- instr['fontsize'] = float(line.split()[1])
- elif line.startswith('numbers'):
- instr['numbers'] = int(line.split()[1])
- elif line.startswith('segment'):
- instr['segment'] = int(line.split()[1])
- elif line.startswith('background'):
- if line.split()[1].strip().lower() in ('y','yes'):
- instr['background'] = 'y'
- elif line.split()[1].strip().lower() in ('n','no', 'none'):
- instr['background'] = 'n'
- except(IndexError, ValueError):
- GError(_("Failed to read instruction %s") % instruction)
- return False
-
- self.instruction.update(instr)
- w, h = self.EstimateSize(scalebarDict = self.instruction, scale = scale)
- x = self.instruction['where'][0] - w / 2
- y = self.instruction['where'][1] - h / 2
- self.instruction['rect'] = wx.Rect2D(x, y, w, h)
- return True
-
- def EstimateSize(self, scalebarDict, scale):
- """!Estimate size to draw scalebar"""
- units = projInfo()['units']
- if not units or units not in self.unitConv.getAllUnits():
- units = 'meters'
- if scalebarDict['unitsLength'] != 'auto':
- length = self.unitConv.convert(value = scalebarDict['length'], fromUnit = scalebarDict['unitsLength'], toUnit = 'inch')
- else:
- length = self.unitConv.convert(value = scalebarDict['length'], fromUnit = units, toUnit = 'inch')
-
- length *= scale
- length *= 1.1 #for numbers on the edge
- height = scalebarDict['height'] + 2 * self.unitConv.convert(value = scalebarDict['fontsize'], fromUnit = 'point', toUnit = 'inch')
- return (length, height)
-
-class RasterLegend(InstructionObject):
- """!Class representing colortable instruction"""
- def __init__(self, id):
- InstructionObject.__init__(self, id = id)
- self.type = 'rasterLegend'
- # default values
- self.defaultInstruction = dict(rLegend = False, unit = 'inch', rasterDefault = True, raster = None,
- discrete = None, type = None,
- where = (0, 0),
- width = None, height = None, cols = 1, font = "Helvetica", fontsize = 10,
- #color = '0:0:0', tickbar = False, range = False, min = 0, max = 0,
- color = 'black', tickbar = 'n', range = False, min = 0, max = 0,
- nodata = 'n')
- # current values
- self.instruction = dict(self.defaultInstruction)
-
- def __str__(self):
- instr = "colortable y\n"
- instr += string.Template(" raster $raster\n").substitute(self.instruction)
- instr += " where %.3f %.3f\n" % (self.instruction['where'][0], self.instruction['where'][1])
- if self.instruction['width']:
- instr += string.Template(" width $width\n").substitute(self.instruction)
- instr += string.Template(" discrete $discrete\n").substitute(self.instruction)
- if self.instruction['discrete'] == 'n':
- if self.instruction['height']:
- instr += string.Template(" height $height\n").substitute(self.instruction)
- instr += string.Template(" tickbar $tickbar\n").substitute(self.instruction)
- if self.instruction['range']:
- instr += string.Template(" range $min $max\n").substitute(self.instruction)
- else:
- instr += string.Template(" cols $cols\n").substitute(self.instruction)
- instr += string.Template(" nodata $nodata\n").substitute(self.instruction)
- instr += string.Template(" font $font\n fontsize $fontsize\n color $color\n")\
- .substitute(self.instruction)
- instr += " end"
- return instr
-
-
- def Read(self, instruction, text, **kwargs):
- """!Read instruction and save information"""
- instr = {}
- instr['rLegend'] = True
- for line in text:
- try:
- if line.startswith('where'):
- instr['where'] = map(float, line.split()[1:3])
- elif line.startswith('font '):
- instr['font'] = line.split()[1]
- elif line.startswith('fontsize'):
- instr['fontsize'] = float(line.split()[1])
- elif line.startswith('color '):
- instr['color'] = line.split()[1]
- elif line.startswith('raster'):
- instr['raster'] = line.split()[1]
- elif line.startswith('width'):
- instr['width'] = float(line.split()[1])
- elif line.startswith('height'):
- instr['height'] = float(line.split()[1])
- elif line.startswith('cols'):
- instr['cols'] = int(line.split()[1])
- elif line.startswith('range'):
- instr['range'] = True
- instr['min'] = float(line.split()[1])
- instr['max'] = float(line.split()[2])
- elif line.startswith('nodata'):
- if line.split()[1].strip().lower() in ('y','yes'):
- instr['nodata'] = 'y'
- elif line.split()[1].strip().lower() in ('n','no', 'none'):
- instr['nodata'] = 'n'
- elif line.startswith('tickbar'):
- if line.split()[1].strip().lower() in ('y','yes'):
- instr['tickbar'] = 'y'
- elif line.split()[1].strip().lower() in ('n','no', 'none'):
- instr['tickbar'] = 'n'
- elif line.startswith('discrete'):
- if line.split()[1].strip().lower() in ('y','yes'):
- instr['discrete'] = 'y'
- elif line.split()[1].strip().lower() in ('n','no', 'none'):
- instr['discrete'] = 'n'
-
- except(IndexError, ValueError):
- GError(_("Failed to read instruction %s") % instruction)
- return False
-
- if 'raster' in instr:
- instr['rasterDefault'] = False
- if 'discrete' not in instr:
- rasterType = getRasterType(map = instr['raster'])
- instr['type'] = rasterType
- if rasterType == 'CELL':
- instr['discrete'] = 'y'
- else:
- instr['discrete'] = 'n'
-
- else:
- instr['rasterDefault'] = True
- self.instruction.update(instr)
- # add 'rect' in the end
-
- return True
-
- def EstimateHeight(self, raster, discrete, fontsize, cols = None, height = None):
- """!Estimate height to draw raster legend"""
- if discrete == 'n':
- if height:
- height = height
- else:
- height = self.unitConv.convert(value = fontsize * 10,
- fromUnit = 'point', toUnit = 'inch')
-
- if discrete == 'y':
- if cols:
- cols = cols
- else:
- cols = 1
-
- rinfo = grass.raster_info(raster)
- if rinfo['datatype'] in ('DCELL', 'FCELL'):
- minim, maxim = rinfo['min'], rinfo['max']
- rows = ceil(maxim / cols )
- else:
- cat = grass.read_command('r.category', map = raster,
- fs = ':').strip().split('\n')
- rows = ceil(float(len(cat)) / cols )
-
-
- height = self.unitConv.convert(value = 1.5 * rows * fontsize, fromUnit = 'point', toUnit = 'inch')
-
- return height
-
- def EstimateWidth(self, raster, discrete, fontsize, cols = None, width = None, paperInstr = None):
- """!Estimate size to draw raster legend"""
-
- if discrete == 'n':
- rinfo = grass.raster_info(raster)
- minim, maxim = rinfo['min'], rinfo['max']
- if width:
- width = width
- else:
- width = self.unitConv.convert(value = fontsize * 2,
- fromUnit = 'point', toUnit = 'inch')
- text = len(max(str(minim), str(maxim), key = len))
- textPart = self.unitConv.convert(value = text * fontsize / 2,
- fromUnit = 'point', toUnit = 'inch')
- width += textPart
-
- elif discrete == 'y':
- if cols:
- cols = cols
- else:
- cols = 1
-
- if width:
- width = width
- else:
- paperWidth = paperInstr['Width'] - paperInstr['Right'] - paperInstr['Left']
- width = (paperWidth / cols) * (cols - 1) + 1
-
- return width
-
-class VectorLegend(InstructionObject):
- """!Class representing colortable instruction"""
- def __init__(self, id):
- InstructionObject.__init__(self, id = id)
- self.type = 'vectorLegend'
- # default values
- self.defaultInstruction = dict(vLegend = False, unit = 'inch', where = (0, 0),
- defaultSize = True, width = 0.4, cols = 1, span = None,
- font = "Helvetica", fontsize = 10,
- border = 'none')
- # current values
- self.instruction = dict(self.defaultInstruction)
-
- def __str__(self):
- instr = "vlegend\n"
- instr += " where %.3f %.3f\n" % (self.instruction['where'][0], self.instruction['where'][1])
- instr += string.Template(" font $font\n fontsize $fontsize\n").substitute(self.instruction)
- instr += string.Template(" width $width\n cols $cols\n").substitute(self.instruction)
- if self.instruction['span']:
- instr += string.Template(" span $span\n").substitute(self.instruction)
- instr += string.Template(" border $border\n").substitute(self.instruction)
- instr += " end"
- return instr
-
- def Read(self, instruction, text, **kwargs):
- """!Read instruction and save information"""
- instr = {}
- instr['vLegend'] = True
- for line in text:
- try:
- if line.startswith('where'):
- instr['where'] = map(float, line.split()[1:3])
- elif line.startswith('font '):
- instr['font'] = line.split()[1]
- elif line.startswith('fontsize'):
- instr['fontsize'] = float(line.split()[1])
- elif line.startswith('width'):
- instr['width'] = float(line.split()[1])
- elif line.startswith('cols'):
- instr['cols'] = int(line.split()[1])
- elif line.startswith('span'):
- instr['span'] = float(line.split()[1])
- elif line.startswith('border'):
- instr['border'] = line.split()[1]
-
- except(IndexError, ValueError):
- GError(_("Failed to read instruction %s") % instruction)
- return False
-
- self.instruction.update(instr)
-
- return True
-
- def EstimateSize(self, vectorInstr, fontsize, width = None, cols = None):
- """!Estimate size to draw vector legend"""
- if width:
- width = width
- else:
- width = fontsize/24.0
-
- if cols:
- cols = cols
- else:
- cols = 1
-
- vectors = vectorInstr['list']
- labels = [vector[4] for vector in vectors if vector[3] != 0]
- extent = (len(max(labels, key = len)) * fontsize / 2, fontsize)
- wExtent = self.unitConv.convert(value = extent[0], fromUnit = 'point', toUnit = 'inch')
- hExtent = self.unitConv.convert(value = extent[1], fromUnit = 'point', toUnit = 'inch')
- w = (width + wExtent) * cols
- h = len(labels) * hExtent / cols
- h *= 1.1
- return (w, h)
-
-
-class Raster(InstructionObject):
- """!Class representing raster instruction"""
- def __init__(self, id):
- InstructionObject.__init__(self, id = id)
- self.type = 'raster'
- # default values
- self.defaultInstruction = dict(isRaster = False, raster = None)
- # current values
- self.instruction = dict(self.defaultInstruction)
-
- def __str__(self):
- instr = string.Template("raster $raster").substitute(self.instruction)
- return instr
-
- def Read(self, instruction, text):
- """!Read instruction and save information"""
- instr = {}
- instr['isRaster'] = True
- try:
- map = text.split()[1]
- except IndexError:
- GError(_("Failed to read instruction %s") % instruction)
- return False
- try:
- info = grass.find_file(map, element = 'cell')
- except grass.ScriptError, e:
- GError(message = e.value)
- return False
- instr['raster'] = info['fullname']
-
-
- self.instruction.update(instr)
- return True
-
-class Vector(InstructionObject):
- """!Class keeps vector layers"""
- def __init__(self, id):
- InstructionObject.__init__(self, id = id)
- self.type = 'vector'
- # default values
- self.defaultInstruction = dict(list = None)# [vmap, type, id, lpos, label]
- # current values
- self.instruction = dict(self.defaultInstruction)
- def __str__(self):
- return ''
-
- def Read(self, instruction, text, **kwargs):
- """!Read instruction and save information"""
- instr = {}
-
- for line in text:
- if line.startswith('vpoints') or line.startswith('vlines') or line.startswith('vareas'):
- # subtype
- if line.startswith('vpoints'):
- subType = 'points'
- elif line.startswith('vlines'):
- subType = 'lines'
- elif line.startswith('vareas'):
- subType = 'areas'
- # name of vector map
- vmap = line.split()[1]
- try:
- info = grass.find_file(vmap, element = 'vector')
- except grass.ScriptError, e:
- GError(message = e.value)
- return False
- vmap = info['fullname']
- # id
- id = kwargs['id']
- # lpos
- lpos = kwargs['vectorMapNumber']
- #label
- label = '('.join(vmap.split('@')) + ')'
- break
- instr = [vmap, subType, id, lpos, label]
- if not self.instruction['list']:
- self.instruction['list'] = []
- self.instruction['list'].append(instr)
-
- return True
-
-class VProperties(InstructionObject):
- """!Class represents instructions vareas, vlines, vpoints"""
- def __init__(self, id, subType):
- InstructionObject.__init__(self, id = id)
- self.type = 'vProperties'
- self.subType = subType
- # default values
- if self.subType == 'points':
- dd = dict(subType = 'points', name = None, type = 'point or centroid', connection = False, layer = '1',
- masked = 'n', color = '0:0:0', width = 1,
- fcolor = '255:0:0', rgbcolumn = None, symbol = os.path.join('basic', 'x'), eps = None,
- size = 5, sizecolumn = None, scale = None,
- rotation = False, rotate = 0, rotatecolumn = None, label = None, lpos = None)
- elif self.subType == 'lines':
- dd = dict(subType = 'lines', name = None, type = 'line or boundary', connection = False, layer = '1',
- masked = 'n', color = '0:0:0', hwidth = 1,
- hcolor = 'none', rgbcolumn = None,
- width = 1, cwidth = None,
- style = 'solid', linecap = 'butt', label = None, lpos = None)
- else: # areas
- dd = dict(subType = 'areas', name = None, connection = False, layer = '1',
- masked = 'n', color = '0:0:0', width = 1,
- fcolor = 'none', rgbcolumn = None,
- pat = None, pwidth = 1, scale = 1, label = None, lpos = None)
- self.defaultInstruction = dd
- # current values
- self.instruction = dict(self.defaultInstruction)
-
- def __str__(self):
- dic = self.instruction
- vInstruction = string.Template("v$subType $name\n").substitute(dic)
- #data selection
- if self.subType in ('points', 'lines'):
- vInstruction += string.Template(" type $type\n").substitute(dic)
- if dic['connection']:
- vInstruction += string.Template(" layer $layer\n").substitute(dic)
- if dic.has_key('cats'):
- vInstruction += string.Template(" cats $cats\n").substitute(dic)
- elif dic.has_key('where'):
- vInstruction += string.Template(" where $where\n").substitute(dic)
- vInstruction += string.Template(" masked $masked\n").substitute(dic)
- #colors
- vInstruction += string.Template(" color $color\n").substitute(dic)
- if self.subType in ('points', 'areas'):
- if dic['color'] != 'none':
- vInstruction += string.Template(" width $width\n").substitute(dic)
- if dic['rgbcolumn']:
- vInstruction += string.Template(" rgbcolumn $rgbcolumn\n").substitute(dic)
- vInstruction += string.Template(" fcolor $fcolor\n").substitute(dic)
- else:
- if dic['rgbcolumn']:
- vInstruction += string.Template(" rgbcolumn $rgbcolumn\n").substitute(dic)
- elif dic['hcolor'] != 'none':
- vInstruction += string.Template(" hwidth $hwidth\n").substitute(dic)
- vInstruction += string.Template(" hcolor $hcolor\n").substitute(dic)
-
- # size and style
- if self.subType == 'points':
- if not dic['eps']:
- vInstruction += string.Template(" symbol $symbol\n").substitute(dic)
- else: #eps
- vInstruction += string.Template(" eps $eps\n").substitute(dic)
- if dic['size']:
- vInstruction += string.Template(" size $size\n").substitute(dic)
- else: # sizecolumn
- vInstruction += string.Template(" sizecolumn $sizecolumn\n").substitute(dic)
- vInstruction += string.Template(" scale $scale\n").substitute(dic)
- if dic['rotation']:
- if dic['rotate'] is not None:
- vInstruction += string.Template(" rotate $rotate\n").substitute(dic)
- else:
- vInstruction += string.Template(" rotatecolumn $rotatecolumn\n").substitute(dic)
-
- if self.subType == 'areas':
- if dic['pat'] is not None:
- vInstruction += string.Template(" pat $pat\n").substitute(dic)
- vInstruction += string.Template(" pwidth $pwidth\n").substitute(dic)
- vInstruction += string.Template(" scale $scale\n").substitute(dic)
-
- if self.subType == 'lines':
- if dic['width'] is not None:
- vInstruction += string.Template(" width $width\n").substitute(dic)
- else:
- vInstruction += string.Template(" cwidth $cwidth\n").substitute(dic)
- vInstruction += string.Template(" style $style\n").substitute(dic)
- vInstruction += string.Template(" linecap $linecap\n").substitute(dic)
- #position and label in vlegend
- vInstruction += string.Template(" label $label\n lpos $lpos\n").substitute(dic)
-
- vInstruction += " end"
- try:
- vInstruction = vInstruction.encode('Latin_1')
- except UnicodeEncodeError, err:
- try:
- print err
- pos = str(err).split('position')[1].split(':')[0].strip()
- except IndexError:
- pos = ''
- if pos:
- message = _("Characters on position %s are not supported "
- "by ISO-8859-1 (Latin 1) encoding "
- "which is required by module ps.map.") % pos
- else:
- message = _("Not all characters are supported "
- "by ISO-8859-1 (Latin 1) encoding "
- "which is required by module ps.map.")
- GMessage(message = message)
- return ''
- return vInstruction
-
- def Read(self, instruction, text, **kwargs):
- """!Read instruction and save information"""
- instr = {}
- try:
- info = grass.find_file(name = text[0].split()[1], element = 'vector')
- except grass.ScriptError, e:
- GError(message = e.value)
- return False
- instr['name'] = info['fullname']
- #connection
- instr['connection'] = True
- self.mapDBInfo = VectorDBInfo(instr['name'])
- self.layers = self.mapDBInfo.layers.keys()
- if not self.layers:
- instr['connection'] = False
-
- # points
- if text[0].startswith('vpoints'):
- for line in text[1:]:
- if line.startswith('type'):
- tp = []
- if line.find('point') != -1:
- tp.append('point')
- if line.find('centroid') != -1:
- tp.append('centroid')
- instr['type'] = ' or '.join(tp)
- elif line.startswith('fcolor'):
- instr['fcolor'] = line.split()[1]
- elif line.startswith('rgbcolumn'):
- instr['rgbcolumn'] = line.split()[1]
- elif line.startswith('symbol'):
- instr['symbol'] = line.split()[1]
- elif line.startswith('eps'):
- instr['eps'] = line.split()[1]
- elif line.startswith('size '):
- instr['size'] = line.split()[1]
- elif line.startswith('sizecolumn'):
- instr['size'] = None
- instr['sizecolumn'] = line.split()[1]
- elif line.startswith('scale '):
- instr['scale'] = float(line.split()[1])
- elif line.startswith('rotate '):
- instr['rotation'] = True
- instr['rotate'] = line.split()[1]
- elif line.startswith('rotatecolumn'):
- instr['rotatecolumn'] = line.split()[1]
- instr['rotation'] = True
- instr['rotate'] = None
-
- # lines
- elif text[0].startswith('vlines'):
- for line in text[1:]:
- if line.startswith('type'):
- tp = []
- if line.find('line') != -1:
- tp.append('line')
- if line.find('boundary') != -1:
- tp.append('boundary')
- instr['type'] = ' or '.join(tp)
- elif line.startswith('hwidth'):
- instr['hwidth'] = float(line.split()[1])
- elif line.startswith('hcolor'):
- instr['hcolor'] = line.split()[1]
- elif line.startswith('rgbcolumn'):
- instr['rgbcolumn'] = line.split()[1]
- elif line.startswith('cwidth'):
- instr['cwidth'] = float(line.split()[1])
- instr['width'] = None
- elif line.startswith('style'):
- instr['style'] = line.split()[1]
- elif line.startswith('linecap'):
- instr['linecap'] = line.split()[1]
-
- elif text[0].startswith('vareas'):
- for line in text[1:]:
- if line.startswith('fcolor'):
- instr['fcolor'] = line.split()[1]
- elif line.startswith('pat'):
- instr['pat'] = line.split()[1]
- elif line.startswith('pwidth'):
- instr['pwidth'] = float(line.split()[1])
- elif line.startswith('scale'):
- instr['scale'] = float(line.split()[1])
-
-
- # same properties for all
- for line in text[1:]:
- if line.startswith('lpos'):
- instr['lpos'] = int(line.split()[1])
- elif line.startswith('label'):
- instr['label'] = line.split(None, 1)[1].decode('latin_1')
- elif line.startswith('layer'):
- instr['layer'] = line.split()[1]
- elif line.startswith('masked'):
- if line.split()[1].lower() in ('y', 'yes'):
- instr['masked'] = 'y'
- else:
- instr['masked'] = 'n'
- elif line.startswith('color'):
- instr['color'] = line.split()[1]
- elif line.startswith('rgbcolumn'):
- instr['rgbcolumn'] = line.split()[1]
- elif line.startswith('width'):
- instr['width'] = float(line.split()[1])
-
- if 'label' not in instr:
- instr['label'] = '('.join(instr['name'].split('@')) + ')'
- if 'lpos' not in instr:
- instr['lpos'] = kwargs['vectorMapNumber']
- self.instruction.update(instr)
-
- return True
-
class PsmapDialog(wx.Dialog):
def __init__(self, parent, id, title, settings, apply = True):
wx.Dialog.__init__(self, parent = parent, id = wx.ID_ANY,
@@ -1903,7 +259,7 @@
northingLabel = wx.StaticText(panel, id = wx.ID_ANY, label = "N:")
panel.position['eCtrl'] = wx.TextCtrl(panel, id = wx.ID_ANY, value = "")
panel.position['nCtrl'] = wx.TextCtrl(panel, id = wx.ID_ANY, value = "")
- east, north = PaperMapCoordinates(map = self.instruction[self.mapId], x = dialogDict['where'][0], y = dialogDict['where'][1], paperToMap = True)
+ east, north = PaperMapCoordinates(mapInstr = self.instruction[self.mapId], x = dialogDict['where'][0], y = dialogDict['where'][1], paperToMap = True)
panel.position['eCtrl'].SetValue(str(east))
panel.position['nCtrl'].SetValue(str(north))
@@ -4679,7 +3035,7 @@
drawWidth = self.rasterLegend.EstimateWidth(raster = self.rLegendDict['raster'], discrete = self.rLegendDict['discrete'],
fontsize = self.rLegendDict['fontsize'], cols = self.rLegendDict['cols'],
width = self.rLegendDict['width'], paperInstr = self.instruction[self.pageId])
- self.rLegendDict['rect'] = wx.Rect2D(x = x, y = y, w = drawWidth, h = drawHeight)
+ self.rLegendDict['rect'] = Rect2D(x = x, y = y, width = drawWidth, height = drawHeight)
# no data
if self.rLegendDict['discrete'] == 'y':
@@ -4782,7 +3138,7 @@
w = (width + wExtent) * self.vLegendDict['cols']
h = len(labels) * hExtent / self.vLegendDict['cols']
h *= 1.1
- self.vLegendDict['rect'] = wx.Rect2D(x, y, w, h)
+ self.vLegendDict['rect'] = Rect2D(x, y, w, h)
#border
if self.borderCheck.GetValue():
@@ -4862,7 +3218,7 @@
class MapinfoDialog(PsmapDialog):
def __init__(self, parent, id, settings):
- PsmapDialog.__init__(self, parent = parent, id = id, title = "Mapinfo settings", settings = settings)
+ PsmapDialog.__init__(self, parent = parent, id = id, title = _("Mapinfo settings"), settings = settings)
self.objectType = ('mapinfo',)
if self.id is not None:
@@ -5290,7 +3646,7 @@
rectSize = self.scalebar.EstimateSize(scalebarDict = self.scalebarDict,
scale = self.instruction[mapId]['scale'])
- self.scalebarDict['rect'] = wx.Rect2D(x = x, y = y, w = rectSize[0], h = rectSize[1])
+ self.scalebarDict['rect'] = Rect2D(x = x, y = y, width = rectSize[0], height = rectSize[1])
self.scalebarDict['where'] = self.scalebarDict['rect'].GetCentre()
if self.id not in self.instruction:
@@ -5331,7 +3687,7 @@
map = self.instruction.FindInstructionByType('initMap')
self.mapId = map.id
- self.textDict['east'], self.textDict['north'] = PaperMapCoordinates(map = map, x = self.textDict['where'][0], y = self.textDict['where'][1], paperToMap = True)
+ self.textDict['east'], self.textDict['north'] = PaperMapCoordinates(mapInstr = map, x = self.textDict['where'][0], y = self.textDict['where'][1], paperToMap = True)
notebook = wx.Notebook(parent = self, id = wx.ID_ANY, style = wx.BK_DEFAULT)
self.textPanel = self._textPanel(notebook)
@@ -5659,7 +4015,7 @@
else:
self.textDict['north'] = self.textDict['north']
- self.textDict['where'] = PaperMapCoordinates(map = self.instruction[self.mapId], x = float(self.textDict['east']),
+ self.textDict['where'] = PaperMapCoordinates(mapInstr = self.instruction[self.mapId], x = float(self.textDict['east']),
y = float(self.textDict['north']), paperToMap = False)
#rotation
if self.rotCtrl.GetValue():
@@ -5722,7 +4078,7 @@
map = self.instruction.FindInstructionByType('initMap')
self.mapId = map.id
- self.imageDict['east'], self.imageDict['north'] = PaperMapCoordinates(map = map, x = self.imageDict['where'][0], y = self.imageDict['where'][1], paperToMap = True)
+ self.imageDict['east'], self.imageDict['north'] = PaperMapCoordinates(mapInstr = map, x = self.imageDict['where'][0], y = self.imageDict['where'][1], paperToMap = True)
notebook = wx.Notebook(parent = self, id = wx.ID_ANY, style = wx.BK_DEFAULT)
self.imagePanelName = imagePanelName
@@ -6037,7 +4393,7 @@
selected = self.imagePanel.image['list'].GetStringSelection()
basePath = self.imagePanel.image['dir'].GetValue()
if not selected:
- gcmd.GMessage(parent = self, message = _("No image selected."))
+ GMessage(parent = self, message = _("No image selected."))
return False
self.imageDict['epsfile'] = os.path.join(basePath, selected)
@@ -6073,7 +4429,7 @@
else:
self.imageDict['north'] = self.imageDict['north']
- x, y = PaperMapCoordinates(map = self.instruction[self.mapId], x = float(self.imageDict['east']),
+ x, y = PaperMapCoordinates(mapInstr = self.instruction[self.mapId], x = float(self.imageDict['east']),
y = float(self.imageDict['north']), paperToMap = False)
#rotation
@@ -6099,9 +4455,9 @@
fromUnit = 'point', toUnit = 'inch')
- self.imageDict['rect'] = wx.Rect2D(x = x, y = y,
- w = w * self.imageDict['scale'],
- h = h * self.imageDict['scale'])
+ self.imageDict['rect'] = Rect2D(x = x, y = y,
+ width = w * self.imageDict['scale'],
+ height = h * self.imageDict['scale'])
if self.id not in self.instruction:
image = self._newObject()
@@ -6161,297 +4517,453 @@
self.imagePanel.image['rotate'].SetValue(360 - convergence)
-def convertRGB(rgb):
- """!Converts wx.Colour(r,g,b,a) to string 'r:g:b' or named color,
- or named color/r:g:b string to wx.Colour, depending on input"""
- # transform a wx.Colour tuple into an r:g:b string
- if type(rgb) == wx.Colour:
- for name, color in grass.named_colors.items():
- if rgb.Red() == int(color[0] * 255) and\
- rgb.Green() == int(color[1] * 255) and\
- rgb.Blue() == int(color[2] * 255):
- return name
- return str(rgb.Red()) + ':' + str(rgb.Green()) + ':' + str(rgb.Blue())
- # transform a GRASS named color or an r:g:b string into a wx.Colour tuple
- else:
- color = (grass.parse_color(rgb)[0]*255,
- grass.parse_color(rgb)[1]*255,
- grass.parse_color(rgb)[2]*255)
- color = wx.Color(*color)
- if color.IsOk():
- return color
- else:
- return None
+class PointDialog(PsmapDialog):
+ """!Dialog for setting point properties."""
+ def __init__(self, parent, id, settings, coordinates = None, pointPanelName = _("Point")):
+ PsmapDialog.__init__(self, parent = parent, id = id, title = "Point settings",
+ settings = settings)
-def PaperMapCoordinates(map, x, y, paperToMap = True):
- """!Converts paper (inch) coordinates -> map coordinates"""
- unitConv = UnitConversion()
- currRegionDict = grass.region()
- cornerEasting, cornerNorthing = currRegionDict['w'], currRegionDict['n']
- xMap = map['rect'][0]
- yMap = map['rect'][1]
- widthMap = map['rect'][2] * 0.0254 # to meter
- heightMap = map['rect'][3] * 0.0254
- xScale = widthMap / abs(currRegionDict['w'] - currRegionDict['e'])
- yScale = heightMap / abs(currRegionDict['n'] - currRegionDict['s'])
- currScale = (xScale + yScale) / 2
-
- if not paperToMap:
- textEasting, textNorthing = x, y
- eastingDiff = textEasting - cornerEasting
- if currRegionDict['w'] > currRegionDict['e']:
- eastingDiff = - eastingDiff
+ self.objectType = ('point',)
+ if self.id is not None:
+ self.pointObj = self.instruction[self.id]
+ self.pointDict = self.instruction[id].GetInstruction()
else:
- eastingDiff = eastingDiff
+ self.id = wx.NewId()
+ self.pointObj = Point(self.id)
+ self.pointDict = self.pointObj.GetInstruction()
+ self.pointDict['where'] = coordinates
+ self.defaultDict = self.pointObj.defaultInstruction
+
+ mapObj = self.instruction.FindInstructionByType('map')
+ if not mapObj:
+ mapObj = self.instruction.FindInstructionByType('initMap')
+ self.mapId = mapObj.id
+
+ self.pointDict['east'], self.pointDict['north'] = PaperMapCoordinates(mapInstr = mapObj, x = self.pointDict['where'][0], y = self.pointDict['where'][1], paperToMap = True)
+
+ notebook = wx.Notebook(parent = self, id = wx.ID_ANY, style = wx.BK_DEFAULT)
+ self.pointPanelName = pointPanelName
+ self.pointPanel = self._pointPanel(notebook)
+ self.positionPanel = self._positionPanel(notebook)
+ self.OnPositionType(None)
+
+
+ self._layout(notebook)
+
+ def _pointPanel(self, notebook):
+ panel = wx.Panel(parent = notebook, id = wx.ID_ANY, size = (-1, -1), style = wx.TAB_TRAVERSAL)
+ notebook.AddPage(page = panel, text = self.pointPanelName)
+ border = wx.BoxSizer(wx.VERTICAL)
+ #
+ # choose image
+ #
+ box = wx.StaticBox (parent = panel, id = wx.ID_ANY, label = " %s " % _("Symbol"))
+ sizer = wx.StaticBoxSizer(box, wx.HORIZONTAL)
+
+ gridSizer = wx.GridBagSizer(hgap = 5, vgap = 5)
+ gridSizer.AddGrowableCol(1)
- northingDiff = textNorthing - cornerNorthing
- if currRegionDict['n'] > currRegionDict['s']:
- northingDiff = - northingDiff
+ gridSizer.Add(item = wx.StaticText(parent = panel, id = wx.ID_ANY, label = _("Select symbol:")),
+ pos = (0, 0), flag = wx.ALIGN_CENTER_VERTICAL)
+
+ self.symbolLabel = wx.StaticText(parent = panel, id = wx.ID_ANY,
+ label = self.pointDict['symbol'])
+ gridSizer.Add(item = self.symbolLabel, pos = (0, 1),
+ flag = wx.ALIGN_CENTER_VERTICAL )
+ bitmap = wx.Bitmap(os.path.join(globalvar.ETCSYMBOLDIR,
+ self.pointDict['symbol']) + '.png')
+ self.symbolButton = wx.BitmapButton(panel, id = wx.ID_ANY, bitmap = bitmap)
+ self.symbolButton.Bind(wx.EVT_BUTTON, self.OnSymbolSelection)
+
+ gridSizer.Add(self.symbolButton, pos = (0, 2), flag = wx.ALIGN_CENTER_VERTICAL)
+ self.noteLabel = wx.StaticText(parent = panel, id = wx.ID_ANY,
+ label = _("Note: Selected symbol is not displayed\n"
+ "in draft mode (only in preview mode)"))
+ gridSizer.Add(self.noteLabel, pos = (1, 0), span = (1, 2), flag = wx.ALIGN_CENTER_VERTICAL)
+
+ sizer.Add(item = gridSizer, proportion = 1, flag = wx.EXPAND | wx.ALL, border = 5)
+
+ border.Add(item = sizer, proportion = 0, flag = wx.ALL | wx.EXPAND, border = 5)
+
+ #
+ # outline/fill color
+ #
+
+ # outline
+ box = wx.StaticBox (parent = panel, id = wx.ID_ANY, label = " %s " % _("Color"))
+ sizer = wx.StaticBoxSizer(box, wx.VERTICAL)
+
+ gridSizer = wx.GridBagSizer(hgap = 5, vgap = 5)
+
+ outlineLabel = wx.StaticText(parent = panel, id = wx.ID_ANY, label = _("Outline color:"))
+ self.outlineColorCtrl = wx.ColourPickerCtrl(panel, id = wx.ID_ANY)
+ self.outlineTranspCtrl = wx.CheckBox(panel, id = wx.ID_ANY, label = _("transparent"))
+
+ if self.pointDict['color'] != 'none':
+ self.outlineTranspCtrl.SetValue(False)
+ self.outlineColorCtrl.SetColour(convertRGB(self.pointDict['color']))
else:
- northingDiff = northingDiff
+ self.outlineTranspCtrl.SetValue(True)
+ self.outlineColorCtrl.SetColour(convertRGB(self.defaultDict['color']))
- xPaper = xMap + unitConv.convert(value = eastingDiff, fromUnit = 'meter', toUnit = 'inch') * currScale
- yPaper = yMap + unitConv.convert(value = northingDiff, fromUnit = 'meter', toUnit = 'inch') * currScale
- return xPaper, yPaper
- else:
- if currRegionDict['w'] < currRegionDict['e']:
- eastingDiff = (x - xMap)
+ gridSizer.Add(item = outlineLabel, pos = (0, 0), flag = wx.ALIGN_CENTER_VERTICAL)
+ gridSizer.Add(item = self.outlineColorCtrl, pos = (0, 1), flag = wx.ALIGN_CENTER_VERTICAL)
+ gridSizer.Add(item = self.outlineTranspCtrl, pos = (0, 2), flag = wx.ALIGN_CENTER_VERTICAL)
+
+ fillLabel = wx.StaticText(parent = panel, id = wx.ID_ANY, label = _("Fill color:"))
+ self.fillColorCtrl = wx.ColourPickerCtrl(panel, id = wx.ID_ANY)
+ self.fillTranspCtrl = wx.CheckBox(panel, id = wx.ID_ANY, label = _("transparent"))
+
+ if self.pointDict['fcolor'] != 'none':
+ self.fillTranspCtrl.SetValue(False)
+ self.fillColorCtrl.SetColour(convertRGB(self.pointDict['fcolor']))
else:
- eastingDiff = (xMap - x)
- if currRegionDict['n'] < currRegionDict['s']:
- northingDiff = (y - yMap)
+ self.fillTranspCtrl.SetValue(True)
+ self.fillColorCtrl.SetColour(convertRGB(self.defaultDict['fcolor']))
+
+ gridSizer.Add(item = fillLabel, pos = (1, 0), flag = wx.ALIGN_CENTER_VERTICAL)
+ gridSizer.Add(item = self.fillColorCtrl, pos = (1, 1), flag = wx.ALIGN_CENTER_VERTICAL)
+ gridSizer.Add(item = self.fillTranspCtrl, pos = (1, 2), flag = wx.ALIGN_CENTER_VERTICAL)
+
+ sizer.Add(item = gridSizer, proportion = 0, flag = wx.EXPAND | wx.ALL, border = 5)
+ border.Add(item = sizer, proportion = 0, flag = wx.ALL | wx.EXPAND, border = 5)
+
+ #
+ # size and rotation
+ #
+
+ # size
+ box = wx.StaticBox (parent = panel, id = wx.ID_ANY, label = " %s " % _("Size and Rotation"))
+ sizer = wx.StaticBoxSizer(box, wx.VERTICAL)
+
+ gridSizer = wx.GridBagSizer(hgap = 5, vgap = 5)
+
+ sizeLabel = wx.StaticText(parent = panel, id = wx.ID_ANY, label = _("Size (pt):"))
+ self.sizeCtrl = wx.SpinCtrl(panel, id = wx.ID_ANY, size = self.spinCtrlSize)
+ self.sizeCtrl.SetToolTipString(_("Symbol size in points"))
+ self.sizeCtrl.SetValue(self.pointDict['size'])
+
+ gridSizer.Add(item = sizeLabel, pos = (0, 0), flag = wx.ALIGN_CENTER_VERTICAL)
+ gridSizer.Add(item = self.sizeCtrl, pos = (0, 1), flag = wx.ALIGN_CENTER_VERTICAL)
+
+ # rotation
+ rotLabel = wx.StaticText(parent = panel, id = wx.ID_ANY, label = _("Rotation angle (deg):"))
+ if fs:
+ self.rotCtrl = fs.FloatSpin(panel, id = wx.ID_ANY, min_val = -360, max_val = 360,
+ increment = 1, value = 0, style = fs.FS_RIGHT, size = self.spinCtrlSize)
+ self.rotCtrl.SetFormat("%f")
+ self.rotCtrl.SetDigits(1)
else:
- northingDiff = (yMap - y)
+ self.rotCtrl = wx.SpinCtrl(parent = panel, id = wx.ID_ANY, size = self.spinCtrlSize,
+ min = -360, max = 360, initial = 0)
+ self.rotCtrl.SetToolTipString(_("Counterclockwise rotation in degrees"))
+ self.rotCtrl.SetValue(float(self.pointDict['rotate']))
+
+ gridSizer.Add(item = rotLabel, pos = (1, 0), flag = wx.ALIGN_CENTER_VERTICAL, border = 0)
+ gridSizer.Add(item = self.rotCtrl, pos = (1, 1), flag = wx.ALIGN_CENTER_VERTICAL)
+
+ sizer.Add(item = gridSizer, proportion = 0, flag = wx.EXPAND | wx.ALL, border = 5)
+ border.Add(item = sizer, proportion = 0, flag = wx.ALL | wx.EXPAND, border = 5)
+
+ panel.SetSizer(border)
+ panel.Fit()
+
+ return panel
+
+ def _positionPanel(self, notebook):
+ panel = wx.Panel(parent = notebook, id = wx.ID_ANY, size = (-1, -1), style = wx.TAB_TRAVERSAL)
+ notebook.AddPage(page = panel, text = _("Position"))
+ border = wx.BoxSizer(wx.VERTICAL)
+ #
+ # set position
+ #
+ box = wx.StaticBox (parent = panel, id = wx.ID_ANY, label = " %s " % _("Position"))
+ sizer = wx.StaticBoxSizer(box, wx.VERTICAL)
+
+ gridBagSizer = wx.GridBagSizer(hgap = 5, vgap = 5)
+ gridBagSizer.AddGrowableCol(0)
+ gridBagSizer.AddGrowableCol(1)
+
+ self.AddExtendedPosition(panel, gridBagSizer, self.pointDict)
+
+ self.Bind(wx.EVT_RADIOBUTTON, self.OnPositionType, panel.position['toPaper'])
+ self.Bind(wx.EVT_RADIOBUTTON, self.OnPositionType, panel.position['toMap'])
+
+
+ sizer.Add(gridBagSizer, proportion = 1, flag = wx.ALIGN_CENTER_VERTICAL| wx.ALL, border = 5)
+ border.Add(item = sizer, proportion = 0, flag = wx.ALL | wx.EXPAND, border = 5)
+
+ panel.SetSizer(border)
+ panel.Fit()
+
+ return panel
+
+ def OnPositionType(self, event):
+ if self.positionPanel.position['toPaper'].GetValue():
+ for widget in self.gridBagSizerP.GetChildren():
+ widget.GetWindow().Enable()
+ for widget in self.gridBagSizerM.GetChildren():
+ widget.GetWindow().Disable()
+ else:
+ for widget in self.gridBagSizerM.GetChildren():
+ widget.GetWindow().Enable()
+ for widget in self.gridBagSizerP.GetChildren():
+ widget.GetWindow().Disable()
+
+ def OnSymbolSelection(self, event):
+ dlg = SymbolDialog(self, symbolPath = globalvar.ETCSYMBOLDIR,
+ currentSymbol = self.symbolLabel.GetLabel())
+ if dlg.ShowModal() == wx.ID_OK:
+ img = dlg.GetSelectedSymbol(fullPath = True)
+ name = dlg.GetSelectedSymbol(fullPath = False)
+ self.symbolButton.SetBitmapLabel(wx.Bitmap(img + '.png'))
+ self.symbolLabel.SetLabel(name)
+
+ dlg.Destroy()
+
+ def update(self):
+ # symbol
+ self.pointDict['symbol'] = self.symbolLabel.GetLabel()
- textEasting = cornerEasting + unitConv.convert(value = eastingDiff, fromUnit = 'inch', toUnit = 'meter') / currScale
- textNorthing = cornerNorthing + unitConv.convert(value = northingDiff, fromUnit = 'inch', toUnit = 'meter') / currScale
- return int(textEasting), int(textNorthing)
-def AutoAdjust(self, scaleType, rect, map = None, mapType = None, region = None):
- """!Computes map scale, center and map frame rectangle to fit region (scale is not fixed)"""
- currRegionDict = {}
- if scaleType == 0 and map:# automatic, region from raster or vector
- res = ''
- if mapType == 'raster':
- try:
- res = grass.read_command("g.region", flags = 'gu', rast = map)
- except grass.ScriptError:
- pass
- elif mapType == 'vector':
- res = grass.read_command("g.region", flags = 'gu', vect = map)
- currRegionDict = grass.parse_key_val(res, val_type = float)
- elif scaleType == 1 and region: # saved region
- res = grass.read_command("g.region", flags = 'gu', region = region)
- currRegionDict = grass.parse_key_val(res, val_type = float)
- elif scaleType == 2: # current region
- env = grass.gisenv()
- windFilePath = os.path.join(env['GISDBASE'], env['LOCATION_NAME'], env['MAPSET'], 'WIND')
- try:
- windFile = open(windFilePath, 'r').read()
- except IOError:
- currRegionDict = grass.region()
- regionDict = grass.parse_key_val(windFile, sep = ':', val_type = float)
- region = grass.read_command("g.region", flags = 'gu', n = regionDict['north'], s = regionDict['south'],
- e = regionDict['east'], w = regionDict['west'])
- currRegionDict = grass.parse_key_val(region, val_type = float)
-
- else:
- return None, None, None
-
- if not currRegionDict:
- return None, None, None
- rX = rect.x
- rY = rect.y
- rW = rect.width
- rH = rect.height
- if not hasattr(self, 'unitConv'):
- self.unitConv = UnitConversion(self)
- toM = 1
- if projInfo()['proj'] != 'xy':
- toM = float(projInfo()['meters'])
+ #position
+ if self.positionPanel.position['toPaper'].GetValue():
+ self.pointDict['XY'] = True
+ currUnit = self.unitConv.findUnit(self.positionPanel.units['unitsCtrl'].GetStringSelection())
+ self.pointDict['unit'] = currUnit
+ if self.positionPanel.position['xCtrl'].GetValue():
+ x = self.positionPanel.position['xCtrl'].GetValue()
+ else:
+ x = self.pointDict['where'][0]
- mW = self.unitConv.convert(value = (currRegionDict['e'] - currRegionDict['w']) * toM, fromUnit = 'meter', toUnit = 'inch')
- mH = self.unitConv.convert(value = (currRegionDict['n'] - currRegionDict['s']) * toM, fromUnit = 'meter', toUnit = 'inch')
- scale = min(rW/mW, rH/mH)
-
- if rW/rH > mW/mH:
- x = rX - (rH*(mW/mH) - rW)/2
- y = rY
- rWNew = rH*(mW/mH)
- rHNew = rH
- else:
- x = rX
- y = rY - (rW*(mH/mW) - rH)/2
- rHNew = rW*(mH/mW)
- rWNew = rW
+ if self.positionPanel.position['yCtrl'].GetValue():
+ y = self.positionPanel.position['yCtrl'].GetValue()
+ else:
+ y = self.pointDict['where'][1]
- # center
- cE = (currRegionDict['w'] + currRegionDict['e'])/2
- cN = (currRegionDict['n'] + currRegionDict['s'])/2
- return scale, (cE, cN), wx.Rect2D(x, y, rWNew, rHNew) #inch
+ x = self.unitConv.convert(value = float(x), fromUnit = currUnit, toUnit = 'inch')
+ y = self.unitConv.convert(value = float(y), fromUnit = currUnit, toUnit = 'inch')
+ self.pointDict['where'] = x, y
+
+ else:
+ self.pointDict['XY'] = False
+ if self.positionPanel.position['eCtrl'].GetValue():
+ e = self.positionPanel.position['eCtrl'].GetValue()
+ else:
+ self.pointDict['east'] = self.pointDict['east']
-def SetResolution(dpi, width, height):
- """!If resolution is too high, lower it
-
- @param dpi max DPI
- @param width map frame width
- @param height map frame height
- """
- region = grass.region()
- if region['cols'] > width * dpi or region['rows'] > height * dpi:
- rows = height * dpi
- cols = width * dpi
- RunCommand('g.region', rows = rows, cols = cols)
-
-def ComputeSetRegion(self, mapDict):
- """!Computes and sets region from current scale, map center coordinates and map rectangle"""
+ if self.positionPanel.position['nCtrl'].GetValue():
+ n = self.positionPanel.position['nCtrl'].GetValue()
+ else:
+ self.pointDict['north'] = self.pointDict['north']
- if mapDict['scaleType'] == 3: # fixed scale
- scale = mapDict['scale']
+ x, y = PaperMapCoordinates(mapInstr = self.instruction[self.mapId], x = float(self.pointDict['east']),
+ y = float(self.pointDict['north']), paperToMap = False)
+
+ #rotation
+ self.pointDict['rotate'] = self.rotCtrl.GetValue()
+
+ # size
+ self.pointDict['size'] = self.sizeCtrl.GetValue()
- if not hasattr(self, 'unitConv'):
- self.unitConv = UnitConversion(self)
+ w = h = self.unitConv.convert(value = self.pointDict['size'],
+ fromUnit = 'point', toUnit = 'inch')
+
+ # outline color
+ if self.outlineTranspCtrl.GetValue():
+ self.pointDict['color'] = 'none'
+ else:
+ self.pointDict['color'] = convertRGB(self.outlineColorCtrl.GetColour())
+
+ # fill color
+ if self.fillTranspCtrl.GetValue():
+ self.pointDict['fcolor'] = 'none'
+ else:
+ self.pointDict['fcolor'] = convertRGB(self.fillColorCtrl.GetColour())
+
+ self.pointDict['rect'] = Rect2D(x = x - w / 2, y = y - h / 2, width = w, height = h)
- fromM = 1
- if projInfo()['proj'] != 'xy':
- fromM = float(projInfo()['meters'])
- rectHalfInch = (mapDict['rect'].width/2, mapDict['rect'].height/2)
- rectHalfMeter = (self.unitConv.convert(value = rectHalfInch[0], fromUnit = 'inch', toUnit = 'meter')/ fromM /scale,
- self.unitConv.convert(value = rectHalfInch[1], fromUnit = 'inch', toUnit = 'meter')/ fromM /scale)
+ if self.id not in self.instruction:
+ point = Point(self.id)
+ self.instruction.AddInstruction(point)
+ self.instruction[self.id].SetInstruction(self.pointDict)
- centerE = mapDict['center'][0]
- centerN = mapDict['center'][1]
+ if self.id not in self.parent.objectId:
+ self.parent.objectId.append(self.id)
+
+ return True
- raster = self.instruction.FindInstructionByType('raster')
- if raster:
- rasterId = raster.id
+ def updateDialog(self):
+ """!Update text coordinates, after moving"""
+ # XY coordinates
+ x, y = self.pointDict['where'][:2]
+ currUnit = self.unitConv.findUnit(self.positionPanel.units['unitsCtrl'].GetStringSelection())
+ x = self.unitConv.convert(value = x, fromUnit = 'inch', toUnit = currUnit)
+ y = self.unitConv.convert(value = y, fromUnit = 'inch', toUnit = currUnit)
+ self.positionPanel.position['xCtrl'].SetValue("%5.3f" % x)
+ self.positionPanel.position['yCtrl'].SetValue("%5.3f" % y)
+ # EN coordinates
+ e, n = self.pointDict['east'], self.pointDict['north']
+ self.positionPanel.position['eCtrl'].SetValue(str(self.pointDict['east']))
+ self.positionPanel.position['nCtrl'].SetValue(str(self.pointDict['north']))
+
+class RectangleDialog(PsmapDialog):
+ def __init__(self, parent, id, settings, type = 'rectangle', coordinates = None):
+ """!
+
+ @param coordinates begin and end point coordinate (wx.Point, wx.Point)
+ """
+ if type == 'rectangle':
+ title = _("Rectangle settings")
else:
- rasterId = None
+ title = _("Line settings")
+ PsmapDialog.__init__(self, parent = parent, id = id, title = title, settings = settings)
+
+ self.objectType = (type,)
- if rasterId:
- RunCommand('g.region', n = ceil(centerN + rectHalfMeter[1]),
- s = floor(centerN - rectHalfMeter[1]),
- e = ceil(centerE + rectHalfMeter[0]),
- w = floor(centerE - rectHalfMeter[0]),
- rast = self.instruction[rasterId]['raster'])
+ if self.id is not None:
+ self.rectObj = self.instruction[self.id]
+ self.rectDict = self.rectObj.GetInstruction()
else:
- RunCommand('g.region', n = ceil(centerN + rectHalfMeter[1]),
- s = floor(centerN - rectHalfMeter[1]),
- e = ceil(centerE + rectHalfMeter[0]),
- w = floor(centerE - rectHalfMeter[0]))
-
-def projInfo():
- """!Return region projection and map units information,
- taken from render.py"""
-
- projinfo = dict()
-
- ret = RunCommand('g.proj', read = True, flags = 'p')
-
- if not ret:
- return projinfo
-
- for line in ret.splitlines():
- if ':' in line:
- key, val = line.split(':')
- projinfo[key.strip()] = val.strip()
- elif "XY location (unprojected)" in line:
- projinfo['proj'] = 'xy'
- projinfo['units'] = ''
- break
-
- return projinfo
+ self.id = wx.NewId()
+ if type == 'rectangle':
+ self.rectObj = Rectangle(self.id)
+ else:
+ self.rectObj = Line(self.id)
+ self.rectDict = self.rectObj.GetInstruction()
-def GetMapBounds(filename, portrait = True):
- """!Run ps.map -b to get information about map bounding box
-
- @param filename psmap input file
- @param portrait page orientation"""
- orient = ''
- if not portrait:
- orient = 'r'
- try:
- bb = map(float, grass.read_command('ps.map',
- flags = 'b' + orient,
- quiet = True,
- input = filename).strip().split('=')[1].split(','))
- except (grass.ScriptError, IndexError):
- GError(message = _("Unable to run `ps.map -b`"))
- return None
- return wx.Rect2D(bb[0], bb[3], bb[2] - bb[0], bb[1] - bb[3])
+ self.rectDict['rect'] = Rect2DPP(coordinates[0], coordinates[1])
+ self.rectDict['where'] = coordinates
-def getRasterType(map):
- """!Returns type of raster map (CELL, FCELL, DCELL)"""
- if map is None:
- map = ''
- file = grass.find_file(name = map, element = 'cell')
- if file['file']:
- rasterType = grass.raster_info(map)['datatype']
- return rasterType
- else:
- return None
-
-def PilImageToWxImage(pilImage, copyAlpha = True):
- """!Convert PIL image to wx.Image
-
- Based on http://wiki.wxpython.org/WorkingWithImages
- """
- hasAlpha = pilImage.mode[-1] == 'A'
- if copyAlpha and hasAlpha : # Make sure there is an alpha layer copy.
- wxImage = wx.EmptyImage( *pilImage.size )
- pilImageCopyRGBA = pilImage.copy()
- pilImageCopyRGB = pilImageCopyRGBA.convert('RGB') # RGBA --> RGB
- pilImageRgbData = pilImageCopyRGB.tostring()
- wxImage.SetData(pilImageRgbData)
- wxImage.SetAlphaData(pilImageCopyRGBA.tostring()[3::4]) # Create layer and insert alpha values.
+ self.defaultDict = self.rectObj.defaultInstruction
+ self.panel = self._rectPanel()
+
+ self._layout(self.panel)
- else : # The resulting image will not have alpha.
- wxImage = wx.EmptyImage(*pilImage.size)
- pilImageCopy = pilImage.copy()
- pilImageCopyRGB = pilImageCopy.convert('RGB') # Discard any alpha from the PIL image.
- pilImageRgbData = pilImageCopyRGB.tostring()
- wxImage.SetData(pilImageRgbData)
+ def _rectPanel(self):
+ panel = wx.Panel(parent = self, id = wx.ID_ANY, style = wx.TAB_TRAVERSAL)
+ border = wx.BoxSizer(wx.VERTICAL)
+
+ # color
+ box = wx.StaticBox (parent = panel, id = wx.ID_ANY, label = " %s " % _("Color"))
+ sizer = wx.StaticBoxSizer(box, wx.VERTICAL)
+ gridSizer = wx.GridBagSizer (hgap = 5, vgap = 5)
+
+ outlineLabel = wx.StaticText(parent = panel, id = wx.ID_ANY, label = _("Outline color:"))
+ self.outlineColorCtrl = wx.ColourPickerCtrl(panel, id = wx.ID_ANY)
+ self.outlineTranspCtrl = wx.CheckBox(panel, id = wx.ID_ANY, label = _("transparent"))
- return wxImage
+ if self.rectDict['color'] != 'none':
+ self.outlineTranspCtrl.SetValue(False)
+ self.outlineColorCtrl.SetColour(convertRGB(self.rectDict['color']))
+ else:
+ self.outlineTranspCtrl.SetValue(True)
+ self.outlineColorCtrl.SetColour(convertRGB(self.defaultDict['color']))
-def BBoxAfterRotation(w, h, angle):
- """!Compute bounding box or rotated rectangle
-
- @param w rectangle width
- @param h rectangle height
- @param angle angle (0, 360) in degrees
- """
- angleRad = angle / 180. * pi
- ct = cos(angleRad)
- st = sin(angleRad)
-
- hct = h * ct
- wct = w * ct
- hst = h * st
- wst = w * st
- y = x = 0
-
- if 0 < angle <= 90:
- y_min = y
- y_max = y + hct + wst
- x_min = x - hst
- x_max = x + wct
- elif 90 < angle <= 180:
- y_min = y + hct
- y_max = y + wst
- x_min = x - hst + wct
- x_max = x
- elif 180 < angle <= 270:
- y_min = y + wst + hct
- y_max = y
- x_min = x + wct
- x_max = x - hst
- elif 270 < angle <= 360:
- y_min = y + wst
- y_max = y + hct
- x_min = x
- x_max = x + wct - hst
+ # transparent outline makes sense only for rectangle
+ if self.objectType == ('line',):
+ self.outlineTranspCtrl.Hide()
+
+ gridSizer.Add(item = outlineLabel, pos = (0, 0), flag = wx.ALIGN_CENTER_VERTICAL)
+ gridSizer.Add(item = self.outlineColorCtrl, pos = (0, 1), flag = wx.ALIGN_CENTER_VERTICAL)
+ gridSizer.Add(item = self.outlineTranspCtrl, pos = (0, 2), flag = wx.ALIGN_CENTER_VERTICAL)
+
+ # fill color only in rectangle
+ if self.objectType == ('rectangle',):
+ fillLabel = wx.StaticText(parent = panel, id = wx.ID_ANY, label = _("Fill color:"))
+ self.fillColorCtrl = wx.ColourPickerCtrl(panel, id = wx.ID_ANY)
+ self.fillTranspCtrl = wx.CheckBox(panel, id = wx.ID_ANY, label = _("transparent"))
+
+ if self.rectDict['fcolor'] != 'none':
+ self.fillTranspCtrl.SetValue(False)
+ self.fillColorCtrl.SetColour(convertRGB(self.rectDict['fcolor']))
+ else:
+ self.fillTranspCtrl.SetValue(True)
+ self.fillColorCtrl.SetColour(wx.WHITE)
+
+ gridSizer.Add(item = fillLabel, pos = (1, 0), flag = wx.ALIGN_CENTER_VERTICAL)
+ gridSizer.Add(item = self.fillColorCtrl, pos = (1, 1), flag = wx.ALIGN_CENTER_VERTICAL)
+ gridSizer.Add(item = self.fillTranspCtrl, pos = (1, 2), flag = wx.ALIGN_CENTER_VERTICAL)
+
+ sizer.Add(gridSizer, proportion = 1, flag = wx.EXPAND|wx.ALL, border = 5)
+ border.Add(item = sizer, proportion = 0, flag = wx.ALL | wx.EXPAND, border = 5)
+ gridSizer = wx.GridBagSizer (hgap = 5, vgap = 5)
+
+ # width
+ box = wx.StaticBox (parent = panel, id = wx.ID_ANY, label = " %s " % _("Line style"))
+ sizer = wx.StaticBoxSizer(box, wx.VERTICAL)
- width = int(ceil(abs(x_max) + abs(x_min)))
- height = int(ceil(abs(y_max) + abs(y_min)))
- return width, height
+ widthLabel = wx.StaticText(parent = panel, id = wx.ID_ANY, label = _("Line width:"))
+ if fs:
+ self.widthCtrl = fs.FloatSpin(panel, id = wx.ID_ANY, min_val = 0, max_val = 50,
+ increment = 1, value = 0, style = fs.FS_RIGHT, size = self.spinCtrlSize)
+ self.widthCtrl.SetFormat("%f")
+ self.widthCtrl.SetDigits(1)
+ else:
+ self.widthCtrl = wx.SpinCtrl(parent = panel, id = wx.ID_ANY, size = self.spinCtrlSize,
+ min = -360, max = 360, initial = 0)
+ self.widthCtrl.SetToolTipString(_("Line width in points"))
+ self.widthCtrl.SetValue(float(self.rectDict['width']))
+
+ gridSizer.Add(item = widthLabel, pos = (0, 0), flag = wx.ALIGN_CENTER_VERTICAL)
+ gridSizer.Add(item = self.widthCtrl, pos = (0, 1), flag = wx.ALIGN_CENTER_VERTICAL)
+
+ sizer.Add(gridSizer, proportion = 1, flag = wx.EXPAND|wx.ALL, border = 5)
+ border.Add(item = sizer, proportion = 0, flag = wx.ALL | wx.EXPAND, border = 5)
+
+ panel.SetSizer(border)
+
+ return panel
+
+
+ def update(self):
+ mapInstr = self.instruction.FindInstructionByType('map')
+ if not mapInstr:
+ mapInstr = self.instruction.FindInstructionByType('initMap')
+ self.mapId = mapInstr.id
+ point1 = self.rectDict['where'][0]
+ point2 = self.rectDict['where'][1]
+ self.rectDict['east1'], self.rectDict['north1'] = PaperMapCoordinates(mapInstr = mapInstr,
+ x = point1[0],
+ y = point1[1],
+ paperToMap = True)
+ self.rectDict['east2'], self.rectDict['north2'] = PaperMapCoordinates(mapInstr = mapInstr,
+ x = point2[0],
+ y = point2[1],
+ paperToMap = True)
+ # width
+ self.rectDict['width'] = self.widthCtrl.GetValue()
+
+ # outline color
+ if self.outlineTranspCtrl.GetValue():
+ self.rectDict['color'] = 'none'
+ else:
+ self.rectDict['color'] = convertRGB(self.outlineColorCtrl.GetColour())
+
+ # fill color
+ if self.objectType == ('rectangle',):
+ if self.fillTranspCtrl.GetValue():
+ self.rectDict['fcolor'] = 'none'
+ else:
+ self.rectDict['fcolor'] = convertRGB(self.fillColorCtrl.GetColour())
+
+ if self.id not in self.instruction:
+ if self.objectType == ('rectangle',):
+ rect = Rectangle(self.id)
+ else:
+ rect = Line(self.id)
+ self.instruction.AddInstruction(rect)
+
+ self.instruction[self.id].SetInstruction(self.rectDict)
+
+ if self.id not in self.parent.objectId:
+ self.parent.objectId.append(self.id)
+
+ self.updateDialog()
+
+ return True
+
+ def updateDialog(self):
+ """!Update text coordinates, after moving"""
+ pass
+
Modified: grass/branches/develbranch_6/gui/wxpython/psmap/frame.py
===================================================================
--- grass/branches/develbranch_6/gui/wxpython/psmap/frame.py 2012-02-17 00:41:01 UTC (rev 50839)
+++ grass/branches/develbranch_6/gui/wxpython/psmap/frame.py 2012-02-17 06:45:00 UTC (rev 50840)
@@ -7,7 +7,7 @@
- frame::PsMapFrame
- frame::PsMapBufferedWindow
-(C) 2011 by Anna Kratochvilova, and the GRASS Development Team
+(C) 2011-2012 by Anna Kratochvilova, and the GRASS Development Team
This program is free software under the GNU General Public License
(>=v2). Read the file COPYING that comes with GRASS for details.
@@ -19,12 +19,7 @@
import sys
import textwrap
import Queue
-from math import sin, cos, pi
-try:
- import Image as PILImage
- havePILImage = True
-except ImportError:
- havePILImage = False
+from math import sin, cos, pi, sqrt
if __name__ == "__main__":
sys.path.append(os.path.join(os.getenv('GISBASE'), 'etc', 'gui', 'wxpython'))
@@ -38,15 +33,17 @@
import grass.script as grass
-from gui_core.menu import Menu
-from gui_core.goutput import CmdThread, EVT_CMD_DONE
-from psmap.toolbars import PsMapToolbar
-from core.gcmd import RunCommand, GError, GMessage
-from core.settings import UserSettings
-from gui_core.forms import GUI
-from psmap.menudata import PsMapData
+from gui_core.menu import Menu
+from gui_core.goutput import CmdThread, EVT_CMD_DONE
+from psmap.toolbars import PsMapToolbar
+from core.gcmd import RunCommand, GError, GMessage
+from core.settings import UserSettings
+from gui_core.forms import GUI
+from psmap.menudata import PsMapData
-from psmap.dialogs import *
+from psmap.dialogs import *
+from psmap.instructions import *
+from psmap.utils import *
class PsMapFrame(wx.Frame):
def __init__(self, parent = None, id = wx.ID_ANY,
@@ -101,6 +98,8 @@
'scalebar': wx.Pen(colour = wx.Color(150, 150, 150), width = 2),
'image': wx.Pen(colour = wx.Color(255, 150, 50), width = 2),
'northArrow': wx.Pen(colour = wx.Color(200, 200, 200), width = 2),
+ 'point': wx.Pen(colour = wx.Color(100, 100, 100), width = 2),
+ 'line': wx.Pen(colour = wx.Color(0, 0, 0), width = 2),
'box': wx.Pen(colour = 'RED', width = 2, style = wx.SHORT_DASH),
'select': wx.Pen(colour = 'BLACK', width = 1, style = wx.SHORT_DASH),
'resize': wx.Pen(colour = 'BLACK', width = 1)
@@ -115,6 +114,8 @@
'scalebar': wx.Brush(wx.Color(200, 200, 200)),
'image': wx.Brush(wx.Color(255, 200, 50)),
'northArrow': wx.Brush(wx.Color(255, 255, 255)),
+ 'point': wx.Brush(wx.Color(200, 200, 200)),
+ 'line': wx.TRANSPARENT_BRUSH,
'box': wx.TRANSPARENT_BRUSH,
'select':wx.TRANSPARENT_BRUSH,
'resize': wx.BLACK_BRUSH
@@ -657,7 +658,81 @@
dlg.SetPosition(position)
dlg.Show()
+ def OnAddPoint(self, event):
+ """!Add point action selected"""
+ self.mouse["use"] = "addPoint"
+ self.canvas.SetCursor(self.cursors["cross"])
+ def AddPoint(self, id = None, coordinates = None):
+ """!Add point and open property dialog.
+
+ @param id id point id (None if creating new point)
+ @param coordinates coordinates of new point
+ """
+ position = None
+ if 'point' in self.openDialogs:
+ position = self.openDialogs['point'].GetPosition()
+ self.openDialogs['point'].OnApply(event = None)
+ self.openDialogs['point'].Destroy()
+ dlg = PointDialog(self, id = id, settings = self.instruction,
+ coordinates = coordinates)
+ self.openDialogs['point'] = dlg
+ if position:
+ dlg.SetPosition(position)
+ if coordinates:
+ dlg.OnApply(event = None)
+ dlg.Show()
+
+ def OnAddLine(self, event):
+ """!Add line action selected"""
+ self.mouse["use"] = "addLine"
+ self.canvas.SetCursor(self.cursors["cross"])
+
+ def AddLine(self, id = None, coordinates = None):
+ """!Add line and open property dialog.
+
+ @param id id line id (None if creating new line)
+ @param coordinates coordinates of new line
+ """
+ position = None
+ if 'line' in self.openDialogs:
+ position = self.openDialogs['line'].GetPosition()
+ self.openDialogs['line'].OnApply(event = None)
+ self.openDialogs['line'].Destroy()
+ dlg = RectangleDialog(self, id = id, settings = self.instruction,
+ type = 'line', coordinates = coordinates)
+ self.openDialogs['line'] = dlg
+ if position:
+ dlg.SetPosition(position)
+ if coordinates:
+ dlg.OnApply(event = None)
+ dlg.Show()
+
+ def OnAddRectangle(self, event):
+ """!Add rectangle action selected"""
+ self.mouse["use"] = "addRectangle"
+ self.canvas.SetCursor(self.cursors["cross"])
+
+ def AddRectangle(self, id = None, coordinates = None):
+ """!Add rectangle and open property dialog.
+
+ @param id id rectangle id (None if creating new rectangle)
+ @param coordinates coordinates of new rectangle
+ """
+ position = None
+ if 'rectangle' in self.openDialogs:
+ position = self.openDialogs['rectangle'].GetPosition()
+ self.openDialogs['rectangle'].OnApply(event = None)
+ self.openDialogs['rectangle'].Destroy()
+ dlg = RectangleDialog(self, id = id, settings = self.instruction,
+ type = 'rectangle', coordinates = coordinates)
+ self.openDialogs['rectangle'] = dlg
+ if position:
+ dlg.SetPosition(position)
+ if coordinates:
+ dlg.OnApply(event = None)
+ dlg.Show()
+
def getModifiedTextBounds(self, x, y, textExtent, rotation):
"""!computes bounding box of rotated text, not very precisely"""
w, h = textExtent
@@ -804,6 +879,32 @@
self.canvas.Draw(pen = self.pen[itype], brush = self.brush[itype],
pdc = self.canvas.pdcObj, drawid = id, pdctype = 'bitmap', bb = drawRectangle)
self.canvas.RedrawSelectBox(id)
+
+ if itype in ('point', 'line', 'rectangle'):
+ drawRectangle = self.canvas.CanvasPaperCoordinates(rect = self.instruction[id]['rect'], canvasToPaper = False)
+ # coords only for line
+ coords = None
+ if itype == 'line':
+ point1 = self.instruction[id]['where'][0]
+ point2 = self.instruction[id]['where'][1]
+ point1Coords = self.canvas.CanvasPaperCoordinates(rect = Rect2DPS(point1, (0, 0)), canvasToPaper = False)[:2]
+ point2Coords = self.canvas.CanvasPaperCoordinates(rect = Rect2DPS(point2, (0, 0)), canvasToPaper = False)[:2]
+ coords = (point1Coords, point2Coords)
+
+ # fill color is not in line
+ fcolor = None
+ if 'fcolor' in self.instruction[id].GetInstruction():
+ fcolor = self.instruction[id]['fcolor']
+ # width is not in point
+ width = None
+ if 'width' in self.instruction[id].GetInstruction():
+ width = self.instruction[id]['width']
+
+ self.canvas.DrawGraphics(drawid = id, color = self.instruction[id]['color'], shape = itype,
+ fcolor = fcolor, width = width, bb = drawRectangle, lineCoords = coords)
+
+ self.canvas.RedrawSelectBox(id)
+
if itype == 'text':
if self.instruction[id]['rotate']:
@@ -812,7 +913,7 @@
rot = 0
extent = self.getTextExtent(textDict = self.instruction[id].GetInstruction())
- rect = wx.Rect2D(self.instruction[id]['where'][0], self.instruction[id]['where'][1], 0, 0)
+ rect = Rect2DPS(self.instruction[id]['where'], (0, 0))
self.instruction[id]['coords'] = list(self.canvas.CanvasPaperCoordinates(rect = rect, canvasToPaper = False)[:2])
#computes text coordinates according to reference point, not precisely
@@ -993,6 +1094,9 @@
self.idBoxTmp = wx.NewId()
self.idZoomBoxTmp = wx.NewId()
self.idResizeBoxTmp = wx.NewId()
+ self.idLinePointsTmp = (wx.NewId(), wx.NewId()) # ids of marks for moving line vertices
+
+ self.resizeBoxSize = wx.Size(8, 8)
@@ -1014,7 +1118,8 @@
self.Bind(wx.EVT_PAINT, self.OnPaint)
self.Bind(wx.EVT_SIZE, self.OnSize)
self.Bind(wx.EVT_IDLE, self.OnIdle)
- self.Bind(wx.EVT_MOUSE_EVENTS, self.OnMouse)
+ # self.Bind(wx.EVT_MOUSE_EVENTS, self.OnMouse)
+ self.Bind(wx.EVT_MOUSE_EVENTS, self.MouseActions)
def Clear(self):
@@ -1051,12 +1156,12 @@
scale = self.currScale
pRectx = units.convert(value = - pRect.x, fromUnit = 'pixel', toUnit = 'inch' ) /scale #inch, real, negative
pRecty = units.convert(value = - pRect.y, fromUnit = 'pixel', toUnit = 'inch' ) /scale
- Width = units.convert(value = rect.width, fromUnit = fromU, toUnit = toU) * scale
- Height = units.convert(value = rect.height, fromUnit = fromU, toUnit = toU) * scale
- X = units.convert(value = (rect.x - pRectx), fromUnit = fromU, toUnit = toU) * scale
- Y = units.convert(value = (rect.y - pRecty), fromUnit = fromU, toUnit = toU) * scale
+ Width = units.convert(value = rect.GetWidth(), fromUnit = fromU, toUnit = toU) * scale
+ Height = units.convert(value = rect.GetHeight(), fromUnit = fromU, toUnit = toU) * scale
+ X = units.convert(value = (rect.GetX() - pRectx), fromUnit = fromU, toUnit = toU) * scale
+ Y = units.convert(value = (rect.GetY() - pRecty), fromUnit = fromU, toUnit = toU) * scale
- return wx.Rect2D(X, Y, Width, Height)
+ return Rect2D(X, Y, Width, Height)
@@ -1099,12 +1204,29 @@
except AttributeError:
mapId = self.instruction.FindInstructionByType('initMap').id
- for itemType in ('text', 'image', 'northArrow'):
+ for itemType in ('text', 'image', 'northArrow', 'point', 'line', 'rectangle'):
items = self.instruction.FindInstructionByType(itemType, list = True)
for item in items:
- e, n = PaperMapCoordinates(map = self.instruction[mapId], x = self.instruction[item.id]['where'][0],
- y = self.instruction[item.id]['where'][1], paperToMap = True)
- self.instruction[item.id]['east'], self.instruction[item.id]['north'] = e, n
+ instr = self.instruction[item.id]
+ if itemType in ('line', 'rectangle'):
+ if itemType == 'line':
+ e1, n1 = PaperMapCoordinates(mapInstr = self.instruction[mapId], x = instr['where'][0][0],
+ y = instr['where'][0][1], paperToMap = True)
+ e2, n2 = PaperMapCoordinates(mapInstr = self.instruction[mapId], x = instr['where'][1][0],
+ y = instr['where'][1][1], paperToMap = True)
+ else:
+ e1, n1 = PaperMapCoordinates(mapInstr = self.instruction[mapId], x = instr['rect'].GetLeft(),
+ y = instr['rect'].GetTop(), paperToMap = True)
+ e2, n2 = PaperMapCoordinates(mapInstr = self.instruction[mapId], x = instr['rect'].GetRight(),
+ y = instr['rect'].GetBottom(), paperToMap = True)
+ instr['east1'] = e1
+ instr['north1'] = n1
+ instr['east2'] = e2
+ instr['north2'] = n2
+ else:
+ e, n = PaperMapCoordinates(mapInstr = self.instruction[mapId], x = instr['where'][0],
+ y = instr['where'][1], paperToMap = True)
+ instr['east'], instr['north'] = e, n
def OnPaint(self, event):
"""!Draw pseudo DC to buffer
@@ -1131,243 +1253,400 @@
self.pdcImage.DrawToDCClipped(dc, rgn.GetBox())
self.pdcTmp.DrawToDCClipped(dc, rgn.GetBox())
- def OnMouse(self, event):
+ def MouseActions(self, event):
+ """!Mouse motion and button click notifier
+ """
+ # zoom with mouse wheel
+ if event.GetWheelRotation() != 0:
+ self.OnMouseWheel(event)
+
+ # left mouse button pressed
+ elif event.LeftDown():
+ self.OnLeftDown(event)
+
+ # left mouse button released
+ elif event.LeftUp():
+ self.OnLeftUp(event)
+
+ # dragging
+ elif event.Dragging():
+ self.OnDragging(event)
+
+ # double click
+ elif event.ButtonDClick():
+ self.OnButtonDClick(event)
+
+ # middle mouse button pressed
+ elif event.MiddleDown():
+ self.OnMiddleDown(event)
+
+ elif event.Moving():
+ self.OnMouseMoving(event)
+
+ def OnMouseWheel(self, event):
+ """!Mouse wheel scrolled.
- if event.GetWheelRotation() and UserSettings.Get(group = 'display',
- key = 'mouseWheelZoom',
- subkey = 'enabled'):
- zoom = event.GetWheelRotation()
- use = self.mouse['use']
- self.mouse['begin'] = event.GetPosition()
+ Changes zoom."""
+ if not UserSettings.Get(group = 'display',
+ key = 'mouseWheelZoom',
+ subkey = 'enabled'):
+ event.Skip()
+ return
+
+ zoom = event.GetWheelRotation()
+ oldUse = self.mouse['use']
+ self.mouse['begin'] = event.GetPosition()
+
+ if UserSettings.Get(group = 'display',
+ key = 'mouseWheelZoom',
+ subkey = 'selection'):
+ zoom *= -1
- if UserSettings.Get(group = 'display',
- key = 'mouseWheelZoom',
- subkey = 'selection'):
- zoom *= -1
+ if zoom > 0:
+ self.mouse['use'] = 'zoomin'
+ else:
+ self.mouse['use'] = 'zoomout'
+
+ zoomFactor, view = self.ComputeZoom(wx.Rect(0, 0, 0, 0))
+ self.Zoom(zoomFactor, view)
+ self.mouse['use'] = oldUse
+
+ def OnMouseMoving(self, event):
+ """!Mouse cursor moving.
+
+ Change cursor when moving over resize marker.
+ """
+ if self.mouse['use'] in ('pointer', 'resize'):
+ pos = event.GetPosition()
+ foundResize = self.pdcTmp.FindObjects(pos[0], pos[1])
+ if foundResize and foundResize[0] in (self.idResizeBoxTmp,) + self.idLinePointsTmp:
+ self.SetCursor(self.cursors["sizenwse"])
+ self.parent.SetStatusText(_('Click and drag to resize object'), 0)
+ else:
+ self.parent.SetStatusText('', 0)
+ self.SetCursor(self.cursors["default"])
- if zoom > 0:
- self.mouse['use'] = 'zoomin'
+ def OnLeftDown(self, event):
+ """!Left mouse button pressed.
+
+ Select objects, redraw, prepare for moving/resizing.
+ """
+ self.mouse['begin'] = event.GetPosition()
+ self.begin = self.mouse['begin']
+
+ # select
+ if self.mouse['use'] == 'pointer':
+ found = self.pdcObj.FindObjects(self.mouse['begin'][0], self.mouse['begin'][1])
+ foundResize = self.pdcTmp.FindObjects(self.mouse['begin'][0], self.mouse['begin'][1])
+
+ if foundResize and foundResize[0] in (self.idResizeBoxTmp,) + self.idLinePointsTmp:
+ self.mouse['use'] = 'resize'
+
+ # when resizing, proportions match region
+ if self.instruction[self.dragId].type == 'map':
+ self.constraint = False
+ self.mapBounds = self.pdcObj.GetIdBounds(self.dragId)
+ if self.instruction[self.dragId]['scaleType'] in (0, 1, 2):
+ self.constraint = True
+ self.mapBounds = self.pdcObj.GetIdBounds(self.dragId)
+
+ if self.instruction[self.dragId].type == 'line':
+ self.currentLinePoint = self.idLinePointsTmp.index(foundResize[0])
+
+ elif found:
+ self.dragId = found[0]
+ self.RedrawSelectBox(self.dragId)
+ if self.instruction[self.dragId].type not in ('map', 'rectangle'):
+ self.pdcTmp.RemoveId(self.idResizeBoxTmp)
+ self.Refresh()
+ if self.instruction[self.dragId].type != 'line':
+ for id in self.idLinePointsTmp:
+ self.pdcTmp.RemoveId(id)
+ self.Refresh()
+
else:
- self.mouse['use'] = 'zoomout'
-
- zoomFactor, view = self.ComputeZoom(wx.Rect(0,0,0,0))
+ self.dragId = -1
+ self.pdcTmp.RemoveId(self.idBoxTmp)
+ self.pdcTmp.RemoveId(self.idResizeBoxTmp)
+ for id in self.idLinePointsTmp:
+ self.pdcTmp.RemoveId(id)
+ self.Refresh()
+
+ def OnLeftUp(self, event):
+ """!Left mouse button released.
+
+ Recalculate zooming/resizing/moving and redraw.
+ """
+ # zoom in, zoom out
+ if self.mouse['use'] in ('zoomin','zoomout'):
+ zoomR = self.pdcTmp.GetIdBounds(self.idZoomBoxTmp)
+ self.pdcTmp.RemoveId(self.idZoomBoxTmp)
+ self.Refresh()
+ zoomFactor, view = self.ComputeZoom(zoomR)
self.Zoom(zoomFactor, view)
- self.mouse['use'] = use
+
+ # draw map frame
+ if self.mouse['use'] == 'addMap':
+ rectTmp = self.pdcTmp.GetIdBounds(self.idZoomBoxTmp)
+ # too small rectangle, it's usually some mistake
+ if rectTmp.GetWidth() < 20 or rectTmp.GetHeight() < 20:
+ self.pdcTmp.RemoveId(self.idZoomBoxTmp)
+ self.Refresh()
+ return
+ rectPaper = self.CanvasPaperCoordinates(rect = rectTmp, canvasToPaper = True)
+
+ dlg = MapDialog(parent = self.parent, id = [None, None, None], settings = self.instruction,
+ rect = rectPaper)
+ self.openDialogs['map'] = dlg
+ self.openDialogs['map'].Show()
- if event.Moving():
- if self.mouse['use'] in ('pointer', 'resize'):
- pos = event.GetPosition()
- foundResize = self.pdcTmp.FindObjects(pos[0], pos[1])
- if foundResize and foundResize[0] == self.idResizeBoxTmp:
- self.SetCursor(self.cursors["sizenwse"])
- self.parent.SetStatusText(_('Click and drag to resize object'), 0)
- else:
- self.parent.SetStatusText('', 0)
- self.SetCursor(self.cursors["default"])
+ self.mouse['use'] = self.parent.mouseOld
+
+ self.SetCursor(self.parent.cursorOld)
+ self.parent.toolbar.ToggleTool(self.parent.actionOld, True)
+ self.parent.toolbar.ToggleTool(self.parent.toolbar.action['id'], False)
+ self.parent.toolbar.action['id'] = self.parent.actionOld
+ return
+
+ # resize resizable objects (map, line, rectangle)
+ if self.mouse['use'] == 'resize':
+ mapObj = self.instruction.FindInstructionByType('map')
+ if not mapObj:
+ mapObj = self.instruction.FindInstructionByType('initMap')
+ mapId = mapObj.id
+
+ if self.dragId == mapId:
+ # necessary to change either map frame (scaleType 0,1,2) or region (scaletype 3)
+ newRectCanvas = self.pdcObj.GetIdBounds(mapId)
+ newRectPaper = self.CanvasPaperCoordinates(rect = newRectCanvas, canvasToPaper = True)
+ self.instruction[mapId]['rect'] = newRectPaper
+
+ if self.instruction[mapId]['scaleType'] in (0, 1, 2):
+ if self.instruction[mapId]['scaleType'] == 0:
+
+ scale, foo, rect = AutoAdjust(self, scaleType = 0,
+ map = self.instruction[mapId]['map'],
+ mapType = self.instruction[mapId]['mapType'],
+ rect = self.instruction[mapId]['rect'])
+
+ elif self.instruction[mapId]['scaleType'] == 1:
+ scale, foo, rect = AutoAdjust(self, scaleType = 1,
+ region = self.instruction[mapId]['region'],
+ rect = self.instruction[mapId]['rect'])
+ else:
+ scale, foo, rect = AutoAdjust(self, scaleType = 2,
+ rect = self.instruction[mapId]['rect'])
+ self.instruction[mapId]['rect'] = rect
+ self.instruction[mapId]['scale'] = scale
- elif event.MiddleDown():
- self.mouse['begin'] = event.GetPosition()
+ rectCanvas = self.CanvasPaperCoordinates(rect = rect, canvasToPaper = False)
+ self.Draw(pen = self.pen['map'], brush = self.brush['map'],
+ pdc = self.pdcObj, drawid = mapId, pdctype = 'rectText', bb = rectCanvas)
+
+ elif self.instruction[mapId]['scaleType'] == 3:
+ ComputeSetRegion(self, mapDict = self.instruction[mapId].GetInstruction())
+ #check resolution
+ SetResolution(dpi = self.instruction[mapId]['resolution'],
+ width = self.instruction[mapId]['rect'].width,
+ height = self.instruction[mapId]['rect'].height)
+
+ self.RedrawSelectBox(mapId)
+ self.Zoom(zoomFactor = 1, view = (0, 0))
+
+ elif self.instruction[self.dragId].type == 'line':
+ points = self.instruction[self.dragId]['where']
+ self.instruction[self.dragId]['rect'] = Rect2DPP(points[0], points[1])
+ self.RecalculatePosition(ids = [self.dragId])
+
+ elif self.instruction[self.dragId].type == 'rectangle':
+ self.RecalculatePosition(ids = [self.dragId])
+
+ self.mouse['use'] = 'pointer'
- elif event.LeftDown():
- self.mouse['begin'] = event.GetPosition()
- self.begin = self.mouse['begin']
- if self.mouse['use'] in ('pan', 'zoomin', 'zoomout', 'addMap'):
- pass
-
- #select
- if self.mouse['use'] == 'pointer':
- found = self.pdcObj.FindObjects(self.mouse['begin'][0], self.mouse['begin'][1])
- foundResize = self.pdcTmp.FindObjects(self.mouse['begin'][0], self.mouse['begin'][1])
+ # recalculate the position of objects after dragging
+ if self.mouse['use'] in ('pointer', 'resize') and self.dragId != -1:
+ if self.mouse['begin'] != event.GetPosition(): #for double click
+
+ self.RecalculatePosition(ids = [self.dragId])
+ if self.instruction[self.dragId].type in self.openDialogs:
+ self.openDialogs[self.instruction[self.dragId].type].updateDialog()
+
+ elif self.mouse['use'] in ('addPoint', 'addLine', 'addRectangle'):
+ endCoordinates = self.CanvasPaperCoordinates(rect = wx.Rect(event.GetX(), event.GetY(), 0, 0),
+ canvasToPaper = True)[:2]
- if foundResize and foundResize[0] == self.idResizeBoxTmp:
- self.mouse['use'] = 'resize'
-
- # when resizing, proportions match region
- if self.instruction[self.dragId].type == 'map':
- self.constraint = False
- self.mapBounds = self.pdcObj.GetIdBounds(self.dragId)
- if self.instruction[self.dragId]['scaleType'] in (0, 1, 2):
- self.constraint = True
- self.mapBounds = self.pdcObj.GetIdBounds(self.dragId)
-
- elif found:
- self.dragId = found[0]
- self.RedrawSelectBox(self.dragId)
- if self.instruction[self.dragId].type != 'map':
- self.pdcTmp.RemoveId(self.idResizeBoxTmp)
- self.Refresh()
-
+ diffX = event.GetX() - self.mouse['begin'][0]
+ diffY = event.GetY() - self.mouse['begin'][1]
+
+ if self.mouse['use'] == 'addPoint':
+ self.parent.AddPoint(coordinates = endCoordinates)
+ elif self.mouse['use'] in ('addLine', 'addRectangle'):
+ # not too small lines/rectangles
+ if sqrt(diffX * diffX + diffY * diffY) < 5:
+ self.pdcTmp.RemoveId(self.idZoomBoxTmp)
+ self.Refresh()
+ return
+
+ beginCoordinates = self.CanvasPaperCoordinates(rect = wx.Rect(self.mouse['begin'][0],
+ self.mouse['begin'][1], 0, 0),
+ canvasToPaper = True)[:2]
+ if self.mouse['use'] == 'addLine':
+ self.parent.AddLine(coordinates = [beginCoordinates, endCoordinates])
else:
- self.dragId = -1
- self.pdcTmp.RemoveId(self.idBoxTmp)
- self.pdcTmp.RemoveId(self.idResizeBoxTmp)
- self.Refresh()
-
- elif event.Dragging() and event.MiddleIsDown():
+ self.parent.AddRectangle(coordinates = [beginCoordinates, endCoordinates])
+ self.pdcTmp.RemoveId(self.idZoomBoxTmp)
+ self.Refresh()
+
+ def OnButtonDClick(self, event):
+ """!Open object dialog for editing."""
+ if self.mouse['use'] == 'pointer' and self.dragId != -1:
+ itemCall = {'text':self.parent.OnAddText,
+ 'mapinfo': self.parent.OnAddMapinfo,
+ 'scalebar': self.parent.OnAddScalebar,
+ 'image': self.parent.OnAddImage,
+ 'northArrow' : self.parent.OnAddNorthArrow,
+ 'point': self.parent.AddPoint,
+ 'line': self.parent.AddLine,
+ 'rectangle': self.parent.AddRectangle,
+ 'rasterLegend': self.parent.OnAddLegend,
+ 'vectorLegend': self.parent.OnAddLegend,
+ 'map': self.parent.OnAddMap}
+
+ itemArg = { 'text': dict(event = None, id = self.dragId),
+ 'mapinfo': dict(event = None),
+ 'scalebar': dict(event = None),
+ 'image': dict(event = None, id = self.dragId),
+ 'northArrow': dict(event = None, id = self.dragId),
+ 'point': dict(id = self.dragId),
+ 'line': dict(id = self.dragId),
+ 'rectangle': dict(id = self.dragId),
+ 'rasterLegend': dict(event = None),
+ 'vectorLegend': dict(event = None, page = 1),
+ 'map': dict(event = None, notebook = True)}
+
+ type = self.instruction[self.dragId].type
+ itemCall[type](**itemArg[type])
+
+ def OnDragging(self, event):
+ """!Process panning/resizing/drawing/moving."""
+ if event.MiddleIsDown():
+ # panning
self.mouse['end'] = event.GetPosition()
self.Pan(begin = self.mouse['begin'], end = self.mouse['end'])
self.mouse['begin'] = event.GetPosition()
-
- elif event.Dragging() and event.LeftIsDown():
- #draw box when zooming, creating map
- if self.mouse['use'] in ('zoomin', 'zoomout', 'addMap'):
+
+ elif event.LeftIsDown():
+ # draw box when zooming, creating map
+ if self.mouse['use'] in ('zoomin', 'zoomout', 'addMap', 'addLine', 'addRectangle'):
self.mouse['end'] = event.GetPosition()
r = wx.Rect(self.mouse['begin'][0], self.mouse['begin'][1],
self.mouse['end'][0]-self.mouse['begin'][0], self.mouse['end'][1]-self.mouse['begin'][1])
r = self.modifyRectangle(r)
- self.Draw(pen = self.pen['box'], brush = self.brush['box'], pdc = self.pdcTmp, drawid = self.idZoomBoxTmp,
- pdctype = 'rect', bb = r)
-
+
+ if self.mouse['use'] in ('addLine', 'addRectangle'):
+ if self.mouse['use'] == 'addLine':
+ pdcType = 'line'
+ lineCoords = (self.mouse['begin'], self.mouse['end'])
+ else:
+ pdcType = 'rect'
+ lineCoords = None
+ if r[2] < 2 or r[3] < 2:
+ # to avoid strange behavoiur
+ return
+
+ self.Draw(pen = self.pen['line'], brush = self.brush['line'],
+ pdc = self.pdcTmp, drawid = self.idZoomBoxTmp,
+ pdctype = pdcType, bb = r, lineCoords = lineCoords)
+
+ else:
+ self.Draw(pen = self.pen['box'], brush = self.brush['box'],
+ pdc = self.pdcTmp, drawid = self.idZoomBoxTmp,
+ pdctype = 'rect', bb = r)
+
# panning
if self.mouse["use"] == 'pan':
self.mouse['end'] = event.GetPosition()
self.Pan(begin = self.mouse['begin'], end = self.mouse['end'])
self.mouse['begin'] = event.GetPosition()
-
- #move object
+
+ # move object
if self.mouse['use'] == 'pointer' and self.dragId != -1:
-
self.mouse['end'] = event.GetPosition()
dx, dy = self.mouse['end'][0] - self.begin[0], self.mouse['end'][1] - self.begin[1]
self.pdcObj.TranslateId(self.dragId, dx, dy)
self.pdcTmp.TranslateId(self.idBoxTmp, dx, dy)
self.pdcTmp.TranslateId(self.idResizeBoxTmp, dx, dy)
+ for id in self.idLinePointsTmp:
+ self.pdcTmp.TranslateId(id, dx, dy)
if self.instruction[self.dragId].type == 'text':
self.instruction[self.dragId]['coords'] = self.instruction[self.dragId]['coords'][0] + dx,\
self.instruction[self.dragId]['coords'][1] + dy
self.begin = event.GetPosition()
self.Refresh()
-
+
# resize object
if self.mouse['use'] == 'resize':
- type = self.instruction[self.dragId].type
pos = event.GetPosition()
- x, y = self.mapBounds.GetX(), self.mapBounds.GetY()
- width, height = self.mapBounds.GetWidth(), self.mapBounds.GetHeight()
diffX = pos[0] - self.mouse['begin'][0]
diffY = pos[1] - self.mouse['begin'][1]
- # match given region
- if self.constraint:
- if width > height:
+ if self.instruction[self.dragId].type == 'map':
+ x, y = self.mapBounds.GetX(), self.mapBounds.GetY()
+ width, height = self.mapBounds.GetWidth(), self.mapBounds.GetHeight()
+ # match given region
+ if self.constraint:
+ if width > height:
+ newWidth = width + diffX
+ newHeight = height + diffX * (float(height) / width)
+ else:
+ newWidth = width + diffY * (float(width) / height)
+ newHeight = height + diffY
+ else:
newWidth = width + diffX
- newHeight = height + diffX * (float(height) / width)
- else:
- newWidth = width + diffY * (float(width) / height)
newHeight = height + diffY
- else:
- newWidth = width + diffX
- newHeight = height + diffY
-
- if newWidth < 10 or newHeight < 10:
- return
-
- bounds = wx.Rect(x, y, newWidth, newHeight)
- self.Draw(pen = self.pen[type], brush = self.brush[type], pdc = self.pdcObj, drawid = self.dragId,
- pdctype = 'rectText', bb = bounds)
- self.RedrawSelectBox(self.dragId)
-
- elif event.LeftUp():
- # zoom in, zoom out
- if self.mouse['use'] in ('zoomin','zoomout'):
- zoomR = self.pdcTmp.GetIdBounds(self.idZoomBoxTmp)
- self.pdcTmp.RemoveId(self.idZoomBoxTmp)
- self.Refresh()
- zoomFactor, view = self.ComputeZoom(zoomR)
- self.Zoom(zoomFactor, view)
+
+ if newWidth < 10 or newHeight < 10:
+ return
-
- # draw map frame
- if self.mouse['use'] == 'addMap':
- rectTmp = self.pdcTmp.GetIdBounds(self.idZoomBoxTmp)
- # too small rectangle, it's usually some mistake
- if rectTmp.GetWidth() < 20 or rectTmp.GetHeight() < 20:
- self.pdcTmp.RemoveId(self.idZoomBoxTmp)
- self.Refresh()
- return
- rectPaper = self.CanvasPaperCoordinates(rect = rectTmp, canvasToPaper = True)
-
- dlg = MapDialog(parent = self.parent, id = [None, None, None], settings = self.instruction,
- rect = rectPaper)
- self.openDialogs['map'] = dlg
- self.openDialogs['map'].Show()
-
-
- self.mouse['use'] = self.parent.mouseOld
+ bounds = wx.Rect(x, y, newWidth, newHeight)
+ self.Draw(pen = self.pen['map'], brush = self.brush['map'], pdc = self.pdcObj, drawid = self.dragId,
+ pdctype = 'rectText', bb = bounds)
- self.SetCursor(self.parent.cursorOld)
- self.parent.toolbar.ToggleTool(self.parent.actionOld, True)
- self.parent.toolbar.ToggleTool(self.parent.toolbar.action['id'], False)
- self.parent.toolbar.action['id'] = self.parent.actionOld
-
+ elif self.instruction[self.dragId].type == 'rectangle':
+ instr = self.instruction[self.dragId]
+ rect = self.CanvasPaperCoordinates(rect = instr['rect'], canvasToPaper = False)
+ rect.SetWidth(rect.GetWidth() + diffX)
+ rect.SetHeight(rect.GetHeight() + diffY)
+ if rect.GetWidth() < 5 or rect.GetHeight() < 5:
+ return
- # resize resizable objects (only map sofar)
- if self.mouse['use'] == 'resize':
- mapId = self.instruction.FindInstructionByType('map').id
-
- if self.dragId == mapId:
- # necessary to change either map frame (scaleType 0,1,2) or region (scaletype 3)
- newRectCanvas = self.pdcObj.GetIdBounds(mapId)
- newRectPaper = self.CanvasPaperCoordinates(rect = newRectCanvas, canvasToPaper = True)
- self.instruction[mapId]['rect'] = newRectPaper
-
- if self.instruction[mapId]['scaleType'] in (0, 1, 2):
- if self.instruction[mapId]['scaleType'] == 0:
-
- scale, foo, rect = AutoAdjust(self, scaleType = 0,
- map = self.instruction[mapId]['map'],
- mapType = self.instruction[mapId]['mapType'],
- rect = self.instruction[mapId]['rect'])
-
- elif self.instruction[mapId]['scaleType'] == 1:
- scale, foo, rect = AutoAdjust(self, scaleType = 1,
- region = self.instruction[mapId]['region'],
- rect = self.instruction[mapId]['rect'])
- else:
- scale, foo, rect = AutoAdjust(self, scaleType = 2,
- rect = self.instruction[mapId]['rect'])
- self.instruction[mapId]['rect'] = rect
- self.instruction[mapId]['scale'] = scale
-
- rectCanvas = self.CanvasPaperCoordinates(rect = rect, canvasToPaper = False)
- self.Draw(pen = self.pen['map'], brush = self.brush['map'],
- pdc = self.pdcObj, drawid = mapId, pdctype = 'rectText', bb = rectCanvas)
-
- elif self.instruction[mapId]['scaleType'] == 3:
- ComputeSetRegion(self, mapDict = self.instruction[mapId].GetInstruction())
- #check resolution
- SetResolution(dpi = self.instruction[mapId]['resolution'],
- width = self.instruction[mapId]['rect'].width,
- height = self.instruction[mapId]['rect'].height)
-
- self.RedrawSelectBox(mapId)
- self.Zoom(zoomFactor = 1, view = (0, 0))
- self.mouse['use'] = 'pointer'
-
- # recalculate the position of objects after dragging
- if self.mouse['use'] in ('pointer', 'resize') and self.dragId != -1:
- if self.mouse['begin'] != event.GetPosition(): #for double click
-
- self.RecalculatePosition(ids = [self.dragId])
- if self.instruction[self.dragId].type in self.openDialogs:
- self.openDialogs[self.instruction[self.dragId].type].updateDialog()
+ self.DrawGraphics(drawid = self.dragId, shape = 'rectangle', color = instr['color'],
+ fcolor = instr['fcolor'], width = instr['width'], bb = rect)
- # double click launches dialogs
- elif event.LeftDClick():
- if self.mouse['use'] == 'pointer' and self.dragId != -1:
- itemCall = { 'text':self.parent.OnAddText, 'mapinfo': self.parent.OnAddMapinfo,
- 'scalebar': self.parent.OnAddScalebar, 'image': self.parent.OnAddImage,
- 'northArrow' : self.parent.OnAddNorthArrow,
- 'rasterLegend': self.parent.OnAddLegend, 'vectorLegend': self.parent.OnAddLegend,
- 'map': self.parent.OnAddMap}
- itemArg = { 'text': dict(event = None, id = self.dragId), 'mapinfo': dict(event = None),
- 'scalebar': dict(event = None), 'image': dict(event = None, id = self.dragId),
- 'northArrow': dict(event = None, id = self.dragId),
- 'rasterLegend': dict(event = None), 'vectorLegend': dict(event = None, page = 1),
- 'map': dict(event = None, notebook = True)}
- type = self.instruction[self.dragId].type
- itemCall[type](**itemArg[type])
+ elif self.instruction[self.dragId].type == 'line':
+ instr = self.instruction[self.dragId]
+ points = instr['where']
+ # moving point
+ if self.currentLinePoint == 0:
+ pPaper = points[1]
+ else:
+ pPaper = points[0]
+ pCanvas = self.CanvasPaperCoordinates(rect = Rect2DPS(pPaper, (0, 0)),
+ canvasToPaper = False)[:2]
+ bounds = wx.RectPP(pCanvas, pos)
+ self.DrawGraphics(drawid = self.dragId, shape = 'line', color = instr['color'],
+ width = instr['width'], bb = bounds, lineCoords = (pos, pCanvas))
+ # update paper coordinates
+ points[self.currentLinePoint] = self.CanvasPaperCoordinates(rect = wx.RectPS(pos, (0, 0)),
+ canvasToPaper = True)[:2]
+
+ self.RedrawSelectBox(self.dragId)
+
+ def OnMiddleDown(self, event):
+ """!Middle mouse button pressed."""
+ self.mouse['begin'] = event.GetPosition()
+
def Pan(self, begin, end):
"""!Move canvas while dragging.
@@ -1381,7 +1660,7 @@
def RecalculatePosition(self, ids):
for id in ids:
itype = self.instruction[id].type
- if itype == 'map':
+ if itype in ('map', 'rectangle'):
self.instruction[id]['rect'] = self.CanvasPaperCoordinates(rect = self.pdcObj.GetIdBounds(id),
canvasToPaper = True)
self.RecalculateEN()
@@ -1393,6 +1672,30 @@
canvasToPaper = True)[:2]
if itype in ('image', 'northArrow'):
self.RecalculateEN()
+
+ elif itype == 'point':
+ rect = self.pdcObj.GetIdBounds(id)
+ self.instruction[id]['rect'] = self.CanvasPaperCoordinates(rect = rect,
+ canvasToPaper = True)
+ rect.OffsetXY(rect.GetWidth()/2, rect.GetHeight()/2)
+ self.instruction[id]['where'] = self.CanvasPaperCoordinates(rect = rect,
+ canvasToPaper = True)[:2]
+ self.RecalculateEN()
+
+ elif itype == 'line':
+ rect = self.pdcObj.GetIdBounds(id)
+ oldRect = self.instruction[id]['rect']
+ newRect = self.CanvasPaperCoordinates(rect = rect, canvasToPaper = True)
+ xDiff = newRect[0] - oldRect[0]
+ yDiff = newRect[1] - oldRect[1]
+ self.instruction[id]['rect'] = newRect
+
+ point1 = wx.Point2D(xDiff, yDiff) + self.instruction[id]['where'][0]
+ point2 = wx.Point2D(xDiff, yDiff) + self.instruction[id]['where'][1]
+ self.instruction[id]['where'] = [point1, point2]
+
+ self.RecalculateEN()
+
elif itype == 'scalebar':
self.instruction[id]['rect'] = self.CanvasPaperCoordinates(rect = self.pdcObj.GetIdBounds(id),
canvasToPaper = True)
@@ -1420,7 +1723,7 @@
x += extent[0]/2 * cos(rot)
y -= extent[0]/2 * sin(rot)
- self.instruction[id]['where'] = self.CanvasPaperCoordinates(rect = wx.Rect2D(x, y, 0, 0),
+ self.instruction[id]['where'] = self.CanvasPaperCoordinates(rect = Rect2D(x, y, 0, 0),
canvasToPaper = True)[:2]
self.RecalculateEN()
@@ -1510,6 +1813,27 @@
elif type == 'northArrow':
self.Draw(pen = self.pen[type], brush = self.brush[type], pdc = self.pdcObj,
drawid = id, pdctype = 'bitmap', bb = oRect)
+
+ elif type in ('point', 'line', 'rectangle'):
+ instr = self.instruction[id]
+ color = self.instruction[id]['color']
+ width = fcolor = coords = None
+
+ if type in ('point', 'rectangle'):
+ fcolor = self.instruction[id]['fcolor']
+ if type in ('line', 'rectangle'):
+ width = self.instruction[id]['width']
+ if type in ('line'):
+ point1, point2 = instr['where'][0], instr['where'][1]
+ point1 = self.CanvasPaperCoordinates(rect = Rect2DPS(point1, (0, 0)),
+ canvasToPaper = False)[:2]
+ point2 = self.CanvasPaperCoordinates(rect = Rect2DPS(point2, (0, 0)),
+ canvasToPaper = False)[:2]
+ coords = (point1, point2)
+
+ self.DrawGraphics(drawid = id, shape = type, bb = oRect, lineCoords = coords,
+ color = color, fcolor = fcolor, width = width)
+
else:
self.Draw(pen = self.pen[type], brush = self.brush[type], pdc = self.pdcObj,
drawid = id, pdctype = 'rectText', bb = oRect)
@@ -1534,8 +1858,14 @@
zoomFactor, view = self.ComputeZoom(zoomP)
self.Zoom(zoomFactor, view)
- def Draw(self, pen, brush, pdc, drawid = None, pdctype = 'rect', bb = wx.Rect(0,0,0,0)):
- """! Draw object"""
+ def Draw(self, pen, brush, pdc, drawid = None, pdctype = 'rect', bb = wx.Rect(0,0,0,0), lineCoords = None):
+ """! Draw object with given pen and brush.
+
+ @param pdc PseudoDC
+ @param pdctype 'bitmap'/'rectText'/'rect'/'point'/'line'
+ @param bb bounding box
+ @param lineCoords coordinates of line start, end points (wx.Point, wx.Point)
+ """
if drawid is None:
drawid = wx.NewId()
bb = bb.Get()
@@ -1580,12 +1910,53 @@
pdc.SetBackgroundMode(wx.TRANSPARENT)
pdc.DrawText(text = text, x = textRect.x, y = textRect.y)
+ elif pdctype == 'point':
+ pdc.DrawCircle(x = bb[0] + bb[2] / 2,
+ y = bb[1] + bb[3] / 2,
+ radius = bb[2] / 2)
+
+ elif pdctype == 'line':
+ pdc.DrawLinePoint(lineCoords[0], lineCoords[1])
+
pdc.SetIdBounds(drawid, bb)
pdc.EndDrawing()
self.Refresh()
return drawid
+ def DrawGraphics(self, drawid, shape, color, bb, width = None, fcolor = None, lineCoords = None):
+ """!Draw point/line/rectangle with given color and width
+
+ @param drawid id of drawn object
+ @param shape drawn shape: 'point'/'line'/'rectangle'
+ @param color pen outline color ('RRR:GGG:BBB')
+ @param fcolor brush fill color, if meaningful ('RRR:GGG:BBB')
+ @param width pen width
+ @param bb bounding box
+ @param lineCoords line coordinates (for line only)
+ """
+ pdctype = {'point' : 'point',
+ 'line' : 'line',
+ 'rectangle' : 'rect'}
+
+ if color == 'none':
+ pen = wx.TRANSPARENT_PEN
+ else:
+ if width is not None:
+ units = UnitConversion(self)
+ width = int(units.convert(value = width, fromUnit = 'point', toUnit = 'pixel') * self.currScale)
+ else:
+ width = 2
+ pen = wx.Pen(colour = convertRGB(color), width = width)
+ pen.SetCap(wx.CAP_BUTT) # this is how ps.map draws
+
+ brush = wx.TRANSPARENT_BRUSH
+ if fcolor and fcolor != 'none':
+ brush = wx.Brush(colour = convertRGB(fcolor))
+
+ self.Draw(pen = pen, brush = brush, pdc = self.pdcObj, pdctype = pdctype[shape],
+ drawid = drawid, bb = bb, lineCoords = lineCoords)
+
def DrawBitmap(self, pdc, filePath, rotation, bbox):
"""!Draw bitmap using PIL"""
pImg = PILImage.open(filePath)
@@ -1702,17 +2073,32 @@
def RedrawSelectBox(self, id):
"""!Redraws select box when selected object changes its size"""
if self.dragId == id:
- rect = [self.pdcObj.GetIdBounds(id).Inflate(3,3)]
- type = ['select']
- ids = [self.idBoxTmp]
- if self.instruction[id].type == 'map':
+ rect = self.pdcObj.GetIdBounds(id)
+ if self.instruction[id].type != 'line':
+ rect = rect.Inflate(3,3)
+ # draw select box around object
+ self.Draw(pen = self.pen['select'], brush = self.brush['select'], pdc = self.pdcTmp,
+ drawid = self.idBoxTmp, pdctype = 'rect', bb = rect)
+
+ # draw small marks signalizing resizing
+ if self.instruction[id].type in ('map', 'rectangle'):
controlP = self.pdcObj.GetIdBounds(id).GetBottomRight()
- rect.append(wx.Rect(controlP.x, controlP.y, 10,10))
- type.append('resize')
- ids.append(self.idResizeBoxTmp)
- for id, type, rect in zip(ids, type, rect):
- self.Draw(pen = self.pen[type], brush = self.brush[type], pdc = self.pdcTmp,
- drawid = id, pdctype = 'rect', bb = rect)
+ rect = wx.RectPS(controlP, self.resizeBoxSize)
+ self.Draw(pen = self.pen['resize'], brush = self.brush['resize'], pdc = self.pdcTmp,
+ drawid = self.idResizeBoxTmp, pdctype = 'rect', bb = rect)
+
+ elif self.instruction[id].type == 'line':
+ p1Paper = self.instruction[id]['where'][0]
+ p2Paper = self.instruction[id]['where'][1]
+ p1Canvas = self.CanvasPaperCoordinates(rect = Rect2DPS(p1Paper, (0, 0)), canvasToPaper = False)[:2]
+ p2Canvas = self.CanvasPaperCoordinates(rect = Rect2DPS(p2Paper, (0, 0)), canvasToPaper = False)[:2]
+ rect = []
+ box = wx.RectS(self.resizeBoxSize)
+ rect.append(box.CenterIn(wx.RectPS(p1Canvas, wx.Size())))
+ rect.append(box.CenterIn(wx.RectPS(p2Canvas, wx.Size())))
+ for i, point in enumerate((p1Canvas, p2Canvas)):
+ self.Draw(pen = self.pen['resize'], brush = self.brush['resize'], pdc = self.pdcTmp,
+ drawid = self.idLinePointsTmp[i], pdctype = 'rect', bb = rect[i])
def UpdateMapLabel(self):
"""!Updates map frame label"""
Copied: grass/branches/develbranch_6/gui/wxpython/psmap/instructions.py (from rev 50798, grass/trunk/gui/wxpython/psmap/instructions.py)
===================================================================
--- grass/branches/develbranch_6/gui/wxpython/psmap/instructions.py (rev 0)
+++ grass/branches/develbranch_6/gui/wxpython/psmap/instructions.py 2012-02-17 06:45:00 UTC (rev 50840)
@@ -0,0 +1,1811 @@
+"""!
+ at package psmap.instructions
+
+ at brief Map feature objects
+
+Classes:
+ - dialogs::Instruction
+ - dialogs::InstructionObject
+ - dialogs::InitMap
+ - dialogs::MapFrame
+ - dialogs::PageSetup
+ - dialogs::Mapinfo
+ - dialogs::Text
+ - dialogs::Image
+ - dialogs::NorthArrow
+ - dialogs::Point
+ - dialogs::Line
+ - dialogs::Rectangle
+ - dialogs::Scalebar
+ - dialogs::RasterLegend
+ - dialogs::VectorLegend
+ - dialogs::Raster
+ - dialogs::Vector
+ - dialogs::VProperties
+
+(C) 2011-2012 by Anna Kratochvilova, and the GRASS Development Team
+
+This program is free software under the GNU General Public License
+(>=v2). Read the file COPYING that comes with GRASS for details.
+
+ at author Anna Kratochvilova <kratochanna gmail.com> (bachelor's project)
+ at author Martin Landa <landa.martin gmail.com> (mentor)
+"""
+
+import os
+import string
+from math import ceil
+from time import strftime, localtime
+
+import wx
+import grass.script as grass
+
+from core.gcmd import RunCommand, GError, GMessage, GWarning
+from core.utils import CmdToTuple, GetCmdString
+from dbmgr.vinfo import VectorDBInfo
+from psmap.utils import *
+
+class Instruction:
+ """!Class which represents instruction file"""
+ def __init__(self, parent, objectsToDraw):
+
+ self.parent = parent
+ self.objectsToDraw = objectsToDraw
+ #here are kept objects like mapinfo, rasterlegend, etc.
+ self.instruction = list()
+
+ def __str__(self):
+ """!Returns text for instruction file"""
+ comment = "# timestamp: " + strftime("%Y-%m-%d %H:%M", localtime()) + '\n'
+ env = grass.gisenv()
+ comment += "# location: %s\n" % env['LOCATION_NAME']
+ comment += "# mapset: %s\n" % env['MAPSET']
+ comment += "# page orientation: %s\n" % self.FindInstructionByType('page')['Orientation']
+ border = ''
+ if not self.FindInstructionByType('map'):
+ border = 'border n\n'
+ text = [str(each) for each in self.instruction]
+ return comment + border + '\n'.join(text) + '\nend'
+
+ def __getitem__(self, id):
+ for each in self.instruction:
+ if each.id == id:
+ return each
+ return None
+
+ def __contains__(self, id):
+ """!Test if instruction is included"""
+ for each in self.instruction:
+ if each.id == id:
+ return True
+ return False
+
+ def __delitem__(self, id):
+ """!Delete instruction"""
+ for each in self.instruction:
+ if each.id == id:
+ if each.type == 'map':
+ #must remove raster, vector layers too
+ vektor = self.FindInstructionByType('vector', list = True)
+ vProperties = self.FindInstructionByType('vProperties', list = True)
+ raster = self.FindInstructionByType('raster', list = True)
+ for item in vektor + vProperties + raster:
+ if item in self.instruction:
+ self.instruction.remove(item)
+
+ self.instruction.remove(each)
+ if id in self.objectsToDraw:
+ self.objectsToDraw.remove(id)
+ return
+
+ def AddInstruction(self, instruction):
+ """!Add instruction"""
+ # add to instructions
+ if instruction.type == 'map':
+ self.instruction.insert(0, instruction)
+ else:
+ self.instruction.append(instruction)
+ # add to drawable objects
+ if instruction.type not in ('page', 'raster', 'vector', 'vProperties', 'initMap'):
+ if instruction.type == 'map':
+ self.objectsToDraw.insert(0, instruction.id)
+ else:
+ self.objectsToDraw.append(instruction.id)
+
+
+ def FindInstructionByType(self, type, list = False):
+ """!Find instruction(s) with the given type"""
+ inst = []
+ for each in self.instruction:
+ if each.type == type:
+ inst.append(each)
+ if len(inst) == 1 and not list:
+ return inst[0]
+ return inst
+
+ def Read(self, filename):
+ """!Reads instruction file and creates instruction objects"""
+ self.filename = filename
+ # open file
+ try:
+ file = open(filename, 'r')
+ except IOError:
+ GError(message = _("Unable to open file\n%s") % filename)
+ return
+ # first read file to get information about region and scaletype
+ isRegionComment = False
+ orientation = 'Portrait'
+ for line in file:
+ if '# g.region' in line:
+ self.SetRegion(regionInstruction = line)
+ isRegionComment = True
+ break
+ if '# page orientation' in line:
+ orientation = line.split(':')[-1].strip()
+
+ if not isRegionComment:
+ self.SetRegion(regionInstruction = None)
+ # then run ps.map -b to get information for maploc
+ # compute scale and center
+ map = self.FindInstructionByType('map')
+ region = grass.region()
+ map['center'] = (region['n'] + region['s']) / 2, (region['w'] + region['e']) / 2
+ mapRect = GetMapBounds(self.filename, portrait = (orientation == 'Portrait'))
+ map['rect'] = mapRect
+ proj = projInfo()
+ toM = 1.0
+ if proj['units']:
+ toM = float(proj['meters'])
+ units = UnitConversion(self.parent)
+ w = units.convert(value = mapRect.Get()[2], fromUnit = 'inch', toUnit = 'meter') / toM
+ map['scale'] = w / abs((region['w'] - region['e']))
+
+ SetResolution(dpi = 300, width = map['rect'].width, height = map['rect'].height)
+
+ # read file again, now with information about map bounds
+ isBuffer = False
+ buffer = []
+ instruction = None
+ vectorMapNumber = 1
+ file.seek(0)
+ for line in file:
+ if not line.strip():
+ continue
+ line = line.strip()
+ if isBuffer:
+ buffer.append(line)
+ if 'end' in line:
+ isBuffer = False
+ kwargs = {}
+ if instruction == 'scalebar':
+ kwargs['scale'] = map['scale']
+ elif instruction in ('text', 'eps', 'point', 'line', 'rectangle'):
+ kwargs['mapInstruction'] = map
+ elif instruction in ('vpoints', 'vlines', 'vareas'):
+ kwargs['id'] = wx.NewId()
+ kwargs['vectorMapNumber'] = vectorMapNumber
+ vectorMapNumber += 1
+ elif instruction == 'paper':
+ kwargs['Orientation'] = orientation
+
+ ok = self.SendToRead(instruction, buffer, **kwargs)
+ if not ok: return False
+ buffer = []
+ continue
+
+ elif line.startswith('paper'):
+ instruction = 'paper'
+ isBuffer = True
+ buffer.append(line)
+
+ elif line.startswith('border'):
+ if line.split()[1].lower() in ('n', 'no', 'none'):
+ ok = self.SendToRead('border', [line])
+ if not ok: return False
+ elif line.split()[1].lower() in ('y', 'yes'):
+ instruction = 'border'
+ isBuffer = True
+ buffer.append(line)
+
+ elif line.startswith('scale '):
+ if isBuffer:
+ continue
+ ok = self.SendToRead('scale', line, isRegionComment = isRegionComment)
+ if not ok: return False
+
+ elif line.startswith('maploc'):
+ ok = self.SendToRead(instruction = 'maploc', text = line)
+ if not ok: return False
+
+ elif line.startswith('raster'):
+ ok = self.SendToRead(instruction = 'raster', text = line)
+ if not ok: return False
+
+ elif line.startswith('mapinfo'):
+ instruction = 'mapinfo'
+ isBuffer = True
+ buffer.append(line)
+
+
+ elif line.startswith('scalebar'):
+ instruction = 'scalebar'
+ isBuffer = True
+ buffer.append(line)
+
+ elif line.startswith('text'):
+ instruction = 'text'
+ isBuffer = True
+ buffer.append(line)
+
+ elif line.startswith('eps'):
+ instruction = 'eps'
+ isBuffer = True
+ buffer.append(line)
+
+ elif line.startswith('point'):
+ instruction = 'point'
+ isBuffer = True
+ buffer.append(line)
+
+ elif line.startswith('line'):
+ instruction = 'line'
+ isBuffer = True
+ buffer.append(line)
+
+ elif line.startswith('rectangle'):
+ instruction = 'rectangle'
+ isBuffer = True
+ buffer.append(line)
+
+ elif line.startswith('colortable'):
+ if len(line.split()) == 2 and line.split()[1].lower() in ('n', 'no', 'none'):
+ break
+ instruction = 'colortable'
+ isBuffer = True
+ buffer.append(line)
+
+ elif line.startswith('vlegend'):
+ instruction = 'vlegend'
+ isBuffer = True
+ buffer.append(line)
+
+ elif line.startswith('vpoints'):
+ instruction = 'vpoints'
+ isBuffer = True
+ buffer.append(line)
+
+ elif line.startswith('vlines'):
+ instruction = 'vlines'
+ isBuffer = True
+ buffer.append(line)
+
+ elif line.startswith('vareas'):
+ instruction = 'vareas'
+ isBuffer = True
+ buffer.append(line)
+
+
+
+ rasterLegend = self.FindInstructionByType('rasterLegend')
+ raster = self.FindInstructionByType('raster')
+ page = self.FindInstructionByType('page')
+ vector = self.FindInstructionByType('vector')
+ vectorLegend = self.FindInstructionByType('vectorLegend')
+ vectorMaps = self.FindInstructionByType('vProperties', list = True)
+
+ # check (in case of scaletype 0) if map is drawn also
+ map['drawMap'] = False
+ if map['scaleType'] == 0:
+ mapForRegion = map['map']
+ if map['mapType'] == 'raster' and raster:
+ if mapForRegion == raster['raster']:
+ map['drawMap'] = True
+ elif map['mapType'] == 'vector' and vector:
+ for vmap in vector['list']:
+ if mapForRegion == vmap[0]:
+ map['drawMap'] = True
+
+ # rasterLegend
+ if rasterLegend:
+ if rasterLegend['rasterDefault'] and raster:
+ rasterLegend['raster'] = raster['raster']
+ if not rasterLegend['discrete']:
+ rasterType = getRasterType(map = rasterLegend['raster'])
+ if rasterType == 'CELL':
+ rasterLegend['discrete'] = 'y'
+ else:
+ rasterLegend['discrete'] = 'n'
+
+ #estimate size
+ height = rasterLegend.EstimateHeight(raster = rasterLegend['raster'], discrete = rasterLegend['discrete'],
+ fontsize = rasterLegend['fontsize'],
+ cols = rasterLegend['cols'],
+ height = rasterLegend['height'])
+ width = rasterLegend.EstimateWidth(raster = rasterLegend['raster'], discrete = rasterLegend['discrete'],
+ fontsize = rasterLegend['fontsize'],
+ cols = rasterLegend['cols'] ,
+ width = rasterLegend['width'],
+ paperInstr = page)
+ rasterLegend['rect'] = Rect2D(x = float(rasterLegend['where'][0]), y = float(rasterLegend['where'][1]),
+ width = width, height = height)
+
+ # vectors, vlegend
+
+ if vector:
+ for vmap in vectorMaps:
+ for i, each in enumerate(vector['list']):
+ if each[2] == vmap.id:
+
+ vector['list'][i][4] = vmap['label']
+ vector['list'][i][3] = vmap['lpos']
+ if vectorLegend:
+ size = vectorLegend.EstimateSize(vectorInstr = vector, fontsize = vectorLegend['fontsize'],
+ width = vectorLegend['width'], cols = vectorLegend['cols'])
+ vectorLegend['rect'] = Rect2D(x = float(vectorLegend['where'][0]), y = float(vectorLegend['where'][1]),
+ width = size[0], height = size[1])
+
+
+ page = self.FindInstructionByType('page')
+ if not page:
+ page = PageSetup(wx.NewId())
+ self.AddInstruction(page)
+ else:
+ page['Orientation'] = orientation
+
+
+ #
+ return True
+
+ def SendToRead(self, instruction, text, **kwargs):
+ psmapInstrDict = dict(paper = ['page'],
+ maploc = ['map'],
+ scale = ['map'],
+ border = ['map'],
+ raster = ['raster'],
+ mapinfo = ['mapinfo'],
+ scalebar = ['scalebar'],
+ text = ['text'],
+ eps = ['image', 'northArrow'],
+ point = ['point'],
+ line = ['line'],
+ rectangle = ['rectangle'],
+ vpoints = ['vector', 'vProperties'],
+ vlines = ['vector', 'vProperties'],
+ vareas = ['vector', 'vProperties'],
+ colortable = ['rasterLegend'],
+ vlegend = ['vectorLegend']
+ )
+
+ myInstrDict = dict(page = PageSetup,
+ map = MapFrame,
+ raster = Raster,
+ mapinfo = Mapinfo,
+ scalebar = Scalebar,
+ text = Text,
+ image = Image,
+ northArrow = NorthArrow,
+ point = Point,
+ line = Line,
+ rectangle = Rectangle,
+ rasterLegend = RasterLegend,
+ vectorLegend = VectorLegend,
+ vector = Vector,
+ vProperties = VProperties
+ )
+
+ myInstruction = psmapInstrDict[instruction]
+
+ for i in myInstruction:
+ instr = self.FindInstructionByType(i)
+ if i in ('text', 'vProperties', 'image', 'northArrow', 'point', 'line', 'rectangle') or not instr:
+
+ id = wx.NewId() #!vProperties expect subtype
+ if i == 'vProperties':
+ id = kwargs['id']
+ newInstr = myInstrDict[i](id, subType = instruction[1:])
+ elif i in ('image', 'northArrow'):
+ commentFound = False
+ for line in text:
+ if line.find("# north arrow") >= 0:
+ commentFound = True
+ if i == 'image' and commentFound or \
+ i == 'northArrow' and not commentFound:
+ continue
+ newInstr = myInstrDict[i](id, settings = self)
+ else:
+ newInstr = myInstrDict[i](id)
+ ok = newInstr.Read(instruction, text, **kwargs)
+ if ok:
+ self.AddInstruction(newInstr)
+ else:
+ return False
+
+ else:
+ ok = instr.Read(instruction, text, **kwargs)
+
+ if not ok:
+ return False
+ return True
+
+ def SetRegion(self, regionInstruction):
+ """!Sets region from file comment or sets current region in case of no comment"""
+ map = MapFrame(wx.NewId())
+ self.AddInstruction(map)
+ if regionInstruction:
+ cmd = CmdToTuple(regionInstruction.strip('# ').split())
+
+ # define scaleType
+ if len(cmd[1]) <= 3:
+ if 'rast' in cmd[1]:
+ map['scaleType'] = 0
+ map['mapType'] = 'raster'
+ map['map'] = cmd[1]['rast']
+ elif 'vect' in cmd[1]:
+ map['scaleType'] = 0
+ map['mapType'] = 'vector'
+ map['map'] = cmd[1]['vect']
+ elif 'region' in cmd[1]:
+ map['scaleType'] = 1
+ map['region'] = cmd[1]['region']
+
+ else:
+ map['scaleType'] = 2
+ else:
+ map['scaleType'] = 2
+ grass.del_temp_region()
+ region = grass.region()
+ grass.use_temp_region()
+ cmd = ['g.region', region]
+ cmdString = GetCmdString(cmd).replace('g.region', '')
+ GMessage(_("Instruction file will be loaded with following region: %s\n") % cmdString)
+ try:
+ RunCommand(cmd[0], **cmd[1])
+
+ except grass.ScriptError, e:
+ GError(_("Region cannot be set\n%s") % e)
+ return False
+
+
+class InstructionObject:
+ """!Abtract class representing single instruction"""
+ def __init__(self, id):
+ self.id = id
+
+ # default values
+ self.defaultInstruction = dict()
+ # current values
+ self.instruction = self.defaultInstruction
+ # converting units
+ self.unitConv = UnitConversion()
+
+ def __str__(self):
+ """!Returns particular part of text instruction"""
+ return ''
+
+ def __getitem__(self, key):
+ for each in self.instruction.keys():
+ if each == key:
+ return self.instruction[key]
+ return None
+
+ def __setitem__(self, key, value):
+ self.instruction[key] = value
+
+ def GetInstruction(self):
+ """!Get current values"""
+ return self.instruction
+
+ def SetInstruction(self, instruction):
+ """!Set default values"""
+ self.instruction = instruction
+
+ def Read(self, instruction, text, **kwargs):
+ """!Read instruction and save them"""
+ pass
+
+ def PercentToReal(self, e, n):
+ """!Converts text coordinates from percent of region to map coordinates"""
+ e, n = float(e.strip('%')), float(n.strip('%'))
+ region = grass.region()
+ N = region['s'] + (region['n'] - region['s']) / 100 * n
+ E = region['w'] + (region['e'] - region['w']) / 100 * e
+ return E, N
+
+class InitMap(InstructionObject):
+ """!Class representing virtual map"""
+ def __init__(self, id):
+ InstructionObject.__init__(self, id = id)
+ self.type = 'initMap'
+
+ # default values
+ self.defaultInstruction = dict(rect = None, scale = None)
+ # current values
+ self.instruction = dict(self.defaultInstruction)
+
+
+class MapFrame(InstructionObject):
+ """!Class representing map (instructions maploc, scale, border)"""
+ def __init__(self, id):
+ InstructionObject.__init__(self, id = id)
+ self.type = 'map'
+ # default values
+ self.defaultInstruction = dict(map = None, mapType = None, drawMap = True, region = None,
+ rect = Rect2D(), scaleType = 0, scale = None, center = None,
+ resolution = 300, border = 'y', width = 1, color = '0:0:0')
+ # current values
+ self.instruction = dict(self.defaultInstruction)
+
+ def __str__(self):
+ instr = ''
+ comment = ''
+
+ #region settings
+ region = grass.region()
+ if self.instruction['scaleType'] == 0: #match map
+ map = self.instruction['map']
+ if self.instruction['mapType'] == 'raster':
+ comment = "# g.region rast=%s nsres=%s ewres=%s\n" % (map, region['nsres'], region['ewres'])
+ else:
+ comment = "# g.region vect=%s\n" % (map)
+ elif self.instruction['scaleType'] == 1:# saved region
+ region = self.instruction['region']
+ comment = "# g.region region=%s\n" % region
+ elif self.instruction['scaleType'] in (2, 3): #current region, fixed scale
+ comment = string.Template("# g.region n=$n s=$s e=$e w=$w rows=$rows cols=$cols \n").substitute(**region)
+
+ instr += comment
+ instr += '\n'
+ # maploc
+ maplocInstruction = "maploc %.3f %.3f" % (self.instruction['rect'].x, self.instruction['rect'].y)
+ if self.instruction['scaleType'] != 3:
+ maplocInstruction += " %.3f %.3f"% (self.instruction['rect'].width, self.instruction['rect'].height)
+ instr += maplocInstruction
+ instr += '\n'
+
+ # scale
+ if self.instruction['scaleType'] == 3: #fixed scale
+ scaleInstruction = "scale 1:%.0f" % (1/self.instruction['scale'])
+ instr += scaleInstruction
+ instr += '\n'
+ # border
+ borderInstruction = ''
+ if self.instruction['border'] == 'n':
+ borderInstruction = "border n"
+ else:
+ borderInstruction = "border y\n"
+ borderInstruction += string.Template(" width $width\n color $color\n").substitute(self.instruction)
+ borderInstruction += " end"
+ instr += borderInstruction
+ instr += '\n'
+
+ return instr
+
+ def Read(self, instruction, text, **kwargs):
+ """!Read instruction and save information"""
+ if 'isRegionComment' in kwargs:
+ isRegionComment = kwargs['isRegionComment']
+ instr = {}
+
+ if instruction == 'border':
+ for line in text:
+ if line.startswith('end'):
+ break
+ try:
+ if line.split()[1].lower() in ('n', 'no', 'none'):
+ instr['border'] = 'n'
+ break
+ elif line.split()[1].lower() in ('y', 'yes'):
+ instr['border'] = 'y'
+ elif line.startswith('width'):
+ instr['width'] = line.split()[1]
+ elif line.startswith('color'):
+ instr['color'] = line.split()[1]
+ except IndexError:
+ GError(_("Failed to read instruction %s") % instruction)
+ return False
+
+ elif instruction == 'scale':
+ try:
+ scaleText = text.strip('scale ').split(':')[1]
+ # when scale instruction given and region comment also, then scaletype is fixed scale
+ if not isRegionComment:
+ instr['scaleType'] = 2
+ else:
+ instr['scaleType'] = 3
+
+ scale = 1/float(scaleText)
+ if abs(scale - self.instruction['scale']) > (0.01 * scale):
+ GWarning(_("Scale has changed, old value: %(old)s\nnew value: %(new)s") % \
+ { 'old' : scale, 'new' : self.instruction['scale'] })
+ except (ValueError, IndexError):
+ GError(_("Failed to read instruction %s.\nUse 1:25000 notation.") % instruction)
+ return False
+
+ elif instruction == 'maploc':
+ maploc = text.strip('maploc ').split()
+ if len(maploc) >= 2:
+ if abs(self.instruction['rect'].Get()[0] - float(maploc[0])) > 0.5 or \
+ abs(self.instruction['rect'].Get()[1] - float(maploc[1])) > 0.5:
+ GWarning(_("Map frame position changed, old value: %(old1)s %(old2)s\nnew value: %(new1)s %(new2)s") % \
+ { 'old1' : maploc[0], 'old2' : maploc[1],
+ 'new1' : self.instruction['rect'].Get()[0], 'new2' : self.instruction['rect'].Get()[1] })
+
+ #instr['rect'] = wx.Rect2D(float(maploc[0]), float(maploc[1]), self.instruction['rect'][2], self.instruction['rect'][3])
+ if len(maploc) == 4:
+ if abs(self.instruction['rect'].Get()[2] - float(maploc[2])) > 0.5 or \
+ abs(self.instruction['rect'].Get()[3] - float(maploc[3])) > 0.5:
+ GWarning(_("Map frame size changed, old value: %(old1)s %(old2)s\nnew value: %(new1)s %(new2)s") % \
+ { 'old1' : maploc[2], 'old2' : maploc[3],
+ 'new1' : self.instruction['rect'].Get()[2], 'new2' : self.instruction['rect'].Get()[3] })
+ #instr['rect'] = wx.Rect2D(*map(float, maploc))
+ self.instruction.update(instr)
+ return True
+
+class PageSetup(InstructionObject):
+ """!Class representing page instruction"""
+ def __init__(self, id):
+ InstructionObject.__init__(self, id = id)
+ self.type = 'page'
+ # default values
+ self.defaultInstruction = dict(Units = 'inch', Format = 'a4', Orientation = 'Portrait',
+ Width = 8.268, Height = 11.693, Left = 0.5, Right = 0.5, Top = 1, Bottom = 1)
+ # current values
+ self.instruction = dict(self.defaultInstruction)
+
+ def __str__(self):
+ if self.instruction['Format'] == 'custom':
+ instr = string.Template("paper\n width $Width\n height $Height\n").substitute(self.instruction)
+ else:
+ instr = string.Template("paper $Format\n").substitute(self.instruction)
+ instr += string.Template(" left $Left\n right $Right\n bottom $Bottom\n top $Top\n end").substitute(self.instruction)
+
+ return instr
+
+ def Read(self, instruction, text, **kwargs):
+ """!Read instruction and save information"""
+ instr = {}
+ self.cats = ['Width', 'Height', 'Left', 'Right', 'Top', 'Bottom']
+ self.subInstr = dict(zip(['width', 'height', 'left', 'right', 'top', 'bottom'], self.cats))
+
+ if instruction == 'paper': # just for sure
+ for line in text:
+ if line.startswith('paper'):
+ if len(line.split()) > 1:
+ pformat = line.split()[1]
+ availableFormats = self._toDict(grass.read_command('ps.map', flags = 'p',
+ quiet = True))
+ # e.g. paper a3
+ try:
+ instr['Format'] = pformat
+ for key, value in availableFormats[pformat].iteritems():
+ instr[key] = float(value)
+ break
+ except KeyError:
+ GError(_("Failed to read instruction %(file)s.\nUnknown format %(for)s") % \
+ { 'file' : instruction, 'for' : format })
+ return False
+ else:
+ # paper
+ # width ...
+ instr['Format'] = 'custom'
+ # read subinstructions
+ elif instr['Format'] == 'custom' and not line.startswith('end'):
+ text = line.split()
+ try:
+ instr[self.subInstr[text[0]]] = float(text[1])
+ except (IndexError, KeyError):
+ GError(_("Failed to read instruction %s.") % instruction)
+ return False
+
+ if 'Orientation' in kwargs and kwargs['Orientation'] == 'Landscape':
+ instr['Width'], instr['Height'] = instr['Height'], instr['Width']
+
+ self.instruction.update(instr)
+ return True
+
+ def _toDict(self, paperStr):
+ sizeDict = dict()
+# cats = self.subInstr[ 'Width', 'Height', 'Left', 'Right', 'Top', 'Bottom']
+ for line in paperStr.strip().split('\n'):
+ d = dict(zip(self.cats, line.split()[1:]))
+ sizeDict[line.split()[0]] = d
+
+ return sizeDict
+
+class Mapinfo(InstructionObject):
+ """!Class representing mapinfo instruction"""
+ def __init__(self, id):
+ InstructionObject.__init__(self, id = id)
+ self.type = 'mapinfo'
+ # default values
+ self.defaultInstruction = dict(unit = 'inch', where = (0, 0),
+ font = 'Helvetica', fontsize = 10, color = '0:0:0', background = 'none',
+ border = 'none', rect = None)
+ # current values
+ self.instruction = dict(self.defaultInstruction)
+
+ def __str__(self):
+ instr = "mapinfo\n"
+ instr += " where %.3f %.3f\n" % (self.instruction['where'][0], self.instruction['where'][1])
+ instr += string.Template(" font $font\n fontsize $fontsize\n color $color\n").substitute(self.instruction)
+ instr += string.Template(" background $background\n border $border\n").substitute(self.instruction)
+ instr += " end"
+ return instr
+
+ def Read(self, instruction, text):
+ """!Read instruction and save information"""
+ instr = {}
+ try:
+ for line in text:
+ sub = line.split(None,1)
+ if sub[0] == 'font':
+ instr['font'] = sub[1]
+ elif sub[0] == 'fontsize':
+ instr['fontsize'] = int(sub[1])
+ elif sub[0] == 'color':
+ instr['color'] = sub[1]
+ elif sub[0] == 'background':
+ instr['background'] = sub[1]
+ elif sub[0] == 'border':
+ instr['border'] = sub[1]
+ elif sub[0] == 'where':
+ instr['where'] = float(sub[1].split()[0]), float(sub[1].split()[1])
+ except (ValueError, IndexError):
+ GError(_("Failed to read instruction %s") % instruction)
+ return False
+ self.instruction.update(instr)
+ self.instruction['rect'] = self.EstimateRect(mapinfoDict = self.instruction)
+ return True
+
+ def EstimateRect(self, mapinfoDict):
+ """!Estimate size to draw mapinfo"""
+ w = mapinfoDict['fontsize'] * 20 # any better estimation?
+ h = mapinfoDict['fontsize'] * 7
+ width = self.unitConv.convert(value = w, fromUnit = 'point', toUnit = 'inch')
+ height = self.unitConv.convert(value = h, fromUnit = 'point', toUnit = 'inch')
+ return Rect2D(x = float(mapinfoDict['where'][0]), y = float(mapinfoDict['where'][1]),
+ width = width, height = height)
+
+class Text(InstructionObject):
+ """!Class representing text instruction"""
+ def __init__(self, id):
+ InstructionObject.__init__(self, id = id)
+ self.type = 'text'
+ # default values
+ self.defaultInstruction = dict(text = "", font = "Helvetica", fontsize = 10, color = 'black', background = 'none',
+ hcolor = 'none', hwidth = 1, border = 'none', width = '1', XY = True,
+ where = (0,0), unit = 'inch', rotate = None,
+ ref = "center center", xoffset = 0, yoffset = 0, east = None, north = None)
+ # current values
+ self.instruction = dict(self.defaultInstruction)
+
+ def __str__(self):
+ text = self.instruction['text'].replace('\n','\\n')
+ instr = u"text %s %s" % (self.instruction['east'], self.instruction['north'])
+ instr += " %s\n" % text
+ instr += (string.Template(" font $font\n fontsize $fontsize\n color $color\n").
+ substitute(self.instruction))
+ instr += string.Template(" hcolor $hcolor\n").substitute(self.instruction)
+ if self.instruction['hcolor'] != 'none':
+ instr += string.Template(" hwidth $hwidth\n").substitute(self.instruction)
+ instr += string.Template(" border $border\n").substitute(self.instruction)
+ if self.instruction['border'] != 'none':
+ instr += string.Template(" width $width\n").substitute(self.instruction)
+ instr += string.Template(" background $background\n").substitute(self.instruction)
+ if self.instruction["ref"] != '0':
+ instr += string.Template(" ref $ref\n").substitute(self.instruction)
+ if self.instruction["rotate"]:
+ instr += string.Template(" rotate $rotate\n").substitute(self.instruction)
+ if float(self.instruction["xoffset"]) or float(self.instruction["yoffset"]):
+ instr += (string.Template(" xoffset $xoffset\n yoffset $yoffset\n").
+ substitute(self.instruction))
+ instr += " end"
+ try:
+ instr = instr.encode('latin1')
+ except UnicodeEncodeError, err:
+ try:
+ pos = str(err).split('position')[1].split(':')[0].strip()
+ except IndexError:
+ pos = ''
+ if pos:
+ message = _("Characters on position %s are not supported "
+ "by ISO-8859-1 (Latin 1) encoding "
+ "which is required by module ps.map.") % pos
+ else:
+ message = _("Not all characters are supported "
+ "by ISO-8859-1 (Latin 1) encoding "
+ "which is required by module ps.map.")
+ GMessage(message = message)
+ return ''
+
+ return instr
+
+ def Read(self, instruction, text, **kwargs):
+ """!Read instruction and save information"""
+ map = kwargs['mapInstruction']
+ instr = {}
+ for line in text:
+ try:
+ sub = line.split(None, 1)[0]
+ if sub == 'text':
+ e, n = line.split(None, 3)[1:3]
+ if '%' in e and '%' in n:
+ instr['XY'] = True
+ instr['east'], instr['north'] = self.PercentToReal(e, n)
+ else:
+ instr['XY'] = False
+ instr['east'], instr['north'] = float(e), float(n)
+
+ instr['text'] = line.split(None, 3)[3].decode('latin_1')
+
+ elif sub == 'font':
+ instr['font'] = line.split(None, 1)[1]
+ elif sub == 'fontsize':
+ instr['fontsize'] = float(line.split(None, 1)[1])
+ elif sub == 'color':
+ instr['color'] = line.split(None, 1)[1]
+ elif sub == 'width':
+ instr['width'] = line.split(None, 1)[1]
+ elif sub == 'hcolor':
+ instr['hcolor'] = line.split(None, 1)[1]
+ elif sub == 'hwidth':
+ instr['hwidth'] = line.split(None, 1)[1]
+ elif sub == 'background':
+ instr['background'] = line.split(None, 1)[1]
+ elif sub == 'border':
+ instr['border'] = line.split(None, 1)[1]
+ elif sub == 'ref':
+ instr['ref'] = line.split(None, 1)[1]
+ elif sub == 'rotate':
+ instr['rotate'] = float(line.split(None, 1)[1])
+ elif sub == 'xoffset':
+ instr['xoffset'] = int(line.split(None, 1)[1])
+ elif sub == 'yoffset':
+ instr['yoffset'] = int(line.split(None, 1)[1])
+ elif sub == 'opaque':
+ if line.split(None, 1)[1].lower() in ('n', 'none'):
+ instr['background'] = 'none'
+
+ except(IndexError, ValueError):
+ GError(_("Failed to read instruction %s") % instruction)
+ return False
+ instr['where'] = PaperMapCoordinates(mapInstr = map, x = instr['east'], y = instr['north'], paperToMap = False)
+ self.instruction.update(instr)
+
+ return True
+
+class Image(InstructionObject):
+ """!Class representing eps instruction - image"""
+ def __init__(self, id, settings):
+ InstructionObject.__init__(self, id = id)
+ self.settings = settings
+ self.type = 'image'
+ # default values
+ self.defaultInstruction = dict(epsfile = "", XY = True, where = (0,0), unit = 'inch',
+ east = None, north = None,
+ rotate = None, scale = 1)
+ # current values
+ self.instruction = dict(self.defaultInstruction)
+
+ def __str__(self):
+ self.ChangeRefPoint(toCenter = True)
+
+ instr = "eps %s %s\n" % (self.instruction['east'], self.instruction['north'])
+ instr += string.Template(" epsfile $epsfile\n").substitute(self.instruction)
+ if self.instruction["rotate"]:
+ instr += string.Template(" rotate $rotate\n").substitute(self.instruction)
+ if self.instruction["scale"]:
+ instr += string.Template(" scale $scale\n").substitute(self.instruction)
+ instr += " end"
+ return instr
+
+ def Read(self, instruction, text, **kwargs):
+ """!Read instruction and save information"""
+ mapInstr = kwargs['mapInstruction']
+ instr = {}
+ for line in text:
+ try:
+ sub = line.split(None, 1)[0]
+ if sub == 'eps':
+ e, n = line.split(None, 3)[1:3]
+ if '%' in e and '%' in n:
+ instr['XY'] = True
+ instr['east'], instr['north'] = self.PercentToReal(e, n)
+ else:
+ instr['XY'] = False
+ instr['east'], instr['north'] = float(e), float(n)
+
+ elif sub == 'epsfile':
+ instr['epsfile'] = line.split(None, 1)[1]
+ elif sub == 'rotate':
+ instr['rotate'] = float(line.split(None, 1)[1])
+ elif sub == 'scale':
+ instr['scale'] = float(line.split(None, 1)[1])
+
+ except(IndexError, ValueError):
+ GError(_("Failed to read instruction %s") % instruction)
+ return False
+ if not os.path.exists(instr['epsfile']):
+ GError(_("Failed to read instruction %(inst)s: "
+ "file %(file)s not found.") % { 'inst' : instruction,
+ 'file' : instr['epsfile'] })
+ return False
+
+ instr['epsfile'] = os.path.abspath(instr['epsfile'])
+ instr['size'] = self.GetImageOrigSize(instr['epsfile'])
+ if 'rotate' in instr:
+ instr['size'] = BBoxAfterRotation(instr['size'][0], instr['size'][1], instr['rotate'])
+ self.instruction.update(instr)
+ self.ChangeRefPoint(toCenter = False)
+ instr['where'] = PaperMapCoordinates(mapInstr = mapInstr, x = self.instruction['east'],
+ y = self.instruction['north'], paperToMap = False)
+ w = self.unitConv.convert(value = instr['size'][0], fromUnit = 'point', toUnit = 'inch')
+ h = self.unitConv.convert(value = instr['size'][1], fromUnit = 'point', toUnit = 'inch')
+ instr['rect'] = Rect2D(x = float(instr['where'][0]), y = float(instr['where'][1]),
+ width = w * self.instruction['scale'], height = h * self.instruction['scale'])
+ self.instruction.update(instr)
+
+ return True
+
+ def ChangeRefPoint(self, toCenter):
+ """!Change reference point (left top x center)"""
+ mapInstr = self.settings.FindInstructionByType('map')
+ if not mapInstr:
+ mapInstr = self.settings.FindInstructionByType('initMap')
+ mapId = mapInstr.id
+ if toCenter:
+ center = self.instruction['rect'].GetCentre()
+ ENCenter = PaperMapCoordinates(mapInstr = self.settings[mapId],
+ x = center[0], y = center[1], paperToMap = True)
+
+ self.instruction['east'], self.instruction['north'] = ENCenter
+ else:
+ x, y = PaperMapCoordinates(mapInstr = self.settings[mapId], x = self.instruction['east'],
+ y = self.instruction['north'], paperToMap = False)
+ w = self.unitConv.convert(value = self.instruction['size'][0], fromUnit = 'point', toUnit = 'inch')
+ h = self.unitConv.convert(value = self.instruction['size'][1], fromUnit = 'point', toUnit = 'inch')
+ x -= w * self.instruction['scale'] / 2
+ y -= h * self.instruction['scale'] / 2
+ e, n = PaperMapCoordinates(mapInstr = self.settings[mapId], x = x, y = y, paperToMap = True)
+ self.instruction['east'], self.instruction['north'] = e, n
+
+ def GetImageOrigSize(self, imagePath):
+ """!Get image size.
+
+ If eps, size is read from image header.
+ """
+ fileName = os.path.split(imagePath)[1]
+ # if eps, read info from header
+ if os.path.splitext(fileName)[1].lower() == '.eps':
+ bbInfo = "%%BoundingBox"
+ file = open(imagePath,"r")
+ w = h = 0
+ while file:
+ line = file.readline()
+ if line.find(bbInfo) == 0:
+ w, h = line.split()[3:5]
+ break
+ file.close()
+ return float(w), float(h)
+ else: # we can use wx.Image
+ img = wx.Image(fileName, type=wx.BITMAP_TYPE_ANY)
+ return img.GetWidth(), img.GetHeight()
+
+class NorthArrow(Image):
+ """!Class representing eps instruction -- North Arrow"""
+ def __init__(self, id, settings):
+ Image.__init__(self, id = id, settings = settings)
+ self.type = 'northArrow'
+
+ def __str__(self):
+ self.ChangeRefPoint(toCenter = True)
+
+ instr = "eps %s %s\n" % (self.instruction['east'], self.instruction['north'])
+ instr += "# north arrow\n"
+ instr += string.Template(" epsfile $epsfile\n").substitute(self.instruction)
+ if self.instruction["rotate"]:
+ instr += string.Template(" rotate $rotate\n").substitute(self.instruction)
+ if self.instruction["scale"]:
+ instr += string.Template(" scale $scale\n").substitute(self.instruction)
+ instr += " end"
+ return instr
+
+class Point(InstructionObject):
+ """!Class representing point instruction"""
+ def __init__(self, id):
+ InstructionObject.__init__(self, id = id)
+ self.type = 'point'
+ # default values
+ self.defaultInstruction = dict(symbol = os.path.join('basic', 'x'),
+ color = '0:0:0', fcolor = '200:200:200',
+ rotate = 0, size = 10,
+ XY = True, where = (0,0), unit = 'inch',
+ east = None, north = None)
+ # current values
+ self.instruction = dict(self.defaultInstruction)
+
+ def __str__(self):
+ instr = string.Template("point $east $north\n").substitute(self.instruction)
+ instr += string.Template(" symbol $symbol\n").substitute(self.instruction)
+ instr += string.Template(" color $color\n").substitute(self.instruction)
+ instr += string.Template(" fcolor $fcolor\n").substitute(self.instruction)
+ instr += string.Template(" rotate $rotate\n").substitute(self.instruction)
+ instr += string.Template(" size $size\n").substitute(self.instruction)
+ instr += " end"
+ return instr
+
+ def Read(self, instruction, text, **kwargs):
+ """!Read instruction and save information"""
+ mapInstr = kwargs['mapInstruction']
+ instr = {}
+ for line in text:
+ try:
+ sub = line.split(None, 1)[0]
+ if sub == 'point':
+ e, n = line.split(None, 3)[1:3]
+ if '%' in e and '%' in n:
+ instr['XY'] = True
+ instr['east'], instr['north'] = self.PercentToReal(e, n)
+ else:
+ instr['XY'] = False
+ instr['east'], instr['north'] = float(e), float(n)
+
+ elif sub == 'symbol':
+ instr['symbol'] = line.split(None, 1)[1]
+ elif sub == 'rotate':
+ instr['rotate'] = float(line.split(None, 1)[1])
+ elif sub == 'size':
+ instr['size'] = float(line.split(None, 1)[1])
+ elif sub == 'color':
+ instr['color'] = line.split(None, 1)[1]
+ elif sub == 'fcolor':
+ instr['fcolor'] = line.split(None, 1)[1]
+
+
+ except(IndexError, ValueError):
+ GError(_("Failed to read instruction %s") % instruction)
+ return False
+
+ self.instruction.update(instr)
+ instr['where'] = PaperMapCoordinates(mapInstr = mapInstr, x = self.instruction['east'],
+ y = self.instruction['north'], paperToMap = False)
+ w = h = self.unitConv.convert(value = instr['size'], fromUnit = 'point', toUnit = 'inch')
+ instr['rect'] = Rect2D(x = float(instr['where'][0]) - w / 2, y = float(instr['where'][1] - h / 2),
+ width = w, height = h)
+ self.instruction.update(instr)
+
+ return True
+
+class Line(InstructionObject):
+ """!Class representing line instruction"""
+ def __init__(self, id):
+ InstructionObject.__init__(self, id = id)
+ self.type = 'line'
+ # default values
+ self.defaultInstruction = dict(color = '0:0:0', width = 2,
+ where = [wx.Point2D(), wx.Point2D()],
+ east1 = None, north1 = None,
+ east2 = None, north2 = None)
+ # current values
+ self.instruction = dict(self.defaultInstruction)
+
+ def __str__(self):
+ instr = string.Template("line $east1 $north1 $east2 $north2\n").substitute(self.instruction)
+ instr += string.Template(" color $color\n").substitute(self.instruction)
+ instr += string.Template(" width $width\n").substitute(self.instruction)
+ instr += " end\n"
+ return instr
+
+ def Read(self, instruction, text, **kwargs):
+ """!Read instruction and save information"""
+ mapInstr = kwargs['mapInstruction']
+ instr = {}
+ for line in text:
+ try:
+ sub = line.split(None, 1)[0]
+ if sub == 'line':
+ e1, n1, e2, n2 = line.split(None, 5)[1:5]
+ if '%' in e1 and '%' in n1 and '%' in e2 and '%' in n2:
+ instr['east1'], instr['north1'] = self.PercentToReal(e1, n1)
+ instr['east2'], instr['north2'] = self.PercentToReal(e2, n2)
+ else:
+ instr['east1'], instr['north1'] = float(e1), float(n1)
+ instr['east2'], instr['north2'] = float(e2), float(n2)
+
+ elif sub == 'width':
+ instr['width'] = float(line.split(None, 1)[1])
+ elif sub == 'color':
+ instr['color'] = line.split(None, 1)[1]
+
+ except(IndexError, ValueError):
+ GError(_("Failed to read instruction %s") % instruction)
+ return False
+
+ self.instruction.update(instr)
+ e1, n1 = PaperMapCoordinates(mapInstr = mapInstr, x = self.instruction['east1'],
+ y = self.instruction['north1'], paperToMap = False)
+ e2, n2 = PaperMapCoordinates(mapInstr = mapInstr, x = self.instruction['east2'],
+ y = self.instruction['north2'], paperToMap = False)
+ instr['where'] = [wx.Point2D(e1, n1), wx.Point2D(e2, n2)]
+ instr['rect'] = Rect2DPP(instr['where'][0], instr['where'][1])
+ self.instruction.update(instr)
+
+ return True
+
+class Rectangle(InstructionObject):
+ """!Class representing rectangle instruction"""
+ def __init__(self, id):
+ InstructionObject.__init__(self, id = id)
+ self.type = 'rectangle'
+ # default values
+ self.defaultInstruction = dict(color = '0:0:0', fcolor = 'none', width = 2,
+ east1 = None, north1 = None,
+ east2 = None, north2 = None)
+ # current values
+ self.instruction = dict(self.defaultInstruction)
+
+ def __str__(self):
+ instr = string.Template("rectangle $east1 $north1 $east2 $north2\n").substitute(self.instruction)
+ instr += string.Template(" color $color\n").substitute(self.instruction)
+ instr += string.Template(" fcolor $fcolor\n").substitute(self.instruction)
+ instr += string.Template(" width $width\n").substitute(self.instruction)
+ instr += " end\n"
+ return instr
+
+ def Read(self, instruction, text, **kwargs):
+ """!Read instruction and save information"""
+ mapInstr = kwargs['mapInstruction']
+ instr = {}
+ for line in text:
+ try:
+ sub = line.split(None, 1)[0]
+ if sub == 'rectangle':
+ e1, n1, e2, n2 = line.split(None, 5)[1:5]
+ if '%' in e1 and '%' in n1 and '%' in e2 and '%' in n2:
+ instr['east1'], instr['north1'] = self.PercentToReal(e1, n1)
+ instr['east2'], instr['north2'] = self.PercentToReal(e2, n2)
+ else:
+ instr['east1'], instr['north1'] = float(e1), float(n1)
+ instr['east2'], instr['north2'] = float(e2), float(n2)
+
+ elif sub == 'width':
+ instr['width'] = float(line.split(None, 1)[1])
+ elif sub == 'color':
+ instr['color'] = line.split(None, 1)[1]
+ elif sub == 'fcolor':
+ instr['fcolor'] = line.split(None, 1)[1]
+
+
+ except(IndexError, ValueError):
+ GError(_("Failed to read instruction %s") % instruction)
+ return False
+
+ self.instruction.update(instr)
+ e1, n1 = PaperMapCoordinates(mapInstr = mapInstr, x = self.instruction['east1'],
+ y = self.instruction['north1'], paperToMap = False)
+ e2, n2 = PaperMapCoordinates(mapInstr = mapInstr, x = self.instruction['east2'],
+ y = self.instruction['north2'], paperToMap = False)
+ instr['rect'] = Rect2DPP(wx.Point2D(e1, n1), wx.Point2D(e2, n2))
+ self.instruction.update(instr)
+
+ return True
+
+class Scalebar(InstructionObject):
+ """!Class representing scalebar instruction"""
+ def __init__(self, id):
+ InstructionObject.__init__(self, id = id)
+ self.type = 'scalebar'
+ # default values
+ self.defaultInstruction = dict(unit = 'inch', where = (1,1),
+ unitsLength = 'auto', unitsHeight = 'inch',
+ length = None, height = 0.1, rect = None,
+ fontsize = 10, background = 'y',
+ scalebar = 'f', segment = 4, numbers = 1)
+ # current values
+ self.instruction = dict(self.defaultInstruction)
+
+ def __str__(self):
+ instr = string.Template("scalebar $scalebar\n").substitute(self.instruction)
+ instr += " where %.3f %.3f\n" % (self.instruction['where'][0], self.instruction['where'][1])
+ instr += string.Template(" length $length\n units $unitsLength\n").substitute(self.instruction)
+ instr += string.Template(" height $height\n").substitute(self.instruction)
+ instr += string.Template(" segment $segment\n numbers $numbers\n").substitute(self.instruction)
+ instr += string.Template(" fontsize $fontsize\n background $background\n").substitute(self.instruction)
+ instr += " end"
+ return instr
+
+ def Read(self, instruction, text, **kwargs):
+ """!Read instruction and save information"""
+ scale = kwargs['scale']
+ instr = {}
+ for line in text:
+ try:
+ if line.startswith('scalebar'):
+ if 'scalebar s' in line:
+ instr['scalebar'] = 's'
+ else:
+ instr['scalebar'] = 'f'
+ elif line.startswith('where'):
+ instr['where'] = map(float, line.split()[1:3])
+ elif line.startswith('length'):
+ instr['length'] = float(line.split()[1])
+ elif line.startswith('units'):
+ if line.split()[1] in ['auto', 'meters', 'kilometers', 'feet', 'miles', 'nautmiles']:
+ instr['unitsLength'] = line.split()[1]
+ elif line.startswith('height'):
+ instr['height'] = float(line.split()[1])
+ elif line.startswith('fontsize'):
+ instr['fontsize'] = float(line.split()[1])
+ elif line.startswith('numbers'):
+ instr['numbers'] = int(line.split()[1])
+ elif line.startswith('segment'):
+ instr['segment'] = int(line.split()[1])
+ elif line.startswith('background'):
+ if line.split()[1].strip().lower() in ('y','yes'):
+ instr['background'] = 'y'
+ elif line.split()[1].strip().lower() in ('n','no', 'none'):
+ instr['background'] = 'n'
+ except(IndexError, ValueError):
+ GError(_("Failed to read instruction %s") % instruction)
+ return False
+
+ self.instruction.update(instr)
+ w, h = self.EstimateSize(scalebarDict = self.instruction, scale = scale)
+ x = self.instruction['where'][0] - w / 2
+ y = self.instruction['where'][1] - h / 2
+ self.instruction['rect'] = Rect2D(x, y, w, h)
+ return True
+
+ def EstimateSize(self, scalebarDict, scale):
+ """!Estimate size to draw scalebar"""
+ units = projInfo()['units']
+ if not units or units not in self.unitConv.getAllUnits():
+ units = 'meters'
+ if scalebarDict['unitsLength'] != 'auto':
+ length = self.unitConv.convert(value = scalebarDict['length'], fromUnit = scalebarDict['unitsLength'], toUnit = 'inch')
+ else:
+ length = self.unitConv.convert(value = scalebarDict['length'], fromUnit = units, toUnit = 'inch')
+
+ length *= scale
+ length *= 1.1 #for numbers on the edge
+ height = scalebarDict['height'] + 2 * self.unitConv.convert(value = scalebarDict['fontsize'], fromUnit = 'point', toUnit = 'inch')
+ return (length, height)
+
+class RasterLegend(InstructionObject):
+ """!Class representing colortable instruction"""
+ def __init__(self, id):
+ InstructionObject.__init__(self, id = id)
+ self.type = 'rasterLegend'
+ # default values
+ self.defaultInstruction = dict(rLegend = False, unit = 'inch', rasterDefault = True, raster = None,
+ discrete = None, type = None,
+ where = (0, 0),
+ width = None, height = None, cols = 1, font = "Helvetica", fontsize = 10,
+ #color = '0:0:0', tickbar = False, range = False, min = 0, max = 0,
+ color = 'black', tickbar = 'n', range = False, min = 0, max = 0,
+ nodata = 'n')
+ # current values
+ self.instruction = dict(self.defaultInstruction)
+
+ def __str__(self):
+ instr = "colortable y\n"
+ instr += string.Template(" raster $raster\n").substitute(self.instruction)
+ instr += " where %.3f %.3f\n" % (self.instruction['where'][0], self.instruction['where'][1])
+ if self.instruction['width']:
+ instr += string.Template(" width $width\n").substitute(self.instruction)
+ instr += string.Template(" discrete $discrete\n").substitute(self.instruction)
+ if self.instruction['discrete'] == 'n':
+ if self.instruction['height']:
+ instr += string.Template(" height $height\n").substitute(self.instruction)
+ instr += string.Template(" tickbar $tickbar\n").substitute(self.instruction)
+ if self.instruction['range']:
+ instr += string.Template(" range $min $max\n").substitute(self.instruction)
+ else:
+ instr += string.Template(" cols $cols\n").substitute(self.instruction)
+ instr += string.Template(" nodata $nodata\n").substitute(self.instruction)
+ instr += string.Template(" font $font\n fontsize $fontsize\n color $color\n")\
+ .substitute(self.instruction)
+ instr += " end"
+ return instr
+
+
+ def Read(self, instruction, text, **kwargs):
+ """!Read instruction and save information"""
+ instr = {}
+ instr['rLegend'] = True
+ for line in text:
+ try:
+ if line.startswith('where'):
+ instr['where'] = map(float, line.split()[1:3])
+ elif line.startswith('font '):
+ instr['font'] = line.split()[1]
+ elif line.startswith('fontsize'):
+ instr['fontsize'] = float(line.split()[1])
+ elif line.startswith('color '):
+ instr['color'] = line.split()[1]
+ elif line.startswith('raster'):
+ instr['raster'] = line.split()[1]
+ elif line.startswith('width'):
+ instr['width'] = float(line.split()[1])
+ elif line.startswith('height'):
+ instr['height'] = float(line.split()[1])
+ elif line.startswith('cols'):
+ instr['cols'] = int(line.split()[1])
+ elif line.startswith('range'):
+ instr['range'] = True
+ instr['min'] = float(line.split()[1])
+ instr['max'] = float(line.split()[2])
+ elif line.startswith('nodata'):
+ if line.split()[1].strip().lower() in ('y','yes'):
+ instr['nodata'] = 'y'
+ elif line.split()[1].strip().lower() in ('n','no', 'none'):
+ instr['nodata'] = 'n'
+ elif line.startswith('tickbar'):
+ if line.split()[1].strip().lower() in ('y','yes'):
+ instr['tickbar'] = 'y'
+ elif line.split()[1].strip().lower() in ('n','no', 'none'):
+ instr['tickbar'] = 'n'
+ elif line.startswith('discrete'):
+ if line.split()[1].strip().lower() in ('y','yes'):
+ instr['discrete'] = 'y'
+ elif line.split()[1].strip().lower() in ('n','no', 'none'):
+ instr['discrete'] = 'n'
+
+ except(IndexError, ValueError):
+ GError(_("Failed to read instruction %s") % instruction)
+ return False
+
+ if 'raster' in instr:
+ instr['rasterDefault'] = False
+ if 'discrete' not in instr:
+ rasterType = getRasterType(map = instr['raster'])
+ instr['type'] = rasterType
+ if rasterType == 'CELL':
+ instr['discrete'] = 'y'
+ else:
+ instr['discrete'] = 'n'
+
+ else:
+ instr['rasterDefault'] = True
+ self.instruction.update(instr)
+ # add 'rect' in the end
+
+ return True
+
+ def EstimateHeight(self, raster, discrete, fontsize, cols = None, height = None):
+ """!Estimate height to draw raster legend"""
+ if discrete == 'n':
+ if height:
+ height = height
+ else:
+ height = self.unitConv.convert(value = fontsize * 10,
+ fromUnit = 'point', toUnit = 'inch')
+
+ if discrete == 'y':
+ if cols:
+ cols = cols
+ else:
+ cols = 1
+
+ rinfo = grass.raster_info(raster)
+ if rinfo['datatype'] in ('DCELL', 'FCELL'):
+ minim, maxim = rinfo['min'], rinfo['max']
+ rows = ceil(maxim / cols )
+ else:
+ cat = grass.read_command('r.category', map = raster,
+ fs = ':').strip().split('\n')
+ rows = ceil(float(len(cat)) / cols )
+
+
+ height = self.unitConv.convert(value = 1.5 * rows * fontsize, fromUnit = 'point', toUnit = 'inch')
+
+ return height
+
+ def EstimateWidth(self, raster, discrete, fontsize, cols = None, width = None, paperInstr = None):
+ """!Estimate size to draw raster legend"""
+
+ if discrete == 'n':
+ rinfo = grass.raster_info(raster)
+ minim, maxim = rinfo['min'], rinfo['max']
+ if width:
+ width = width
+ else:
+ width = self.unitConv.convert(value = fontsize * 2,
+ fromUnit = 'point', toUnit = 'inch')
+ text = len(max(str(minim), str(maxim), key = len))
+ textPart = self.unitConv.convert(value = text * fontsize / 2,
+ fromUnit = 'point', toUnit = 'inch')
+ width += textPart
+
+ elif discrete == 'y':
+ if cols:
+ cols = cols
+ else:
+ cols = 1
+
+ if width:
+ width = width
+ else:
+ paperWidth = paperInstr['Width'] - paperInstr['Right'] - paperInstr['Left']
+ width = (paperWidth / cols) * (cols - 1) + 1
+
+ return width
+
+class VectorLegend(InstructionObject):
+ """!Class representing colortable instruction"""
+ def __init__(self, id):
+ InstructionObject.__init__(self, id = id)
+ self.type = 'vectorLegend'
+ # default values
+ self.defaultInstruction = dict(vLegend = False, unit = 'inch', where = (0, 0),
+ defaultSize = True, width = 0.4, cols = 1, span = None,
+ font = "Helvetica", fontsize = 10,
+ border = 'none')
+ # current values
+ self.instruction = dict(self.defaultInstruction)
+
+ def __str__(self):
+ instr = "vlegend\n"
+ instr += " where %.3f %.3f\n" % (self.instruction['where'][0], self.instruction['where'][1])
+ instr += string.Template(" font $font\n fontsize $fontsize\n").substitute(self.instruction)
+ instr += string.Template(" width $width\n cols $cols\n").substitute(self.instruction)
+ if self.instruction['span']:
+ instr += string.Template(" span $span\n").substitute(self.instruction)
+ instr += string.Template(" border $border\n").substitute(self.instruction)
+ instr += " end"
+ return instr
+
+ def Read(self, instruction, text, **kwargs):
+ """!Read instruction and save information"""
+ instr = {}
+ instr['vLegend'] = True
+ for line in text:
+ try:
+ if line.startswith('where'):
+ instr['where'] = map(float, line.split()[1:3])
+ elif line.startswith('font '):
+ instr['font'] = line.split()[1]
+ elif line.startswith('fontsize'):
+ instr['fontsize'] = float(line.split()[1])
+ elif line.startswith('width'):
+ instr['width'] = float(line.split()[1])
+ elif line.startswith('cols'):
+ instr['cols'] = int(line.split()[1])
+ elif line.startswith('span'):
+ instr['span'] = float(line.split()[1])
+ elif line.startswith('border'):
+ instr['border'] = line.split()[1]
+
+ except(IndexError, ValueError):
+ GError(_("Failed to read instruction %s") % instruction)
+ return False
+
+ self.instruction.update(instr)
+
+ return True
+
+ def EstimateSize(self, vectorInstr, fontsize, width = None, cols = None):
+ """!Estimate size to draw vector legend"""
+ if width:
+ width = width
+ else:
+ width = fontsize/24.0
+
+ if cols:
+ cols = cols
+ else:
+ cols = 1
+
+ vectors = vectorInstr['list']
+ labels = [vector[4] for vector in vectors if vector[3] != 0]
+ extent = (len(max(labels, key = len)) * fontsize / 2, fontsize)
+ wExtent = self.unitConv.convert(value = extent[0], fromUnit = 'point', toUnit = 'inch')
+ hExtent = self.unitConv.convert(value = extent[1], fromUnit = 'point', toUnit = 'inch')
+ w = (width + wExtent) * cols
+ h = len(labels) * hExtent / cols
+ h *= 1.1
+ return (w, h)
+
+
+class Raster(InstructionObject):
+ """!Class representing raster instruction"""
+ def __init__(self, id):
+ InstructionObject.__init__(self, id = id)
+ self.type = 'raster'
+ # default values
+ self.defaultInstruction = dict(isRaster = False, raster = None)
+ # current values
+ self.instruction = dict(self.defaultInstruction)
+
+ def __str__(self):
+ instr = string.Template("raster $raster").substitute(self.instruction)
+ return instr
+
+ def Read(self, instruction, text):
+ """!Read instruction and save information"""
+ instr = {}
+ instr['isRaster'] = True
+ try:
+ map = text.split()[1]
+ except IndexError:
+ GError(_("Failed to read instruction %s") % instruction)
+ return False
+ try:
+ info = grass.find_file(map, element = 'cell')
+ except grass.ScriptError, e:
+ GError(message = e.value)
+ return False
+ instr['raster'] = info['fullname']
+
+
+ self.instruction.update(instr)
+ return True
+
+class Vector(InstructionObject):
+ """!Class keeps vector layers"""
+ def __init__(self, id):
+ InstructionObject.__init__(self, id = id)
+ self.type = 'vector'
+ # default values
+ self.defaultInstruction = dict(list = None)# [vmap, type, id, lpos, label]
+ # current values
+ self.instruction = dict(self.defaultInstruction)
+ def __str__(self):
+ return ''
+
+ def Read(self, instruction, text, **kwargs):
+ """!Read instruction and save information"""
+ instr = {}
+
+ for line in text:
+ if line.startswith('vpoints') or line.startswith('vlines') or line.startswith('vareas'):
+ # subtype
+ if line.startswith('vpoints'):
+ subType = 'points'
+ elif line.startswith('vlines'):
+ subType = 'lines'
+ elif line.startswith('vareas'):
+ subType = 'areas'
+ # name of vector map
+ vmap = line.split()[1]
+ try:
+ info = grass.find_file(vmap, element = 'vector')
+ except grass.ScriptError, e:
+ GError(message = e.value)
+ return False
+ vmap = info['fullname']
+ # id
+ id = kwargs['id']
+ # lpos
+ lpos = kwargs['vectorMapNumber']
+ #label
+ label = '('.join(vmap.split('@')) + ')'
+ break
+ instr = [vmap, subType, id, lpos, label]
+ if not self.instruction['list']:
+ self.instruction['list'] = []
+ self.instruction['list'].append(instr)
+
+ return True
+
+class VProperties(InstructionObject):
+ """!Class represents instructions vareas, vlines, vpoints"""
+ def __init__(self, id, subType):
+ InstructionObject.__init__(self, id = id)
+ self.type = 'vProperties'
+ self.subType = subType
+ # default values
+ if self.subType == 'points':
+ dd = dict(subType = 'points', name = None, type = 'point or centroid', connection = False, layer = '1',
+ masked = 'n', color = '0:0:0', width = 1,
+ fcolor = '255:0:0', rgbcolumn = None, symbol = os.path.join('basic', 'x'), eps = None,
+ size = 5, sizecolumn = None, scale = None,
+ rotation = False, rotate = 0, rotatecolumn = None, label = None, lpos = None)
+ elif self.subType == 'lines':
+ dd = dict(subType = 'lines', name = None, type = 'line or boundary', connection = False, layer = '1',
+ masked = 'n', color = '0:0:0', hwidth = 1,
+ hcolor = 'none', rgbcolumn = None,
+ width = 1, cwidth = None,
+ style = 'solid', linecap = 'butt', label = None, lpos = None)
+ else: # areas
+ dd = dict(subType = 'areas', name = None, connection = False, layer = '1',
+ masked = 'n', color = '0:0:0', width = 1,
+ fcolor = 'none', rgbcolumn = None,
+ pat = None, pwidth = 1, scale = 1, label = None, lpos = None)
+ self.defaultInstruction = dd
+ # current values
+ self.instruction = dict(self.defaultInstruction)
+
+ def __str__(self):
+ dic = self.instruction
+ vInstruction = string.Template("v$subType $name\n").substitute(dic)
+ #data selection
+ if self.subType in ('points', 'lines'):
+ vInstruction += string.Template(" type $type\n").substitute(dic)
+ if dic['connection']:
+ vInstruction += string.Template(" layer $layer\n").substitute(dic)
+ if dic.has_key('cats'):
+ vInstruction += string.Template(" cats $cats\n").substitute(dic)
+ elif dic.has_key('where'):
+ vInstruction += string.Template(" where $where\n").substitute(dic)
+ vInstruction += string.Template(" masked $masked\n").substitute(dic)
+ #colors
+ vInstruction += string.Template(" color $color\n").substitute(dic)
+ if self.subType in ('points', 'areas'):
+ if dic['color'] != 'none':
+ vInstruction += string.Template(" width $width\n").substitute(dic)
+ if dic['rgbcolumn']:
+ vInstruction += string.Template(" rgbcolumn $rgbcolumn\n").substitute(dic)
+ vInstruction += string.Template(" fcolor $fcolor\n").substitute(dic)
+ else:
+ if dic['rgbcolumn']:
+ vInstruction += string.Template(" rgbcolumn $rgbcolumn\n").substitute(dic)
+ elif dic['hcolor'] != 'none':
+ vInstruction += string.Template(" hwidth $hwidth\n").substitute(dic)
+ vInstruction += string.Template(" hcolor $hcolor\n").substitute(dic)
+
+ # size and style
+ if self.subType == 'points':
+ if not dic['eps']:
+ vInstruction += string.Template(" symbol $symbol\n").substitute(dic)
+ else: #eps
+ vInstruction += string.Template(" eps $eps\n").substitute(dic)
+ if dic['size']:
+ vInstruction += string.Template(" size $size\n").substitute(dic)
+ else: # sizecolumn
+ vInstruction += string.Template(" sizecolumn $sizecolumn\n").substitute(dic)
+ vInstruction += string.Template(" scale $scale\n").substitute(dic)
+ if dic['rotation']:
+ if dic['rotate'] is not None:
+ vInstruction += string.Template(" rotate $rotate\n").substitute(dic)
+ else:
+ vInstruction += string.Template(" rotatecolumn $rotatecolumn\n").substitute(dic)
+
+ if self.subType == 'areas':
+ if dic['pat'] is not None:
+ vInstruction += string.Template(" pat $pat\n").substitute(dic)
+ vInstruction += string.Template(" pwidth $pwidth\n").substitute(dic)
+ vInstruction += string.Template(" scale $scale\n").substitute(dic)
+
+ if self.subType == 'lines':
+ if dic['width'] is not None:
+ vInstruction += string.Template(" width $width\n").substitute(dic)
+ else:
+ vInstruction += string.Template(" cwidth $cwidth\n").substitute(dic)
+ vInstruction += string.Template(" style $style\n").substitute(dic)
+ vInstruction += string.Template(" linecap $linecap\n").substitute(dic)
+ #position and label in vlegend
+ vInstruction += string.Template(" label $label\n lpos $lpos\n").substitute(dic)
+
+ vInstruction += " end"
+ try:
+ vInstruction = vInstruction.encode('Latin_1')
+ except UnicodeEncodeError, err:
+ try:
+ pos = str(err).split('position')[1].split(':')[0].strip()
+ except IndexError:
+ pos = ''
+ if pos:
+ message = _("Characters on position %s are not supported "
+ "by ISO-8859-1 (Latin 1) encoding "
+ "which is required by module ps.map.") % pos
+ else:
+ message = _("Not all characters are supported "
+ "by ISO-8859-1 (Latin 1) encoding "
+ "which is required by module ps.map.")
+ GMessage(message = message)
+ return ''
+ return vInstruction
+
+ def Read(self, instruction, text, **kwargs):
+ """!Read instruction and save information"""
+ instr = {}
+ try:
+ info = grass.find_file(name = text[0].split()[1], element = 'vector')
+ except grass.ScriptError, e:
+ GError(message = e.value)
+ return False
+ instr['name'] = info['fullname']
+ #connection
+ instr['connection'] = True
+ self.mapDBInfo = VectorDBInfo(instr['name'])
+ self.layers = self.mapDBInfo.layers.keys()
+ if not self.layers:
+ instr['connection'] = False
+
+ # points
+ if text[0].startswith('vpoints'):
+ for line in text[1:]:
+ if line.startswith('type'):
+ tp = []
+ if line.find('point') != -1:
+ tp.append('point')
+ if line.find('centroid') != -1:
+ tp.append('centroid')
+ instr['type'] = ' or '.join(tp)
+ elif line.startswith('fcolor'):
+ instr['fcolor'] = line.split()[1]
+ elif line.startswith('rgbcolumn'):
+ instr['rgbcolumn'] = line.split()[1]
+ elif line.startswith('symbol'):
+ instr['symbol'] = line.split()[1]
+ elif line.startswith('eps'):
+ instr['eps'] = line.split()[1]
+ elif line.startswith('size '):
+ instr['size'] = line.split()[1]
+ elif line.startswith('sizecolumn'):
+ instr['size'] = None
+ instr['sizecolumn'] = line.split()[1]
+ elif line.startswith('scale '):
+ instr['scale'] = float(line.split()[1])
+ elif line.startswith('rotate '):
+ instr['rotation'] = True
+ instr['rotate'] = line.split()[1]
+ elif line.startswith('rotatecolumn'):
+ instr['rotatecolumn'] = line.split()[1]
+ instr['rotation'] = True
+ instr['rotate'] = None
+
+ # lines
+ elif text[0].startswith('vlines'):
+ for line in text[1:]:
+ if line.startswith('type'):
+ tp = []
+ if line.find('line') != -1:
+ tp.append('line')
+ if line.find('boundary') != -1:
+ tp.append('boundary')
+ instr['type'] = ' or '.join(tp)
+ elif line.startswith('hwidth'):
+ instr['hwidth'] = float(line.split()[1])
+ elif line.startswith('hcolor'):
+ instr['hcolor'] = line.split()[1]
+ elif line.startswith('rgbcolumn'):
+ instr['rgbcolumn'] = line.split()[1]
+ elif line.startswith('cwidth'):
+ instr['cwidth'] = float(line.split()[1])
+ instr['width'] = None
+ elif line.startswith('style'):
+ instr['style'] = line.split()[1]
+ elif line.startswith('linecap'):
+ instr['linecap'] = line.split()[1]
+
+ elif text[0].startswith('vareas'):
+ for line in text[1:]:
+ if line.startswith('fcolor'):
+ instr['fcolor'] = line.split()[1]
+ elif line.startswith('pat'):
+ instr['pat'] = line.split()[1]
+ elif line.startswith('pwidth'):
+ instr['pwidth'] = float(line.split()[1])
+ elif line.startswith('scale'):
+ instr['scale'] = float(line.split()[1])
+
+
+ # same properties for all
+ for line in text[1:]:
+ if line.startswith('lpos'):
+ instr['lpos'] = int(line.split()[1])
+ elif line.startswith('label'):
+ instr['label'] = line.split(None, 1)[1].decode('latin_1')
+ elif line.startswith('layer'):
+ instr['layer'] = line.split()[1]
+ elif line.startswith('masked'):
+ if line.split()[1].lower() in ('y', 'yes'):
+ instr['masked'] = 'y'
+ else:
+ instr['masked'] = 'n'
+ elif line.startswith('color'):
+ instr['color'] = line.split()[1]
+ elif line.startswith('rgbcolumn'):
+ instr['rgbcolumn'] = line.split()[1]
+ elif line.startswith('width'):
+ instr['width'] = float(line.split()[1])
+
+ if 'label' not in instr:
+ instr['label'] = '('.join(instr['name'].split('@')) + ')'
+ if 'lpos' not in instr:
+ instr['lpos'] = kwargs['vectorMapNumber']
+ self.instruction.update(instr)
+
+ return True
Modified: grass/branches/develbranch_6/gui/wxpython/psmap/toolbars.py
===================================================================
--- grass/branches/develbranch_6/gui/wxpython/psmap/toolbars.py 2012-02-17 00:41:01 UTC (rev 50839)
+++ grass/branches/develbranch_6/gui/wxpython/psmap/toolbars.py 2012-02-17 06:45:00 UTC (rev 50840)
@@ -83,6 +83,14 @@
label = _('Image')),
'addNorthArrow': MetaIcon(img = 'north-arrow-add',
label = _('North Arrow')),
+ 'drawGraphics': MetaIcon(img = 'edit',
+ label = _('Add simple graphics')),
+ 'pointAdd' : MetaIcon(img = '',
+ label = _('Point')),
+ 'lineAdd' : MetaIcon(img = '',
+ label = _('Line')),
+ 'rectangleAdd': MetaIcon(img = '',
+ label = _('Rectangle')),
}
self.icons = icons
@@ -113,6 +121,8 @@
self.parent.OnAddVect),
("dec", BaseIcons["overlay"],
self.OnDecoration),
+ ("drawGraphics", icons["drawGraphics"],
+ self.OnDrawGraphics, wx.ITEM_CHECK),
("delete", icons["deleteObj"],
self.parent.OnDelete),
(None, ),
@@ -138,3 +148,15 @@
(self.icons["addText"], self.parent.OnAddText),
(self.icons["addImage"], self.parent.OnAddImage),
(self.icons["addNorthArrow"], self.parent.OnAddNorthArrow)))
+
+ def OnDrawGraphics(self, event):
+ """!Simple geometry features (point, line, rectangle) overlay menu
+ """
+ # we need the previous id
+ self.actionOld = self.action['id']
+ self.OnTool(event)
+ self.action['id'] = self.actionOld
+ self._onMenu(((self.icons["pointAdd"], self.parent.OnAddPoint),
+ (self.icons["lineAdd"], self.parent.OnAddLine),
+ (self.icons["rectangleAdd"], self.parent.OnAddRectangle),
+ ))
Copied: grass/branches/develbranch_6/gui/wxpython/psmap/utils.py (from rev 50797, grass/trunk/gui/wxpython/psmap/utils.py)
===================================================================
--- grass/branches/develbranch_6/gui/wxpython/psmap/utils.py (rev 0)
+++ grass/branches/develbranch_6/gui/wxpython/psmap/utils.py 2012-02-17 06:45:00 UTC (rev 50840)
@@ -0,0 +1,422 @@
+"""!
+ at package psmap.utils
+
+ at brief utilities for wxpsmap (classes, functions)
+
+Classes:
+ - utils::Rect2D
+ - utils::Rect2DPP
+ - utils::Rect2DPS
+ - utils::UnitConversion
+
+(C) 2012 by Anna Kratochvilova, and the GRASS Development Team
+This program is free software under the GNU General Public License
+(>=v2). Read the file COPYING that comes with GRASS for details.
+
+ at author Anna Kratochvilova <kratochanna gmail.com>
+"""
+
+import wx
+from math import ceil, floor, sin, cos, pi
+
+try:
+ import Image as PILImage
+ havePILImage = True
+except ImportError:
+ havePILImage = False
+
+import grass.script as grass
+from core.gcmd import RunCommand
+
+class Rect2D(wx.Rect2D):
+ """!Class representing rectangle with floating point values.
+
+ Overrides wx.Rect2D to unify Rect access methods, which are
+ different (e.g. wx.Rect.GetTopLeft() x wx.Rect2D.GetLeftTop()).
+ More methods can be added depending on needs.
+ """
+ def __init__(self, x = 0, y = 0, width = 0, height = 0):
+ wx.Rect2D.__init__(self, x = x, y = y, w = width, h = height)
+
+ def GetX(self):
+ return self.x
+
+ def GetY(self):
+ return self.y
+
+ def GetWidth(self):
+ return self.width
+
+ def SetWidth(self, width):
+ self.width = width
+
+ def GetHeight(self):
+ return self.height
+
+ def SetHeight(self, height):
+ self.height = height
+
+class Rect2DPP(Rect2D):
+ """!Rectangle specified by 2 points (with floating point values).
+
+ @see Rect2D, Rect2DPS
+ """
+ def __init__(self, topLeft = wx.Point2D(), bottomRight = wx.Point2D()):
+ Rect2D.__init__(self, x = 0, y = 0, width = 0, height = 0)
+
+ x1, y1 = topLeft[0], topLeft[1]
+ x2, y2 = bottomRight[0], bottomRight[1]
+
+ self.SetLeft(min(x1, x2))
+ self.SetTop(min(y1, y2))
+ self.SetRight(max(x1, x2))
+ self.SetBottom(max(y1, y2))
+
+class Rect2DPS(Rect2D):
+ """!Rectangle specified by point and size (with floating point values).
+
+ @see Rect2D, Rect2DPP
+ """
+ def __init__(self, pos = wx.Point2D(), size = (0, 0)):
+ Rect2D.__init__(self, x = pos[0], y = pos[1], width = size[0], height = size[1])
+
+class UnitConversion:
+ """! Class for converting units"""
+ def __init__(self, parent = None):
+ self.parent = parent
+ if self.parent:
+ ppi = wx.ClientDC(self.parent).GetPPI()
+ else:
+ ppi = (72, 72)
+ self._unitsPage = { 'inch' : {'val': 1.0, 'tr' : _("inch")},
+ 'point' : {'val': 72.0, 'tr' : _("point")},
+ 'centimeter' : {'val': 2.54, 'tr' : _("centimeter")},
+ 'millimeter' : {'val': 25.4, 'tr' : _("millimeter")}}
+ self._unitsMap = { 'meters' : {'val': 0.0254, 'tr' : _("meters")},
+ 'kilometers' : {'val': 2.54e-5, 'tr' : _("kilometers")},
+ 'feet' : {'val': 1./12, 'tr' : _("feet")},
+ 'miles' : {'val': 1./63360, 'tr' : _("miles")},
+ 'nautical miles': {'val': 1/72913.386, 'tr' : _("nautical miles")}}
+
+ self._units = { 'pixel' : {'val': ppi[0], 'tr' : _("pixel")},
+ 'meter' : {'val': 0.0254, 'tr' : _("meter")},
+ 'nautmiles' : {'val': 1/72913.386, 'tr' :_("nautical miles")},
+ 'degrees' : {'val': 0.0254 , 'tr' : _("degree")} #like 1 meter, incorrect
+ }
+ self._units.update(self._unitsPage)
+ self._units.update(self._unitsMap)
+
+ def getPageUnitsNames(self):
+ return sorted(self._unitsPage[unit]['tr'] for unit in self._unitsPage.keys())
+
+ def getMapUnitsNames(self):
+ return sorted(self._unitsMap[unit]['tr'] for unit in self._unitsMap.keys())
+
+ def getAllUnits(self):
+ return sorted(self._units.keys())
+
+ def findUnit(self, name):
+ """!Returns unit by its tr. string"""
+ for unit in self._units.keys():
+ if self._units[unit]['tr'] == name:
+ return unit
+ return None
+
+ def findName(self, unit):
+ """!Returns tr. string of a unit"""
+ try:
+ return self._units[unit]['tr']
+ except KeyError:
+ return None
+
+ def convert(self, value, fromUnit = None, toUnit = None):
+ return float(value)/self._units[fromUnit]['val']*self._units[toUnit]['val']
+
+def convertRGB(rgb):
+ """!Converts wx.Colour(r,g,b,a) to string 'r:g:b' or named color,
+ or named color/r:g:b string to wx.Colour, depending on input"""
+ # transform a wx.Colour tuple into an r:g:b string
+ if type(rgb) == wx.Colour:
+ for name, color in grass.named_colors.items():
+ if rgb.Red() == int(color[0] * 255) and\
+ rgb.Green() == int(color[1] * 255) and\
+ rgb.Blue() == int(color[2] * 255):
+ return name
+ return str(rgb.Red()) + ':' + str(rgb.Green()) + ':' + str(rgb.Blue())
+ # transform a GRASS named color or an r:g:b string into a wx.Colour tuple
+ else:
+ color = (grass.parse_color(rgb)[0]*255,
+ grass.parse_color(rgb)[1]*255,
+ grass.parse_color(rgb)[2]*255)
+ color = wx.Color(*color)
+ if color.IsOk():
+ return color
+ else:
+ return None
+
+
+def PaperMapCoordinates(mapInstr, x, y, paperToMap = True):
+ """!Converts paper (inch) coordinates <-> map coordinates.
+
+ @param mapInstr map frame instruction
+ @param x,y paper coords in inches or mapcoords in map units
+ @param paperToMap specify conversion direction
+ """
+ region = grass.region()
+ mapWidthPaper = mapInstr['rect'].GetWidth()
+ mapHeightPaper = mapInstr['rect'].GetHeight()
+ mapWidthEN = region['e'] - region['w']
+ mapHeightEN = region['n'] - region['s']
+
+ if paperToMap:
+ diffX = x - mapInstr['rect'].GetX()
+ diffY = y - mapInstr['rect'].GetY()
+ diffEW = diffX * mapWidthEN / mapWidthPaper
+ diffNS = diffY * mapHeightEN / mapHeightPaper
+ e = region['w'] + diffEW
+ n = region['n'] - diffNS
+
+ if projInfo()['proj'] == 'll':
+ return e, n
+ else:
+ return int(e), int(n)
+
+ else:
+ diffEW = x - region['w']
+ diffNS = region['n'] - y
+ diffX = mapWidthPaper * diffEW / mapWidthEN
+ diffY = mapHeightPaper * diffNS / mapHeightEN
+ xPaper = mapInstr['rect'].GetX() + diffX
+ yPaper = mapInstr['rect'].GetY() + diffY
+
+ return xPaper, yPaper
+
+
+def AutoAdjust(self, scaleType, rect, map = None, mapType = None, region = None):
+ """!Computes map scale, center and map frame rectangle to fit region (scale is not fixed)"""
+ currRegionDict = {}
+ if scaleType == 0 and map:# automatic, region from raster or vector
+ res = ''
+ if mapType == 'raster':
+ try:
+ res = grass.read_command("g.region", flags = 'gu', rast = map)
+ except grass.ScriptError:
+ pass
+ elif mapType == 'vector':
+ res = grass.read_command("g.region", flags = 'gu', vect = map)
+ currRegionDict = grass.parse_key_val(res, val_type = float)
+ elif scaleType == 1 and region: # saved region
+ res = grass.read_command("g.region", flags = 'gu', region = region)
+ currRegionDict = grass.parse_key_val(res, val_type = float)
+ elif scaleType == 2: # current region
+ env = grass.gisenv()
+ windFilePath = os.path.join(env['GISDBASE'], env['LOCATION_NAME'], env['MAPSET'], 'WIND')
+ try:
+ windFile = open(windFilePath, 'r').read()
+ except IOError:
+ currRegionDict = grass.region()
+ regionDict = grass.parse_key_val(windFile, sep = ':', val_type = float)
+ region = grass.read_command("g.region", flags = 'gu', n = regionDict['north'], s = regionDict['south'],
+ e = regionDict['east'], w = regionDict['west'])
+ currRegionDict = grass.parse_key_val(region, val_type = float)
+
+ else:
+ return None, None, None
+
+ if not currRegionDict:
+ return None, None, None
+ rX = rect.x
+ rY = rect.y
+ rW = rect.width
+ rH = rect.height
+ if not hasattr(self, 'unitConv'):
+ self.unitConv = UnitConversion(self)
+ toM = 1
+ if projInfo()['proj'] != 'xy':
+ toM = float(projInfo()['meters'])
+
+ mW = self.unitConv.convert(value = (currRegionDict['e'] - currRegionDict['w']) * toM, fromUnit = 'meter', toUnit = 'inch')
+ mH = self.unitConv.convert(value = (currRegionDict['n'] - currRegionDict['s']) * toM, fromUnit = 'meter', toUnit = 'inch')
+ scale = min(rW/mW, rH/mH)
+
+ if rW/rH > mW/mH:
+ x = rX - (rH*(mW/mH) - rW)/2
+ y = rY
+ rWNew = rH*(mW/mH)
+ rHNew = rH
+ else:
+ x = rX
+ y = rY - (rW*(mH/mW) - rH)/2
+ rHNew = rW*(mH/mW)
+ rWNew = rW
+
+ # center
+ cE = (currRegionDict['w'] + currRegionDict['e'])/2
+ cN = (currRegionDict['n'] + currRegionDict['s'])/2
+ return scale, (cE, cN), Rect2D(x, y, rWNew, rHNew) #inch
+
+def SetResolution(dpi, width, height):
+ """!If resolution is too high, lower it
+
+ @param dpi max DPI
+ @param width map frame width
+ @param height map frame height
+ """
+ region = grass.region()
+ if region['cols'] > width * dpi or region['rows'] > height * dpi:
+ rows = height * dpi
+ cols = width * dpi
+ RunCommand('g.region', rows = rows, cols = cols)
+
+def ComputeSetRegion(self, mapDict):
+ """!Computes and sets region from current scale, map center coordinates and map rectangle"""
+
+ if mapDict['scaleType'] == 3: # fixed scale
+ scale = mapDict['scale']
+
+ if not hasattr(self, 'unitConv'):
+ self.unitConv = UnitConversion(self)
+
+ fromM = 1
+ if projInfo()['proj'] != 'xy':
+ fromM = float(projInfo()['meters'])
+ rectHalfInch = (mapDict['rect'].width/2, mapDict['rect'].height/2)
+ rectHalfMeter = (self.unitConv.convert(value = rectHalfInch[0], fromUnit = 'inch', toUnit = 'meter')/ fromM /scale,
+ self.unitConv.convert(value = rectHalfInch[1], fromUnit = 'inch', toUnit = 'meter')/ fromM /scale)
+
+ centerE = mapDict['center'][0]
+ centerN = mapDict['center'][1]
+
+ raster = self.instruction.FindInstructionByType('raster')
+ if raster:
+ rasterId = raster.id
+ else:
+ rasterId = None
+
+ if rasterId:
+ RunCommand('g.region', n = ceil(centerN + rectHalfMeter[1]),
+ s = floor(centerN - rectHalfMeter[1]),
+ e = ceil(centerE + rectHalfMeter[0]),
+ w = floor(centerE - rectHalfMeter[0]),
+ rast = self.instruction[rasterId]['raster'])
+ else:
+ RunCommand('g.region', n = ceil(centerN + rectHalfMeter[1]),
+ s = floor(centerN - rectHalfMeter[1]),
+ e = ceil(centerE + rectHalfMeter[0]),
+ w = floor(centerE - rectHalfMeter[0]))
+
+def projInfo():
+ """!Return region projection and map units information,
+ taken from render.py"""
+
+ projinfo = dict()
+
+ ret = RunCommand('g.proj', read = True, flags = 'p')
+
+ if not ret:
+ return projinfo
+
+ for line in ret.splitlines():
+ if ':' in line:
+ key, val = line.split(':')
+ projinfo[key.strip()] = val.strip()
+ elif "XY location (unprojected)" in line:
+ projinfo['proj'] = 'xy'
+ projinfo['units'] = ''
+ break
+
+ return projinfo
+
+def GetMapBounds(filename, portrait = True):
+ """!Run ps.map -b to get information about map bounding box
+
+ @param filename psmap input file
+ @param portrait page orientation"""
+ orient = ''
+ if not portrait:
+ orient = 'r'
+ try:
+ bb = map(float, grass.read_command('ps.map',
+ flags = 'b' + orient,
+ quiet = True,
+ input = filename).strip().split('=')[1].split(','))
+ except (grass.ScriptError, IndexError):
+ GError(message = _("Unable to run `ps.map -b`"))
+ return None
+ return Rect2D(bb[0], bb[3], bb[2] - bb[0], bb[1] - bb[3])
+
+def getRasterType(map):
+ """!Returns type of raster map (CELL, FCELL, DCELL)"""
+ if map is None:
+ map = ''
+ file = grass.find_file(name = map, element = 'cell')
+ if file['file']:
+ rasterType = grass.raster_info(map)['datatype']
+ return rasterType
+ else:
+ return None
+
+def PilImageToWxImage(pilImage, copyAlpha = True):
+ """!Convert PIL image to wx.Image
+
+ Based on http://wiki.wxpython.org/WorkingWithImages
+ """
+ hasAlpha = pilImage.mode[-1] == 'A'
+ if copyAlpha and hasAlpha : # Make sure there is an alpha layer copy.
+ wxImage = wx.EmptyImage( *pilImage.size )
+ pilImageCopyRGBA = pilImage.copy()
+ pilImageCopyRGB = pilImageCopyRGBA.convert('RGB') # RGBA --> RGB
+ pilImageRgbData = pilImageCopyRGB.tostring()
+ wxImage.SetData(pilImageRgbData)
+ wxImage.SetAlphaData(pilImageCopyRGBA.tostring()[3::4]) # Create layer and insert alpha values.
+
+ else : # The resulting image will not have alpha.
+ wxImage = wx.EmptyImage(*pilImage.size)
+ pilImageCopy = pilImage.copy()
+ pilImageCopyRGB = pilImageCopy.convert('RGB') # Discard any alpha from the PIL image.
+ pilImageRgbData = pilImageCopyRGB.tostring()
+ wxImage.SetData(pilImageRgbData)
+
+ return wxImage
+
+def BBoxAfterRotation(w, h, angle):
+ """!Compute bounding box or rotated rectangle
+
+ @param w rectangle width
+ @param h rectangle height
+ @param angle angle (0, 360) in degrees
+ """
+ angleRad = angle / 180. * pi
+ ct = cos(angleRad)
+ st = sin(angleRad)
+
+ hct = h * ct
+ wct = w * ct
+ hst = h * st
+ wst = w * st
+ y = x = 0
+
+ if 0 < angle <= 90:
+ y_min = y
+ y_max = y + hct + wst
+ x_min = x - hst
+ x_max = x + wct
+ elif 90 < angle <= 180:
+ y_min = y + hct
+ y_max = y + wst
+ x_min = x - hst + wct
+ x_max = x
+ elif 180 < angle <= 270:
+ y_min = y + wst + hct
+ y_max = y
+ x_min = x + wct
+ x_max = x - hst
+ elif 270 < angle <= 360:
+ y_min = y + wst
+ y_max = y + hct
+ x_min = x
+ x_max = x + wct - hst
+
+ width = int(ceil(abs(x_max) + abs(x_min)))
+ height = int(ceil(abs(y_max) + abs(y_min)))
+ return width, height
Modified: grass/branches/develbranch_6/gui/wxpython/wxpythonlib.dox
===================================================================
--- grass/branches/develbranch_6/gui/wxpython/wxpythonlib.dox 2012-02-17 00:41:01 UTC (rev 50839)
+++ grass/branches/develbranch_6/gui/wxpython/wxpythonlib.dox 2012-02-17 06:45:00 UTC (rev 50840)
@@ -353,10 +353,25 @@
\subsection psmap Cartograpic Composer
- psmap::dialogs
- - dialogs::UnitConversion
- dialogs::TCValidator
- dialogs::PenStyleComboBox
- dialogs::CheckListCtrl
+ - dialogs::PsmapDialog
+ - dialogs::PageSetupDialog
+ - dialogs::MapDialog
+ - dialogs::MapFramePanel
+ - dialogs::RasterPanel
+ - dialogs::VectorPanel
+ - dialogs::RasterDialog
+ - dialogs::MainVectorDialog
+ - dialogs::VPropertiesDialog
+ - dialogs::LegendDialog
+ - dialogs::MapinfoDialog
+ - dialogs::ScalebarDialog
+ - dialogs::TextDialog
+ - dialogs::ImageDialog
+ - dialogs::NorthArrowDialog
+- psmap::instructions
- dialogs::Instruction
- dialogs::InstructionObject
- dialogs::InitMap
@@ -366,27 +381,20 @@
- dialogs::Text
- dialogs::Image
- dialogs::NorthArrow
+ - dialogs::Point
+ - dialogs::Line
+ - dialogs::Rectangle
- dialogs::Scalebar
- dialogs::RasterLegend
- dialogs::VectorLegend
- dialogs::Raster
- dialogs::Vector
- dialogs::VProperties
- - dialogs::PsmapDialog
- - dialogs::PageSetupDialog
- - dialogs::MapDialog
- - dialogs::MapFramePanel
- - dialogs::RasterPanel
- - dialogs::VectorPanel
- - dialogs::RasterDialog
- - dialogs::MainVectorDialog
- - dialogs::VPropertiesDialog
- - dialogs::LegendDialog
- - dialogs::MapinfoDialog
- - dialogs::ScalebarDialog
- - dialogs::TextDialog
- - dialogs::ImageDialog
- - dialogs::NorthArrowDialog
+- psmap::utils
+ - utils::Rect2D
+ - utils::Rect2DPP
+ - utils::Rect2DPS
+ - utils::UnitConversion
- psmap::frame
- frame::PsMapFrame
- frame::PsMapBufferedWindow
More information about the grass-commit
mailing list