GRASS Programmer's Manual  6.5.svn(2012)-r51648
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Defines
instructions.py
Go to the documentation of this file.
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