12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760176117621763176417651766176717681769177017711772177317741775177617771778177917801781178217831784178517861787178817891790179117921793179417951796179717981799180018011802180318041805180618071808180918101811181218131814181518161817 |
- """!
- @package psmap.instructions
- @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.
- @author Anna Kratochvilova <kratochanna gmail.com> (bachelor's project)
- @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)
- epsfile = self.instruction['epsfile'].replace(os.getenv('GISBASE'), "$GISBASE")
-
- instr = "eps %s %s\n" % (self.instruction['east'], self.instruction['north'])
- instr += " epsfile %s\n" % epsfile
- 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':
- epsfile = line.split(None, 1)[1]
- instr['epsfile'] = epsfile.replace("$GISBASE", os.getenv("GISBASE"))
- 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)
- epsfile = self.instruction['epsfile'].replace(os.getenv('GISBASE'), "$GISBASE")
- instr = "eps %s %s\n" % (self.instruction['east'], self.instruction['north'])
- instr += "# north arrow\n"
- instr += " epsfile %s\n" % epsfile
- 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,
- sep = ':').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:
- patternFile = dic['pat'].replace(os.getenv("GISBASE"), "$GISBASE")
- vInstruction += " pat %s\n" % patternFile
- 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'):
- patternFile = line.split()[1]
- instr['pat'] = patternFile.replace("$GISBASE", os.getenv("GISBASE"))
- 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
|