instructions.py 80 KB

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