2 @package vdigit.wxdisplay
4 @brief wxGUI vector digitizer (display driver)
6 Code based on wxVdigit C++ component from GRASS 6.4.0
7 (gui/wxpython/vdigit). Converted to Python in 2010/12-2011/01.
10 - wxdisplay::DisplayDriver
12 (C) 2007-2011 by the GRASS Development Team
14 This program is free software under the GNU General Public License
15 (>=v2). Read the file COPYING that comes with GRASS for details.
17 @author Martin Landa <landa.martin gmail.com>
38 """!Redirect stderr"""
48 """!Redirect progress info"""
51 progress.SetValue(value)
57 errtype = CFUNCTYPE(UNCHECKED(c_int), String, c_int)
59 pertype = CFUNCTYPE(UNCHECKED(c_int), c_int)
63 def __init__(self, device, deviceTmp, mapObj, window, glog, gprogress):
64 """!Display driver used by vector digitizer
66 @param device wx.PseudoDC device where to draw vector objects
67 @param deviceTmp wx.PseudoDC device where to draw temporary vector objects
68 @param mapOng Map Object (render.Map)
69 @param windiow parent window for dialogs
70 @param glog logging device (None to discard messages)
71 @param gprogress progress bar device (None to discard message)
73 global errfunc, perfunc, log, progress
78 locale.setlocale(locale.LC_NUMERIC,
'C')
89 self.
region = mapObj.GetCurrentRegion()
111 'highlightDupl' : {
'enabled' :
False,
113 'point' : {
'enabled' :
False,
115 'line' : {
'enabled' :
False,
117 'boundaryNo' : {
'enabled' :
False,
119 'boundaryOne' : {
'enabled' :
False,
121 'boundaryTwo' : {
'enabled' :
False,
123 'centroidIn' : {
'enabled' :
False,
125 'centroidOut' : {
'enabled' :
False,
127 'centroidDup' : {
'enabled' :
False,
129 'nodeOne' : {
'enabled' :
False,
131 'nodeTwo' : {
'enabled' :
False,
133 'vertex' : {
'enabled' :
False,
135 'area' : {
'enabled' :
False,
137 'direction' : {
'enabled' :
False,
151 """!Close currently open vector map"""
161 def _resetTopology(self):
162 """!Reset topology dict
179 def _cell2Pixel(self, east, north, elev):
180 """!Conversion from geographic coordinates (east, north)
185 @param east, north, elev geographical coordinates
187 @return x, y screen coordinates (integer)
190 w = self.
region[
'center_easting'] - (self.mapObj.width / 2) * map_res
191 n = self.
region[
'center_northing'] + (self.mapObj.height / 2) * map_res
193 return int((east - w) / map_res), int((n - north) / map_res)
195 def _drawCross(self, pdc, point, size = 5):
196 """!Draw cross symbol of given size to device content
198 Used for points, nodes, vertices
200 @param[in,out] PseudoDC where to draw
201 @param point coordinates of center
202 @param size size of the cross symbol
205 @return -1 on failure
207 if not pdc
or not point:
210 pdc.DrawLine(point.x - size, point.y, point.x + size, point.y)
211 pdc.DrawLine(point.x, point.y - size, point.x, point.y + size)
215 def _drawObject(self, robj):
216 """!Draw given object to the device
218 The object is defined as robject() from vedit.h.
220 @param robj object to be rendered
223 @return -1 on failure (vector feature marked as dead, etc.)
225 if not self.
dc or not self.
dcTmp:
228 Debug.msg(3,
"_drawObject(): line=%d type=%d npoints=%d", robj.fid, robj.type, robj.npoints)
232 if robj.type == TYPE_AREA:
236 pen = wx.Pen(self.
settings[
'highlightDupl'][
'color'], self.
settings[
'lineWidth'], wx.SOLID)
238 pen = wx.Pen(self.
settings[
'highlight'], self.
settings[
'lineWidth'], wx.SOLID)
253 if robj.type & (TYPE_POINT | TYPE_CENTROIDIN | TYPE_CENTROIDOUT | TYPE_CENTROIDDUP |
254 TYPE_NODEONE | TYPE_NODETWO | TYPE_VERTEX):
256 if robj.type == TYPE_VERTEX:
258 elif robj.type & (TYPE_NODEONE | TYPE_NODETWO):
265 for i
in range(robj.npoints):
277 while i < robj.npoints - 1:
278 point_beg = wx.Point(robj.point[i].x, robj.point[i].y)
279 point_end = wx.Point(robj.point[i+1].x, robj.point[i+1].y)
282 pdc.SetIdBounds(dcId - 1, wx.Rect(point_beg.x, point_beg.y, 0, 0))
283 pdc.SetIdBounds(dcId, wx.RectPP(point_beg, point_end))
284 pdc.DrawLine(point_beg.x, point_beg.y,
285 point_end.x, point_end.y)
288 pdc.SetIdBounds(dcId - 1, wx.Rect(robj.point[robj.npoints - 1].x,
289 robj.point[robj.npoints - 1].y,
293 for i
in range(robj.npoints):
295 points.append(wx.Point(p.x, p.y))
297 if robj.type == TYPE_AREA:
298 pdc.DrawPolygon(points)
300 pdc.DrawLines(points)
302 def _definePen(self, rtype):
303 """!Define pen/brush based on rendered object)
305 Updates also self.topology dict
309 if rtype == TYPE_POINT:
311 elif rtype == TYPE_LINE:
313 elif rtype == TYPE_BOUNDARYNO:
315 elif rtype == TYPE_BOUNDARYTWO:
317 elif rtype == TYPE_BOUNDARYONE:
319 elif rtype == TYPE_CENTROIDIN:
321 elif rtype == TYPE_CENTROIDOUT:
323 elif rtype == TYPE_CENTROIDDUP:
325 elif rtype == TYPE_NODEONE:
327 elif rtype == TYPE_NODETWO:
329 elif rtype == TYPE_VERTEX:
331 elif rtype == TYPE_AREA:
333 elif rtype == TYPE_ISLE:
335 elif rtype == TYPE_DIRECTION:
338 if key
not in (
'direction',
'area',
'isle'):
341 if key
in (
'area',
'isle'):
342 pen = wx.TRANSPARENT_PEN
344 brush = wx.Brush(self.
settings[key][
'color'], wx.SOLID)
346 brush = wx.TRANSPARENT_BRUSH
348 pen = wx.Pen(self.
settings[key][
'color'], self.
settings[
'lineWidth'], wx.SOLID)
353 def _getDrawFlag(self):
354 """!Get draw flag from the settings
356 See vedit.h for list of draw flags.
358 @return draw flag (int)
361 if self.
settings[
'point'][
'enabled']:
363 if self.
settings[
'line'][
'enabled']:
365 if self.
settings[
'boundaryNo'][
'enabled']:
366 ret |= DRAW_BOUNDARYNO
367 if self.
settings[
'boundaryTwo'][
'enabled']:
368 ret |= DRAW_BOUNDARYTWO
369 if self.
settings[
'boundaryOne'][
'enabled']:
370 ret |= DRAW_BOUNDARYONE
371 if self.
settings[
'centroidIn'][
'enabled']:
372 ret |= DRAW_CENTROIDIN
373 if self.
settings[
'centroidOut'][
'enabled']:
374 ret |= DRAW_CENTROIDOUT
375 if self.
settings[
'centroidDup'][
'enabled']:
376 ret |= DRAW_CENTROIDDUP
377 if self.
settings[
'nodeOne'][
'enabled']:
379 if self.
settings[
'nodeTwo'][
'enabled']:
381 if self.
settings[
'vertex'][
'enabled']:
383 if self.
settings[
'area'][
'enabled']:
385 if self.
settings[
'direction'][
'enabled']:
386 ret |= DRAW_DIRECTION
390 def _isSelected(self, line, force = False):
391 """!Check if vector object selected?
393 @param line feature id
395 @return True if vector object is selected
396 @return False if vector object is not selected
403 def _isDuplicated(self, line):
404 """!Check for already marked duplicates
406 @param line feature id
408 @return True line already marked as duplicated
409 @return False not duplicated
411 return line
in self.
selected[
'idsDupl']
413 def _getRegionBox(self):
414 """!Get bound_box() from current region
424 box.T = PORT_DOUBLE_MAX
425 box.B = -PORT_DOUBLE_MAX
430 """!Draw content of the vector map to the device
432 @param force force drawing
433 @return number of drawn features
436 Debug.msg(1,
"DisplayDriver.DrawMap(): force=%d", force)
442 self.
region[
'center_easting'], self.
region[
'center_northing'],
443 self.mapObj.width, self.mapObj.height,
448 self.dc.BeginDrawing()
449 self.dcTmp.BeginDrawing()
452 for i
in range(rlist.nitems):
453 robj = rlist.item[i].contents
457 self.dcTmp.EndDrawing()
464 def _getSelectType(self):
465 """!Get type(s) to be selected
467 Used by SelectLinesByBox() and SelectLineByPoint()
470 for feature
in ((
'point', GV_POINT),
472 (
'centroid', GV_CENTROID),
473 (
'boundary', GV_BOUNDARY)):
474 if UserSettings.Get(group =
'vdigit', key =
'selectType',
475 subkey = [feature[0],
'enabled']):
480 def _validLine(self, line):
481 """!Check if feature id is valid
483 @param line feature id
485 @return True valid feature id
486 @return False invalid
494 """!Select vector objects by given bounding box
496 If line id is already in the list of selected lines, then it will
497 be excluded from this list.
499 @param bbox bounding box definition
500 @param drawSeg True to draw segments of line
501 @param poMapInfo use external Map_info, None for self.poMapInfo
503 @return number of selected features
504 @return None on error
506 thisMapInfo = poMapInfo
is None
534 flist = poList.contents
535 nlines = flist.n_values
536 Debug.msg(1,
"DisplayDriver.SelectLinesByBox() num = %d", nlines)
537 for i
in range(nlines):
538 line = flist.value[i]
539 if UserSettings.Get(group =
'vdigit', key =
'selectInside',
545 points = self.poPoints.contents
546 for p
in range(points.n_points):
566 """!Select vector feature by given point in given
569 Only one vector object can be selected. Bounding boxes of
570 all segments are stores.
572 @param point points coordinates (x, y)
573 @param poMapInfo use external Map_info, None for self.poMapInfo
575 @return dict {'line' : feature id, 'point' : point on line}
577 thisMapInfo = poMapInfo
is None
582 return {
'line' : -1,
'point':
None }
594 Debug.msg(1,
"DisplayDriver.SelectLineByPoint() found = %d", lineNearest)
598 self.
selected[
'ids'].append(lineNearest)
600 self.
selected[
'ids'].remove(lineNearest)
606 return {
'line' : -1,
'point':
None }
608 Vect_line_distance (self.
poPoints, point[0], point[1], 0.0, self.
is3D,
609 byref(px), byref(py), byref(pz),
613 if self.
settings[
'highlightDupl'][
'enabled']:
614 found = poFound.contents
615 for i
in range(found.n_values):
616 line = found.value[i]
617 if line != lineNearest:
622 for i
in range(found.n_values):
623 line = found.value[i]
634 return {
'line' : lineNearest,
635 'point' : (px.value, py.value, pz.value) }
637 def _listToIList(self, plist):
638 """!Generate from list struct_ilist
647 """!Get list of selected objects as struct_ilist
649 Returned IList must be freed by Vect_destroy_list().
659 """!Get ids of selected objects
661 @param grassId True for feature id, False for PseudoDC id
663 @return list of ids of selected vector objects
676 points = self.poPoints.contents
678 for i
in range(1, 2 * points.n_points):
684 """!Set selected vector objects
686 @param list of ids (None to unselect features)
687 @param layer layer number for features selected based on category number
701 for line
in range(1, nlines + 1):
706 if not (ltype & (GV_POINTS | GV_LINES)):
710 cats = self.poCats.contents
711 for i
in range(0, cats.n_cats):
713 if cats.cat[i] == cat:
723 """!Get PseudoDC vertex id of selected line
725 Set bounding box for vertices of line.
729 @return id of center, left and right vertex
730 @return 0 no line found
749 points = self.poPoints.contents
750 for idx
in range(points.n_points):
752 points.x[idx], points.y[idx], points.z[idx], 0)
762 vx, vy = self.
_cell2Pixel(points.x[idx], points.y[idx], points.z[idx])
763 rect = wx.Rect(vx, vy, 0, 0)
764 self.dc.SetIdBounds(DCid, rect)
774 returnId.append(DCid)
779 returnId.append(DCid - 2)
781 if DCid == (points.n_points - 1) * 2 + startId:
784 returnId.append(DCid + 2)
789 """!Get minimal region extent of selected features
793 regionBox = bound_box()
794 lineBox = bound_box()
801 if area > 0
and area <= nareas:
814 return regionBox.N, regionBox.S, regionBox.W, regionBox.E
817 """!Draw selected features
819 @param flag True to draw selected features
827 @return non-zero on error
842 def OpenMap(self, name, mapset, update = True):
843 """!Open vector map by the driver
845 @param name name of vector map to be open
846 @param mapset name of mapset where the vector map lives
849 @return None on error
851 Debug.msg(
"DisplayDriver.OpenMap(): name=%s mapset=%s updated=%d",
852 name, mapset, update)
868 dlg = wx.MessageDialog(parent = self.
window,
869 message = _(
"Topology for vector map <%s> is not available. "
870 "Topology is required by digitizer. Do you want to "
871 "rebuild topology (takes some time) and open the vector map "
872 "for editing?") % name,
873 caption=_(
"Topology missing"),
874 style = wx.YES_NO | wx.YES_DEFAULT | wx.ICON_QUESTION | wx.CENTRE)
875 ret = dlg.ShowModal()
885 """!Get bounding box of (opened) vector map layer
887 @return (w,s,b,e,n,t)
895 return bbox.W, bbox.S, bbox.B, \
896 bbox.E, bbox.N, bbox.T
899 """!Update display driver settings
903 @alpha color value for aplha channel
906 for key
in self.settings.keys():
907 if key ==
'lineWidth':
908 self.
settings[key] = int(UserSettings.Get(group =
'vdigit', key =
'lineWidth',
912 color = wx.Colour(UserSettings.Get(group =
'vdigit', key =
'symbol',
913 subkey = [key,
'color'])[0],
914 UserSettings.Get(group =
'vdigit', key =
'symbol',
915 subkey = [key,
'color'])[1],
916 UserSettings.Get(group =
'vdigit', key =
'symbol',
917 subkey = [key,
'color'])[2],
920 if key ==
'highlight':
924 if key ==
'highlightDupl':
925 self.
settings[key][
'enabled'] = bool(UserSettings.Get(group =
'vdigit', key =
'checkForDupl',
928 self.
settings[key][
'enabled'] = bool(UserSettings.Get(group =
'vdigit', key =
'symbol',
929 subkey = [key,
'enabled']))
934 """!Update geographical region used by display driver
936 self.
region = self.mapObj.GetCurrentRegion()
939 """!Return threshold value in map units
941 @param type snapping mode (node, vertex)
942 @param value threshold to be set up
943 @param units units (map, screen)
945 @return threshold value
948 value = UserSettings.Get(group =
'vdigit', key = type, subkey =
'value')
951 units = UserSettings.Get(group =
'vdigit', key = type, subkey =
'units')
954 value = (self.
region[
'nsres'] + self.
region[
'ewres']) / 2.0
956 if units ==
"screen pixels":
964 """!Return ids of (selected) duplicated vector features
992 self.
selected[
'idsDupl'].append(line1)
995 self.
selected[
'idsDupl'].append(line2)
1002 def _getCatString(self, line):
1005 cats = self.poCats.contents
1007 for i
in range(cats.n_cats):
1008 layer = cats.field[i]
1009 if layer
not in catsDict:
1010 catsDict[layer] = list()
1011 catsDict[layer].append(cats.cat[i])
1014 for l, c
in catsDict.iteritems():
1015 catsStr =
'%d: (%s)' % (l,
','.join(map(str, c)))
1020 """!Unselect vector features
1022 @param lines list of feature id(s)
1024 checkForDupl =
False
def _cell2Pixel
Conversion from geographic coordinates (east, north) to screen (x, y)
def _isSelected
Check if vector object selected?
def _drawCross
Draw cross symbol of given size to device content.
int Vect_destroy_list(struct ilist *list)
Frees all memory associated with a struct ilist, including the struct itself.
def _validLine
Check if feature id is valid.
int G_unset_error_routine(void)
After this call subsequent error messages will be handled in the default method.
def _getRegionBox
Get bound_box() from current region.
def GetSelectedIList
Get list of selected objects as struct_ilist.
def print_progress
Redirect progress info.
def _drawObject
Draw given object to the device.
struct line_pnts * Vect_new_line_struct()
Creates and initializes a struct line_pnts.
def __init__
Display driver used by vector digitizer.
struct ilist * Vect_new_list(void)
Creates and initializes a struct ilist.
def DrawMap
Draw content of the vector map to the device.
int Vect_find_line_list(struct Map_info *map, double ux, double uy, double uz, int type, double maxdist, int with_z, struct ilist *exclude, struct ilist *found)
Find the nearest line(s).
int G_set_error_routine(int(*error_routine)(const char *, int))
Establishes error_routine as the routine that will handle the printing of subsequent error messages...
int Vect_get_num_areas(struct Map_info *map)
Get number of areas in vector map.
def CloseMap
Close vector map.
int Vect_get_area_box(struct Map_info *Map, int area, BOUND_BOX *Box)
Get boundary box of area.
void G_set_percent_routine(int(*percent_routine)(int))
Establishes percent_routine as the routine that will handle the printing of percentage progress messa...
def _isDuplicated
Check for already marked duplicates.
def _resetTopology
Reset topology dict.
int Vect_append_point(struct line_pnts *Points, double x, double y, double z)
Appends one point to the end of a line.
def UnSelect
Unselect vector features.
def SelectLinesByBox
Select vector objects by given bounding box.
def print_error
Redirect stderr.
int Vect_box_extend(BOUND_BOX *A, BOUND_BOX *B)
Extend box A by box B.
def SetSelected
Set selected vector objects.
int Vect_build(struct Map_info *Map)
Build topology for vector map.
def _definePen
Define pen/brush based on rendered object)
def GetThreshold
Return threshold value in map units.
int Vect_open_update(struct Map_info *Map, const char *name, const char *mapset)
Open existing vector for reading/writing.
struct robject_list * Vedit_render_map(struct Map_info *Map, struct bound_box *box, int draw_flag, double center_easting, double center_northing, int map_width, int map_height, double map_res)
Render vector features into list.
int Vect_box_copy(BOUND_BOX *A, BOUND_BOX *B)
Copy box B to box A.
def __del__
Close currently open vector map.
int Vect_destroy_cats_struct(struct line_cats *p)
Frees all memory associated with line_cats structure, including the struct itself.
void G_unset_percent_routine(void)
After this call subsequent percentage progress messages will be handled in the default method...
int Vect_list_append(struct ilist *list, int val)
Append new item to the end of list if not yet present.
int Vect_select_lines_by_polygon(struct Map_info *Map, struct line_pnts *Polygon, int nisles, struct line_pnts **Isles, int type, struct ilist *List)
Select lines by Polygon with optional isles.
def UpdateSettings
Update display driver settings.
int Vect_get_map_box(struct Map_info *Map, BOUND_BOX *Box)
Get boundary box of map.
def OpenMap
Open vector map by the driver.
int Vect_open_old(struct Map_info *Map, const char *name, const char *mapset)
Open existing vector for reading.
int Vect_line_alive(struct Map_info *Map, int line)
Check if feature is alive or dead.
def _getDrawFlag
Get draw flag from the settings.
int Vect_close(struct Map_info *Map)
Close vector data file.
int Vect_point_in_poly(double X, double Y, struct line_pnts *Points)
Determines if a point (X,Y) is inside a polygon.
struct line_cats * Vect_new_cats_struct()
Creates and initializes line_cats structure.
int Vect_get_num_lines(struct Map_info *map)
Fetch number of features (points, lines, boundaries, centroids) in vector map.
int Vect_line_check_duplicate(const struct line_pnts *APoints, const struct line_pnts *BPoints, int with_z)
Check for duplicate lines.
def _getSelectType
Get type(s) to be selected.
double Vect_points_distance(double x1, double y1, double z1, double x2, double y2, double z2, int with_z)
Calculate distance of 2 points.
def SelectLineByPoint
Select vector feature by given point in given threshold.
int Vect_get_centroid_area(struct Map_info *Map, int centroid)
Get area id the centroid is within.
int Vect_get_line_box(struct Map_info *Map, int line, BOUND_BOX *Box)
Get boundary box of line.
def GetSelectedVertex
Get PseudoDC vertex id of selected line.
def GetSelected
Get ids of selected objects.
def DrawSelected
Draw selected features.
def GetDuplicates
Return ids of (selected) duplicated vector features.
def _listToIList
Generate from list struct_ilist.
def UpdateRegion
Update geographical region used by display driver.
def GetRegionSelected
Get minimal region extent of selected features.
def GetMapBoundingBox
Get bounding box of (opened) vector map layer.
int Vect_build_partial(struct Map_info *Map, int build)
Build partial topology for vector map.
int Vect_destroy_line_struct(struct line_pnts *p)
Frees all memory associated with a struct line_pnts, including the struct itself. ...
int Vect_read_line(struct Map_info *Map, struct line_pnts *line_p, struct line_cats *line_c, int line)
Read vector feature.