File: drawshape.py

package info (click to toggle)
thuban 1.2.2-2
  • links: PTS, VCS
  • area: main
  • in suites: squeeze
  • size: 7,596 kB
  • ctags: 5,301
  • sloc: python: 30,411; ansic: 6,181; xml: 4,127; cpp: 1,595; makefile: 166; sh: 101
file content (155 lines) | stat: -rw-r--r-- 5,068 bytes parent folder | download | duplicates (5)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
# Copyright (C) 2003 by Intevation GmbH
# Authors:
# Bernhard Herzog <bh@intevation.de>
#
# This program is free software under the GPL (>=v2)
# Read the file COPYING coming with the software for details.

"""Extension to draw polygons

*** Warning: ***

This extension is very experimental and may corrupt your data. Use at
your own peril.
"""

__version__ = "$Revision: 2746 $"
# $Source$
# $Id: drawshape.py 2746 2007-03-17 13:31:31Z dpinte $


import os

import wx

import shapelib
import Thuban
from Thuban import _
from Thuban.Model.data import SHAPETYPE_POLYGON
from Thuban.Model.table import FIELDTYPE_INT, FIELDTYPE_STRING, \
     FIELDTYPE_DOUBLE
from Thuban.UI.command import registry, ToolCommand
from Thuban.UI.mainwindow import main_menu, main_toolbar
from Thuban.UI.viewport import Tool


def write_empty_row(table, row):
    """Write an empty record to the row

    The values in the record will be set to suitable default values
    depending on the type: 0 for numeric types and the empty string for
    strings.
    """
    values = {}
    for col in table.Columns():
        if col.type == FIELDTYPE_INT:
            value = 0
        elif col.type == FIELDTYPE_DOUBLE:
            value = 0.0
        elif col.type == FIELDTYPE_STRING:
            value = ""
        else:
            print "write_empty_row: Unhandled col.type", col.type
        values[col.name] = value
    table.write_record(row, values)


def write_shape(shapestore, points):
    """Addd the points as a new shape to the shapestore

    The points argument should be a list of the same structure as that
    returned by the shapelib bindings for a polygon. It is passed
    directly to the SHPObject constructor.
    """
    shapefile = shapelib.ShapeFile(shapestore.FileName(), "r+b")
    obj = shapelib.SHPObject(shapelib.SHPT_POLYGON, 1, points)
    newid = shapefile.write_object(-1, obj)
    write_empty_row(shapestore.Table(), newid)
    shapefile.close()
    shapestore._open_shapefile()


class ShapeDrawTool(Tool):

    def __init__(self, view):
        Tool.__init__(self, view)
        self.points = []

    def Name(self):
        return "ShapeDrawTool"

    def find_shapestore(self):
        """Return the shapestore into which to write and the projection

        If the currently selected layer is a layer with polygons return
        a tuple of the shapestore and the layer's projection.
        Otherwise return a tuple of Nones.
        """
        layer = self.view.SelectedLayer()
        if layer is not None and layer.HasShapes() \
               and layer.ShapeType() == SHAPETYPE_POLYGON:
            return layer.ShapeStore(), layer.GetProjection()
        return None, None

    def MouseDown(self, event):
        Tool.MouseDown(self, event)
        if event.RightDown():
            map_proj = self.view.Map().GetProjection()
            shapestore, proj = self.find_shapestore()
            if shapestore is not None and len(self.points) > 2:
                points = self.points[:]
                if map_proj is not None:
                    points = [tuple(map_proj.Inverse(*p)) for p in points]
                if proj is not None:
                    points = [tuple(proj.Forward(*p)) for p in points]
                points.append(points[0])
                write_shape(shapestore, [points])
                self.points = []
                self.view.full_redraw()
        else:
            if not self.points:
                self.points.append(self.view.win_to_proj(*self.current))

    def MouseUp(self, event):
        Tool.MouseUp(self, event)
        self.points.append(self.view.win_to_proj(*self.current))

    def draw(self, dc):
        points = [self.view.proj_to_win(*p) for p in self.points] \
                 + [self.current]
        if len(points) == 2:
            dc.DrawLines(points)
        else:
            dc.DrawPolygon(points)

    def DrawPermanent(self, dc):
        dc.SetPen(wx.Pen(wx.Color(255, 128, 0), 2))
        dc.SetBrush(wx.TRANSPARENT_BRUSH)
        dc.DrawPolygon([self.view.proj_to_win(*p) for p in self.points])


def shape_draw_tool(context):
    canvas = context.mainwindow.canvas
    canvas.SelectTool(ShapeDrawTool(canvas))

def check_shape_draw_tool(context):
    return context.mainwindow.canvas.CurrentTool() == "ShapeDrawTool"


iconfile = os.path.join(os.path.abspath(Thuban.__path__[0]),
                        "..", "Resources", "Bitmaps", "identify")
registry.Add(ToolCommand("shape_draw_tool", "Shape Draw Tool",
                         shape_draw_tool, icon = iconfile,
                         helptext = "Draw a shape",
                         checked = check_shape_draw_tool))

# Add the command to the toolbar
main_toolbar.InsertSeparator()
main_toolbar.InsertItem("shape_draw_tool")

# find the experimental menu (create it anew if not found)
experimental_menu = main_menu.FindOrInsertMenu('experimental',
                                               _('Experimenta&l'))

# finally add the new command to the experimental menu
experimental_menu.InsertItem('shape_draw_tool')