|
GRASS Programmer's Manual
6.5.svn(2012)-r51648
|
00001 """! 00002 @package psmap.instructions 00003 00004 @brief Map feature objects 00005 00006 Classes: 00007 - dialogs::Instruction 00008 - dialogs::InstructionObject 00009 - dialogs::InitMap 00010 - dialogs::MapFrame 00011 - dialogs::PageSetup 00012 - dialogs::Mapinfo 00013 - dialogs::Text 00014 - dialogs::Image 00015 - dialogs::NorthArrow 00016 - dialogs::Point 00017 - dialogs::Line 00018 - dialogs::Rectangle 00019 - dialogs::Scalebar 00020 - dialogs::RasterLegend 00021 - dialogs::VectorLegend 00022 - dialogs::Raster 00023 - dialogs::Vector 00024 - dialogs::VProperties 00025 00026 (C) 2011-2012 by Anna Kratochvilova, and the GRASS Development Team 00027 00028 This program is free software under the GNU General Public License 00029 (>=v2). Read the file COPYING that comes with GRASS for details. 00030 00031 @author Anna Kratochvilova <kratochanna gmail.com> (bachelor's project) 00032 @author Martin Landa <landa.martin gmail.com> (mentor) 00033 """ 00034 00035 import os 00036 import string 00037 from math import ceil 00038 from time import strftime, localtime 00039 00040 import wx 00041 import grass.script as grass 00042 00043 from core.gcmd import RunCommand, GError, GMessage, GWarning 00044 from core.utils import CmdToTuple, GetCmdString 00045 from dbmgr.vinfo import VectorDBInfo 00046 from psmap.utils import * 00047 00048 class Instruction: 00049 """!Class which represents instruction file""" 00050 def __init__(self, parent, objectsToDraw): 00051 00052 self.parent = parent 00053 self.objectsToDraw = objectsToDraw 00054 #here are kept objects like mapinfo, rasterlegend, etc. 00055 self.instruction = list() 00056 00057 def __str__(self): 00058 """!Returns text for instruction file""" 00059 comment = "# timestamp: " + strftime("%Y-%m-%d %H:%M", localtime()) + '\n' 00060 env = grass.gisenv() 00061 comment += "# location: %s\n" % env['LOCATION_NAME'] 00062 comment += "# mapset: %s\n" % env['MAPSET'] 00063 comment += "# page orientation: %s\n" % self.FindInstructionByType('page')['Orientation'] 00064 border = '' 00065 if not self.FindInstructionByType('map'): 00066 border = 'border n\n' 00067 text = [str(each) for each in self.instruction] 00068 return comment + border + '\n'.join(text) + '\nend' 00069 00070 def __getitem__(self, id): 00071 for each in self.instruction: 00072 if each.id == id: 00073 return each 00074 return None 00075 00076 def __contains__(self, id): 00077 """!Test if instruction is included""" 00078 for each in self.instruction: 00079 if each.id == id: 00080 return True 00081 return False 00082 00083 def __delitem__(self, id): 00084 """!Delete instruction""" 00085 for each in self.instruction: 00086 if each.id == id: 00087 if each.type == 'map': 00088 #must remove raster, vector layers too 00089 vektor = self.FindInstructionByType('vector', list = True) 00090 vProperties = self.FindInstructionByType('vProperties', list = True) 00091 raster = self.FindInstructionByType('raster', list = True) 00092 for item in vektor + vProperties + raster: 00093 if item in self.instruction: 00094 self.instruction.remove(item) 00095 00096 self.instruction.remove(each) 00097 if id in self.objectsToDraw: 00098 self.objectsToDraw.remove(id) 00099 return 00100 00101 def AddInstruction(self, instruction): 00102 """!Add instruction""" 00103 # add to instructions 00104 if instruction.type == 'map': 00105 self.instruction.insert(0, instruction) 00106 else: 00107 self.instruction.append(instruction) 00108 # add to drawable objects 00109 if instruction.type not in ('page', 'raster', 'vector', 'vProperties', 'initMap'): 00110 if instruction.type == 'map': 00111 self.objectsToDraw.insert(0, instruction.id) 00112 else: 00113 self.objectsToDraw.append(instruction.id) 00114 00115 00116 def FindInstructionByType(self, type, list = False): 00117 """!Find instruction(s) with the given type""" 00118 inst = [] 00119 for each in self.instruction: 00120 if each.type == type: 00121 inst.append(each) 00122 if len(inst) == 1 and not list: 00123 return inst[0] 00124 return inst 00125 00126 def Read(self, filename): 00127 """!Reads instruction file and creates instruction objects""" 00128 self.filename = filename 00129 # open file 00130 try: 00131 file = open(filename, 'r') 00132 except IOError: 00133 GError(message = _("Unable to open file\n%s") % filename) 00134 return 00135 # first read file to get information about region and scaletype 00136 isRegionComment = False 00137 orientation = 'Portrait' 00138 for line in file: 00139 if '# g.region' in line: 00140 self.SetRegion(regionInstruction = line) 00141 isRegionComment = True 00142 break 00143 if '# page orientation' in line: 00144 orientation = line.split(':')[-1].strip() 00145 00146 if not isRegionComment: 00147 self.SetRegion(regionInstruction = None) 00148 # then run ps.map -b to get information for maploc 00149 # compute scale and center 00150 map = self.FindInstructionByType('map') 00151 region = grass.region() 00152 map['center'] = (region['n'] + region['s']) / 2, (region['w'] + region['e']) / 2 00153 mapRect = GetMapBounds(self.filename, portrait = (orientation == 'Portrait')) 00154 map['rect'] = mapRect 00155 proj = projInfo() 00156 toM = 1.0 00157 if proj['units']: 00158 toM = float(proj['meters']) 00159 units = UnitConversion(self.parent) 00160 w = units.convert(value = mapRect.Get()[2], fromUnit = 'inch', toUnit = 'meter') / toM 00161 map['scale'] = w / abs((region['w'] - region['e'])) 00162 00163 SetResolution(dpi = 300, width = map['rect'].width, height = map['rect'].height) 00164 00165 # read file again, now with information about map bounds 00166 isBuffer = False 00167 buffer = [] 00168 instruction = None 00169 vectorMapNumber = 1 00170 file.seek(0) 00171 for line in file: 00172 if not line.strip(): 00173 continue 00174 line = line.strip() 00175 if isBuffer: 00176 buffer.append(line) 00177 if 'end' in line: 00178 isBuffer = False 00179 kwargs = {} 00180 if instruction == 'scalebar': 00181 kwargs['scale'] = map['scale'] 00182 elif instruction in ('text', 'eps', 'point', 'line', 'rectangle'): 00183 kwargs['mapInstruction'] = map 00184 elif instruction in ('vpoints', 'vlines', 'vareas'): 00185 kwargs['id'] = wx.NewId() 00186 kwargs['vectorMapNumber'] = vectorMapNumber 00187 vectorMapNumber += 1 00188 elif instruction == 'paper': 00189 kwargs['Orientation'] = orientation 00190 00191 ok = self.SendToRead(instruction, buffer, **kwargs) 00192 if not ok: return False 00193 buffer = [] 00194 continue 00195 00196 elif line.startswith('paper'): 00197 instruction = 'paper' 00198 isBuffer = True 00199 buffer.append(line) 00200 00201 elif line.startswith('border'): 00202 if line.split()[1].lower() in ('n', 'no', 'none'): 00203 ok = self.SendToRead('border', [line]) 00204 if not ok: return False 00205 elif line.split()[1].lower() in ('y', 'yes'): 00206 instruction = 'border' 00207 isBuffer = True 00208 buffer.append(line) 00209 00210 elif line.startswith('scale '): 00211 if isBuffer: 00212 continue 00213 ok = self.SendToRead('scale', line, isRegionComment = isRegionComment) 00214 if not ok: return False 00215 00216 elif line.startswith('maploc'): 00217 ok = self.SendToRead(instruction = 'maploc', text = line) 00218 if not ok: return False 00219 00220 elif line.startswith('raster'): 00221 ok = self.SendToRead(instruction = 'raster', text = line) 00222 if not ok: return False 00223 00224 elif line.startswith('mapinfo'): 00225 instruction = 'mapinfo' 00226 isBuffer = True 00227 buffer.append(line) 00228 00229 00230 elif line.startswith('scalebar'): 00231 instruction = 'scalebar' 00232 isBuffer = True 00233 buffer.append(line) 00234 00235 elif line.startswith('text'): 00236 instruction = 'text' 00237 isBuffer = True 00238 buffer.append(line) 00239 00240 elif line.startswith('eps'): 00241 instruction = 'eps' 00242 isBuffer = True 00243 buffer.append(line) 00244 00245 elif line.startswith('point'): 00246 instruction = 'point' 00247 isBuffer = True 00248 buffer.append(line) 00249 00250 elif line.startswith('line'): 00251 instruction = 'line' 00252 isBuffer = True 00253 buffer.append(line) 00254 00255 elif line.startswith('rectangle'): 00256 instruction = 'rectangle' 00257 isBuffer = True 00258 buffer.append(line) 00259 00260 elif line.startswith('colortable'): 00261 if len(line.split()) == 2 and line.split()[1].lower() in ('n', 'no', 'none'): 00262 break 00263 instruction = 'colortable' 00264 isBuffer = True 00265 buffer.append(line) 00266 00267 elif line.startswith('vlegend'): 00268 instruction = 'vlegend' 00269 isBuffer = True 00270 buffer.append(line) 00271 00272 elif line.startswith('vpoints'): 00273 instruction = 'vpoints' 00274 isBuffer = True 00275 buffer.append(line) 00276 00277 elif line.startswith('vlines'): 00278 instruction = 'vlines' 00279 isBuffer = True 00280 buffer.append(line) 00281 00282 elif line.startswith('vareas'): 00283 instruction = 'vareas' 00284 isBuffer = True 00285 buffer.append(line) 00286 00287 00288 00289 rasterLegend = self.FindInstructionByType('rasterLegend') 00290 raster = self.FindInstructionByType('raster') 00291 page = self.FindInstructionByType('page') 00292 vector = self.FindInstructionByType('vector') 00293 vectorLegend = self.FindInstructionByType('vectorLegend') 00294 vectorMaps = self.FindInstructionByType('vProperties', list = True) 00295 00296 # check (in case of scaletype 0) if map is drawn also 00297 map['drawMap'] = False 00298 if map['scaleType'] == 0: 00299 mapForRegion = map['map'] 00300 if map['mapType'] == 'raster' and raster: 00301 if mapForRegion == raster['raster']: 00302 map['drawMap'] = True 00303 elif map['mapType'] == 'vector' and vector: 00304 for vmap in vector['list']: 00305 if mapForRegion == vmap[0]: 00306 map['drawMap'] = True 00307 00308 # rasterLegend 00309 if rasterLegend: 00310 if rasterLegend['rasterDefault'] and raster: 00311 rasterLegend['raster'] = raster['raster'] 00312 if not rasterLegend['discrete']: 00313 rasterType = getRasterType(map = rasterLegend['raster']) 00314 if rasterType == 'CELL': 00315 rasterLegend['discrete'] = 'y' 00316 else: 00317 rasterLegend['discrete'] = 'n' 00318 00319 #estimate size 00320 height = rasterLegend.EstimateHeight(raster = rasterLegend['raster'], discrete = rasterLegend['discrete'], 00321 fontsize = rasterLegend['fontsize'], 00322 cols = rasterLegend['cols'], 00323 height = rasterLegend['height']) 00324 width = rasterLegend.EstimateWidth(raster = rasterLegend['raster'], discrete = rasterLegend['discrete'], 00325 fontsize = rasterLegend['fontsize'], 00326 cols = rasterLegend['cols'] , 00327 width = rasterLegend['width'], 00328 paperInstr = page) 00329 rasterLegend['rect'] = Rect2D(x = float(rasterLegend['where'][0]), y = float(rasterLegend['where'][1]), 00330 width = width, height = height) 00331 00332 # vectors, vlegend 00333 00334 if vector: 00335 for vmap in vectorMaps: 00336 for i, each in enumerate(vector['list']): 00337 if each[2] == vmap.id: 00338 00339 vector['list'][i][4] = vmap['label'] 00340 vector['list'][i][3] = vmap['lpos'] 00341 if vectorLegend: 00342 size = vectorLegend.EstimateSize(vectorInstr = vector, fontsize = vectorLegend['fontsize'], 00343 width = vectorLegend['width'], cols = vectorLegend['cols']) 00344 vectorLegend['rect'] = Rect2D(x = float(vectorLegend['where'][0]), y = float(vectorLegend['where'][1]), 00345 width = size[0], height = size[1]) 00346 00347 00348 page = self.FindInstructionByType('page') 00349 if not page: 00350 page = PageSetup(wx.NewId()) 00351 self.AddInstruction(page) 00352 else: 00353 page['Orientation'] = orientation 00354 00355 00356 # 00357 return True 00358 00359 def SendToRead(self, instruction, text, **kwargs): 00360 psmapInstrDict = dict(paper = ['page'], 00361 maploc = ['map'], 00362 scale = ['map'], 00363 border = ['map'], 00364 raster = ['raster'], 00365 mapinfo = ['mapinfo'], 00366 scalebar = ['scalebar'], 00367 text = ['text'], 00368 eps = ['image', 'northArrow'], 00369 point = ['point'], 00370 line = ['line'], 00371 rectangle = ['rectangle'], 00372 vpoints = ['vector', 'vProperties'], 00373 vlines = ['vector', 'vProperties'], 00374 vareas = ['vector', 'vProperties'], 00375 colortable = ['rasterLegend'], 00376 vlegend = ['vectorLegend'] 00377 ) 00378 00379 myInstrDict = dict(page = PageSetup, 00380 map = MapFrame, 00381 raster = Raster, 00382 mapinfo = Mapinfo, 00383 scalebar = Scalebar, 00384 text = Text, 00385 image = Image, 00386 northArrow = NorthArrow, 00387 point = Point, 00388 line = Line, 00389 rectangle = Rectangle, 00390 rasterLegend = RasterLegend, 00391 vectorLegend = VectorLegend, 00392 vector = Vector, 00393 vProperties = VProperties 00394 ) 00395 00396 myInstruction = psmapInstrDict[instruction] 00397 00398 for i in myInstruction: 00399 instr = self.FindInstructionByType(i) 00400 if i in ('text', 'vProperties', 'image', 'northArrow', 'point', 'line', 'rectangle') or not instr: 00401 00402 id = wx.NewId() #!vProperties expect subtype 00403 if i == 'vProperties': 00404 id = kwargs['id'] 00405 newInstr = myInstrDict[i](id, subType = instruction[1:]) 00406 elif i in ('image', 'northArrow'): 00407 commentFound = False 00408 for line in text: 00409 if line.find("# north arrow") >= 0: 00410 commentFound = True 00411 if i == 'image' and commentFound or \ 00412 i == 'northArrow' and not commentFound: 00413 continue 00414 newInstr = myInstrDict[i](id, settings = self) 00415 else: 00416 newInstr = myInstrDict[i](id) 00417 ok = newInstr.Read(instruction, text, **kwargs) 00418 if ok: 00419 self.AddInstruction(newInstr) 00420 else: 00421 return False 00422 00423 else: 00424 ok = instr.Read(instruction, text, **kwargs) 00425 00426 if not ok: 00427 return False 00428 return True 00429 00430 def SetRegion(self, regionInstruction): 00431 """!Sets region from file comment or sets current region in case of no comment""" 00432 map = MapFrame(wx.NewId()) 00433 self.AddInstruction(map) 00434 if regionInstruction: 00435 cmd = CmdToTuple(regionInstruction.strip('# ').split()) 00436 00437 # define scaleType 00438 if len(cmd[1]) <= 3: 00439 if 'rast' in cmd[1]: 00440 map['scaleType'] = 0 00441 map['mapType'] = 'raster' 00442 map['map'] = cmd[1]['rast'] 00443 elif 'vect' in cmd[1]: 00444 map['scaleType'] = 0 00445 map['mapType'] = 'vector' 00446 map['map'] = cmd[1]['vect'] 00447 elif 'region' in cmd[1]: 00448 map['scaleType'] = 1 00449 map['region'] = cmd[1]['region'] 00450 00451 else: 00452 map['scaleType'] = 2 00453 else: 00454 map['scaleType'] = 2 00455 grass.del_temp_region() 00456 region = grass.region() 00457 grass.use_temp_region() 00458 cmd = ['g.region', region] 00459 cmdString = GetCmdString(cmd).replace('g.region', '') 00460 GMessage(_("Instruction file will be loaded with following region: %s\n") % cmdString) 00461 try: 00462 RunCommand(cmd[0], **cmd[1]) 00463 00464 except grass.ScriptError, e: 00465 GError(_("Region cannot be set\n%s") % e) 00466 return False 00467 00468 00469 class InstructionObject: 00470 """!Abtract class representing single instruction""" 00471 def __init__(self, id): 00472 self.id = id 00473 00474 # default values 00475 self.defaultInstruction = dict() 00476 # current values 00477 self.instruction = self.defaultInstruction 00478 # converting units 00479 self.unitConv = UnitConversion() 00480 00481 def __str__(self): 00482 """!Returns particular part of text instruction""" 00483 return '' 00484 00485 def __getitem__(self, key): 00486 for each in self.instruction.keys(): 00487 if each == key: 00488 return self.instruction[key] 00489 return None 00490 00491 def __setitem__(self, key, value): 00492 self.instruction[key] = value 00493 00494 def GetInstruction(self): 00495 """!Get current values""" 00496 return self.instruction 00497 00498 def SetInstruction(self, instruction): 00499 """!Set default values""" 00500 self.instruction = instruction 00501 00502 def Read(self, instruction, text, **kwargs): 00503 """!Read instruction and save them""" 00504 pass 00505 00506 def PercentToReal(self, e, n): 00507 """!Converts text coordinates from percent of region to map coordinates""" 00508 e, n = float(e.strip('%')), float(n.strip('%')) 00509 region = grass.region() 00510 N = region['s'] + (region['n'] - region['s']) / 100 * n 00511 E = region['w'] + (region['e'] - region['w']) / 100 * e 00512 return E, N 00513 00514 class InitMap(InstructionObject): 00515 """!Class representing virtual map""" 00516 def __init__(self, id): 00517 InstructionObject.__init__(self, id = id) 00518 self.type = 'initMap' 00519 00520 # default values 00521 self.defaultInstruction = dict(rect = None, scale = None) 00522 # current values 00523 self.instruction = dict(self.defaultInstruction) 00524 00525 00526 class MapFrame(InstructionObject): 00527 """!Class representing map (instructions maploc, scale, border)""" 00528 def __init__(self, id): 00529 InstructionObject.__init__(self, id = id) 00530 self.type = 'map' 00531 # default values 00532 self.defaultInstruction = dict(map = None, mapType = None, drawMap = True, region = None, 00533 rect = Rect2D(), scaleType = 0, scale = None, center = None, 00534 resolution = 300, border = 'y', width = 1, color = '0:0:0') 00535 # current values 00536 self.instruction = dict(self.defaultInstruction) 00537 00538 def __str__(self): 00539 instr = '' 00540 comment = '' 00541 00542 #region settings 00543 region = grass.region() 00544 if self.instruction['scaleType'] == 0: #match map 00545 map = self.instruction['map'] 00546 if self.instruction['mapType'] == 'raster': 00547 comment = "# g.region rast=%s nsres=%s ewres=%s\n" % (map, region['nsres'], region['ewres']) 00548 else: 00549 comment = "# g.region vect=%s\n" % (map) 00550 elif self.instruction['scaleType'] == 1:# saved region 00551 region = self.instruction['region'] 00552 comment = "# g.region region=%s\n" % region 00553 elif self.instruction['scaleType'] in (2, 3): #current region, fixed scale 00554 comment = string.Template("# g.region n=$n s=$s e=$e w=$w rows=$rows cols=$cols \n").substitute(**region) 00555 00556 instr += comment 00557 instr += '\n' 00558 # maploc 00559 maplocInstruction = "maploc %.3f %.3f" % (self.instruction['rect'].x, self.instruction['rect'].y) 00560 if self.instruction['scaleType'] != 3: 00561 maplocInstruction += " %.3f %.3f"% (self.instruction['rect'].width, self.instruction['rect'].height) 00562 instr += maplocInstruction 00563 instr += '\n' 00564 00565 # scale 00566 if self.instruction['scaleType'] == 3: #fixed scale 00567 scaleInstruction = "scale 1:%.0f" % (1/self.instruction['scale']) 00568 instr += scaleInstruction 00569 instr += '\n' 00570 # border 00571 borderInstruction = '' 00572 if self.instruction['border'] == 'n': 00573 borderInstruction = "border n" 00574 else: 00575 borderInstruction = "border y\n" 00576 borderInstruction += string.Template(" width $width\n color $color\n").substitute(self.instruction) 00577 borderInstruction += " end" 00578 instr += borderInstruction 00579 instr += '\n' 00580 00581 return instr 00582 00583 def Read(self, instruction, text, **kwargs): 00584 """!Read instruction and save information""" 00585 if 'isRegionComment' in kwargs: 00586 isRegionComment = kwargs['isRegionComment'] 00587 instr = {} 00588 00589 if instruction == 'border': 00590 for line in text: 00591 if line.startswith('end'): 00592 break 00593 try: 00594 if line.split()[1].lower() in ('n', 'no', 'none'): 00595 instr['border'] = 'n' 00596 break 00597 elif line.split()[1].lower() in ('y', 'yes'): 00598 instr['border'] = 'y' 00599 elif line.startswith('width'): 00600 instr['width'] = line.split()[1] 00601 elif line.startswith('color'): 00602 instr['color'] = line.split()[1] 00603 except IndexError: 00604 GError(_("Failed to read instruction %s") % instruction) 00605 return False 00606 00607 elif instruction == 'scale': 00608 try: 00609 scaleText = text.strip('scale ').split(':')[1] 00610 # when scale instruction given and region comment also, then scaletype is fixed scale 00611 if not isRegionComment: 00612 instr['scaleType'] = 2 00613 else: 00614 instr['scaleType'] = 3 00615 00616 scale = 1/float(scaleText) 00617 if abs(scale - self.instruction['scale']) > (0.01 * scale): 00618 GWarning(_("Scale has changed, old value: %(old)s\nnew value: %(new)s") % \ 00619 { 'old' : scale, 'new' : self.instruction['scale'] }) 00620 except (ValueError, IndexError): 00621 GError(_("Failed to read instruction %s.\nUse 1:25000 notation.") % instruction) 00622 return False 00623 00624 elif instruction == 'maploc': 00625 maploc = text.strip('maploc ').split() 00626 if len(maploc) >= 2: 00627 if abs(self.instruction['rect'].Get()[0] - float(maploc[0])) > 0.5 or \ 00628 abs(self.instruction['rect'].Get()[1] - float(maploc[1])) > 0.5: 00629 GWarning(_("Map frame position changed, old value: %(old1)s %(old2)s\nnew value: %(new1)s %(new2)s") % \ 00630 { 'old1' : maploc[0], 'old2' : maploc[1], 00631 'new1' : self.instruction['rect'].Get()[0], 'new2' : self.instruction['rect'].Get()[1] }) 00632 00633 #instr['rect'] = wx.Rect2D(float(maploc[0]), float(maploc[1]), self.instruction['rect'][2], self.instruction['rect'][3]) 00634 if len(maploc) == 4: 00635 if abs(self.instruction['rect'].Get()[2] - float(maploc[2])) > 0.5 or \ 00636 abs(self.instruction['rect'].Get()[3] - float(maploc[3])) > 0.5: 00637 GWarning(_("Map frame size changed, old value: %(old1)s %(old2)s\nnew value: %(new1)s %(new2)s") % \ 00638 { 'old1' : maploc[2], 'old2' : maploc[3], 00639 'new1' : self.instruction['rect'].Get()[2], 'new2' : self.instruction['rect'].Get()[3] }) 00640 #instr['rect'] = wx.Rect2D(*map(float, maploc)) 00641 self.instruction.update(instr) 00642 return True 00643 00644 class PageSetup(InstructionObject): 00645 """!Class representing page instruction""" 00646 def __init__(self, id): 00647 InstructionObject.__init__(self, id = id) 00648 self.type = 'page' 00649 # default values 00650 self.defaultInstruction = dict(Units = 'inch', Format = 'a4', Orientation = 'Portrait', 00651 Width = 8.268, Height = 11.693, Left = 0.5, Right = 0.5, Top = 1, Bottom = 1) 00652 # current values 00653 self.instruction = dict(self.defaultInstruction) 00654 00655 def __str__(self): 00656 if self.instruction['Format'] == 'custom': 00657 instr = string.Template("paper\n width $Width\n height $Height\n").substitute(self.instruction) 00658 else: 00659 instr = string.Template("paper $Format\n").substitute(self.instruction) 00660 instr += string.Template(" left $Left\n right $Right\n bottom $Bottom\n top $Top\n end").substitute(self.instruction) 00661 00662 return instr 00663 00664 def Read(self, instruction, text, **kwargs): 00665 """!Read instruction and save information""" 00666 instr = {} 00667 self.cats = ['Width', 'Height', 'Left', 'Right', 'Top', 'Bottom'] 00668 self.subInstr = dict(zip(['width', 'height', 'left', 'right', 'top', 'bottom'], self.cats)) 00669 00670 if instruction == 'paper': # just for sure 00671 for line in text: 00672 if line.startswith('paper'): 00673 if len(line.split()) > 1: 00674 pformat = line.split()[1] 00675 availableFormats = self._toDict(grass.read_command('ps.map', flags = 'p', 00676 quiet = True)) 00677 # e.g. paper a3 00678 try: 00679 instr['Format'] = pformat 00680 for key, value in availableFormats[pformat].iteritems(): 00681 instr[key] = float(value) 00682 break 00683 except KeyError: 00684 GError(_("Failed to read instruction %(file)s.\nUnknown format %(for)s") % \ 00685 { 'file' : instruction, 'for' : format }) 00686 return False 00687 else: 00688 # paper 00689 # width ... 00690 instr['Format'] = 'custom' 00691 # read subinstructions 00692 elif instr['Format'] == 'custom' and not line.startswith('end'): 00693 text = line.split() 00694 try: 00695 instr[self.subInstr[text[0]]] = float(text[1]) 00696 except (IndexError, KeyError): 00697 GError(_("Failed to read instruction %s.") % instruction) 00698 return False 00699 00700 if 'Orientation' in kwargs and kwargs['Orientation'] == 'Landscape': 00701 instr['Width'], instr['Height'] = instr['Height'], instr['Width'] 00702 00703 self.instruction.update(instr) 00704 return True 00705 00706 def _toDict(self, paperStr): 00707 sizeDict = dict() 00708 # cats = self.subInstr[ 'Width', 'Height', 'Left', 'Right', 'Top', 'Bottom'] 00709 for line in paperStr.strip().split('\n'): 00710 d = dict(zip(self.cats, line.split()[1:])) 00711 sizeDict[line.split()[0]] = d 00712 00713 return sizeDict 00714 00715 class Mapinfo(InstructionObject): 00716 """!Class representing mapinfo instruction""" 00717 def __init__(self, id): 00718 InstructionObject.__init__(self, id = id) 00719 self.type = 'mapinfo' 00720 # default values 00721 self.defaultInstruction = dict(unit = 'inch', where = (0, 0), 00722 font = 'Helvetica', fontsize = 10, color = '0:0:0', background = 'none', 00723 border = 'none', rect = None) 00724 # current values 00725 self.instruction = dict(self.defaultInstruction) 00726 00727 def __str__(self): 00728 instr = "mapinfo\n" 00729 instr += " where %.3f %.3f\n" % (self.instruction['where'][0], self.instruction['where'][1]) 00730 instr += string.Template(" font $font\n fontsize $fontsize\n color $color\n").substitute(self.instruction) 00731 instr += string.Template(" background $background\n border $border\n").substitute(self.instruction) 00732 instr += " end" 00733 return instr 00734 00735 def Read(self, instruction, text): 00736 """!Read instruction and save information""" 00737 instr = {} 00738 try: 00739 for line in text: 00740 sub = line.split(None,1) 00741 if sub[0] == 'font': 00742 instr['font'] = sub[1] 00743 elif sub[0] == 'fontsize': 00744 instr['fontsize'] = int(sub[1]) 00745 elif sub[0] == 'color': 00746 instr['color'] = sub[1] 00747 elif sub[0] == 'background': 00748 instr['background'] = sub[1] 00749 elif sub[0] == 'border': 00750 instr['border'] = sub[1] 00751 elif sub[0] == 'where': 00752 instr['where'] = float(sub[1].split()[0]), float(sub[1].split()[1]) 00753 except (ValueError, IndexError): 00754 GError(_("Failed to read instruction %s") % instruction) 00755 return False 00756 self.instruction.update(instr) 00757 self.instruction['rect'] = self.EstimateRect(mapinfoDict = self.instruction) 00758 return True 00759 00760 def EstimateRect(self, mapinfoDict): 00761 """!Estimate size to draw mapinfo""" 00762 w = mapinfoDict['fontsize'] * 20 # any better estimation? 00763 h = mapinfoDict['fontsize'] * 7 00764 width = self.unitConv.convert(value = w, fromUnit = 'point', toUnit = 'inch') 00765 height = self.unitConv.convert(value = h, fromUnit = 'point', toUnit = 'inch') 00766 return Rect2D(x = float(mapinfoDict['where'][0]), y = float(mapinfoDict['where'][1]), 00767 width = width, height = height) 00768 00769 class Text(InstructionObject): 00770 """!Class representing text instruction""" 00771 def __init__(self, id): 00772 InstructionObject.__init__(self, id = id) 00773 self.type = 'text' 00774 # default values 00775 self.defaultInstruction = dict(text = "", font = "Helvetica", fontsize = 10, color = 'black', background = 'none', 00776 hcolor = 'none', hwidth = 1, border = 'none', width = '1', XY = True, 00777 where = (0,0), unit = 'inch', rotate = None, 00778 ref = "center center", xoffset = 0, yoffset = 0, east = None, north = None) 00779 # current values 00780 self.instruction = dict(self.defaultInstruction) 00781 00782 def __str__(self): 00783 text = self.instruction['text'].replace('\n','\\n') 00784 instr = u"text %s %s" % (self.instruction['east'], self.instruction['north']) 00785 instr += " %s\n" % text 00786 instr += (string.Template(" font $font\n fontsize $fontsize\n color $color\n"). 00787 substitute(self.instruction)) 00788 instr += string.Template(" hcolor $hcolor\n").substitute(self.instruction) 00789 if self.instruction['hcolor'] != 'none': 00790 instr += string.Template(" hwidth $hwidth\n").substitute(self.instruction) 00791 instr += string.Template(" border $border\n").substitute(self.instruction) 00792 if self.instruction['border'] != 'none': 00793 instr += string.Template(" width $width\n").substitute(self.instruction) 00794 instr += string.Template(" background $background\n").substitute(self.instruction) 00795 if self.instruction["ref"] != '0': 00796 instr += string.Template(" ref $ref\n").substitute(self.instruction) 00797 if self.instruction["rotate"]: 00798 instr += string.Template(" rotate $rotate\n").substitute(self.instruction) 00799 if float(self.instruction["xoffset"]) or float(self.instruction["yoffset"]): 00800 instr += (string.Template(" xoffset $xoffset\n yoffset $yoffset\n"). 00801 substitute(self.instruction)) 00802 instr += " end" 00803 try: 00804 instr = instr.encode('latin1') 00805 except UnicodeEncodeError, err: 00806 try: 00807 pos = str(err).split('position')[1].split(':')[0].strip() 00808 except IndexError: 00809 pos = '' 00810 if pos: 00811 message = _("Characters on position %s are not supported " 00812 "by ISO-8859-1 (Latin 1) encoding " 00813 "which is required by module ps.map.") % pos 00814 else: 00815 message = _("Not all characters are supported " 00816 "by ISO-8859-1 (Latin 1) encoding " 00817 "which is required by module ps.map.") 00818 GMessage(message = message) 00819 return '' 00820 00821 return instr 00822 00823 def Read(self, instruction, text, **kwargs): 00824 """!Read instruction and save information""" 00825 map = kwargs['mapInstruction'] 00826 instr = {} 00827 for line in text: 00828 try: 00829 sub = line.split(None, 1)[0] 00830 if sub == 'text': 00831 e, n = line.split(None, 3)[1:3] 00832 if '%' in e and '%' in n: 00833 instr['XY'] = True 00834 instr['east'], instr['north'] = self.PercentToReal(e, n) 00835 else: 00836 instr['XY'] = False 00837 instr['east'], instr['north'] = float(e), float(n) 00838 00839 instr['text'] = line.split(None, 3)[3].decode('latin_1') 00840 00841 elif sub == 'font': 00842 instr['font'] = line.split(None, 1)[1] 00843 elif sub == 'fontsize': 00844 instr['fontsize'] = float(line.split(None, 1)[1]) 00845 elif sub == 'color': 00846 instr['color'] = line.split(None, 1)[1] 00847 elif sub == 'width': 00848 instr['width'] = line.split(None, 1)[1] 00849 elif sub == 'hcolor': 00850 instr['hcolor'] = line.split(None, 1)[1] 00851 elif sub == 'hwidth': 00852 instr['hwidth'] = line.split(None, 1)[1] 00853 elif sub == 'background': 00854 instr['background'] = line.split(None, 1)[1] 00855 elif sub == 'border': 00856 instr['border'] = line.split(None, 1)[1] 00857 elif sub == 'ref': 00858 instr['ref'] = line.split(None, 1)[1] 00859 elif sub == 'rotate': 00860 instr['rotate'] = float(line.split(None, 1)[1]) 00861 elif sub == 'xoffset': 00862 instr['xoffset'] = int(line.split(None, 1)[1]) 00863 elif sub == 'yoffset': 00864 instr['yoffset'] = int(line.split(None, 1)[1]) 00865 elif sub == 'opaque': 00866 if line.split(None, 1)[1].lower() in ('n', 'none'): 00867 instr['background'] = 'none' 00868 00869 except(IndexError, ValueError): 00870 GError(_("Failed to read instruction %s") % instruction) 00871 return False 00872 instr['where'] = PaperMapCoordinates(mapInstr = map, x = instr['east'], y = instr['north'], paperToMap = False) 00873 self.instruction.update(instr) 00874 00875 return True 00876 00877 class Image(InstructionObject): 00878 """!Class representing eps instruction - image""" 00879 def __init__(self, id, settings): 00880 InstructionObject.__init__(self, id = id) 00881 self.settings = settings 00882 self.type = 'image' 00883 # default values 00884 self.defaultInstruction = dict(epsfile = "", XY = True, where = (0,0), unit = 'inch', 00885 east = None, north = None, 00886 rotate = None, scale = 1) 00887 # current values 00888 self.instruction = dict(self.defaultInstruction) 00889 00890 def __str__(self): 00891 self.ChangeRefPoint(toCenter = True) 00892 epsfile = self.instruction['epsfile'].replace(os.getenv('GISBASE'), "$GISBASE") 00893 00894 instr = "eps %s %s\n" % (self.instruction['east'], self.instruction['north']) 00895 instr += " epsfile %s\n" % epsfile 00896 if self.instruction["rotate"]: 00897 instr += string.Template(" rotate $rotate\n").substitute(self.instruction) 00898 if self.instruction["scale"]: 00899 instr += string.Template(" scale $scale\n").substitute(self.instruction) 00900 instr += " end" 00901 return instr 00902 00903 def Read(self, instruction, text, **kwargs): 00904 """!Read instruction and save information""" 00905 mapInstr = kwargs['mapInstruction'] 00906 instr = {} 00907 for line in text: 00908 try: 00909 sub = line.split(None, 1)[0] 00910 if sub == 'eps': 00911 e, n = line.split(None, 3)[1:3] 00912 if '%' in e and '%' in n: 00913 instr['XY'] = True 00914 instr['east'], instr['north'] = self.PercentToReal(e, n) 00915 else: 00916 instr['XY'] = False 00917 instr['east'], instr['north'] = float(e), float(n) 00918 00919 elif sub == 'epsfile': 00920 epsfile = line.split(None, 1)[1] 00921 instr['epsfile'] = epsfile.replace("$GISBASE", os.getenv("GISBASE")) 00922 elif sub == 'rotate': 00923 instr['rotate'] = float(line.split(None, 1)[1]) 00924 elif sub == 'scale': 00925 instr['scale'] = float(line.split(None, 1)[1]) 00926 00927 except(IndexError, ValueError): 00928 GError(_("Failed to read instruction %s") % instruction) 00929 return False 00930 if not os.path.exists(instr['epsfile']): 00931 GError(_("Failed to read instruction %(inst)s: " 00932 "file %(file)s not found.") % { 'inst' : instruction, 00933 'file' : instr['epsfile'] }) 00934 return False 00935 00936 instr['epsfile'] = os.path.abspath(instr['epsfile']) 00937 instr['size'] = self.GetImageOrigSize(instr['epsfile']) 00938 if 'rotate' in instr: 00939 instr['size'] = BBoxAfterRotation(instr['size'][0], instr['size'][1], instr['rotate']) 00940 self.instruction.update(instr) 00941 self.ChangeRefPoint(toCenter = False) 00942 instr['where'] = PaperMapCoordinates(mapInstr = mapInstr, x = self.instruction['east'], 00943 y = self.instruction['north'], paperToMap = False) 00944 w = self.unitConv.convert(value = instr['size'][0], fromUnit = 'point', toUnit = 'inch') 00945 h = self.unitConv.convert(value = instr['size'][1], fromUnit = 'point', toUnit = 'inch') 00946 instr['rect'] = Rect2D(x = float(instr['where'][0]), y = float(instr['where'][1]), 00947 width = w * self.instruction['scale'], height = h * self.instruction['scale']) 00948 self.instruction.update(instr) 00949 00950 return True 00951 00952 def ChangeRefPoint(self, toCenter): 00953 """!Change reference point (left top x center)""" 00954 mapInstr = self.settings.FindInstructionByType('map') 00955 if not mapInstr: 00956 mapInstr = self.settings.FindInstructionByType('initMap') 00957 mapId = mapInstr.id 00958 if toCenter: 00959 center = self.instruction['rect'].GetCentre() 00960 ENCenter = PaperMapCoordinates(mapInstr = self.settings[mapId], 00961 x = center[0], y = center[1], paperToMap = True) 00962 00963 self.instruction['east'], self.instruction['north'] = ENCenter 00964 else: 00965 x, y = PaperMapCoordinates(mapInstr = self.settings[mapId], x = self.instruction['east'], 00966 y = self.instruction['north'], paperToMap = False) 00967 w = self.unitConv.convert(value = self.instruction['size'][0], fromUnit = 'point', toUnit = 'inch') 00968 h = self.unitConv.convert(value = self.instruction['size'][1], fromUnit = 'point', toUnit = 'inch') 00969 x -= w * self.instruction['scale'] / 2 00970 y -= h * self.instruction['scale'] / 2 00971 e, n = PaperMapCoordinates(mapInstr = self.settings[mapId], x = x, y = y, paperToMap = True) 00972 self.instruction['east'], self.instruction['north'] = e, n 00973 00974 def GetImageOrigSize(self, imagePath): 00975 """!Get image size. 00976 00977 If eps, size is read from image header. 00978 """ 00979 fileName = os.path.split(imagePath)[1] 00980 # if eps, read info from header 00981 if os.path.splitext(fileName)[1].lower() == '.eps': 00982 bbInfo = "%%BoundingBox" 00983 file = open(imagePath,"r") 00984 w = h = 0 00985 while file: 00986 line = file.readline() 00987 if line.find(bbInfo) == 0: 00988 w, h = line.split()[3:5] 00989 break 00990 file.close() 00991 return float(w), float(h) 00992 else: # we can use wx.Image 00993 img = wx.Image(fileName, type=wx.BITMAP_TYPE_ANY) 00994 return img.GetWidth(), img.GetHeight() 00995 00996 class NorthArrow(Image): 00997 """!Class representing eps instruction -- North Arrow""" 00998 def __init__(self, id, settings): 00999 Image.__init__(self, id = id, settings = settings) 01000 self.type = 'northArrow' 01001 01002 def __str__(self): 01003 self.ChangeRefPoint(toCenter = True) 01004 epsfile = self.instruction['epsfile'].replace(os.getenv('GISBASE'), "$GISBASE") 01005 01006 instr = "eps %s %s\n" % (self.instruction['east'], self.instruction['north']) 01007 instr += "# north arrow\n" 01008 instr += " epsfile %s\n" % epsfile 01009 if self.instruction["rotate"]: 01010 instr += string.Template(" rotate $rotate\n").substitute(self.instruction) 01011 if self.instruction["scale"]: 01012 instr += string.Template(" scale $scale\n").substitute(self.instruction) 01013 instr += " end" 01014 return instr 01015 01016 class Point(InstructionObject): 01017 """!Class representing point instruction""" 01018 def __init__(self, id): 01019 InstructionObject.__init__(self, id = id) 01020 self.type = 'point' 01021 # default values 01022 self.defaultInstruction = dict(symbol = os.path.join('basic', 'x'), 01023 color = '0:0:0', fcolor = '200:200:200', 01024 rotate = 0, size = 10, 01025 XY = True, where = (0,0), unit = 'inch', 01026 east = None, north = None) 01027 # current values 01028 self.instruction = dict(self.defaultInstruction) 01029 01030 def __str__(self): 01031 instr = string.Template("point $east $north\n").substitute(self.instruction) 01032 instr += string.Template(" symbol $symbol\n").substitute(self.instruction) 01033 instr += string.Template(" color $color\n").substitute(self.instruction) 01034 instr += string.Template(" fcolor $fcolor\n").substitute(self.instruction) 01035 instr += string.Template(" rotate $rotate\n").substitute(self.instruction) 01036 instr += string.Template(" size $size\n").substitute(self.instruction) 01037 instr += " end" 01038 return instr 01039 01040 def Read(self, instruction, text, **kwargs): 01041 """!Read instruction and save information""" 01042 mapInstr = kwargs['mapInstruction'] 01043 instr = {} 01044 for line in text: 01045 try: 01046 sub = line.split(None, 1)[0] 01047 if sub == 'point': 01048 e, n = line.split(None, 3)[1:3] 01049 if '%' in e and '%' in n: 01050 instr['XY'] = True 01051 instr['east'], instr['north'] = self.PercentToReal(e, n) 01052 else: 01053 instr['XY'] = False 01054 instr['east'], instr['north'] = float(e), float(n) 01055 01056 elif sub == 'symbol': 01057 instr['symbol'] = line.split(None, 1)[1] 01058 elif sub == 'rotate': 01059 instr['rotate'] = float(line.split(None, 1)[1]) 01060 elif sub == 'size': 01061 instr['size'] = float(line.split(None, 1)[1]) 01062 elif sub == 'color': 01063 instr['color'] = line.split(None, 1)[1] 01064 elif sub == 'fcolor': 01065 instr['fcolor'] = line.split(None, 1)[1] 01066 01067 01068 except(IndexError, ValueError): 01069 GError(_("Failed to read instruction %s") % instruction) 01070 return False 01071 01072 self.instruction.update(instr) 01073 instr['where'] = PaperMapCoordinates(mapInstr = mapInstr, x = self.instruction['east'], 01074 y = self.instruction['north'], paperToMap = False) 01075 w = h = self.unitConv.convert(value = instr['size'], fromUnit = 'point', toUnit = 'inch') 01076 instr['rect'] = Rect2D(x = float(instr['where'][0]) - w / 2, y = float(instr['where'][1] - h / 2), 01077 width = w, height = h) 01078 self.instruction.update(instr) 01079 01080 return True 01081 01082 class Line(InstructionObject): 01083 """!Class representing line instruction""" 01084 def __init__(self, id): 01085 InstructionObject.__init__(self, id = id) 01086 self.type = 'line' 01087 # default values 01088 self.defaultInstruction = dict(color = '0:0:0', width = 2, 01089 where = [wx.Point2D(), wx.Point2D()], 01090 east1 = None, north1 = None, 01091 east2 = None, north2 = None) 01092 # current values 01093 self.instruction = dict(self.defaultInstruction) 01094 01095 def __str__(self): 01096 instr = string.Template("line $east1 $north1 $east2 $north2\n").substitute(self.instruction) 01097 instr += string.Template(" color $color\n").substitute(self.instruction) 01098 instr += string.Template(" width $width\n").substitute(self.instruction) 01099 instr += " end\n" 01100 return instr 01101 01102 def Read(self, instruction, text, **kwargs): 01103 """!Read instruction and save information""" 01104 mapInstr = kwargs['mapInstruction'] 01105 instr = {} 01106 for line in text: 01107 try: 01108 sub = line.split(None, 1)[0] 01109 if sub == 'line': 01110 e1, n1, e2, n2 = line.split(None, 5)[1:5] 01111 if '%' in e1 and '%' in n1 and '%' in e2 and '%' in n2: 01112 instr['east1'], instr['north1'] = self.PercentToReal(e1, n1) 01113 instr['east2'], instr['north2'] = self.PercentToReal(e2, n2) 01114 else: 01115 instr['east1'], instr['north1'] = float(e1), float(n1) 01116 instr['east2'], instr['north2'] = float(e2), float(n2) 01117 01118 elif sub == 'width': 01119 instr['width'] = float(line.split(None, 1)[1]) 01120 elif sub == 'color': 01121 instr['color'] = line.split(None, 1)[1] 01122 01123 except(IndexError, ValueError): 01124 GError(_("Failed to read instruction %s") % instruction) 01125 return False 01126 01127 self.instruction.update(instr) 01128 e1, n1 = PaperMapCoordinates(mapInstr = mapInstr, x = self.instruction['east1'], 01129 y = self.instruction['north1'], paperToMap = False) 01130 e2, n2 = PaperMapCoordinates(mapInstr = mapInstr, x = self.instruction['east2'], 01131 y = self.instruction['north2'], paperToMap = False) 01132 instr['where'] = [wx.Point2D(e1, n1), wx.Point2D(e2, n2)] 01133 instr['rect'] = Rect2DPP(instr['where'][0], instr['where'][1]) 01134 self.instruction.update(instr) 01135 01136 return True 01137 01138 class Rectangle(InstructionObject): 01139 """!Class representing rectangle instruction""" 01140 def __init__(self, id): 01141 InstructionObject.__init__(self, id = id) 01142 self.type = 'rectangle' 01143 # default values 01144 self.defaultInstruction = dict(color = '0:0:0', fcolor = 'none', width = 2, 01145 east1 = None, north1 = None, 01146 east2 = None, north2 = None) 01147 # current values 01148 self.instruction = dict(self.defaultInstruction) 01149 01150 def __str__(self): 01151 instr = string.Template("rectangle $east1 $north1 $east2 $north2\n").substitute(self.instruction) 01152 instr += string.Template(" color $color\n").substitute(self.instruction) 01153 instr += string.Template(" fcolor $fcolor\n").substitute(self.instruction) 01154 instr += string.Template(" width $width\n").substitute(self.instruction) 01155 instr += " end\n" 01156 return instr 01157 01158 def Read(self, instruction, text, **kwargs): 01159 """!Read instruction and save information""" 01160 mapInstr = kwargs['mapInstruction'] 01161 instr = {} 01162 for line in text: 01163 try: 01164 sub = line.split(None, 1)[0] 01165 if sub == 'rectangle': 01166 e1, n1, e2, n2 = line.split(None, 5)[1:5] 01167 if '%' in e1 and '%' in n1 and '%' in e2 and '%' in n2: 01168 instr['east1'], instr['north1'] = self.PercentToReal(e1, n1) 01169 instr['east2'], instr['north2'] = self.PercentToReal(e2, n2) 01170 else: 01171 instr['east1'], instr['north1'] = float(e1), float(n1) 01172 instr['east2'], instr['north2'] = float(e2), float(n2) 01173 01174 elif sub == 'width': 01175 instr['width'] = float(line.split(None, 1)[1]) 01176 elif sub == 'color': 01177 instr['color'] = line.split(None, 1)[1] 01178 elif sub == 'fcolor': 01179 instr['fcolor'] = line.split(None, 1)[1] 01180 01181 01182 except(IndexError, ValueError): 01183 GError(_("Failed to read instruction %s") % instruction) 01184 return False 01185 01186 self.instruction.update(instr) 01187 e1, n1 = PaperMapCoordinates(mapInstr = mapInstr, x = self.instruction['east1'], 01188 y = self.instruction['north1'], paperToMap = False) 01189 e2, n2 = PaperMapCoordinates(mapInstr = mapInstr, x = self.instruction['east2'], 01190 y = self.instruction['north2'], paperToMap = False) 01191 instr['rect'] = Rect2DPP(wx.Point2D(e1, n1), wx.Point2D(e2, n2)) 01192 self.instruction.update(instr) 01193 01194 return True 01195 01196 class Scalebar(InstructionObject): 01197 """!Class representing scalebar instruction""" 01198 def __init__(self, id): 01199 InstructionObject.__init__(self, id = id) 01200 self.type = 'scalebar' 01201 # default values 01202 self.defaultInstruction = dict(unit = 'inch', where = (1,1), 01203 unitsLength = 'auto', unitsHeight = 'inch', 01204 length = None, height = 0.1, rect = None, 01205 fontsize = 10, background = 'y', 01206 scalebar = 'f', segment = 4, numbers = 1) 01207 # current values 01208 self.instruction = dict(self.defaultInstruction) 01209 01210 def __str__(self): 01211 instr = string.Template("scalebar $scalebar\n").substitute(self.instruction) 01212 instr += " where %.3f %.3f\n" % (self.instruction['where'][0], self.instruction['where'][1]) 01213 instr += string.Template(" length $length\n units $unitsLength\n").substitute(self.instruction) 01214 instr += string.Template(" height $height\n").substitute(self.instruction) 01215 instr += string.Template(" segment $segment\n numbers $numbers\n").substitute(self.instruction) 01216 instr += string.Template(" fontsize $fontsize\n background $background\n").substitute(self.instruction) 01217 instr += " end" 01218 return instr 01219 01220 def Read(self, instruction, text, **kwargs): 01221 """!Read instruction and save information""" 01222 scale = kwargs['scale'] 01223 instr = {} 01224 for line in text: 01225 try: 01226 if line.startswith('scalebar'): 01227 if 'scalebar s' in line: 01228 instr['scalebar'] = 's' 01229 else: 01230 instr['scalebar'] = 'f' 01231 elif line.startswith('where'): 01232 instr['where'] = map(float, line.split()[1:3]) 01233 elif line.startswith('length'): 01234 instr['length'] = float(line.split()[1]) 01235 elif line.startswith('units'): 01236 if line.split()[1] in ['auto', 'meters', 'kilometers', 'feet', 'miles', 'nautmiles']: 01237 instr['unitsLength'] = line.split()[1] 01238 elif line.startswith('height'): 01239 instr['height'] = float(line.split()[1]) 01240 elif line.startswith('fontsize'): 01241 instr['fontsize'] = float(line.split()[1]) 01242 elif line.startswith('numbers'): 01243 instr['numbers'] = int(line.split()[1]) 01244 elif line.startswith('segment'): 01245 instr['segment'] = int(line.split()[1]) 01246 elif line.startswith('background'): 01247 if line.split()[1].strip().lower() in ('y','yes'): 01248 instr['background'] = 'y' 01249 elif line.split()[1].strip().lower() in ('n','no', 'none'): 01250 instr['background'] = 'n' 01251 except(IndexError, ValueError): 01252 GError(_("Failed to read instruction %s") % instruction) 01253 return False 01254 01255 self.instruction.update(instr) 01256 w, h = self.EstimateSize(scalebarDict = self.instruction, scale = scale) 01257 x = self.instruction['where'][0] - w / 2 01258 y = self.instruction['where'][1] - h / 2 01259 self.instruction['rect'] = Rect2D(x, y, w, h) 01260 return True 01261 01262 def EstimateSize(self, scalebarDict, scale): 01263 """!Estimate size to draw scalebar""" 01264 units = projInfo()['units'] 01265 if not units or units not in self.unitConv.getAllUnits(): 01266 units = 'meters' 01267 if scalebarDict['unitsLength'] != 'auto': 01268 length = self.unitConv.convert(value = scalebarDict['length'], fromUnit = scalebarDict['unitsLength'], toUnit = 'inch') 01269 else: 01270 length = self.unitConv.convert(value = scalebarDict['length'], fromUnit = units, toUnit = 'inch') 01271 01272 length *= scale 01273 length *= 1.1 #for numbers on the edge 01274 height = scalebarDict['height'] + 2 * self.unitConv.convert(value = scalebarDict['fontsize'], fromUnit = 'point', toUnit = 'inch') 01275 return (length, height) 01276 01277 class RasterLegend(InstructionObject): 01278 """!Class representing colortable instruction""" 01279 def __init__(self, id): 01280 InstructionObject.__init__(self, id = id) 01281 self.type = 'rasterLegend' 01282 # default values 01283 self.defaultInstruction = dict(rLegend = False, unit = 'inch', rasterDefault = True, raster = None, 01284 discrete = None, type = None, 01285 where = (0, 0), 01286 width = None, height = None, cols = 1, font = "Helvetica", fontsize = 10, 01287 #color = '0:0:0', tickbar = False, range = False, min = 0, max = 0, 01288 color = 'black', tickbar = 'n', range = False, min = 0, max = 0, 01289 nodata = 'n') 01290 # current values 01291 self.instruction = dict(self.defaultInstruction) 01292 01293 def __str__(self): 01294 instr = "colortable y\n" 01295 instr += string.Template(" raster $raster\n").substitute(self.instruction) 01296 instr += " where %.3f %.3f\n" % (self.instruction['where'][0], self.instruction['where'][1]) 01297 if self.instruction['width']: 01298 instr += string.Template(" width $width\n").substitute(self.instruction) 01299 instr += string.Template(" discrete $discrete\n").substitute(self.instruction) 01300 if self.instruction['discrete'] == 'n': 01301 if self.instruction['height']: 01302 instr += string.Template(" height $height\n").substitute(self.instruction) 01303 instr += string.Template(" tickbar $tickbar\n").substitute(self.instruction) 01304 if self.instruction['range']: 01305 instr += string.Template(" range $min $max\n").substitute(self.instruction) 01306 else: 01307 instr += string.Template(" cols $cols\n").substitute(self.instruction) 01308 instr += string.Template(" nodata $nodata\n").substitute(self.instruction) 01309 instr += string.Template(" font $font\n fontsize $fontsize\n color $color\n")\ 01310 .substitute(self.instruction) 01311 instr += " end" 01312 return instr 01313 01314 01315 def Read(self, instruction, text, **kwargs): 01316 """!Read instruction and save information""" 01317 instr = {} 01318 instr['rLegend'] = True 01319 for line in text: 01320 try: 01321 if line.startswith('where'): 01322 instr['where'] = map(float, line.split()[1:3]) 01323 elif line.startswith('font '): 01324 instr['font'] = line.split()[1] 01325 elif line.startswith('fontsize'): 01326 instr['fontsize'] = float(line.split()[1]) 01327 elif line.startswith('color '): 01328 instr['color'] = line.split()[1] 01329 elif line.startswith('raster'): 01330 instr['raster'] = line.split()[1] 01331 elif line.startswith('width'): 01332 instr['width'] = float(line.split()[1]) 01333 elif line.startswith('height'): 01334 instr['height'] = float(line.split()[1]) 01335 elif line.startswith('cols'): 01336 instr['cols'] = int(line.split()[1]) 01337 elif line.startswith('range'): 01338 instr['range'] = True 01339 instr['min'] = float(line.split()[1]) 01340 instr['max'] = float(line.split()[2]) 01341 elif line.startswith('nodata'): 01342 if line.split()[1].strip().lower() in ('y','yes'): 01343 instr['nodata'] = 'y' 01344 elif line.split()[1].strip().lower() in ('n','no', 'none'): 01345 instr['nodata'] = 'n' 01346 elif line.startswith('tickbar'): 01347 if line.split()[1].strip().lower() in ('y','yes'): 01348 instr['tickbar'] = 'y' 01349 elif line.split()[1].strip().lower() in ('n','no', 'none'): 01350 instr['tickbar'] = 'n' 01351 elif line.startswith('discrete'): 01352 if line.split()[1].strip().lower() in ('y','yes'): 01353 instr['discrete'] = 'y' 01354 elif line.split()[1].strip().lower() in ('n','no', 'none'): 01355 instr['discrete'] = 'n' 01356 01357 except(IndexError, ValueError): 01358 GError(_("Failed to read instruction %s") % instruction) 01359 return False 01360 01361 if 'raster' in instr: 01362 instr['rasterDefault'] = False 01363 if 'discrete' not in instr: 01364 rasterType = getRasterType(map = instr['raster']) 01365 instr['type'] = rasterType 01366 if rasterType == 'CELL': 01367 instr['discrete'] = 'y' 01368 else: 01369 instr['discrete'] = 'n' 01370 01371 else: 01372 instr['rasterDefault'] = True 01373 self.instruction.update(instr) 01374 # add 'rect' in the end 01375 01376 return True 01377 01378 def EstimateHeight(self, raster, discrete, fontsize, cols = None, height = None): 01379 """!Estimate height to draw raster legend""" 01380 if discrete == 'n': 01381 if height: 01382 height = height 01383 else: 01384 height = self.unitConv.convert(value = fontsize * 10, 01385 fromUnit = 'point', toUnit = 'inch') 01386 01387 if discrete == 'y': 01388 if cols: 01389 cols = cols 01390 else: 01391 cols = 1 01392 01393 rinfo = grass.raster_info(raster) 01394 if rinfo['datatype'] in ('DCELL', 'FCELL'): 01395 minim, maxim = rinfo['min'], rinfo['max'] 01396 rows = ceil(maxim / cols ) 01397 else: 01398 cat = grass.read_command('r.category', map = raster, 01399 fs = ':').strip().split('\n') 01400 rows = ceil(float(len(cat)) / cols ) 01401 01402 01403 height = self.unitConv.convert(value = 1.5 * rows * fontsize, fromUnit = 'point', toUnit = 'inch') 01404 01405 return height 01406 01407 def EstimateWidth(self, raster, discrete, fontsize, cols = None, width = None, paperInstr = None): 01408 """!Estimate size to draw raster legend""" 01409 01410 if discrete == 'n': 01411 rinfo = grass.raster_info(raster) 01412 minim, maxim = rinfo['min'], rinfo['max'] 01413 if width: 01414 width = width 01415 else: 01416 width = self.unitConv.convert(value = fontsize * 2, 01417 fromUnit = 'point', toUnit = 'inch') 01418 text = len(max(str(minim), str(maxim), key = len)) 01419 textPart = self.unitConv.convert(value = text * fontsize / 2, 01420 fromUnit = 'point', toUnit = 'inch') 01421 width += textPart 01422 01423 elif discrete == 'y': 01424 if cols: 01425 cols = cols 01426 else: 01427 cols = 1 01428 01429 if width: 01430 width = width 01431 else: 01432 paperWidth = paperInstr['Width'] - paperInstr['Right'] - paperInstr['Left'] 01433 width = (paperWidth / cols) * (cols - 1) + 1 01434 01435 return width 01436 01437 class VectorLegend(InstructionObject): 01438 """!Class representing colortable instruction""" 01439 def __init__(self, id): 01440 InstructionObject.__init__(self, id = id) 01441 self.type = 'vectorLegend' 01442 # default values 01443 self.defaultInstruction = dict(vLegend = False, unit = 'inch', where = (0, 0), 01444 defaultSize = True, width = 0.4, cols = 1, span = None, 01445 font = "Helvetica", fontsize = 10, 01446 border = 'none') 01447 # current values 01448 self.instruction = dict(self.defaultInstruction) 01449 01450 def __str__(self): 01451 instr = "vlegend\n" 01452 instr += " where %.3f %.3f\n" % (self.instruction['where'][0], self.instruction['where'][1]) 01453 instr += string.Template(" font $font\n fontsize $fontsize\n").substitute(self.instruction) 01454 instr += string.Template(" width $width\n cols $cols\n").substitute(self.instruction) 01455 if self.instruction['span']: 01456 instr += string.Template(" span $span\n").substitute(self.instruction) 01457 instr += string.Template(" border $border\n").substitute(self.instruction) 01458 instr += " end" 01459 return instr 01460 01461 def Read(self, instruction, text, **kwargs): 01462 """!Read instruction and save information""" 01463 instr = {} 01464 instr['vLegend'] = True 01465 for line in text: 01466 try: 01467 if line.startswith('where'): 01468 instr['where'] = map(float, line.split()[1:3]) 01469 elif line.startswith('font '): 01470 instr['font'] = line.split()[1] 01471 elif line.startswith('fontsize'): 01472 instr['fontsize'] = float(line.split()[1]) 01473 elif line.startswith('width'): 01474 instr['width'] = float(line.split()[1]) 01475 elif line.startswith('cols'): 01476 instr['cols'] = int(line.split()[1]) 01477 elif line.startswith('span'): 01478 instr['span'] = float(line.split()[1]) 01479 elif line.startswith('border'): 01480 instr['border'] = line.split()[1] 01481 01482 except(IndexError, ValueError): 01483 GError(_("Failed to read instruction %s") % instruction) 01484 return False 01485 01486 self.instruction.update(instr) 01487 01488 return True 01489 01490 def EstimateSize(self, vectorInstr, fontsize, width = None, cols = None): 01491 """!Estimate size to draw vector legend""" 01492 if width: 01493 width = width 01494 else: 01495 width = fontsize/24.0 01496 01497 if cols: 01498 cols = cols 01499 else: 01500 cols = 1 01501 01502 vectors = vectorInstr['list'] 01503 labels = [vector[4] for vector in vectors if vector[3] != 0] 01504 extent = (len(max(labels, key = len)) * fontsize / 2, fontsize) 01505 wExtent = self.unitConv.convert(value = extent[0], fromUnit = 'point', toUnit = 'inch') 01506 hExtent = self.unitConv.convert(value = extent[1], fromUnit = 'point', toUnit = 'inch') 01507 w = (width + wExtent) * cols 01508 h = len(labels) * hExtent / cols 01509 h *= 1.1 01510 return (w, h) 01511 01512 01513 class Raster(InstructionObject): 01514 """!Class representing raster instruction""" 01515 def __init__(self, id): 01516 InstructionObject.__init__(self, id = id) 01517 self.type = 'raster' 01518 # default values 01519 self.defaultInstruction = dict(isRaster = False, raster = None) 01520 # current values 01521 self.instruction = dict(self.defaultInstruction) 01522 01523 def __str__(self): 01524 instr = string.Template("raster $raster").substitute(self.instruction) 01525 return instr 01526 01527 def Read(self, instruction, text): 01528 """!Read instruction and save information""" 01529 instr = {} 01530 instr['isRaster'] = True 01531 try: 01532 map = text.split()[1] 01533 except IndexError: 01534 GError(_("Failed to read instruction %s") % instruction) 01535 return False 01536 try: 01537 info = grass.find_file(map, element = 'cell') 01538 except grass.ScriptError, e: 01539 GError(message = e.value) 01540 return False 01541 instr['raster'] = info['fullname'] 01542 01543 01544 self.instruction.update(instr) 01545 return True 01546 01547 class Vector(InstructionObject): 01548 """!Class keeps vector layers""" 01549 def __init__(self, id): 01550 InstructionObject.__init__(self, id = id) 01551 self.type = 'vector' 01552 # default values 01553 self.defaultInstruction = dict(list = None)# [vmap, type, id, lpos, label] 01554 # current values 01555 self.instruction = dict(self.defaultInstruction) 01556 def __str__(self): 01557 return '' 01558 01559 def Read(self, instruction, text, **kwargs): 01560 """!Read instruction and save information""" 01561 instr = {} 01562 01563 for line in text: 01564 if line.startswith('vpoints') or line.startswith('vlines') or line.startswith('vareas'): 01565 # subtype 01566 if line.startswith('vpoints'): 01567 subType = 'points' 01568 elif line.startswith('vlines'): 01569 subType = 'lines' 01570 elif line.startswith('vareas'): 01571 subType = 'areas' 01572 # name of vector map 01573 vmap = line.split()[1] 01574 try: 01575 info = grass.find_file(vmap, element = 'vector') 01576 except grass.ScriptError, e: 01577 GError(message = e.value) 01578 return False 01579 vmap = info['fullname'] 01580 # id 01581 id = kwargs['id'] 01582 # lpos 01583 lpos = kwargs['vectorMapNumber'] 01584 #label 01585 label = '('.join(vmap.split('@')) + ')' 01586 break 01587 instr = [vmap, subType, id, lpos, label] 01588 if not self.instruction['list']: 01589 self.instruction['list'] = [] 01590 self.instruction['list'].append(instr) 01591 01592 return True 01593 01594 class VProperties(InstructionObject): 01595 """!Class represents instructions vareas, vlines, vpoints""" 01596 def __init__(self, id, subType): 01597 InstructionObject.__init__(self, id = id) 01598 self.type = 'vProperties' 01599 self.subType = subType 01600 # default values 01601 if self.subType == 'points': 01602 dd = dict(subType = 'points', name = None, type = 'point or centroid', connection = False, layer = '1', 01603 masked = 'n', color = '0:0:0', width = 1, 01604 fcolor = '255:0:0', rgbcolumn = None, symbol = os.path.join('basic', 'x'), eps = None, 01605 size = 5, sizecolumn = None, scale = None, 01606 rotation = False, rotate = 0, rotatecolumn = None, label = None, lpos = None) 01607 elif self.subType == 'lines': 01608 dd = dict(subType = 'lines', name = None, type = 'line or boundary', connection = False, layer = '1', 01609 masked = 'n', color = '0:0:0', hwidth = 1, 01610 hcolor = 'none', rgbcolumn = None, 01611 width = 1, cwidth = None, 01612 style = 'solid', linecap = 'butt', label = None, lpos = None) 01613 else: # areas 01614 dd = dict(subType = 'areas', name = None, connection = False, layer = '1', 01615 masked = 'n', color = '0:0:0', width = 1, 01616 fcolor = 'none', rgbcolumn = None, 01617 pat = None, pwidth = 1, scale = 1, label = None, lpos = None) 01618 self.defaultInstruction = dd 01619 # current values 01620 self.instruction = dict(self.defaultInstruction) 01621 01622 def __str__(self): 01623 dic = self.instruction 01624 vInstruction = string.Template("v$subType $name\n").substitute(dic) 01625 #data selection 01626 if self.subType in ('points', 'lines'): 01627 vInstruction += string.Template(" type $type\n").substitute(dic) 01628 if dic['connection']: 01629 vInstruction += string.Template(" layer $layer\n").substitute(dic) 01630 if dic.has_key('cats'): 01631 vInstruction += string.Template(" cats $cats\n").substitute(dic) 01632 elif dic.has_key('where'): 01633 vInstruction += string.Template(" where $where\n").substitute(dic) 01634 vInstruction += string.Template(" masked $masked\n").substitute(dic) 01635 #colors 01636 vInstruction += string.Template(" color $color\n").substitute(dic) 01637 if self.subType in ('points', 'areas'): 01638 if dic['color'] != 'none': 01639 vInstruction += string.Template(" width $width\n").substitute(dic) 01640 if dic['rgbcolumn']: 01641 vInstruction += string.Template(" rgbcolumn $rgbcolumn\n").substitute(dic) 01642 vInstruction += string.Template(" fcolor $fcolor\n").substitute(dic) 01643 else: 01644 if dic['rgbcolumn']: 01645 vInstruction += string.Template(" rgbcolumn $rgbcolumn\n").substitute(dic) 01646 elif dic['hcolor'] != 'none': 01647 vInstruction += string.Template(" hwidth $hwidth\n").substitute(dic) 01648 vInstruction += string.Template(" hcolor $hcolor\n").substitute(dic) 01649 01650 # size and style 01651 if self.subType == 'points': 01652 if not dic['eps']: 01653 vInstruction += string.Template(" symbol $symbol\n").substitute(dic) 01654 else: #eps 01655 vInstruction += string.Template(" eps $eps\n").substitute(dic) 01656 if dic['size']: 01657 vInstruction += string.Template(" size $size\n").substitute(dic) 01658 else: # sizecolumn 01659 vInstruction += string.Template(" sizecolumn $sizecolumn\n").substitute(dic) 01660 vInstruction += string.Template(" scale $scale\n").substitute(dic) 01661 if dic['rotation']: 01662 if dic['rotate'] is not None: 01663 vInstruction += string.Template(" rotate $rotate\n").substitute(dic) 01664 else: 01665 vInstruction += string.Template(" rotatecolumn $rotatecolumn\n").substitute(dic) 01666 01667 if self.subType == 'areas': 01668 if dic['pat'] is not None: 01669 patternFile = dic['pat'].replace(os.getenv("GISBASE"), "$GISBASE") 01670 vInstruction += " pat %s\n" % patternFile 01671 vInstruction += string.Template(" pwidth $pwidth\n").substitute(dic) 01672 vInstruction += string.Template(" scale $scale\n").substitute(dic) 01673 01674 if self.subType == 'lines': 01675 if dic['width'] is not None: 01676 vInstruction += string.Template(" width $width\n").substitute(dic) 01677 else: 01678 vInstruction += string.Template(" cwidth $cwidth\n").substitute(dic) 01679 vInstruction += string.Template(" style $style\n").substitute(dic) 01680 vInstruction += string.Template(" linecap $linecap\n").substitute(dic) 01681 #position and label in vlegend 01682 vInstruction += string.Template(" label $label\n lpos $lpos\n").substitute(dic) 01683 01684 vInstruction += " end" 01685 try: 01686 vInstruction = vInstruction.encode('Latin_1') 01687 except UnicodeEncodeError, err: 01688 try: 01689 pos = str(err).split('position')[1].split(':')[0].strip() 01690 except IndexError: 01691 pos = '' 01692 if pos: 01693 message = _("Characters on position %s are not supported " 01694 "by ISO-8859-1 (Latin 1) encoding " 01695 "which is required by module ps.map.") % pos 01696 else: 01697 message = _("Not all characters are supported " 01698 "by ISO-8859-1 (Latin 1) encoding " 01699 "which is required by module ps.map.") 01700 GMessage(message = message) 01701 return '' 01702 return vInstruction 01703 01704 def Read(self, instruction, text, **kwargs): 01705 """!Read instruction and save information""" 01706 instr = {} 01707 try: 01708 info = grass.find_file(name = text[0].split()[1], element = 'vector') 01709 except grass.ScriptError, e: 01710 GError(message = e.value) 01711 return False 01712 instr['name'] = info['fullname'] 01713 #connection 01714 instr['connection'] = True 01715 self.mapDBInfo = VectorDBInfo(instr['name']) 01716 self.layers = self.mapDBInfo.layers.keys() 01717 if not self.layers: 01718 instr['connection'] = False 01719 01720 # points 01721 if text[0].startswith('vpoints'): 01722 for line in text[1:]: 01723 if line.startswith('type'): 01724 tp = [] 01725 if line.find('point') != -1: 01726 tp.append('point') 01727 if line.find('centroid') != -1: 01728 tp.append('centroid') 01729 instr['type'] = ' or '.join(tp) 01730 elif line.startswith('fcolor'): 01731 instr['fcolor'] = line.split()[1] 01732 elif line.startswith('rgbcolumn'): 01733 instr['rgbcolumn'] = line.split()[1] 01734 elif line.startswith('symbol'): 01735 instr['symbol'] = line.split()[1] 01736 elif line.startswith('eps'): 01737 instr['eps'] = line.split()[1] 01738 elif line.startswith('size '): 01739 instr['size'] = line.split()[1] 01740 elif line.startswith('sizecolumn'): 01741 instr['size'] = None 01742 instr['sizecolumn'] = line.split()[1] 01743 elif line.startswith('scale '): 01744 instr['scale'] = float(line.split()[1]) 01745 elif line.startswith('rotate '): 01746 instr['rotation'] = True 01747 instr['rotate'] = line.split()[1] 01748 elif line.startswith('rotatecolumn'): 01749 instr['rotatecolumn'] = line.split()[1] 01750 instr['rotation'] = True 01751 instr['rotate'] = None 01752 01753 # lines 01754 elif text[0].startswith('vlines'): 01755 for line in text[1:]: 01756 if line.startswith('type'): 01757 tp = [] 01758 if line.find('line') != -1: 01759 tp.append('line') 01760 if line.find('boundary') != -1: 01761 tp.append('boundary') 01762 instr['type'] = ' or '.join(tp) 01763 elif line.startswith('hwidth'): 01764 instr['hwidth'] = float(line.split()[1]) 01765 elif line.startswith('hcolor'): 01766 instr['hcolor'] = line.split()[1] 01767 elif line.startswith('rgbcolumn'): 01768 instr['rgbcolumn'] = line.split()[1] 01769 elif line.startswith('cwidth'): 01770 instr['cwidth'] = float(line.split()[1]) 01771 instr['width'] = None 01772 elif line.startswith('style'): 01773 instr['style'] = line.split()[1] 01774 elif line.startswith('linecap'): 01775 instr['linecap'] = line.split()[1] 01776 01777 elif text[0].startswith('vareas'): 01778 for line in text[1:]: 01779 if line.startswith('fcolor'): 01780 instr['fcolor'] = line.split()[1] 01781 elif line.startswith('pat'): 01782 patternFile = line.split()[1] 01783 instr['pat'] = patternFile.replace("$GISBASE", os.getenv("GISBASE")) 01784 elif line.startswith('pwidth'): 01785 instr['pwidth'] = float(line.split()[1]) 01786 elif line.startswith('scale'): 01787 instr['scale'] = float(line.split()[1]) 01788 01789 01790 # same properties for all 01791 for line in text[1:]: 01792 if line.startswith('lpos'): 01793 instr['lpos'] = int(line.split()[1]) 01794 elif line.startswith('label'): 01795 instr['label'] = line.split(None, 1)[1].decode('latin_1') 01796 elif line.startswith('layer'): 01797 instr['layer'] = line.split()[1] 01798 elif line.startswith('masked'): 01799 if line.split()[1].lower() in ('y', 'yes'): 01800 instr['masked'] = 'y' 01801 else: 01802 instr['masked'] = 'n' 01803 elif line.startswith('color'): 01804 instr['color'] = line.split()[1] 01805 elif line.startswith('rgbcolumn'): 01806 instr['rgbcolumn'] = line.split()[1] 01807 elif line.startswith('width'): 01808 instr['width'] = float(line.split()[1]) 01809 01810 if 'label' not in instr: 01811 instr['label'] = '('.join(instr['name'].split('@')) + ')' 01812 if 'lpos' not in instr: 01813 instr['lpos'] = kwargs['vectorMapNumber'] 01814 self.instruction.update(instr) 01815 01816 return True