-
Notifications
You must be signed in to change notification settings - Fork 2
/
Copy pathautoTrace.py
187 lines (148 loc) · 6.96 KB
/
autoTrace.py
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
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
# -*- coding: utf-8 -*-
# AutoTrace - An editing tool for QGIS that allows users to 'trace' new
# feature geometry based on existing features.
# Copyright (C) 2012 Peter Wells for Lutra Consulting
# Based on traceDigitize by Cédric Möri with lots of stuff from Stefan
# Ziegler (CAD-Tools)
# peter dot wells at lutraconsulting dot co dot uk
# Lutra Consulting
# 23 Chestnut Close
# Burgess Hill
# West Sussex
# RH15 8HN
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2
# of the License, or (at your option) any later version.
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
from PyQt4.QtCore import *
from PyQt4.QtGui import *
from qgis.core import *
from qgis.gui import *
# initialize Qt resources from file resources.py
import resources
#Import own tools
from vertexTracerTool import VertexTracerTool
# Our main class for the plugin
class AutoTrace:
def __init__(self, iface):
# Save reference to the QGIS interface
self.iface = iface
self.canvas = self.iface.mapCanvas()
def initGui(self):
mc = self.canvas
layer = mc.currentLayer()
self.rubberBand = 0
# Create an action for getting help
self.helpAction = QAction(QIcon(":/plugins/autoTrace/iconAutoTrace.png"), "Help", self.iface.mainWindow())
QObject.connect(self.helpAction, SIGNAL("triggered()"), self.openHelp)
self.menu = self.iface.pluginMenu().addMenu(QIcon(":/plugins/autoTrace/iconAutoTrace.png"), "AutoTrace")
self.menu.addAction(self.helpAction)
# Create action that will start plugin configuration
self.action = QAction(QIcon(":/plugins/autoTrace/iconAutoTrace.png"), "Auto-trace", self.iface.mainWindow())
self.action.setEnabled(False)
self.action.setCheckable(True)
self.action.setChecked(False)
#Connect to signals for button behaviour
QObject.connect(self.action, SIGNAL("triggered()"), self.run)
QObject.connect(self.iface, SIGNAL("currentLayerChanged(QgsMapLayer*)"), self.toggle)
QObject.connect(mc, SIGNAL("mapToolSet(QgsMapTool*)"), self.deactivate)
# Add toolbar button
self.iface.digitizeToolBar().addAction(self.action)
#Get the Tool
self.tool = VertexTracerTool(self.canvas)
def unload(self):
self.iface.digitizeToolBar().removeAction(self.action)
self.menu.removeAction(self.helpAction)
self.iface.pluginMenu().removeAction(self.menu.menuAction())
def openHelp(self):
# Open the help page
QDesktopServices.openUrl(QUrl('http://www.lutraconsulting.co.uk/resources/autotrace'))
def toggle(self):
mc = self.canvas
layer = mc.currentLayer()
#Decide whether the plugin button/menu is enabled or disabled
if layer <> None:
if layer.isEditable() and (layer.geometryType() == 1 or layer.geometryType() == 2):
self.action.setEnabled(True)
QObject.connect(layer,SIGNAL("editingStopped()"),self.toggle)
QObject.disconnect(layer,SIGNAL("editingStarted()"),self.toggle)
else:
self.action.setEnabled(False)
QObject.connect(layer,SIGNAL("editingStarted()"),self.toggle)
QObject.disconnect(layer,SIGNAL("editingStopped()"),self.toggle)
def deactivate(self):
#uncheck the button/menu and get rid off the VTTool signal
self.action.setChecked(False)
QObject.disconnect(self.tool, SIGNAL("traceFound(PyQt_PyObject)"), self.createFeature)
def run(self):
#Here we go...
mc = self.canvas
layer = mc.currentLayer()
#bring our tool into action
mc.setMapTool(self.tool)
self.action.setChecked(True)
#Connect to the VTtool
QObject.connect(self.tool, SIGNAL("traceFound(PyQt_PyObject)"), self.createFeature)
# Warn if there are no snapable layers
if self.snappableLayerCount() < 1:
self.iface.messageBar().pushMessage("AutoTrace", \
"None of the enabled layers have snapping enabled - AutoTrace needs snappable layers in order to trace.", level=QgsMessageBar.WARNING)
def snappableLayerCount(self):
count = 0
proj = QgsProject.instance()
for layer in self.iface.mapCanvas().layers(): # Visible layers
if proj.snapSettingsForLayer( layer.id() )[1]:
count += 1
return count
def createFeature(self, geom):
if not geom:
return False # invalid geometry (e.g. just one point for a polyline)
layer = self.canvas.currentLayer()
provider = layer.dataProvider()
fields = provider.fields()
f = QgsFeature(fields)
errors = geom.validateGeometry()
if len(errors) == 0:
f.setGeometry(geom)
else:
# Concatenate errors into a string
errorsString = ""
for error in errors:
locationString = "[" + str(error.where().x()) + "," + str(error.where().y()) + "]"
errorsString += error.what()
errorsString += "\n "
errorsString += locationString
errorsString += "\n"
reply = QMessageBox.question(self.iface.mainWindow(), 'Feature not valid',
"The geometry of the feature you just added isn't valid. Do you want to use it anyway?\n\n" +
"Errors were:\n\n" +
errorsString,
QMessageBox.Yes, QMessageBox.No)
if reply == QMessageBox.Yes:
f.setGeometry(geom)
else:
return False
# this is the preferred way of adding features in QGIS >= 2.4
# it respects default values, suppression of attribute form, reuse of recent values etc.
if QGis.QGIS_VERSION_INT >= 20400:
if self.iface.vectorLayerTools().addFeature(layer, {}, geom):
self.canvas.refresh()
return True
else:
return False
# compatibility code for older versions: QGIS < 2.4
layer.beginEditCommand("Feature added")
layer.addFeature(f)
# let the user set some attributes
if not self.iface.openFeatureForm(layer, f):
layer.destroyEditCommand()
return False
layer.endEditCommand()
self.canvas.refresh()