instructions.py 81 KB

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