instructions.py 80 KB

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