wxvdriver.py 27 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821
  1. """!
  2. @package wxvdriver.py
  3. @brief wxGUI vector digitizer (display driver)
  4. Code based on wxVdigit C++ component from GRASS 6.4.0
  5. (gui/wxpython/vdigit). Converted to Python in 2010/12-2011/01.
  6. List of classes:
  7. - DisplayDriver
  8. (C) 2007-2011 by the GRASS Development Team
  9. This program is free software under the GNU General Public License
  10. (>=v2). Read the file COPYING that comes with GRASS for details.
  11. @author Martin Landa <landa.martin gmail.com>
  12. """
  13. import math
  14. import wx
  15. from debug import Debug as Debug
  16. from preferences import globalSettings as UserSettings
  17. from grass.lib.grass import *
  18. from grass.lib.vector import *
  19. from grass.lib.vedit import *
  20. class DisplayDriver:
  21. def __init__(self, device, deviceTmp, mapObj, log = None):
  22. """Display driver used by vector digitizer
  23. @param device wx.PseudoDC device where to draw vector objects
  24. @param deviceTmp wx.PseudoDC device where to draw temporary vector objects
  25. @param mapOng Map Object (render.Map)
  26. @param log logging device (None to discard messages)
  27. """
  28. G_gisinit('') # initialize GRASS libs
  29. self.mapInfo = None # open vector map (Map_Info structure)
  30. self.poMapInfo = None # pointer to self.mapInfo
  31. self.is3D = False # is open vector map 3D
  32. self.dc = device # PseudoDC devices
  33. self.dcTmp = deviceTmp
  34. self.mapObj = mapObj
  35. self.region = mapObj.GetCurrentRegion()
  36. self.log = log # log device
  37. # GRASS lib
  38. self.poPoints = Vect_new_line_struct()
  39. self.poCats = Vect_new_cats_struct()
  40. # selected objects
  41. self.selected = {
  42. 'field' : -1, # field number
  43. 'cats' : list(), # list of cats
  44. 'ids' : list(), # list of ids
  45. 'idsDupl' : list(), # list of duplicated features
  46. }
  47. # digitizer settings
  48. self.settings = {
  49. 'highlight' : None,
  50. 'highlightDupl' : { 'enabled' : False,
  51. 'color' : None },
  52. 'point' : { 'enabled' : False,
  53. 'color' : None },
  54. 'line' : { 'enabled' : False,
  55. 'color' : None },
  56. 'boundaryNo' : { 'enabled' : False,
  57. 'color' : None },
  58. 'boundaryOne' : { 'enabled' : False,
  59. 'color' : None },
  60. 'boundaryTwo' : { 'enabled' : False,
  61. 'color' : None },
  62. 'centroidIn' : { 'enabled' : False,
  63. 'color' : None },
  64. 'centroidOut' : { 'enabled' : False,
  65. 'color' : None },
  66. 'centroidDup' : { 'enabled' : False,
  67. 'color' : None },
  68. 'nodeOne' : { 'enabled' : False,
  69. 'color' : None },
  70. 'nodeTwo' : { 'enabled' : False,
  71. 'color' : None },
  72. 'vertex' : { 'enabled' : False,
  73. 'color' : None },
  74. 'area' : { 'enabled' : False,
  75. 'color' : None },
  76. 'direction' : { 'enabled' : False,
  77. 'color' : None },
  78. 'lineWidth' : -1, # screen units
  79. }
  80. # topology
  81. self.topology = {
  82. 'highlight' : 0,
  83. 'point' : 0,
  84. 'line' : 0,
  85. 'boundaryNo' : 0,
  86. 'boundaryOne' : 0,
  87. 'boundaryTwo' : 0,
  88. 'centroidIn' : 0,
  89. 'centroidOut' : 0,
  90. 'centroidDup' : 0,
  91. 'nodeOne' : 0,
  92. 'nodeTwo' : 0,
  93. 'vertex' : 0,
  94. }
  95. self.drawSelected = False
  96. self.drawSegments = False
  97. self.UpdateSettings()
  98. Vect_set_fatal_error(GV_FATAL_PRINT)
  99. def __del__(self):
  100. """!Close currently open vector map"""
  101. if self.poMapInfo:
  102. self.CloseMap()
  103. Vect_destroy_line_struct(self.poPoints)
  104. Vect_destroy_cats_struct(self.poCats)
  105. def _cell2Pixel(self, east, north, elev):
  106. """!Conversion from geographic coordinates (east, north)
  107. to screen (x, y)
  108. @todo 3D stuff...
  109. @param east, north, elev geographical coordinates
  110. @return x, y screen coordinates (integer)
  111. """
  112. map_res = max(self.region['ewres'], self.region['nsres'])
  113. w = self.region['center_easting'] - (self.mapObj.width / 2) * map_res
  114. n = self.region['center_northing'] + (self.mapObj.height / 2) * map_res
  115. return int((east - w) / map_res), int((n - north) / map_res)
  116. def _drawCross(self, pdc, point, size = 5):
  117. """!Draw cross symbol of given size to device content
  118. Used for points, nodes, vertices
  119. @param[in,out] PseudoDC where to draw
  120. @param point coordinates of center
  121. @param size size of the cross symbol
  122. @return 0 on success
  123. @return -1 on failure
  124. """
  125. if not pdc or not point:
  126. return -1
  127. pdc.DrawLine(point.x - size, point.y, point.x + size, point.y)
  128. pdc.DrawLine(point.x, point.y - size, point.x, point.y + size)
  129. return 0
  130. def _drawObject(self, robj):
  131. """!Draw given object to the device
  132. The object is defined as robject() from vedit.h.
  133. @param robj object to be rendered
  134. @return 1 on success
  135. @return -1 on failure (vector feature marked as dead, etc.)
  136. """
  137. if not self.dc or not self.dcTmp:
  138. return -1
  139. Debug.msg(3, "_drawObject(): type=%d npoints=%d", robj.type, robj.npoints)
  140. brush = None
  141. if self._isSelected(robj.fid):
  142. pdc = self.dcTmp
  143. if self.settings['highlightDupl']['enabled'] and self._isDuplicated(robj.fid):
  144. pen = wx.Pen(self.settings['highlightDupl'], self.settings['lineWidth'], wx.SOLID)
  145. else:
  146. pen = wx.Pen(self.settings['highlight'], self.settings['lineWidth'], wx.SOLID)
  147. dcId = 1
  148. self.topology['highlight'] += 1
  149. else:
  150. pdc = self.dc
  151. pen, brush = self._definePen(robj.type)
  152. dcId = 0
  153. pdc.SetPen(pen)
  154. if brush:
  155. pdc.SetBrush(brush)
  156. if robj.type & (TYPE_POINT | TYPE_CENTROIDIN | TYPE_CENTROIDOUT | TYPE_CENTROIDDUP |
  157. TYPE_NODEONE | TYPE_NODETWO | TYPE_VERTEX): # -> point
  158. for i in range(robj.npoints):
  159. p = robj.point[i]
  160. self._drawCross(pdc, p)
  161. else:
  162. if dcId > 0 and self.drawSegments:
  163. dcId = 2 # first segment
  164. i = 0
  165. while i < robj.npoints - 1:
  166. point_beg = wx.Point(robj.point[i].x, robj.point[i].y)
  167. point_end = wx.Point(robj.point[i+1].x, robj.point[i+1].y)
  168. pdc.SetId(dcId) # set unique id & set bbox for each segment
  169. pdc.SetPen(pen)
  170. rect = wx.RectPP(point_beg, point_end)
  171. pdc.SetIdBounds(dcId, rect)
  172. pdc.DrawLine(point_beg.x, point_beg.y,
  173. point_end.x, point_end.y)
  174. i += 1
  175. dcId += 2
  176. else:
  177. points = list()
  178. for i in range(robj.npoints):
  179. p = robj.point[i]
  180. points.append(wx.Point(p.x, p.y))
  181. if robj.type == TYPE_AREA:
  182. pdc.DrawPolygon(points)
  183. else:
  184. pdc.DrawLines(points)
  185. def _definePen(self, rtype):
  186. """!Define pen/brush based on rendered object)
  187. Updates also self.topology dict
  188. @return pen, brush
  189. """
  190. if rtype == TYPE_POINT:
  191. key = 'point'
  192. elif rtype == TYPE_LINE:
  193. key = 'line'
  194. elif rtype == TYPE_BOUNDARYNO:
  195. key = 'boundaryNo'
  196. elif rtype == TYPE_BOUNDARYTWO:
  197. key = 'boundaryTwo'
  198. elif rtype == TYPE_BOUNDARYONE:
  199. key = 'boundaryOne'
  200. elif rtype == TYPE_CENTROIDIN:
  201. key = 'centroidIn'
  202. elif rtype == TYPE_CENTROIDOUT:
  203. key = 'centroidOut'
  204. elif rtype == TYPE_CENTROIDDUP:
  205. key = 'centroidDup'
  206. elif rtype == TYPE_NODEONE:
  207. key = 'nodeOne'
  208. elif rtype == TYPE_NODETWO:
  209. key = 'nodeTwo'
  210. elif rtype == TYPE_VERTEX:
  211. key = 'vertex'
  212. elif rtype == TYPE_AREA:
  213. key = 'area'
  214. elif rtype == TYPE_ISLE:
  215. key = 'isle'
  216. elif rtype == TYPE_DIRECTION:
  217. key = 'direction'
  218. if key not in ('direction', 'area', 'isle'):
  219. self.topology[key] += 1
  220. if key in ('area', 'isle'):
  221. pen = wx.TRANSPARENT_PEN
  222. if key == 'area':
  223. brush = wx.Brush(self.settings[key]['color'], wx.SOLID)
  224. else:
  225. brush = wx.TRANSPARENT_BRUSH
  226. else:
  227. pen = wx.Pen(self.settings[key]['color'], self.settings['lineWidth'], wx.SOLID)
  228. brush = None
  229. return pen, brush
  230. def _getDrawFlag(self):
  231. """!Get draw flag from the settings
  232. See vedit.h for list of draw flags.
  233. @return draw flag (int)
  234. """
  235. ret = 0
  236. if self.settings['point']['enabled']:
  237. ret |= TYPE_POINT
  238. if self.settings['line']['enabled']:
  239. ret |= TYPE_LINE
  240. if self.settings['boundaryNo']['enabled']:
  241. ret |= TYPE_BOUNDARYNO
  242. if self.settings['boundaryTwo']['enabled']:
  243. ret |= TYPE_BOUNDARYTWO
  244. if self.settings['boundaryOne']['enabled']:
  245. ret |= TYPE_BOUNDARYONE
  246. if self.settings['centroidIn']['enabled']:
  247. ret |= TYPE_CENTROIDIN
  248. if self.settings['centroidOut']['enabled']:
  249. ret |= TYPE_CENTROIDOUT
  250. if self.settings['centroidDup']['enabled']:
  251. ret |= TYPE_CENTROIDDUP
  252. if self.settings['nodeOne']['enabled']:
  253. ret |= TYPE_NODEONE
  254. if self.settings['nodeTwo']['enabled']:
  255. ret |= TYPE_NODETWO
  256. if self.settings['vertex']['enabled']:
  257. ret |= TYPE_VERTEX
  258. if self.settings['area']['enabled']:
  259. ret |= TYPE_AREA
  260. if self.settings['direction']['enabled']:
  261. ret |= TYPE_DIRECTION
  262. return ret
  263. def _printIds(self):
  264. pass
  265. def _isSelected(self, line, force = False):
  266. """!Check if vector object selected?
  267. @param line feature id
  268. @return True if vector object is selected
  269. @return False if vector object is not selected
  270. """
  271. if len(self.selected['cats']) < 1 or force:
  272. # select by id
  273. if line in self.selected['ids']:
  274. return True
  275. else:
  276. # select by cat
  277. cats = self.poCats.contents
  278. for i in range(cats.n_cats):
  279. if cats.field[i] == self.selected['field'] and \
  280. cats.cat[i] in self.selected['cats']:
  281. # remember id
  282. # -> after drawing all features selected.cats is reseted */
  283. self.selected['ids'].append(line)
  284. return True
  285. return False
  286. def _isDuplicated(self, featId):
  287. return False
  288. def _resetTopology(self):
  289. pass
  290. def _getRegionBox(self):
  291. """!Get bound_box() from current region
  292. @return bound_box
  293. """
  294. box = bound_box()
  295. box.N = self.region['n']
  296. box.S = self.region['s']
  297. box.E = self.region['e']
  298. box.W = self.region['w']
  299. box.T = PORT_DOUBLE_MAX
  300. box.B = -PORT_DOUBLE_MAX
  301. return box
  302. def DrawMap(self, force = False):
  303. """!Draw content of the vector map to the device
  304. @param force force drawing
  305. @return number of drawn features
  306. @return -1 on error
  307. """
  308. Debug.msg(1, "DisplayDriver.DrawMap(): force=%d", force)
  309. if not self.poMapInfo or not self.dc or not self.dcTmp:
  310. return -1
  311. rlist = Vedit_render_map(self.poMapInfo, byref(self._getRegionBox()), self._getDrawFlag(),
  312. self.region['center_easting'], self.region['center_northing'],
  313. self.mapObj.width, self.mapObj.height,
  314. max(self.region['nsres'], self.region['ewres'])).contents
  315. # ResetTopology()
  316. #self.dc.BeginDrawing()
  317. #self.dcTmp.BeginDrawing()
  318. # draw objects
  319. for i in range(rlist.nitems):
  320. robj = rlist.item[i].contents
  321. self._drawObject(robj)
  322. #self.dc.EndDrawing()
  323. #self.dcTmp.EndDrawing()
  324. # reset list of selected features by cat
  325. # list of ids - see IsSelected()
  326. self.selected['field'] = -1
  327. self.selected['cats'] = list()
  328. def _getSelectType(self):
  329. """!Get type(s) to be selected
  330. Used by SelectLinesByBox() and SelectLinesByPoint()
  331. """
  332. ftype = 0
  333. for feature in (('point', GV_POINT),
  334. ('line', GV_LINE),
  335. ('centroid', GV_CENTROID),
  336. ('boundary', GV_BOUNDARY)):
  337. if UserSettings.Get(group = 'vdigit', key = 'selectType',
  338. subkey = [feature[0], 'enabled']):
  339. ftype |= feature[1]
  340. return ftype
  341. def SelectLinesByBox(self, bbox, drawSeg = False):
  342. """!Select vector objects by given bounding box
  343. If line id is already in the list of selected lines, then it will
  344. be excluded from this list.
  345. @param bbox bounding box definition
  346. @param drawSeg True to draw segments of line
  347. @return number of selected features
  348. @return -1 on error
  349. """
  350. if not self.poMapInfo:
  351. return -1
  352. self.drawSegments = drawSeg
  353. self.drawSelected = True
  354. # select by ids
  355. self.selected['cats'] = list()
  356. poList = Vect_new_list()
  357. poBbox = Vect_new_line_struct()
  358. x1, y1 = bbox[0]
  359. x2, y2 = bbox[1]
  360. Vect_append_point(poBbox, x1, y1, 0.0)
  361. Vect_append_point(poBbox, x2, y1, 0.0)
  362. Vect_append_point(poBbox, x2, y2, 0.0)
  363. Vect_append_point(poBbox, x1, y2, 0.0)
  364. Vect_append_point(poBbox, x1, y1, 0.0)
  365. Vect_select_lines_by_polygon(self.poMapInfo, poBbox,
  366. 0, None, # isles
  367. self._getSelectType(), poList)
  368. flist = poList.contents
  369. nlines = flist.n_values
  370. for i in range(nlines):
  371. line = flist.value[i]
  372. if UserSettings.Get(group = 'vdigit', key = 'selectInside',
  373. subkey = 'enabled'):
  374. inside = True
  375. Vect_read_line(self.poMapInfo, self.poPoints, None, line)
  376. points = poPoints.contents
  377. for p in range(points.n_points):
  378. if not Vect_point_in_poly(points.x[p], points.y[p],
  379. byref(bbox)):
  380. inside = False
  381. break
  382. if not inside:
  383. continue # skip lines just overlapping bbox
  384. if not self._isSelected(line):
  385. self.selected['ids'].append(line)
  386. else:
  387. self.selected['ids'].remove(line)
  388. Vect_destroy_line_struct(poBbox)
  389. Vect_destroy_list(poList)
  390. return nlines
  391. def SelectLineByPoint(self, point):
  392. """!Select vector feature by given point in given
  393. threshold
  394. Only one vector object can be selected. Bounding boxes of
  395. all segments are stores.
  396. @param point points coordinates (x, y)
  397. @return point on line if line found
  398. """
  399. self.drawSelected = True
  400. poFound = Vect_new_list()
  401. # select by ids
  402. self.selected['cats'] = list()
  403. line_nearest = Vect_find_line_list(self.poMapInfo, point[0], point[1], 0,
  404. self._getSelectType(), self.GetThreshold(), self.is3D,
  405. None, poFound)
  406. if line_nearest > 0:
  407. if not self._isSelected(line_nearest):
  408. self.selected['ids'].append(line_nearest)
  409. else:
  410. self.selected['ids'].remove(line_nearest)
  411. px = c_double()
  412. py = c_double()
  413. pz = c_double()
  414. ftype = Vect_read_line(self.poMapInfo, self.poPoints, self.poCats, line_nearest)
  415. Vect_line_distance (self.poPoints, point[0], point[1], 0.0, self.is3D,
  416. byref(px), byref(py), byref(pz),
  417. None, None, None)
  418. # check for duplicates
  419. if self.settings['highlightDupl']['enabled']:
  420. found = poFound.contents
  421. for i in range(found.n_values):
  422. line = found.value[i]
  423. if line != line_nearest:
  424. self.selected['ids'].append(line)
  425. self.getDuplicates()
  426. for i in range(found.n_values):
  427. line = found.value[i]
  428. if line != line_nearest and not self._isDuplicated(line):
  429. self.selected['ids'].remove(line)
  430. Vect_destroy_list(poFound)
  431. # drawing segments can be very expensive
  432. # only one features selected
  433. self.drawSegments = True
  434. return (px.value, py.value, pz.value)
  435. def GetSelected(self, grassId = True):
  436. """!Get ids of selected objects
  437. @param grassId if true return GRASS line ids, false to return PseudoDC ids
  438. @return list of ids of selected vector objects
  439. """
  440. if grassId:
  441. return self.selected['ids']
  442. dc_ids = list()
  443. if not self.drawSegments:
  444. dc_ids.append(1)
  445. else:
  446. # only first selected feature
  447. # Vect_read_line(self.poMapInfo, byref(self.points), None,
  448. # self.selected.ids->value[0]);
  449. # npoints = self.points.n_points
  450. # node - segment - vertex - segment - node
  451. # for i in range(1, 2 * self.points.npoints):
  452. # dc_ids.append(i)
  453. pass
  454. return dc_ids
  455. def GetSelectedCoord(self):
  456. pass
  457. def GetDuplicates(self):
  458. pass
  459. def GetRegionSelected(self):
  460. pass
  461. def SetSelected(self, ids, layer = -1):
  462. """!Set selected vector objects
  463. @param list of ids (None to unselect features)
  464. @param layer layer number for features selected based on category number
  465. """
  466. if ids:
  467. self.drawSelected = True
  468. else:
  469. self.drawSelected = False
  470. if layer > 0:
  471. selected.field = layer
  472. self.selected['cats'] = ids
  473. else:
  474. field = -1
  475. self.selected['ids'] = ids
  476. def GetSelectedVertex(self, pos):
  477. """Get PseudoDC vertex id of selected line
  478. Set bounding box for vertices of line.
  479. \param pos position
  480. \return id of center, left and right vertex
  481. \return 0 no line found
  482. \return -1 on error
  483. """
  484. returnId = list()
  485. # only one object can be selected
  486. if len(self.selected['ids']) != 1 or not self.drawSegments:
  487. return returnId
  488. startId = 1
  489. line = self.selected['ids'][0]
  490. ftype = Vect_read_line(self.poMapInfo, self.poPoints, self.poCats, line)
  491. minDist = 0.0
  492. Gid = -1
  493. # find the closest vertex (x, y)
  494. DCid = 1
  495. points = self.poPoints.contents
  496. for idx in range(points.n_points):
  497. dist = Vect_points_distance(pos[0], pos[1], 0.0,
  498. points.x[idx], points.y[idx], points.z[idx], 0)
  499. if idx == 0:
  500. minDist = dist
  501. Gid = idx
  502. else:
  503. if minDist > dist:
  504. minDist = dist
  505. Gid = idx
  506. vx, vy = self._cell2Pixel(points.x[idx], points.y[idx], points.z[idx])
  507. rect = wx.Rect(vx, vy, 0, 0)
  508. self.dc.SetIdBounds(DCid, rect)
  509. DCid += 2
  510. if minDist > self.GetThreshold():
  511. return returnId
  512. # translate id
  513. DCid = Gid * 2 + 1
  514. # add selected vertex
  515. returnId.append(DCid)
  516. # left vertex
  517. if DCid == startId:
  518. returnId.append(-1)
  519. else:
  520. returnId.append(DCid - 2)
  521. # right vertex
  522. if DCid == (points.n_points - 1) * 2 + startId:
  523. returnId.append(-1)
  524. else:
  525. returnId.append(DCid + 2)
  526. return returnId
  527. def DrawSelected(self):
  528. pass
  529. def CloseMap(self):
  530. """!Close vector map
  531. @return 0 on success
  532. @return non-zero on error
  533. """
  534. ret = 0
  535. if self.poMapInfo:
  536. # rebuild topology
  537. Vect_build_partial(self.poMapInfo, GV_BUILD_NONE)
  538. Vect_build(self.poMapInfo)
  539. # close map and store topo/cidx
  540. ret = Vect_close(self.poMapInfo)
  541. del self.mapInfo
  542. self.poMapInfo = self.mapInfo = None
  543. return ret
  544. def OpenMap(self, name, mapset, update = True):
  545. """!Open vector map by the driver
  546. @param name name of vector map to be open
  547. @param mapset name of mapset where the vector map lives
  548. @return map_info
  549. @return None on error
  550. """
  551. Debug.msg("DisplayDriver.OpenMap(): name=%s mapset=%s updated=%d",
  552. name, mapset, update)
  553. if not self.mapInfo:
  554. self.mapInfo = Map_info()
  555. self.poMapInfo = pointer(self.mapInfo)
  556. # define open level (level 2: topology)
  557. Vect_set_open_level(2)
  558. # avoid GUI crash when G_fatal_error() is called (opening the vector map)
  559. Vect_set_fatal_error(GV_FATAL_PRINT)
  560. # open existing map
  561. if update:
  562. ret = Vect_open_update(self.poMapInfo, name, mapset)
  563. else:
  564. ret = Vect_open_old(self.poMapInfo, name, mapset)
  565. self.is3D = Vect_is_3d(self.poMapInfo)
  566. if ret == -1: # error
  567. del self.mapInfo
  568. self.poMapInfo = self.mapInfo = None
  569. return self.poMapInfo
  570. def ReloadMap(self):
  571. pass
  572. def SetDevice(self):
  573. pass
  574. def GetMapBoundingBox(self):
  575. """!Get bounding box of (opened) vector map layer
  576. @return (w,s,b,e,n,t)
  577. """
  578. if not self.poMapInfo:
  579. return None
  580. bbox = bound_box()
  581. Vect_get_map_box(self.poMapInfo, byref(bbox))
  582. return bbox.W, bbox.S, bbox.B, \
  583. bbox.E, bbox.N, bbox.T
  584. def Is3D(self):
  585. pass
  586. def SetRegion(self):
  587. pass
  588. def UpdateSettings(self, alpha = 255):
  589. """!Update display driver settings
  590. @todo map units
  591. @alpha color value for aplha channel
  592. """
  593. color = dict()
  594. for key in self.settings.keys():
  595. if key == 'lineWidth':
  596. self.settings[key] = int(UserSettings.Get(group = 'vdigit', key = 'lineWidth',
  597. subkey = 'value'))
  598. continue
  599. color = wx.Color(UserSettings.Get(group = 'vdigit', key = 'symbol',
  600. subkey = [key, 'color'])[0],
  601. UserSettings.Get(group = 'vdigit', key = 'symbol',
  602. subkey = [key, 'color'])[1],
  603. UserSettings.Get(group = 'vdigit', key = 'symbol',
  604. subkey = [key, 'color'])[2])
  605. if key == 'highlight':
  606. self.settings[key] = color
  607. continue
  608. if key == 'highlightDupl':
  609. self.settings[key]['enabled'] = bool(UserSettings.Get(group = 'vdigit', key = 'checkForDupl',
  610. subkey = 'enabled'))
  611. else:
  612. self.settings[key]['enabled'] = bool(UserSettings.Get(group = 'vdigit', key = 'symbol',
  613. subkey = [key, 'enabled']))
  614. self.settings[key]['color'] = color
  615. def UpdateRegion(self):
  616. """!Update geographical region used by display driver
  617. """
  618. self.region = self.mapObj.GetCurrentRegion()
  619. def GetSnapMode(self):
  620. """!Get snapping mode
  621. - snap to vertex
  622. - snap to nodes
  623. - no snapping
  624. @return snap mode
  625. """
  626. threshold = self.GetThreshold()
  627. if threshold > 0.0:
  628. if UserSettings.Get(group = 'vdigit', key = 'snapToVertex', subkey = 'enabled'):
  629. return SNAPVERTEX
  630. else:
  631. return SNAP
  632. else:
  633. return NO_SNAP
  634. def GetThreshold(self, type = 'snapping', value = None, units = None):
  635. """!Return threshold value in map units
  636. @param type snapping mode (node, vertex)
  637. @param value threshold to be set up
  638. @param units units (map, screen)
  639. @return threshold value
  640. """
  641. if value is None:
  642. value = UserSettings.Get(group = 'vdigit', key = type, subkey = 'value')
  643. if units is None:
  644. units = UserSettings.Get(group = 'vdigit', key = type, subkey = 'units')
  645. if value < 0:
  646. value = (self.region['nsres'] + self.region['ewres']) / 2.0
  647. if units == "screen pixels":
  648. # pixel -> cell
  649. res = max(self.region['nsres'], self.region['ewres'])
  650. return value * res
  651. return value