instructions.py 81 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798179918001801180218031804180518061807180818091810181118121813181418151816181718181819182018211822182318241825182618271828182918301831183218331834183518361837183818391840184118421843184418451846184718481849185018511852185318541855
  1. """
  2. @package psmap.instructions
  3. @brief Map feature objects
  4. Classes:
  5. - dialogs::Instruction
  6. - dialogs::InstructionObject
  7. - dialogs::InitMap
  8. - dialogs::MapFrame
  9. - dialogs::PageSetup
  10. - dialogs::Mapinfo
  11. - dialogs::Text
  12. - dialogs::Image
  13. - dialogs::NorthArrow
  14. - dialogs::Point
  15. - dialogs::Line
  16. - dialogs::Rectangle
  17. - dialogs::Scalebar
  18. - dialogs::RasterLegend
  19. - dialogs::VectorLegend
  20. - dialogs::Raster
  21. - dialogs::Vector
  22. - dialogs::VProperties
  23. (C) 2011-2012 by Anna Kratochvilova, and the GRASS Development Team
  24. This program is free software under the GNU General Public License
  25. (>=v2). Read the file COPYING that comes with GRASS for details.
  26. @author Anna Kratochvilova <kratochanna gmail.com> (bachelor's project)
  27. @author Martin Landa <landa.martin gmail.com> (mentor)
  28. """
  29. import os
  30. import string
  31. from math import ceil
  32. from time import strftime, localtime
  33. import wx
  34. import grass.script as grass
  35. from core.gcmd import RunCommand, GError, GMessage, GWarning
  36. from core.utils import CmdToTuple, GetCmdString, _
  37. from dbmgr.vinfo import VectorDBInfo
  38. from psmap.utils import *
  39. class Instruction:
  40. """Class which represents instruction file"""
  41. def __init__(self, parent, objectsToDraw):
  42. self.parent = parent
  43. self.objectsToDraw = objectsToDraw
  44. #here are kept objects like mapinfo, rasterlegend, etc.
  45. self.instruction = list()
  46. def __str__(self):
  47. """Returns text for instruction file"""
  48. comment = "# timestamp: " + strftime("%Y-%m-%d %H:%M", localtime()) + '\n'
  49. env = grass.gisenv()
  50. comment += "# location: %s\n" % env['LOCATION_NAME']
  51. comment += "# mapset: %s\n" % env['MAPSET']
  52. comment += "# page orientation: %s\n" % self.FindInstructionByType('page')['Orientation']
  53. border = ''
  54. if not self.FindInstructionByType('map'):
  55. border = 'border n\n'
  56. text = [str(each) for each in self.instruction]
  57. return comment + border + '\n'.join(text) + '\nend'
  58. def __getitem__(self, id):
  59. for each in self.instruction:
  60. if each.id == id:
  61. return each
  62. return None
  63. def __contains__(self, id):
  64. """Test if instruction is included"""
  65. for each in self.instruction:
  66. if each.id == id:
  67. return True
  68. return False
  69. def __delitem__(self, id):
  70. """Delete instruction"""
  71. for each in self.instruction:
  72. if each.id == id:
  73. if each.type == 'map':
  74. #must remove raster, vector layers too
  75. vektor = self.FindInstructionByType('vector', list = True)
  76. vProperties = self.FindInstructionByType('vProperties', list = True)
  77. raster = self.FindInstructionByType('raster', list = True)
  78. for item in vektor + vProperties + raster:
  79. if item in self.instruction:
  80. self.instruction.remove(item)
  81. self.instruction.remove(each)
  82. if id in self.objectsToDraw:
  83. self.objectsToDraw.remove(id)
  84. return
  85. def AddInstruction(self, instruction):
  86. """Add instruction"""
  87. # add to instructions
  88. if instruction.type == 'map':
  89. self.instruction.insert(0, instruction)
  90. else:
  91. self.instruction.append(instruction)
  92. # add to drawable objects
  93. if instruction.type not in ('page', 'raster', 'vector', 'vProperties', 'initMap'):
  94. if instruction.type == 'map':
  95. self.objectsToDraw.insert(0, instruction.id)
  96. else:
  97. self.objectsToDraw.append(instruction.id)
  98. def FindInstructionByType(self, type, list = False):
  99. """Find instruction(s) with the given type"""
  100. inst = []
  101. for each in self.instruction:
  102. if each.type == type:
  103. inst.append(each)
  104. if len(inst) == 1 and not list:
  105. return inst[0]
  106. return inst
  107. def Read(self, filename):
  108. """Reads instruction file and creates instruction objects"""
  109. self.filename = filename
  110. # open file
  111. try:
  112. file = open(filename, 'r')
  113. except IOError:
  114. GError(message = _("Unable to open file\n%s") % filename)
  115. return
  116. # first read file to get information about region and scaletype
  117. isRegionComment = False
  118. orientation = 'Portrait'
  119. for line in file:
  120. if '# g.region' in line:
  121. self.SetRegion(regionInstruction = line)
  122. isRegionComment = True
  123. break
  124. if '# page orientation' in line:
  125. orientation = line.split(':')[-1].strip()
  126. if not isRegionComment:
  127. self.SetRegion(regionInstruction = None)
  128. # then run ps.map -b to get information for maploc
  129. # compute scale and center
  130. map = self.FindInstructionByType('map')
  131. region = grass.region()
  132. map['center'] = (region['n'] + region['s']) / 2, (region['w'] + region['e']) / 2
  133. mapRect = GetMapBounds(self.filename, portrait = (orientation == 'Portrait'))
  134. map['rect'] = mapRect
  135. proj = projInfo()
  136. toM = 1.0
  137. if proj['units']:
  138. toM = float(proj['meters'])
  139. units = UnitConversion(self.parent)
  140. w = units.convert(value = mapRect.Get()[2], fromUnit = 'inch', toUnit = 'meter') / toM
  141. map['scale'] = w / abs((region['w'] - region['e']))
  142. SetResolution(dpi = 300, width = map['rect'].width, height = map['rect'].height)
  143. # read file again, now with information about map bounds
  144. isBuffer = False
  145. buffer = []
  146. instruction = None
  147. vectorMapNumber = 1
  148. file.seek(0)
  149. for line in file:
  150. if not line.strip():
  151. continue
  152. line = line.strip()
  153. if isBuffer:
  154. buffer.append(line)
  155. if 'end' in line:
  156. isBuffer = False
  157. kwargs = {}
  158. if instruction == 'scalebar':
  159. kwargs['scale'] = map['scale']
  160. elif instruction in ('text', 'eps', 'point', 'line', 'rectangle'):
  161. kwargs['mapInstruction'] = map
  162. elif instruction in ('vpoints', 'vlines', 'vareas'):
  163. kwargs['id'] = wx.NewId()
  164. kwargs['vectorMapNumber'] = vectorMapNumber
  165. vectorMapNumber += 1
  166. elif instruction == 'paper':
  167. kwargs['Orientation'] = orientation
  168. ok = self.SendToRead(instruction, buffer, **kwargs)
  169. if not ok: return False
  170. buffer = []
  171. continue
  172. elif line.startswith('paper'):
  173. instruction = 'paper'
  174. isBuffer = True
  175. buffer.append(line)
  176. elif line.startswith('border'):
  177. if line.split()[1].lower() in ('n', 'no', 'none'):
  178. ok = self.SendToRead('border', [line])
  179. if not ok: return False
  180. elif line.split()[1].lower() in ('y', 'yes'):
  181. instruction = 'border'
  182. isBuffer = True
  183. buffer.append(line)
  184. elif line.startswith('scale '):
  185. if isBuffer:
  186. continue
  187. ok = self.SendToRead('scale', line, isRegionComment = isRegionComment)
  188. if not ok: return False
  189. elif line.startswith('maploc'):
  190. ok = self.SendToRead(instruction = 'maploc', text = line)
  191. if not ok: return False
  192. elif line.startswith('raster'):
  193. ok = self.SendToRead(instruction = 'raster', text = line)
  194. if not ok: return False
  195. elif line.startswith('mapinfo'):
  196. instruction = 'mapinfo'
  197. isBuffer = True
  198. buffer.append(line)
  199. elif line.startswith('scalebar'):
  200. instruction = 'scalebar'
  201. isBuffer = True
  202. buffer.append(line)
  203. elif line.startswith('text'):
  204. instruction = 'text'
  205. isBuffer = True
  206. buffer.append(line)
  207. elif line.startswith('eps'):
  208. instruction = 'eps'
  209. isBuffer = True
  210. buffer.append(line)
  211. elif line.startswith('point'):
  212. instruction = 'point'
  213. isBuffer = True
  214. buffer.append(line)
  215. elif line.startswith('line'):
  216. instruction = 'line'
  217. isBuffer = True
  218. buffer.append(line)
  219. elif line.startswith('rectangle'):
  220. instruction = 'rectangle'
  221. isBuffer = True
  222. buffer.append(line)
  223. elif line.startswith('colortable'):
  224. if len(line.split()) == 2 and line.split()[1].lower() in ('n', 'no', 'none'):
  225. break
  226. instruction = 'colortable'
  227. isBuffer = True
  228. buffer.append(line)
  229. elif line.startswith('vlegend'):
  230. instruction = 'vlegend'
  231. isBuffer = True
  232. buffer.append(line)
  233. elif line.startswith('vpoints'):
  234. instruction = 'vpoints'
  235. isBuffer = True
  236. buffer.append(line)
  237. elif line.startswith('vlines'):
  238. instruction = 'vlines'
  239. isBuffer = True
  240. buffer.append(line)
  241. elif line.startswith('vareas'):
  242. instruction = 'vareas'
  243. isBuffer = True
  244. buffer.append(line)
  245. elif line.startswith('labels'):
  246. instruction = 'labels'
  247. isBuffer = True
  248. buffer.append(line)
  249. rasterLegend = self.FindInstructionByType('rasterLegend')
  250. raster = self.FindInstructionByType('raster')
  251. page = self.FindInstructionByType('page')
  252. vector = self.FindInstructionByType('vector')
  253. vectorLegend = self.FindInstructionByType('vectorLegend')
  254. vectorMaps = self.FindInstructionByType('vProperties', list = True)
  255. # check (in case of scaletype 0) if map is drawn also
  256. map['drawMap'] = False
  257. if map['scaleType'] == 0:
  258. mapForRegion = map['map']
  259. if map['mapType'] == 'raster' and raster:
  260. if mapForRegion == raster['raster']:
  261. map['drawMap'] = True
  262. elif map['mapType'] == 'vector' and vector:
  263. for vmap in vector['list']:
  264. if mapForRegion == vmap[0]:
  265. map['drawMap'] = True
  266. # rasterLegend
  267. if rasterLegend:
  268. if rasterLegend['rasterDefault'] and raster:
  269. rasterLegend['raster'] = raster['raster']
  270. if not rasterLegend['discrete']:
  271. rasterType = getRasterType(map = rasterLegend['raster'])
  272. if rasterType == 'CELL':
  273. rasterLegend['discrete'] = 'y'
  274. else:
  275. rasterLegend['discrete'] = 'n'
  276. #estimate size
  277. height = rasterLegend.EstimateHeight(raster = rasterLegend['raster'], discrete = rasterLegend['discrete'],
  278. fontsize = rasterLegend['fontsize'],
  279. cols = rasterLegend['cols'],
  280. height = rasterLegend['height'])
  281. width = rasterLegend.EstimateWidth(raster = rasterLegend['raster'], discrete = rasterLegend['discrete'],
  282. fontsize = rasterLegend['fontsize'],
  283. cols = rasterLegend['cols'] ,
  284. width = rasterLegend['width'],
  285. paperInstr = page)
  286. rasterLegend['rect'] = Rect2D(x = float(rasterLegend['where'][0]), y = float(rasterLegend['where'][1]),
  287. width = width, height = height)
  288. # vectors, vlegend
  289. if vector:
  290. for vmap in vectorMaps:
  291. for i, each in enumerate(vector['list']):
  292. if each[2] == vmap.id:
  293. vector['list'][i][4] = vmap['label']
  294. vector['list'][i][3] = vmap['lpos']
  295. if vectorLegend:
  296. size = vectorLegend.EstimateSize(vectorInstr = vector, fontsize = vectorLegend['fontsize'],
  297. width = vectorLegend['width'], cols = vectorLegend['cols'])
  298. vectorLegend['rect'] = Rect2D(x = float(vectorLegend['where'][0]), y = float(vectorLegend['where'][1]),
  299. width = size[0], height = size[1])
  300. page = self.FindInstructionByType('page')
  301. if not page:
  302. page = PageSetup(wx.NewId())
  303. self.AddInstruction(page)
  304. else:
  305. page['Orientation'] = orientation
  306. #
  307. return True
  308. def SendToRead(self, instruction, text, **kwargs):
  309. psmapInstrDict = dict(paper = ['page'],
  310. maploc = ['map'],
  311. scale = ['map'],
  312. border = ['map'],
  313. raster = ['raster'],
  314. mapinfo = ['mapinfo'],
  315. scalebar = ['scalebar'],
  316. text = ['text'],
  317. eps = ['image', 'northArrow'],
  318. point = ['point'],
  319. line = ['line'],
  320. rectangle = ['rectangle'],
  321. vpoints = ['vector', 'vProperties'],
  322. vlines = ['vector', 'vProperties'],
  323. vareas = ['vector', 'vProperties'],
  324. colortable = ['rasterLegend'],
  325. vlegend = ['vectorLegend'],
  326. labels = ['labels']
  327. )
  328. myInstrDict = dict(page = PageSetup,
  329. map = MapFrame,
  330. raster = Raster,
  331. mapinfo = Mapinfo,
  332. scalebar = Scalebar,
  333. text = Text,
  334. image = Image,
  335. northArrow = NorthArrow,
  336. point = Point,
  337. line = Line,
  338. rectangle = Rectangle,
  339. rasterLegend = RasterLegend,
  340. vectorLegend = VectorLegend,
  341. vector = Vector,
  342. vProperties = VProperties,
  343. labels = Labels
  344. )
  345. myInstruction = psmapInstrDict[instruction]
  346. for i in myInstruction:
  347. instr = self.FindInstructionByType(i)
  348. if i in ('text', 'vProperties', 'image', 'northArrow', 'point', 'line', 'rectangle') or not instr:
  349. id = wx.NewId() #!vProperties expect subtype
  350. if i == 'vProperties':
  351. id = kwargs['id']
  352. newInstr = myInstrDict[i](id, subType = instruction[1:])
  353. elif i in ('image', 'northArrow'):
  354. commentFound = False
  355. for line in text:
  356. if line.find("# north arrow") >= 0:
  357. commentFound = True
  358. if i == 'image' and commentFound or \
  359. i == 'northArrow' and not commentFound:
  360. continue
  361. newInstr = myInstrDict[i](id, settings = self)
  362. else:
  363. newInstr = myInstrDict[i](id)
  364. ok = newInstr.Read(instruction, text, **kwargs)
  365. if ok:
  366. self.AddInstruction(newInstr)
  367. else:
  368. return False
  369. else:
  370. ok = instr.Read(instruction, text, **kwargs)
  371. if not ok:
  372. return False
  373. return True
  374. def SetRegion(self, regionInstruction):
  375. """Sets region from file comment or sets current region in case of no comment"""
  376. map = MapFrame(wx.NewId())
  377. self.AddInstruction(map)
  378. if regionInstruction:
  379. cmd = CmdToTuple(regionInstruction.strip('# ').split())
  380. # define scaleType
  381. if len(cmd[1]) <= 3:
  382. if 'raster' in cmd[1]:
  383. map['scaleType'] = 0
  384. map['mapType'] = 'raster'
  385. map['map'] = cmd[1]['raster']
  386. elif 'vector' in cmd[1]:
  387. map['scaleType'] = 0
  388. map['mapType'] = 'vector'
  389. map['map'] = cmd[1]['vector']
  390. elif 'region' in cmd[1]:
  391. map['scaleType'] = 1
  392. map['region'] = cmd[1]['region']
  393. else:
  394. map['scaleType'] = 2
  395. else:
  396. map['scaleType'] = 2
  397. grass.del_temp_region()
  398. region = grass.region()
  399. grass.use_temp_region()
  400. cmd = ['g.region', region]
  401. cmdString = GetCmdString(cmd).replace('g.region', '')
  402. GMessage(_("Instruction file will be loaded with following region: %s\n") % cmdString)
  403. try:
  404. RunCommand(cmd[0], **cmd[1])
  405. except grass.ScriptError as e:
  406. GError(_("Region cannot be set\n%s") % e)
  407. return False
  408. class InstructionObject:
  409. """Abtract class representing single instruction"""
  410. def __init__(self, id):
  411. self.id = id
  412. # default values
  413. self.defaultInstruction = dict()
  414. # current values
  415. self.instruction = self.defaultInstruction
  416. # converting units
  417. self.unitConv = UnitConversion()
  418. def __str__(self):
  419. """Returns particular part of text instruction"""
  420. return ''
  421. def __getitem__(self, key):
  422. for each in self.instruction.keys():
  423. if each == key:
  424. return self.instruction[key]
  425. return None
  426. def __setitem__(self, key, value):
  427. self.instruction[key] = value
  428. def GetInstruction(self):
  429. """Get current values"""
  430. return self.instruction
  431. def SetInstruction(self, instruction):
  432. """Set default values"""
  433. self.instruction = instruction
  434. def Read(self, instruction, text, **kwargs):
  435. """Read instruction and save them"""
  436. pass
  437. def PercentToReal(self, e, n):
  438. """Converts text coordinates from percent of region to map coordinates"""
  439. e, n = float(e.strip('%')), float(n.strip('%'))
  440. region = grass.region()
  441. N = region['s'] + (region['n'] - region['s']) / 100 * n
  442. E = region['w'] + (region['e'] - region['w']) / 100 * e
  443. return E, N
  444. class InitMap(InstructionObject):
  445. """Class representing virtual map"""
  446. def __init__(self, id):
  447. InstructionObject.__init__(self, id = id)
  448. self.type = 'initMap'
  449. # default values
  450. self.defaultInstruction = dict(rect = None, scale = None)
  451. # current values
  452. self.instruction = dict(self.defaultInstruction)
  453. class MapFrame(InstructionObject):
  454. """Class representing map (instructions maploc, scale, border)"""
  455. def __init__(self, id):
  456. InstructionObject.__init__(self, id = id)
  457. self.type = 'map'
  458. # default values
  459. self.defaultInstruction = dict(map = None, mapType = None, drawMap = True, region = None,
  460. rect = Rect2D(), scaleType = 0, scale = None, center = None,
  461. resolution = 300, border = 'y', width = 1, color = '0:0:0')
  462. # current values
  463. self.instruction = dict(self.defaultInstruction)
  464. def __str__(self):
  465. instr = ''
  466. comment = ''
  467. #region settings
  468. region = grass.region()
  469. if self.instruction['scaleType'] == 0: #match map
  470. map = self.instruction['map']
  471. if self.instruction['mapType'] == 'raster':
  472. comment = "# g.region raster=%s nsres=%s ewres=%s\n" % (map, region['nsres'], region['ewres'])
  473. else:
  474. comment = "# g.region vector=%s\n" % (map)
  475. elif self.instruction['scaleType'] == 1:# saved region
  476. region = self.instruction['region']
  477. comment = "# g.region region=%s\n" % region
  478. elif self.instruction['scaleType'] in (2, 3): #current region, fixed scale
  479. comment = string.Template("# g.region n=$n s=$s e=$e w=$w rows=$rows cols=$cols \n").substitute(**region)
  480. instr += comment
  481. instr += '\n'
  482. # maploc
  483. maplocInstruction = "maploc %.3f %.3f" % (self.instruction['rect'].x, self.instruction['rect'].y)
  484. if self.instruction['scaleType'] != 3:
  485. maplocInstruction += " %.3f %.3f"% (self.instruction['rect'].width, self.instruction['rect'].height)
  486. instr += maplocInstruction
  487. instr += '\n'
  488. # scale
  489. if self.instruction['scaleType'] == 3: #fixed scale
  490. scaleInstruction = "scale 1:%.0f" % (1/self.instruction['scale'])
  491. instr += scaleInstruction
  492. instr += '\n'
  493. # border
  494. borderInstruction = ''
  495. if self.instruction['border'] == 'n':
  496. borderInstruction = "border n"
  497. else:
  498. borderInstruction = "border y\n"
  499. borderInstruction += string.Template(" width $width\n color $color\n").substitute(self.instruction)
  500. borderInstruction += " end"
  501. instr += borderInstruction
  502. instr += '\n'
  503. return instr
  504. def Read(self, instruction, text, **kwargs):
  505. """Read instruction and save information"""
  506. if 'isRegionComment' in kwargs:
  507. isRegionComment = kwargs['isRegionComment']
  508. instr = {}
  509. if instruction == 'border':
  510. for line in text:
  511. if line.startswith('end'):
  512. break
  513. try:
  514. if line.split()[1].lower() in ('n', 'no', 'none'):
  515. instr['border'] = 'n'
  516. break
  517. elif line.split()[1].lower() in ('y', 'yes'):
  518. instr['border'] = 'y'
  519. elif line.startswith('width'):
  520. instr['width'] = line.split()[1]
  521. elif line.startswith('color'):
  522. instr['color'] = line.split()[1]
  523. except IndexError:
  524. GError(_("Failed to read instruction %s") % instruction)
  525. return False
  526. elif instruction == 'scale':
  527. try:
  528. scaleText = text.strip('scale ').split(':')[1]
  529. # when scale instruction given and region comment also, then scaletype is fixed scale
  530. if not isRegionComment:
  531. instr['scaleType'] = 2
  532. else:
  533. instr['scaleType'] = 3
  534. scale = 1/float(scaleText)
  535. if abs(scale - self.instruction['scale']) > (0.01 * scale):
  536. GWarning(_("Scale has changed, old value: %(old)s\nnew value: %(new)s") % \
  537. { 'old' : scale, 'new' : self.instruction['scale'] })
  538. except (ValueError, IndexError):
  539. GError(_("Failed to read instruction %s.\nUse 1:25000 notation.") % instruction)
  540. return False
  541. elif instruction == 'maploc':
  542. maploc = text.strip('maploc ').split()
  543. if len(maploc) >= 2:
  544. if abs(self.instruction['rect'].Get()[0] - float(maploc[0])) > 0.5 or \
  545. abs(self.instruction['rect'].Get()[1] - float(maploc[1])) > 0.5:
  546. GWarning(_("Map frame position changed, old value: %(old1)s %(old2)s\nnew value: %(new1)s %(new2)s") % \
  547. { 'old1' : maploc[0], 'old2' : maploc[1],
  548. 'new1' : self.instruction['rect'].Get()[0], 'new2' : self.instruction['rect'].Get()[1] })
  549. #instr['rect'] = wx.Rect2D(float(maploc[0]), float(maploc[1]), self.instruction['rect'][2], self.instruction['rect'][3])
  550. if len(maploc) == 4:
  551. if abs(self.instruction['rect'].Get()[2] - float(maploc[2])) > 0.5 or \
  552. abs(self.instruction['rect'].Get()[3] - float(maploc[3])) > 0.5:
  553. GWarning(_("Map frame size changed, old value: %(old1)s %(old2)s\nnew value: %(new1)s %(new2)s") % \
  554. { 'old1' : maploc[2], 'old2' : maploc[3],
  555. 'new1' : self.instruction['rect'].Get()[2], 'new2' : self.instruction['rect'].Get()[3] })
  556. #instr['rect'] = wx.Rect2D(*map(float, maploc))
  557. self.instruction.update(instr)
  558. return True
  559. class PageSetup(InstructionObject):
  560. """Class representing page instruction"""
  561. def __init__(self, id):
  562. InstructionObject.__init__(self, id = id)
  563. self.type = 'page'
  564. # default values
  565. self.defaultInstruction = dict(Units = 'inch', Format = 'a4', Orientation = 'Portrait',
  566. Width = 8.268, Height = 11.693, Left = 0.5, Right = 0.5, Top = 1, Bottom = 1)
  567. # current values
  568. self.instruction = dict(self.defaultInstruction)
  569. def __str__(self):
  570. if self.instruction['Format'] == 'custom':
  571. instr = string.Template("paper\n width $Width\n height $Height\n").substitute(self.instruction)
  572. else:
  573. instr = string.Template("paper $Format\n").substitute(self.instruction)
  574. instr += string.Template(" left $Left\n right $Right\n bottom $Bottom\n top $Top\n end").substitute(self.instruction)
  575. return instr
  576. def Read(self, instruction, text, **kwargs):
  577. """Read instruction and save information"""
  578. instr = {}
  579. self.cats = ['Width', 'Height', 'Left', 'Right', 'Top', 'Bottom']
  580. self.subInstr = dict(zip(['width', 'height', 'left', 'right', 'top', 'bottom'], self.cats))
  581. if instruction == 'paper': # just for sure
  582. for line in text:
  583. if line.startswith('paper'):
  584. if len(line.split()) > 1:
  585. pformat = line.split()[1]
  586. availableFormats = self._toDict(grass.read_command('ps.map', flags = 'p',
  587. quiet = True))
  588. # e.g. paper a3
  589. try:
  590. instr['Format'] = pformat
  591. for key, value in availableFormats[pformat].iteritems():
  592. instr[key] = float(value)
  593. break
  594. except KeyError:
  595. GError(_("Failed to read instruction %(file)s.\nUnknown format %(for)s") % \
  596. { 'file' : instruction, 'for' : format })
  597. return False
  598. else:
  599. # paper
  600. # width ...
  601. instr['Format'] = 'custom'
  602. # read subinstructions
  603. elif instr['Format'] == 'custom' and not line.startswith('end'):
  604. text = line.split()
  605. try:
  606. instr[self.subInstr[text[0]]] = float(text[1])
  607. except (IndexError, KeyError):
  608. GError(_("Failed to read instruction %s.") % instruction)
  609. return False
  610. if 'Orientation' in kwargs and kwargs['Orientation'] == 'Landscape':
  611. instr['Width'], instr['Height'] = instr['Height'], instr['Width']
  612. self.instruction.update(instr)
  613. return True
  614. def _toDict(self, paperStr):
  615. sizeDict = dict()
  616. # cats = self.subInstr[ 'Width', 'Height', 'Left', 'Right', 'Top', 'Bottom']
  617. for line in paperStr.strip().split('\n'):
  618. d = dict(zip(self.cats, line.split()[1:]))
  619. sizeDict[line.split()[0]] = d
  620. return sizeDict
  621. class Mapinfo(InstructionObject):
  622. """Class representing mapinfo instruction"""
  623. def __init__(self, id):
  624. InstructionObject.__init__(self, id = id)
  625. self.type = 'mapinfo'
  626. # default values
  627. self.defaultInstruction = dict(unit = 'inch', where = (0, 0),
  628. font = 'Helvetica', fontsize = 10, color = '0:0:0', background = 'none',
  629. border = 'none', rect = None)
  630. # current values
  631. self.instruction = dict(self.defaultInstruction)
  632. def __str__(self):
  633. instr = "mapinfo\n"
  634. instr += " where %.3f %.3f\n" % (self.instruction['where'][0], self.instruction['where'][1])
  635. instr += string.Template(" font $font\n fontsize $fontsize\n color $color\n").substitute(self.instruction)
  636. instr += string.Template(" background $background\n border $border\n").substitute(self.instruction)
  637. instr += " end"
  638. return instr
  639. def Read(self, instruction, text):
  640. """Read instruction and save information"""
  641. instr = {}
  642. try:
  643. for line in text:
  644. sub = line.split(None,1)
  645. if sub[0] == 'font':
  646. instr['font'] = sub[1]
  647. elif sub[0] == 'fontsize':
  648. instr['fontsize'] = int(sub[1])
  649. elif sub[0] == 'color':
  650. instr['color'] = sub[1]
  651. elif sub[0] == 'background':
  652. instr['background'] = sub[1]
  653. elif sub[0] == 'border':
  654. instr['border'] = sub[1]
  655. elif sub[0] == 'where':
  656. instr['where'] = float(sub[1].split()[0]), float(sub[1].split()[1])
  657. except (ValueError, IndexError):
  658. GError(_("Failed to read instruction %s") % instruction)
  659. return False
  660. self.instruction.update(instr)
  661. self.instruction['rect'] = self.EstimateRect(mapinfoDict = self.instruction)
  662. return True
  663. def EstimateRect(self, mapinfoDict):
  664. """Estimate size to draw mapinfo"""
  665. w = mapinfoDict['fontsize'] * 20 # any better estimation?
  666. h = mapinfoDict['fontsize'] * 7
  667. width = self.unitConv.convert(value = w, fromUnit = 'point', toUnit = 'inch')
  668. height = self.unitConv.convert(value = h, fromUnit = 'point', toUnit = 'inch')
  669. return Rect2D(x = float(mapinfoDict['where'][0]), y = float(mapinfoDict['where'][1]),
  670. width = width, height = height)
  671. class Text(InstructionObject):
  672. """Class representing text instruction"""
  673. def __init__(self, id):
  674. InstructionObject.__init__(self, id = id)
  675. self.type = 'text'
  676. # default values
  677. self.defaultInstruction = dict(text = "", font = "Helvetica", fontsize = 10, color = 'black', background = 'none',
  678. hcolor = 'none', hwidth = 1, border = 'none', width = '1', XY = True,
  679. where = (0,0), unit = 'inch', rotate = None,
  680. ref = "center center", xoffset = 0, yoffset = 0, east = None, north = None)
  681. # current values
  682. self.instruction = dict(self.defaultInstruction)
  683. def __str__(self):
  684. text = self.instruction['text'].replace('\n','\\n')
  685. instr = u"text %s %s" % (self.instruction['east'], self.instruction['north'])
  686. instr += " %s\n" % text
  687. instr += (string.Template(" font $font\n fontsize $fontsize\n color $color\n").
  688. substitute(self.instruction))
  689. instr += string.Template(" hcolor $hcolor\n").substitute(self.instruction)
  690. if self.instruction['hcolor'] != 'none':
  691. instr += string.Template(" hwidth $hwidth\n").substitute(self.instruction)
  692. instr += string.Template(" border $border\n").substitute(self.instruction)
  693. if self.instruction['border'] != 'none':
  694. instr += string.Template(" width $width\n").substitute(self.instruction)
  695. instr += string.Template(" background $background\n").substitute(self.instruction)
  696. if self.instruction["ref"] != '0':
  697. instr += string.Template(" ref $ref\n").substitute(self.instruction)
  698. if self.instruction["rotate"]:
  699. instr += string.Template(" rotate $rotate\n").substitute(self.instruction)
  700. if float(self.instruction["xoffset"]) or float(self.instruction["yoffset"]):
  701. instr += (string.Template(" xoffset $xoffset\n yoffset $yoffset\n").
  702. substitute(self.instruction))
  703. instr += " end"
  704. try:
  705. instr = instr.encode('latin1')
  706. except UnicodeEncodeError as err:
  707. try:
  708. pos = str(err).split('position')[1].split(':')[0].strip()
  709. except IndexError:
  710. pos = ''
  711. if pos:
  712. message = _("Characters on position %s are not supported "
  713. "by ISO-8859-1 (Latin 1) encoding "
  714. "which is required by module ps.map.") % pos
  715. else:
  716. message = _("Not all characters are supported "
  717. "by ISO-8859-1 (Latin 1) encoding "
  718. "which is required by module ps.map.")
  719. GMessage(message = message)
  720. return ''
  721. return instr
  722. def Read(self, instruction, text, **kwargs):
  723. """Read instruction and save information"""
  724. map = kwargs['mapInstruction']
  725. instr = {}
  726. for line in text:
  727. try:
  728. sub = line.split(None, 1)[0]
  729. if sub == 'text':
  730. e, n = line.split(None, 3)[1:3]
  731. if '%' in e and '%' in n:
  732. instr['XY'] = True
  733. instr['east'], instr['north'] = self.PercentToReal(e, n)
  734. else:
  735. instr['XY'] = False
  736. instr['east'], instr['north'] = float(e), float(n)
  737. instr['text'] = line.split(None, 3)[3].decode('latin_1')
  738. elif sub == 'font':
  739. instr['font'] = line.split(None, 1)[1]
  740. elif sub == 'fontsize':
  741. instr['fontsize'] = float(line.split(None, 1)[1])
  742. elif sub == 'color':
  743. instr['color'] = line.split(None, 1)[1]
  744. elif sub == 'width':
  745. instr['width'] = line.split(None, 1)[1]
  746. elif sub == 'hcolor':
  747. instr['hcolor'] = line.split(None, 1)[1]
  748. elif sub == 'hwidth':
  749. instr['hwidth'] = line.split(None, 1)[1]
  750. elif sub == 'background':
  751. instr['background'] = line.split(None, 1)[1]
  752. elif sub == 'border':
  753. instr['border'] = line.split(None, 1)[1]
  754. elif sub == 'ref':
  755. instr['ref'] = line.split(None, 1)[1]
  756. elif sub == 'rotate':
  757. instr['rotate'] = float(line.split(None, 1)[1])
  758. elif sub == 'xoffset':
  759. instr['xoffset'] = int(line.split(None, 1)[1])
  760. elif sub == 'yoffset':
  761. instr['yoffset'] = int(line.split(None, 1)[1])
  762. elif sub == 'opaque':
  763. if line.split(None, 1)[1].lower() in ('n', 'none'):
  764. instr['background'] = 'none'
  765. except(IndexError, ValueError):
  766. GError(_("Failed to read instruction %s") % instruction)
  767. return False
  768. instr['where'] = PaperMapCoordinates(mapInstr = map, x = instr['east'], y = instr['north'], paperToMap = False)
  769. self.instruction.update(instr)
  770. return True
  771. class Image(InstructionObject):
  772. """Class representing eps instruction - image"""
  773. def __init__(self, id, settings):
  774. InstructionObject.__init__(self, id = id)
  775. self.settings = settings
  776. self.type = 'image'
  777. # default values
  778. self.defaultInstruction = dict(epsfile = "", XY = True, where = (0,0), unit = 'inch',
  779. east = None, north = None,
  780. rotate = None, scale = 1)
  781. # current values
  782. self.instruction = dict(self.defaultInstruction)
  783. def __str__(self):
  784. self.ChangeRefPoint(toCenter = True)
  785. epsfile = self.instruction['epsfile'].replace(os.getenv('GISBASE'), "$GISBASE")
  786. instr = "eps %s %s\n" % (self.instruction['east'], self.instruction['north'])
  787. instr += " epsfile %s\n" % epsfile
  788. if self.instruction["rotate"]:
  789. instr += string.Template(" rotate $rotate\n").substitute(self.instruction)
  790. if self.instruction["scale"]:
  791. instr += string.Template(" scale $scale\n").substitute(self.instruction)
  792. instr += " end"
  793. return instr
  794. def Read(self, instruction, text, **kwargs):
  795. """Read instruction and save information"""
  796. mapInstr = kwargs['mapInstruction']
  797. instr = {}
  798. for line in text:
  799. try:
  800. sub = line.split(None, 1)[0]
  801. if sub == 'eps':
  802. e, n = line.split(None, 3)[1:3]
  803. if '%' in e and '%' in n:
  804. instr['XY'] = True
  805. instr['east'], instr['north'] = self.PercentToReal(e, n)
  806. else:
  807. instr['XY'] = False
  808. instr['east'], instr['north'] = float(e), float(n)
  809. elif sub == 'epsfile':
  810. epsfile = line.split(None, 1)[1]
  811. instr['epsfile'] = epsfile.replace("$GISBASE", os.getenv("GISBASE"))
  812. elif sub == 'rotate':
  813. instr['rotate'] = float(line.split(None, 1)[1])
  814. elif sub == 'scale':
  815. instr['scale'] = float(line.split(None, 1)[1])
  816. except(IndexError, ValueError):
  817. GError(_("Failed to read instruction %s") % instruction)
  818. return False
  819. if not os.path.exists(instr['epsfile']):
  820. GError(_("Failed to read instruction %(inst)s: "
  821. "file %(file)s not found.") % { 'inst' : instruction,
  822. 'file' : instr['epsfile'] })
  823. return False
  824. instr['epsfile'] = os.path.abspath(instr['epsfile'])
  825. instr['size'] = self.GetImageOrigSize(instr['epsfile'])
  826. if 'rotate' in instr:
  827. instr['size'] = BBoxAfterRotation(instr['size'][0], instr['size'][1], instr['rotate'])
  828. self.instruction.update(instr)
  829. self.ChangeRefPoint(toCenter = False)
  830. instr['where'] = PaperMapCoordinates(mapInstr = mapInstr, x = self.instruction['east'],
  831. y = self.instruction['north'], paperToMap = False)
  832. w = self.unitConv.convert(value = instr['size'][0], fromUnit = 'point', toUnit = 'inch')
  833. h = self.unitConv.convert(value = instr['size'][1], fromUnit = 'point', toUnit = 'inch')
  834. instr['rect'] = Rect2D(x = float(instr['where'][0]), y = float(instr['where'][1]),
  835. width = w * self.instruction['scale'], height = h * self.instruction['scale'])
  836. self.instruction.update(instr)
  837. return True
  838. def ChangeRefPoint(self, toCenter):
  839. """Change reference point (left top x center)"""
  840. mapInstr = self.settings.FindInstructionByType('map')
  841. if not mapInstr:
  842. mapInstr = self.settings.FindInstructionByType('initMap')
  843. mapId = mapInstr.id
  844. if toCenter:
  845. center = self.instruction['rect'].GetCentre()
  846. ENCenter = PaperMapCoordinates(mapInstr = self.settings[mapId],
  847. x = center[0], y = center[1], paperToMap = True)
  848. self.instruction['east'], self.instruction['north'] = ENCenter
  849. else:
  850. x, y = PaperMapCoordinates(mapInstr = self.settings[mapId], x = self.instruction['east'],
  851. y = self.instruction['north'], paperToMap = False)
  852. w = self.unitConv.convert(value = self.instruction['size'][0], fromUnit = 'point', toUnit = 'inch')
  853. h = self.unitConv.convert(value = self.instruction['size'][1], fromUnit = 'point', toUnit = 'inch')
  854. x -= w * self.instruction['scale'] / 2
  855. y -= h * self.instruction['scale'] / 2
  856. e, n = PaperMapCoordinates(mapInstr = self.settings[mapId], x = x, y = y, paperToMap = True)
  857. self.instruction['east'], self.instruction['north'] = e, n
  858. def GetImageOrigSize(self, imagePath):
  859. """Get image size.
  860. If eps, size is read from image header.
  861. """
  862. fileName = os.path.split(imagePath)[1]
  863. # if eps, read info from header
  864. if os.path.splitext(fileName)[1].lower() == '.eps':
  865. bbInfo = "%%BoundingBox"
  866. file = open(imagePath,"r")
  867. w = h = 0
  868. while file:
  869. line = file.readline()
  870. if line.find(bbInfo) == 0:
  871. w, h = line.split()[3:5]
  872. break
  873. file.close()
  874. return float(w), float(h)
  875. else: # we can use wx.Image
  876. img = wx.Image(fileName, type=wx.BITMAP_TYPE_ANY)
  877. return img.GetWidth(), img.GetHeight()
  878. class NorthArrow(Image):
  879. """Class representing eps instruction -- North Arrow"""
  880. def __init__(self, id, settings):
  881. Image.__init__(self, id = id, settings = settings)
  882. self.type = 'northArrow'
  883. def __str__(self):
  884. self.ChangeRefPoint(toCenter = True)
  885. epsfile = self.instruction['epsfile'].replace(os.getenv('GISBASE'), "$GISBASE")
  886. instr = "eps %s %s\n" % (self.instruction['east'], self.instruction['north'])
  887. instr += "# north arrow\n"
  888. instr += " epsfile %s\n" % epsfile
  889. if self.instruction["rotate"]:
  890. instr += string.Template(" rotate $rotate\n").substitute(self.instruction)
  891. if self.instruction["scale"]:
  892. instr += string.Template(" scale $scale\n").substitute(self.instruction)
  893. instr += " end"
  894. return instr
  895. class Point(InstructionObject):
  896. """Class representing point instruction"""
  897. def __init__(self, id):
  898. InstructionObject.__init__(self, id = id)
  899. self.type = 'point'
  900. # default values
  901. self.defaultInstruction = dict(symbol = os.path.join('basic', 'x'),
  902. color = '0:0:0', fcolor = '200:200:200',
  903. rotate = 0, size = 10,
  904. XY = True, where = (0,0), unit = 'inch',
  905. east = None, north = None)
  906. # current values
  907. self.instruction = dict(self.defaultInstruction)
  908. def __str__(self):
  909. instr = string.Template("point $east $north\n").substitute(self.instruction)
  910. instr += string.Template(" symbol $symbol\n").substitute(self.instruction)
  911. instr += string.Template(" color $color\n").substitute(self.instruction)
  912. instr += string.Template(" fcolor $fcolor\n").substitute(self.instruction)
  913. instr += string.Template(" rotate $rotate\n").substitute(self.instruction)
  914. instr += string.Template(" size $size\n").substitute(self.instruction)
  915. instr += " end"
  916. return instr
  917. def Read(self, instruction, text, **kwargs):
  918. """Read instruction and save information"""
  919. mapInstr = kwargs['mapInstruction']
  920. instr = {}
  921. for line in text:
  922. try:
  923. sub = line.split(None, 1)[0]
  924. if sub == 'point':
  925. e, n = line.split(None, 3)[1:3]
  926. if '%' in e and '%' in n:
  927. instr['XY'] = True
  928. instr['east'], instr['north'] = self.PercentToReal(e, n)
  929. else:
  930. instr['XY'] = False
  931. instr['east'], instr['north'] = float(e), float(n)
  932. elif sub == 'symbol':
  933. instr['symbol'] = line.split(None, 1)[1]
  934. elif sub == 'rotate':
  935. instr['rotate'] = float(line.split(None, 1)[1])
  936. elif sub == 'size':
  937. instr['size'] = float(line.split(None, 1)[1])
  938. elif sub == 'color':
  939. instr['color'] = line.split(None, 1)[1]
  940. elif sub == 'fcolor':
  941. instr['fcolor'] = line.split(None, 1)[1]
  942. except(IndexError, ValueError):
  943. GError(_("Failed to read instruction %s") % instruction)
  944. return False
  945. self.instruction.update(instr)
  946. instr['where'] = PaperMapCoordinates(mapInstr = mapInstr, x = self.instruction['east'],
  947. y = self.instruction['north'], paperToMap = False)
  948. w = h = self.unitConv.convert(value = instr['size'], fromUnit = 'point', toUnit = 'inch')
  949. instr['rect'] = Rect2D(x = float(instr['where'][0]) - w / 2, y = float(instr['where'][1] - h / 2),
  950. width = w, height = h)
  951. self.instruction.update(instr)
  952. return True
  953. class Line(InstructionObject):
  954. """Class representing line instruction"""
  955. def __init__(self, id):
  956. InstructionObject.__init__(self, id = id)
  957. self.type = 'line'
  958. # default values
  959. self.defaultInstruction = dict(color = '0:0:0', width = 2,
  960. where = [wx.Point2D(), wx.Point2D()],
  961. east1 = None, north1 = None,
  962. east2 = None, north2 = None)
  963. # current values
  964. self.instruction = dict(self.defaultInstruction)
  965. def __str__(self):
  966. instr = string.Template("line $east1 $north1 $east2 $north2\n").substitute(self.instruction)
  967. instr += string.Template(" color $color\n").substitute(self.instruction)
  968. instr += string.Template(" width $width\n").substitute(self.instruction)
  969. instr += " end\n"
  970. return instr
  971. def Read(self, instruction, text, **kwargs):
  972. """Read instruction and save information"""
  973. mapInstr = kwargs['mapInstruction']
  974. instr = {}
  975. for line in text:
  976. try:
  977. sub = line.split(None, 1)[0]
  978. if sub == 'line':
  979. e1, n1, e2, n2 = line.split(None, 5)[1:5]
  980. if '%' in e1 and '%' in n1 and '%' in e2 and '%' in n2:
  981. instr['east1'], instr['north1'] = self.PercentToReal(e1, n1)
  982. instr['east2'], instr['north2'] = self.PercentToReal(e2, n2)
  983. else:
  984. instr['east1'], instr['north1'] = float(e1), float(n1)
  985. instr['east2'], instr['north2'] = float(e2), float(n2)
  986. elif sub == 'width':
  987. instr['width'] = float(line.split(None, 1)[1])
  988. elif sub == 'color':
  989. instr['color'] = line.split(None, 1)[1]
  990. except(IndexError, ValueError):
  991. GError(_("Failed to read instruction %s") % instruction)
  992. return False
  993. self.instruction.update(instr)
  994. e1, n1 = PaperMapCoordinates(mapInstr = mapInstr, x = self.instruction['east1'],
  995. y = self.instruction['north1'], paperToMap = False)
  996. e2, n2 = PaperMapCoordinates(mapInstr = mapInstr, x = self.instruction['east2'],
  997. y = self.instruction['north2'], paperToMap = False)
  998. instr['where'] = [wx.Point2D(e1, n1), wx.Point2D(e2, n2)]
  999. instr['rect'] = Rect2DPP(instr['where'][0], instr['where'][1])
  1000. self.instruction.update(instr)
  1001. return True
  1002. class Rectangle(InstructionObject):
  1003. """Class representing rectangle instruction"""
  1004. def __init__(self, id):
  1005. InstructionObject.__init__(self, id = id)
  1006. self.type = 'rectangle'
  1007. # default values
  1008. self.defaultInstruction = dict(color = '0:0:0', fcolor = 'none', width = 2,
  1009. east1 = None, north1 = None,
  1010. east2 = None, north2 = None)
  1011. # current values
  1012. self.instruction = dict(self.defaultInstruction)
  1013. def __str__(self):
  1014. instr = string.Template("rectangle $east1 $north1 $east2 $north2\n").substitute(self.instruction)
  1015. instr += string.Template(" color $color\n").substitute(self.instruction)
  1016. instr += string.Template(" fcolor $fcolor\n").substitute(self.instruction)
  1017. instr += string.Template(" width $width\n").substitute(self.instruction)
  1018. instr += " end\n"
  1019. return instr
  1020. def Read(self, instruction, text, **kwargs):
  1021. """Read instruction and save information"""
  1022. mapInstr = kwargs['mapInstruction']
  1023. instr = {}
  1024. for line in text:
  1025. try:
  1026. sub = line.split(None, 1)[0]
  1027. if sub == 'rectangle':
  1028. e1, n1, e2, n2 = line.split(None, 5)[1:5]
  1029. if '%' in e1 and '%' in n1 and '%' in e2 and '%' in n2:
  1030. instr['east1'], instr['north1'] = self.PercentToReal(e1, n1)
  1031. instr['east2'], instr['north2'] = self.PercentToReal(e2, n2)
  1032. else:
  1033. instr['east1'], instr['north1'] = float(e1), float(n1)
  1034. instr['east2'], instr['north2'] = float(e2), float(n2)
  1035. elif sub == 'width':
  1036. instr['width'] = float(line.split(None, 1)[1])
  1037. elif sub == 'color':
  1038. instr['color'] = line.split(None, 1)[1]
  1039. elif sub == 'fcolor':
  1040. instr['fcolor'] = line.split(None, 1)[1]
  1041. except(IndexError, ValueError):
  1042. GError(_("Failed to read instruction %s") % instruction)
  1043. return False
  1044. self.instruction.update(instr)
  1045. e1, n1 = PaperMapCoordinates(mapInstr = mapInstr, x = self.instruction['east1'],
  1046. y = self.instruction['north1'], paperToMap = False)
  1047. e2, n2 = PaperMapCoordinates(mapInstr = mapInstr, x = self.instruction['east2'],
  1048. y = self.instruction['north2'], paperToMap = False)
  1049. instr['rect'] = Rect2DPP(wx.Point2D(e1, n1), wx.Point2D(e2, n2))
  1050. self.instruction.update(instr)
  1051. return True
  1052. class Scalebar(InstructionObject):
  1053. """Class representing scalebar instruction"""
  1054. def __init__(self, id):
  1055. InstructionObject.__init__(self, id = id)
  1056. self.type = 'scalebar'
  1057. # default values
  1058. self.defaultInstruction = dict(unit = 'inch', where = (1,1),
  1059. unitsLength = 'auto', unitsHeight = 'inch',
  1060. length = None, height = 0.1, rect = None,
  1061. fontsize = 10, background = 'y',
  1062. scalebar = 'f', segment = 4, numbers = 1)
  1063. # current values
  1064. self.instruction = dict(self.defaultInstruction)
  1065. def __str__(self):
  1066. instr = string.Template("scalebar $scalebar\n").substitute(self.instruction)
  1067. instr += " where %.3f %.3f\n" % (self.instruction['where'][0], self.instruction['where'][1])
  1068. instr += string.Template(" length $length\n units $unitsLength\n").substitute(self.instruction)
  1069. instr += string.Template(" height $height\n").substitute(self.instruction)
  1070. instr += string.Template(" segment $segment\n numbers $numbers\n").substitute(self.instruction)
  1071. instr += string.Template(" fontsize $fontsize\n background $background\n").substitute(self.instruction)
  1072. instr += " end"
  1073. return instr
  1074. def Read(self, instruction, text, **kwargs):
  1075. """Read instruction and save information"""
  1076. scale = kwargs['scale']
  1077. instr = {}
  1078. for line in text:
  1079. try:
  1080. if line.startswith('scalebar'):
  1081. if 'scalebar s' in line:
  1082. instr['scalebar'] = 's'
  1083. else:
  1084. instr['scalebar'] = 'f'
  1085. elif line.startswith('where'):
  1086. instr['where'] = map(float, line.split()[1:3])
  1087. elif line.startswith('length'):
  1088. instr['length'] = float(line.split()[1])
  1089. elif line.startswith('units'):
  1090. if line.split()[1] in ['auto', 'meters', 'kilometers', 'feet', 'miles', 'nautmiles']:
  1091. instr['unitsLength'] = line.split()[1]
  1092. elif line.startswith('height'):
  1093. instr['height'] = float(line.split()[1])
  1094. elif line.startswith('fontsize'):
  1095. instr['fontsize'] = float(line.split()[1])
  1096. elif line.startswith('numbers'):
  1097. instr['numbers'] = int(line.split()[1])
  1098. elif line.startswith('segment'):
  1099. instr['segment'] = int(line.split()[1])
  1100. elif line.startswith('background'):
  1101. if line.split()[1].strip().lower() in ('y','yes'):
  1102. instr['background'] = 'y'
  1103. elif line.split()[1].strip().lower() in ('n','no', 'none'):
  1104. instr['background'] = 'n'
  1105. except(IndexError, ValueError):
  1106. GError(_("Failed to read instruction %s") % instruction)
  1107. return False
  1108. self.instruction.update(instr)
  1109. w, h = self.EstimateSize(scalebarDict = self.instruction, scale = scale)
  1110. x = self.instruction['where'][0] - w / 2
  1111. y = self.instruction['where'][1] - h / 2
  1112. self.instruction['rect'] = Rect2D(x, y, w, h)
  1113. return True
  1114. def EstimateSize(self, scalebarDict, scale):
  1115. """Estimate size to draw scalebar"""
  1116. units = projInfo()['units']
  1117. if not units or units not in self.unitConv.getAllUnits():
  1118. units = 'meters'
  1119. if scalebarDict['unitsLength'] != 'auto':
  1120. length = self.unitConv.convert(value = scalebarDict['length'], fromUnit = scalebarDict['unitsLength'], toUnit = 'inch')
  1121. else:
  1122. length = self.unitConv.convert(value = scalebarDict['length'], fromUnit = units, toUnit = 'inch')
  1123. length *= scale
  1124. length *= 1.1 #for numbers on the edge
  1125. height = scalebarDict['height'] + 2 * self.unitConv.convert(value = scalebarDict['fontsize'], fromUnit = 'point', toUnit = 'inch')
  1126. return (length, height)
  1127. class RasterLegend(InstructionObject):
  1128. """Class representing colortable instruction"""
  1129. def __init__(self, id):
  1130. InstructionObject.__init__(self, id = id)
  1131. self.type = 'rasterLegend'
  1132. # default values
  1133. self.defaultInstruction = dict(rLegend = False, unit = 'inch', rasterDefault = True, raster = None,
  1134. discrete = None, type = None,
  1135. where = (0, 0),
  1136. width = None, height = None, cols = 1, font = "Helvetica", fontsize = 10,
  1137. #color = '0:0:0', tickbar = False, range = False, min = 0, max = 0,
  1138. color = 'black', tickbar = 'n', range = False, min = 0, max = 0,
  1139. nodata = 'n')
  1140. # current values
  1141. self.instruction = dict(self.defaultInstruction)
  1142. def __str__(self):
  1143. instr = "colortable y\n"
  1144. instr += string.Template(" raster $raster\n").substitute(self.instruction)
  1145. instr += " where %.3f %.3f\n" % (self.instruction['where'][0], self.instruction['where'][1])
  1146. if self.instruction['width']:
  1147. instr += string.Template(" width $width\n").substitute(self.instruction)
  1148. instr += string.Template(" discrete $discrete\n").substitute(self.instruction)
  1149. if self.instruction['discrete'] == 'n':
  1150. if self.instruction['height']:
  1151. instr += string.Template(" height $height\n").substitute(self.instruction)
  1152. instr += string.Template(" tickbar $tickbar\n").substitute(self.instruction)
  1153. if self.instruction['range']:
  1154. instr += string.Template(" range $min $max\n").substitute(self.instruction)
  1155. else:
  1156. instr += string.Template(" cols $cols\n").substitute(self.instruction)
  1157. instr += string.Template(" nodata $nodata\n").substitute(self.instruction)
  1158. instr += string.Template(" font $font\n fontsize $fontsize\n color $color\n")\
  1159. .substitute(self.instruction)
  1160. instr += " end"
  1161. return instr
  1162. def Read(self, instruction, text, **kwargs):
  1163. """Read instruction and save information"""
  1164. instr = {}
  1165. instr['rLegend'] = True
  1166. for line in text:
  1167. try:
  1168. if line.startswith('where'):
  1169. instr['where'] = map(float, line.split()[1:3])
  1170. elif line.startswith('font '):
  1171. instr['font'] = line.split()[1]
  1172. elif line.startswith('fontsize'):
  1173. instr['fontsize'] = float(line.split()[1])
  1174. elif line.startswith('color '):
  1175. instr['color'] = line.split()[1]
  1176. elif line.startswith('raster'):
  1177. instr['raster'] = line.split()[1]
  1178. elif line.startswith('width'):
  1179. instr['width'] = float(line.split()[1])
  1180. elif line.startswith('height'):
  1181. instr['height'] = float(line.split()[1])
  1182. elif line.startswith('cols'):
  1183. instr['cols'] = int(line.split()[1])
  1184. elif line.startswith('range'):
  1185. instr['range'] = True
  1186. instr['min'] = float(line.split()[1])
  1187. instr['max'] = float(line.split()[2])
  1188. elif line.startswith('nodata'):
  1189. if line.split()[1].strip().lower() in ('y','yes'):
  1190. instr['nodata'] = 'y'
  1191. elif line.split()[1].strip().lower() in ('n','no', 'none'):
  1192. instr['nodata'] = 'n'
  1193. elif line.startswith('tickbar'):
  1194. if line.split()[1].strip().lower() in ('y','yes'):
  1195. instr['tickbar'] = 'y'
  1196. elif line.split()[1].strip().lower() in ('n','no', 'none'):
  1197. instr['tickbar'] = 'n'
  1198. elif line.startswith('discrete'):
  1199. if line.split()[1].strip().lower() in ('y','yes'):
  1200. instr['discrete'] = 'y'
  1201. elif line.split()[1].strip().lower() in ('n','no', 'none'):
  1202. instr['discrete'] = 'n'
  1203. except(IndexError, ValueError):
  1204. GError(_("Failed to read instruction %s") % instruction)
  1205. return False
  1206. if 'raster' in instr:
  1207. instr['rasterDefault'] = False
  1208. if 'discrete' not in instr:
  1209. rasterType = getRasterType(map = instr['raster'])
  1210. instr['type'] = rasterType
  1211. if rasterType == 'CELL':
  1212. instr['discrete'] = 'y'
  1213. else:
  1214. instr['discrete'] = 'n'
  1215. else:
  1216. instr['rasterDefault'] = True
  1217. self.instruction.update(instr)
  1218. # add 'rect' in the end
  1219. return True
  1220. def EstimateHeight(self, raster, discrete, fontsize, cols = None, height = None):
  1221. """Estimate height to draw raster legend"""
  1222. if discrete == 'n':
  1223. if height:
  1224. height = height
  1225. else:
  1226. height = self.unitConv.convert(value = fontsize * 10,
  1227. fromUnit = 'point', toUnit = 'inch')
  1228. if discrete == 'y':
  1229. if cols:
  1230. cols = cols
  1231. else:
  1232. cols = 1
  1233. rinfo = grass.raster_info(raster)
  1234. if rinfo['datatype'] in ('DCELL', 'FCELL'):
  1235. minim, maxim = rinfo['min'], rinfo['max']
  1236. rows = ceil(maxim / cols )
  1237. else:
  1238. cat = grass.read_command('r.category', map = raster,
  1239. sep = ':').strip().split('\n')
  1240. rows = ceil(float(len(cat)) / cols )
  1241. height = self.unitConv.convert(value = 1.5 * rows * fontsize, fromUnit = 'point', toUnit = 'inch')
  1242. return height
  1243. def EstimateWidth(self, raster, discrete, fontsize, cols = None, width = None, paperInstr = None):
  1244. """Estimate size to draw raster legend"""
  1245. if discrete == 'n':
  1246. rinfo = grass.raster_info(raster)
  1247. minim, maxim = rinfo['min'], rinfo['max']
  1248. if width:
  1249. width = width
  1250. else:
  1251. width = self.unitConv.convert(value = fontsize * 2,
  1252. fromUnit = 'point', toUnit = 'inch')
  1253. text = len(max(str(minim), str(maxim), key = len))
  1254. textPart = self.unitConv.convert(value = text * fontsize / 2,
  1255. fromUnit = 'point', toUnit = 'inch')
  1256. width += textPart
  1257. elif discrete == 'y':
  1258. if cols:
  1259. cols = cols
  1260. else:
  1261. cols = 1
  1262. if width:
  1263. width = width
  1264. else:
  1265. paperWidth = paperInstr['Width'] - paperInstr['Right'] - paperInstr['Left']
  1266. width = (paperWidth / cols) * (cols - 1) + 1
  1267. return width
  1268. class VectorLegend(InstructionObject):
  1269. """Class representing colortable instruction"""
  1270. def __init__(self, id):
  1271. InstructionObject.__init__(self, id = id)
  1272. self.type = 'vectorLegend'
  1273. # default values
  1274. self.defaultInstruction = dict(vLegend = False, unit = 'inch', where = (0, 0),
  1275. defaultSize = True, width = 0.4, cols = 1, span = None,
  1276. font = "Helvetica", fontsize = 10,
  1277. border = 'none')
  1278. # current values
  1279. self.instruction = dict(self.defaultInstruction)
  1280. def __str__(self):
  1281. instr = "vlegend\n"
  1282. instr += " where %.3f %.3f\n" % (self.instruction['where'][0], self.instruction['where'][1])
  1283. instr += string.Template(" font $font\n fontsize $fontsize\n").substitute(self.instruction)
  1284. instr += string.Template(" width $width\n cols $cols\n").substitute(self.instruction)
  1285. if self.instruction['span']:
  1286. instr += string.Template(" span $span\n").substitute(self.instruction)
  1287. instr += string.Template(" border $border\n").substitute(self.instruction)
  1288. instr += " end"
  1289. return instr
  1290. def Read(self, instruction, text, **kwargs):
  1291. """Read instruction and save information"""
  1292. instr = {}
  1293. instr['vLegend'] = True
  1294. for line in text:
  1295. try:
  1296. if line.startswith('where'):
  1297. instr['where'] = map(float, line.split()[1:3])
  1298. elif line.startswith('font '):
  1299. instr['font'] = line.split()[1]
  1300. elif line.startswith('fontsize'):
  1301. instr['fontsize'] = float(line.split()[1])
  1302. elif line.startswith('width'):
  1303. instr['width'] = float(line.split()[1])
  1304. elif line.startswith('cols'):
  1305. instr['cols'] = int(line.split()[1])
  1306. elif line.startswith('span'):
  1307. instr['span'] = float(line.split()[1])
  1308. elif line.startswith('border'):
  1309. instr['border'] = line.split()[1]
  1310. except(IndexError, ValueError):
  1311. GError(_("Failed to read instruction %s") % instruction)
  1312. return False
  1313. self.instruction.update(instr)
  1314. return True
  1315. def EstimateSize(self, vectorInstr, fontsize, width = None, cols = None):
  1316. """Estimate size to draw vector legend"""
  1317. if width:
  1318. width = width
  1319. else:
  1320. width = fontsize/24.0
  1321. if cols:
  1322. cols = cols
  1323. else:
  1324. cols = 1
  1325. vectors = vectorInstr['list']
  1326. labels = [vector[4] for vector in vectors if vector[3] != 0]
  1327. extent = (len(max(labels, key = len)) * fontsize / 2, fontsize)
  1328. wExtent = self.unitConv.convert(value = extent[0], fromUnit = 'point', toUnit = 'inch')
  1329. hExtent = self.unitConv.convert(value = extent[1], fromUnit = 'point', toUnit = 'inch')
  1330. w = (width + wExtent) * cols
  1331. h = len(labels) * hExtent / cols
  1332. h *= 1.1
  1333. return (w, h)
  1334. class Raster(InstructionObject):
  1335. """Class representing raster instruction"""
  1336. def __init__(self, id):
  1337. InstructionObject.__init__(self, id = id)
  1338. self.type = 'raster'
  1339. # default values
  1340. self.defaultInstruction = dict(isRaster = False, raster = None)
  1341. # current values
  1342. self.instruction = dict(self.defaultInstruction)
  1343. def __str__(self):
  1344. instr = string.Template("raster $raster").substitute(self.instruction)
  1345. return instr
  1346. def Read(self, instruction, text):
  1347. """Read instruction and save information"""
  1348. instr = {}
  1349. instr['isRaster'] = True
  1350. try:
  1351. map = text.split()[1]
  1352. except IndexError:
  1353. GError(_("Failed to read instruction %s") % instruction)
  1354. return False
  1355. try:
  1356. info = grass.find_file(map, element = 'cell')
  1357. except grass.ScriptError as e:
  1358. GError(message = e.value)
  1359. return False
  1360. instr['raster'] = info['fullname']
  1361. self.instruction.update(instr)
  1362. return True
  1363. class Vector(InstructionObject):
  1364. """Class keeps vector layers"""
  1365. def __init__(self, id):
  1366. InstructionObject.__init__(self, id = id)
  1367. self.type = 'vector'
  1368. # default values
  1369. self.defaultInstruction = dict(list = None)# [vmap, type, id, lpos, label]
  1370. # current values
  1371. self.instruction = dict(self.defaultInstruction)
  1372. def __str__(self):
  1373. return ''
  1374. def Read(self, instruction, text, **kwargs):
  1375. """Read instruction and save information"""
  1376. instr = {}
  1377. for line in text:
  1378. if line.startswith('vpoints') or line.startswith('vlines') or line.startswith('vareas'):
  1379. # subtype
  1380. if line.startswith('vpoints'):
  1381. subType = 'points'
  1382. elif line.startswith('vlines'):
  1383. subType = 'lines'
  1384. elif line.startswith('vareas'):
  1385. subType = 'areas'
  1386. # name of vector map
  1387. vmap = line.split()[1]
  1388. try:
  1389. info = grass.find_file(vmap, element = 'vector')
  1390. except grass.ScriptError as e:
  1391. GError(message = e.value)
  1392. return False
  1393. vmap = info['fullname']
  1394. # id
  1395. id = kwargs['id']
  1396. # lpos
  1397. lpos = kwargs['vectorMapNumber']
  1398. #label
  1399. label = '('.join(vmap.split('@')) + ')'
  1400. break
  1401. instr = [vmap, subType, id, lpos, label]
  1402. if not self.instruction['list']:
  1403. self.instruction['list'] = []
  1404. self.instruction['list'].append(instr)
  1405. return True
  1406. class VProperties(InstructionObject):
  1407. """Class represents instructions vareas, vlines, vpoints"""
  1408. def __init__(self, id, subType):
  1409. InstructionObject.__init__(self, id = id)
  1410. self.type = 'vProperties'
  1411. self.subType = subType
  1412. # default values
  1413. if self.subType == 'points':
  1414. dd = dict(subType = 'points', name = None, type = 'point or centroid', connection = False, layer = '1',
  1415. masked = 'n', color = '0:0:0', width = 1,
  1416. fcolor = '255:0:0', rgbcolumn = None, symbol = os.path.join('basic', 'x'), eps = None,
  1417. size = 5, sizecolumn = None, scale = None,
  1418. rotation = False, rotate = 0, rotatecolumn = None, label = None, lpos = None)
  1419. elif self.subType == 'lines':
  1420. dd = dict(subType = 'lines', name = None, type = 'line or boundary', connection = False, layer = '1',
  1421. masked = 'n', color = '0:0:0', hwidth = 1,
  1422. hcolor = 'none', rgbcolumn = None,
  1423. width = 1, cwidth = None,
  1424. style = 'solid', linecap = 'butt', label = None, lpos = None)
  1425. else: # areas
  1426. dd = dict(subType = 'areas', name = None, connection = False, layer = '1',
  1427. masked = 'n', color = '0:0:0', width = 1,
  1428. fcolor = 'none', rgbcolumn = None,
  1429. pat = None, pwidth = 1, scale = 1, label = None, lpos = None)
  1430. self.defaultInstruction = dd
  1431. # current values
  1432. self.instruction = dict(self.defaultInstruction)
  1433. def __str__(self):
  1434. dic = self.instruction
  1435. vInstruction = string.Template("v$subType $name\n").substitute(dic)
  1436. #data selection
  1437. if self.subType in ('points', 'lines'):
  1438. vInstruction += string.Template(" type $type\n").substitute(dic)
  1439. if dic['connection']:
  1440. vInstruction += string.Template(" layer $layer\n").substitute(dic)
  1441. if dic.has_key('cats'):
  1442. vInstruction += string.Template(" cats $cats\n").substitute(dic)
  1443. elif dic.has_key('where'):
  1444. vInstruction += string.Template(" where $where\n").substitute(dic)
  1445. vInstruction += string.Template(" masked $masked\n").substitute(dic)
  1446. #colors
  1447. vInstruction += string.Template(" color $color\n").substitute(dic)
  1448. if self.subType in ('points', 'areas'):
  1449. if dic['color'] != 'none':
  1450. vInstruction += string.Template(" width $width\n").substitute(dic)
  1451. if dic['rgbcolumn']:
  1452. vInstruction += string.Template(" rgbcolumn $rgbcolumn\n").substitute(dic)
  1453. vInstruction += string.Template(" fcolor $fcolor\n").substitute(dic)
  1454. else:
  1455. if dic['rgbcolumn']:
  1456. vInstruction += string.Template(" rgbcolumn $rgbcolumn\n").substitute(dic)
  1457. elif dic['hcolor'] != 'none':
  1458. vInstruction += string.Template(" hwidth $hwidth\n").substitute(dic)
  1459. vInstruction += string.Template(" hcolor $hcolor\n").substitute(dic)
  1460. # size and style
  1461. if self.subType == 'points':
  1462. if not dic['eps']:
  1463. vInstruction += string.Template(" symbol $symbol\n").substitute(dic)
  1464. else: #eps
  1465. vInstruction += string.Template(" eps $eps\n").substitute(dic)
  1466. if dic['size']:
  1467. vInstruction += string.Template(" size $size\n").substitute(dic)
  1468. else: # sizecolumn
  1469. vInstruction += string.Template(" sizecolumn $sizecolumn\n").substitute(dic)
  1470. vInstruction += string.Template(" scale $scale\n").substitute(dic)
  1471. if dic['rotation']:
  1472. if dic['rotate'] is not None:
  1473. vInstruction += string.Template(" rotate $rotate\n").substitute(dic)
  1474. else:
  1475. vInstruction += string.Template(" rotatecolumn $rotatecolumn\n").substitute(dic)
  1476. if self.subType == 'areas':
  1477. if dic['pat'] is not None:
  1478. patternFile = dic['pat'].replace(os.getenv("GISBASE"), "$GISBASE")
  1479. vInstruction += " pat %s\n" % patternFile
  1480. vInstruction += string.Template(" pwidth $pwidth\n").substitute(dic)
  1481. vInstruction += string.Template(" scale $scale\n").substitute(dic)
  1482. if self.subType == 'lines':
  1483. if dic['width'] is not None:
  1484. vInstruction += string.Template(" width $width\n").substitute(dic)
  1485. else:
  1486. vInstruction += string.Template(" cwidth $cwidth\n").substitute(dic)
  1487. vInstruction += string.Template(" style $style\n").substitute(dic)
  1488. vInstruction += string.Template(" linecap $linecap\n").substitute(dic)
  1489. #position and label in vlegend
  1490. vInstruction += string.Template(" label $label\n lpos $lpos\n").substitute(dic)
  1491. vInstruction += " end"
  1492. try:
  1493. vInstruction = vInstruction.encode('Latin_1')
  1494. except UnicodeEncodeError as err:
  1495. try:
  1496. pos = str(err).split('position')[1].split(':')[0].strip()
  1497. except IndexError:
  1498. pos = ''
  1499. if pos:
  1500. message = _("Characters on position %s are not supported "
  1501. "by ISO-8859-1 (Latin 1) encoding "
  1502. "which is required by module ps.map.") % pos
  1503. else:
  1504. message = _("Not all characters are supported "
  1505. "by ISO-8859-1 (Latin 1) encoding "
  1506. "which is required by module ps.map.")
  1507. GMessage(message = message)
  1508. return ''
  1509. return vInstruction
  1510. def Read(self, instruction, text, **kwargs):
  1511. """Read instruction and save information"""
  1512. instr = {}
  1513. try:
  1514. info = grass.find_file(name = text[0].split()[1], element = 'vector')
  1515. except grass.ScriptError as e:
  1516. GError(message = e.value)
  1517. return False
  1518. instr['name'] = info['fullname']
  1519. #connection
  1520. instr['connection'] = True
  1521. self.mapDBInfo = VectorDBInfo(instr['name'])
  1522. self.layers = self.mapDBInfo.layers.keys()
  1523. if not self.layers:
  1524. instr['connection'] = False
  1525. # points
  1526. if text[0].startswith('vpoints'):
  1527. for line in text[1:]:
  1528. if line.startswith('type'):
  1529. tp = []
  1530. if line.find('point') != -1:
  1531. tp.append('point')
  1532. if line.find('centroid') != -1:
  1533. tp.append('centroid')
  1534. instr['type'] = ' or '.join(tp)
  1535. elif line.startswith('fcolor'):
  1536. instr['fcolor'] = line.split()[1]
  1537. elif line.startswith('rgbcolumn'):
  1538. instr['rgbcolumn'] = line.split()[1]
  1539. elif line.startswith('symbol'):
  1540. instr['symbol'] = line.split()[1]
  1541. elif line.startswith('eps'):
  1542. instr['eps'] = line.split()[1]
  1543. elif line.startswith('size '):
  1544. instr['size'] = line.split()[1]
  1545. elif line.startswith('sizecolumn'):
  1546. instr['size'] = None
  1547. instr['sizecolumn'] = line.split()[1]
  1548. elif line.startswith('scale '):
  1549. instr['scale'] = float(line.split()[1])
  1550. elif line.startswith('rotate '):
  1551. instr['rotation'] = True
  1552. instr['rotate'] = line.split()[1]
  1553. elif line.startswith('rotatecolumn'):
  1554. instr['rotatecolumn'] = line.split()[1]
  1555. instr['rotation'] = True
  1556. instr['rotate'] = None
  1557. # lines
  1558. elif text[0].startswith('vlines'):
  1559. for line in text[1:]:
  1560. if line.startswith('type'):
  1561. tp = []
  1562. if line.find('line') != -1:
  1563. tp.append('line')
  1564. if line.find('boundary') != -1:
  1565. tp.append('boundary')
  1566. instr['type'] = ' or '.join(tp)
  1567. elif line.startswith('hwidth'):
  1568. instr['hwidth'] = float(line.split()[1])
  1569. elif line.startswith('hcolor'):
  1570. instr['hcolor'] = line.split()[1]
  1571. elif line.startswith('rgbcolumn'):
  1572. instr['rgbcolumn'] = line.split()[1]
  1573. elif line.startswith('cwidth'):
  1574. instr['cwidth'] = float(line.split()[1])
  1575. instr['width'] = None
  1576. elif line.startswith('style'):
  1577. instr['style'] = line.split()[1]
  1578. elif line.startswith('linecap'):
  1579. instr['linecap'] = line.split()[1]
  1580. elif text[0].startswith('vareas'):
  1581. for line in text[1:]:
  1582. if line.startswith('fcolor'):
  1583. instr['fcolor'] = line.split()[1]
  1584. elif line.startswith('pat'):
  1585. patternFile = line.split()[1]
  1586. instr['pat'] = patternFile.replace("$GISBASE", os.getenv("GISBASE"))
  1587. elif line.startswith('pwidth'):
  1588. instr['pwidth'] = float(line.split()[1])
  1589. elif line.startswith('scale'):
  1590. instr['scale'] = float(line.split()[1])
  1591. # same properties for all
  1592. for line in text[1:]:
  1593. if line.startswith('lpos'):
  1594. instr['lpos'] = int(line.split()[1])
  1595. elif line.startswith('label'):
  1596. instr['label'] = line.split(None, 1)[1].decode('latin_1')
  1597. elif line.startswith('layer'):
  1598. instr['layer'] = line.split()[1]
  1599. elif line.startswith('masked'):
  1600. if line.split()[1].lower() in ('y', 'yes'):
  1601. instr['masked'] = 'y'
  1602. else:
  1603. instr['masked'] = 'n'
  1604. elif line.startswith('color'):
  1605. instr['color'] = line.split()[1]
  1606. elif line.startswith('rgbcolumn'):
  1607. instr['rgbcolumn'] = line.split()[1]
  1608. elif line.startswith('width'):
  1609. instr['width'] = float(line.split()[1])
  1610. if 'label' not in instr:
  1611. instr['label'] = '('.join(instr['name'].split('@')) + ')'
  1612. if 'lpos' not in instr:
  1613. instr['lpos'] = kwargs['vectorMapNumber']
  1614. self.instruction.update(instr)
  1615. return True
  1616. class Labels(InstructionObject):
  1617. """Class representing labels instruction"""
  1618. def __init__(self, id):
  1619. InstructionObject.__init__(self, id = id)
  1620. self.type = 'labels'
  1621. # default values
  1622. self.defaultInstruction = dict(labels=[])
  1623. # current values
  1624. self.instruction = dict(self.defaultInstruction)
  1625. def __str__(self):
  1626. instr = ''
  1627. for label in self.instruction['labels']:
  1628. instr += "labels %s\n" % label
  1629. instr += "end\n"
  1630. return instr
  1631. def Read(self, instruction, text, **kwargs):
  1632. """Read instruction and save information"""
  1633. for line in text:
  1634. try:
  1635. if line.startswith('labels'):
  1636. labels = line.split(None, 1)[1]
  1637. self.instruction['labels'].append(labels)
  1638. except(IndexError, ValueError):
  1639. GError(_("Failed to read instruction %s") % instruction)
  1640. return False
  1641. return True