instructions.py 80 KB

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