|
| 1 | +# -*- coding: utf-8 -*- |
1 | 2 | #-----------------------------------------------------------
|
2 | 3 | #
|
3 | 4 | # Generate Random Points
|
@@ -47,213 +48,218 @@ def __init__(self, iface):
|
47 | 48 | QObject.connect(self.inShape, SIGNAL("currentIndexChanged(QString)"), self.update)
|
48 | 49 | self.progressBar.setValue(0)
|
49 | 50 | self.setWindowTitle(self.tr("Random Points"))
|
50 |
| - mapCanvas = self.iface.mapCanvas() |
51 |
| - for i in range(mapCanvas.layerCount()): |
52 |
| - layer = mapCanvas.layer(i) |
| 51 | + self.mapCanvas = self.iface.mapCanvas() |
| 52 | + for i in range(self.mapCanvas.layerCount()): |
| 53 | + layer = self.mapCanvas.layer(i) |
53 | 54 | if (layer.type() == layer.VectorLayer and layer.geometryType() == QGis.Polygon) or layer.type() == layer.RasterLayer:
|
54 |
| - self.inShape.addItem(layer.name()) |
| 55 | + self.inShape.addItem(layer.name()) |
55 | 56 |
|
56 |
| -# If input layer is changed, update field list |
| 57 | +# If input layer is changed, update field list |
57 | 58 | def update(self, inputLayer):
|
58 | 59 | self.cmbField.clear()
|
59 | 60 | changedLayer = self.getMapLayerByName(inputLayer)
|
60 | 61 | if changedLayer.type() == changedLayer.VectorLayer:
|
61 |
| - self.rdoStratified.setEnabled(True) |
62 |
| - self.rdoDensity.setEnabled(True) |
63 |
| - self.rdoField.setEnabled(True) |
64 |
| - self.label_4.setEnabled(True) |
65 |
| - changedLayer = self.getVectorLayerByName(inputLayer) |
66 |
| - changedFields = self.getFieldList(changedLayer) |
67 |
| - for i in changedFields: |
68 |
| - self.cmbField.addItem(unicode(changedFields[i].name())) |
| 62 | + self.rdoStratified.setEnabled(True) |
| 63 | + self.rdoDensity.setEnabled(True) |
| 64 | + self.rdoField.setEnabled(True) |
| 65 | + self.label_4.setEnabled(True) |
| 66 | + changedLayer = self.getVectorLayerByName(inputLayer) |
| 67 | + changedFields = self.getFieldList(changedLayer) |
| 68 | + for i in changedFields: |
| 69 | + self.cmbField.addItem(unicode(changedFields[i].name())) |
69 | 70 | else:
|
70 |
| - self.rdoUnstratified.setChecked(True) |
71 |
| - self.rdoStratified.setEnabled(False) |
72 |
| - self.rdoDensity.setEnabled(False) |
73 |
| - self.rdoField.setEnabled(False) |
74 |
| - self.spnStratified.setEnabled(False) |
75 |
| - self.spnDensity.setEnabled(False) |
76 |
| - self.cmbField.setEnabled(False) |
77 |
| - self.label_4.setEnabled(False) |
| 71 | + self.rdoUnstratified.setChecked(True) |
| 72 | + self.rdoStratified.setEnabled(False) |
| 73 | + self.rdoDensity.setEnabled(False) |
| 74 | + self.rdoField.setEnabled(False) |
| 75 | + self.spnStratified.setEnabled(False) |
| 76 | + self.spnDensity.setEnabled(False) |
| 77 | + self.cmbField.setEnabled(False) |
| 78 | + self.label_4.setEnabled(False) |
78 | 79 |
|
79 | 80 | # when 'OK' button is pressed, gather required inputs, and initiate random points generation
|
80 | 81 | def accept(self):
|
81 |
| - if self.inShape.currentText() == "": |
82 |
| - QMessageBox.information(self, self.tr("Random Points"), self.tr("No input layer specified")) |
83 |
| - elif self.outShape.text() == "": |
84 |
| - QMessageBox.information(self, self.tr("Random Points"), self.tr("Please specify output shapefile")) |
85 |
| - else: |
86 |
| - inName = self.inShape.currentText() |
87 |
| - self.progressBar.setValue(1) |
88 |
| - outPath = self.outShape.text() |
89 |
| - self.progressBar.setValue(2.5) |
90 |
| - if outPath.contains("\\"): |
91 |
| - outName = outPath.right((outPath.length() - outPath.lastIndexOf("\\")) - 1) |
92 |
| - else: |
93 |
| - outName = outPath.right((outPath.length() - outPath.lastIndexOf("/")) - 1) |
94 |
| - if outName.endsWith(".shp"): |
95 |
| - outName = outName.left(outName.length() - 4) |
96 |
| - self.progressBar.setValue(5) |
97 |
| - mLayer = self.getMapLayerByName(unicode(inName)) |
98 |
| - if mLayer.type() == mLayer.VectorLayer: |
99 |
| - inLayer = QgsVectorLayer(unicode(mLayer.source(),'latin1'), unicode(mLayer.name(),'latin1'), unicode(mLayer.dataProvider().name())) |
100 |
| - if self.rdoUnstratified.isChecked(): |
101 |
| - design = self.tr("unstratified") |
102 |
| - value = self.spnUnstratified.value() |
103 |
| - elif self.rdoStratified.isChecked(): |
104 |
| - design = self.tr("stratified") |
105 |
| - value = self.spnStratified.value() |
106 |
| - elif self.rdoDensity.isChecked(): |
107 |
| - design = self.tr("density") |
108 |
| - value = self.spnDensity.value() |
109 |
| - else: |
110 |
| - design = self.tr("field") |
111 |
| - value = unicode(self.cmbField.currentText()) |
112 |
| - elif mLayer.type() == mLayer.RasterLayer: |
113 |
| - inLayer = QgsRasterLayer(unicode(mLayer.source(),'latin1'), unicode(mLayer.name(),'latin1')) |
114 |
| - design = self.tr("unstratified") |
115 |
| - value = self.spnUnstratified.value() |
116 |
| - else: |
117 |
| - QMessageBox.information(self, self.tr("Random Points"), self.tr("Unknown layer type...")) |
118 |
| - if self.chkMinimum.isChecked(): |
119 |
| - minimum = self.spnMinimum.value() |
120 |
| - else: |
121 |
| - minimum = 0.00 |
122 |
| - self.progressBar.setValue(10) |
123 |
| - self.randomize(inLayer, outPath, minimum, design, value, self.progressBar) |
124 |
| - self.progressBar.setValue(100) |
125 |
| - self.outShape.clear() |
126 |
| - addToTOC = QMessageBox.question(self, self.tr("Random Points"), self.tr("Created output point shapefile:\n%1\n\nWould you like to add the new layer to the TOC?").arg(outPath), QMessageBox.Yes, QMessageBox.No, QMessageBox.NoButton) |
127 |
| - if addToTOC == QMessageBox.Yes: |
128 |
| - self.vlayer = QgsVectorLayer(outPath, unicode(outName), "ogr") |
129 |
| - QgsMapLayerRegistry.instance().addMapLayer(self.vlayer) |
130 |
| - self.progressBar.setValue(0) |
| 82 | + if self.inShape.currentText() == "": |
| 83 | + QMessageBox.information(self, self.tr("Random Points"), self.tr("No input layer specified")) |
| 84 | + elif self.outShape.text() == "": |
| 85 | + QMessageBox.information(self, self.tr("Random Points"), self.tr("Please specify output shapefile")) |
| 86 | + else: |
| 87 | + inName = self.inShape.currentText() |
| 88 | + self.progressBar.setValue(1) |
| 89 | + outPath = self.outShape.text() |
| 90 | + self.progressBar.setValue(2.5) |
| 91 | + if outPath.contains("\\"): |
| 92 | + outName = outPath.right((outPath.length() - outPath.lastIndexOf("\\")) - 1) |
| 93 | + else: |
| 94 | + outName = outPath.right((outPath.length() - outPath.lastIndexOf("/")) - 1) |
| 95 | + if outName.endsWith(".shp"): |
| 96 | + outName = outName.left(outName.length() - 4) |
| 97 | + self.progressBar.setValue(5) |
| 98 | + mLayer = self.getMapLayerByName(unicode(inName)) |
| 99 | + if mLayer.type() == mLayer.VectorLayer: |
| 100 | + inLayer = QgsVectorLayer(unicode(mLayer.source()), unicode(mLayer.name()), unicode(mLayer.dataProvider().name())) |
| 101 | + if self.rdoUnstratified.isChecked(): |
| 102 | + design = self.tr("unstratified") |
| 103 | + value = self.spnUnstratified.value() |
| 104 | + elif self.rdoStratified.isChecked(): |
| 105 | + design = self.tr("stratified") |
| 106 | + value = self.spnStratified.value() |
| 107 | + elif self.rdoDensity.isChecked(): |
| 108 | + design = self.tr("density") |
| 109 | + value = self.spnDensity.value() |
| 110 | + else: |
| 111 | + design = self.tr("field") |
| 112 | + value = unicode(self.cmbField.currentText()) |
| 113 | + elif mLayer.type() == mLayer.RasterLayer: |
| 114 | + inLayer = QgsRasterLayer(unicode(mLayer.source()), unicode(mLayer.name())) |
| 115 | + design = self.tr("unstratified") |
| 116 | + value = self.spnUnstratified.value() |
| 117 | + else: |
| 118 | + QMessageBox.information(self, self.tr("Random Points"), self.tr("Unknown layer type...")) |
| 119 | + if self.chkMinimum.isChecked(): |
| 120 | + minimum = self.spnMinimum.value() |
| 121 | + else: |
| 122 | + minimum = 0.00 |
| 123 | + self.progressBar.setValue(10) |
| 124 | + self.randomize(inLayer, outPath, minimum, design, value) |
| 125 | + self.progressBar.setValue(100) |
| 126 | + self.outShape.clear() |
| 127 | + addToTOC = QMessageBox.question(self, self.tr("Random Points"), |
| 128 | + self.tr("Created output point shapefile:\n%1\n\nWould you like to add the new layer to the TOC?").arg(outPath), QMessageBox.Yes, QMessageBox.No, QMessageBox.NoButton) |
| 129 | + if addToTOC == QMessageBox.Yes: |
| 130 | + self.vlayer = QgsVectorLayer(outPath, unicode(outName), "ogr") |
| 131 | + QgsMapLayerRegistry.instance().addMapLayer(self.vlayer) |
| 132 | + self.progressBar.setValue(0) |
131 | 133 |
|
132 | 134 | def outFile(self):
|
133 |
| - self.outShape.clear() |
134 |
| - ( self.shapefileName, self.encoding ) = ftools_utils.saveDialog( self ) |
135 |
| - if self.shapefileName is None or self.encoding is None: |
136 |
| - return |
137 |
| - self.outShape.setText( QString( self.shapefileName ) ) |
138 |
| - |
| 135 | + self.outShape.clear() |
| 136 | + ( self.shapefileName, self.encoding ) = ftools_utils.saveDialog( self ) |
| 137 | + if self.shapefileName is None or self.encoding is None: |
| 138 | + return |
| 139 | + self.outShape.setText( QString( self.shapefileName ) ) |
| 140 | + |
139 | 141 | # combine all polygons in layer to create single polygon (slow for complex polygons)
|
140 |
| - def createSinglePolygon(self, vlayer, progressBar): |
141 |
| - provider = vlayer.dataProvider() |
142 |
| - allAttrs = provider.attributeIndexes() |
143 |
| - provider.select(allAttrs) |
144 |
| - feat = QgsFeature() |
145 |
| - geom = QgsGeometry() |
146 |
| - geom2 = QgsGeometry() |
147 |
| - provider.nextFeature(feat) |
148 |
| - geom = feat.geometry() |
149 |
| - count = 10.00 |
150 |
| - add = 40.00 / provider.featureCount() |
151 |
| - provider.rewind() |
152 |
| - provider.nextFeature(feat) |
153 |
| - geom = QgsGeometry(feat.geometry()) |
154 |
| - while provider.nextFeature(feat): |
155 |
| - geom = geom.combine(QgsGeometry( feat.geometry() )) |
156 |
| - count = count + add |
157 |
| - progressBar.setValue(count) |
158 |
| - return geom |
159 |
| - |
| 142 | + def createSinglePolygon(self, vlayer): |
| 143 | + provider = vlayer.dataProvider() |
| 144 | + allAttrs = provider.attributeIndexes() |
| 145 | + provider.select(allAttrs) |
| 146 | + feat = QgsFeature() |
| 147 | + geom = QgsGeometry() |
| 148 | + geom2 = QgsGeometry() |
| 149 | + provider.nextFeature(feat) |
| 150 | + geom = feat.geometry() |
| 151 | + count = 10.00 |
| 152 | + add = ( 40.00 - 10.00 ) / provider.featureCount() |
| 153 | + provider.rewind() |
| 154 | + provider.nextFeature(feat) |
| 155 | + geom = QgsGeometry(feat.geometry()) |
| 156 | + while provider.nextFeature(feat): |
| 157 | + geom = geom.combine(QgsGeometry( feat.geometry() )) |
| 158 | + count = count + add |
| 159 | + self.progressBar.setValue(count) |
| 160 | + return geom |
| 161 | + |
160 | 162 | # Generate list of random points
|
161 | 163 | def simpleRandom(self, n, bound, xmin, xmax, ymin, ymax):
|
162 |
| - seed() |
163 |
| - points = [] |
164 |
| - i = 1 |
165 |
| - while i <= n: |
166 |
| - pGeom = QgsGeometry().fromPoint(QgsPoint(xmin + (xmax-xmin) * random(), ymin + (ymax-ymin) * random())) |
167 |
| - if pGeom.intersects(bound): |
168 |
| - points.append(pGeom) |
169 |
| - i = i + 1 |
170 |
| - return points |
171 |
| - |
| 164 | + seed() |
| 165 | + points = [] |
| 166 | + i = 1 |
| 167 | + count = 40.00 |
| 168 | + add = ( 70.00 - 40.00 ) / n |
| 169 | + while i <= n: |
| 170 | + pGeom = QgsGeometry().fromPoint(QgsPoint(xmin + (xmax-xmin) * random(), ymin + (ymax-ymin) * random())) |
| 171 | + if pGeom.intersects(bound): |
| 172 | + points.append(pGeom) |
| 173 | + i = i + 1 |
| 174 | + count = count + add |
| 175 | + self.progressBar.setValue(count) |
| 176 | + return points |
| 177 | + |
172 | 178 | # Get vector layer by name from TOC
|
173 | 179 | def getVectorLayerByName(self, myName):
|
174 |
| - mc = self.iface.mapCanvas() |
175 |
| - nLayers = mc.layerCount() |
176 |
| - for l in range(nLayers): |
177 |
| - layer = mc.layer(l) |
178 |
| - if layer.name() == unicode(myName): |
179 |
| - vlayer = QgsVectorLayer(unicode(layer.source()), unicode(myName), unicode(layer.dataProvider().name())) |
180 |
| - if vlayer.isValid(): |
181 |
| - return vlayer |
182 |
| - else: |
183 |
| - QMessageBox.information(self, self.tr("Generate Centroids"), self.tr("Vector layer is not valid")) |
184 |
| - |
| 180 | + mc = self.mapCanvas |
| 181 | + nLayers = mc.layerCount() |
| 182 | + for l in range(nLayers): |
| 183 | + layer = mc.layer(l) |
| 184 | + if layer.name() == unicode(myName): |
| 185 | + vlayer = QgsVectorLayer(unicode(layer.source()), unicode(myName), unicode(layer.dataProvider().name())) |
| 186 | + if vlayer.isValid(): |
| 187 | + return vlayer |
| 188 | + else: |
| 189 | + QMessageBox.information(self, self.tr("Random Points"), self.tr("Vector layer is not valid")) |
| 190 | + |
185 | 191 | # Get map layer by name from TOC
|
186 | 192 | def getMapLayerByName(self, myName):
|
187 |
| - mc = self.iface.mapCanvas() |
188 |
| - nLayers = mc.layerCount() |
189 |
| - for l in range(nLayers): |
190 |
| - layer = mc.layer(l) |
191 |
| - if layer.name() == unicode(myName): |
192 |
| - if layer.isValid(): |
193 |
| - return layer |
| 193 | + mc = self.mapCanvas |
| 194 | + nLayers = mc.layerCount() |
| 195 | + for l in range(nLayers): |
| 196 | + layer = mc.layer(l) |
| 197 | + if layer.name() == unicode(myName): |
| 198 | + if layer.isValid(): |
| 199 | + return layer |
194 | 200 | # Retrieve the field map of a vector Layer
|
195 | 201 | def getFieldList(self, vlayer):
|
196 |
| - fProvider = vlayer.dataProvider() |
197 |
| - feat = QgsFeature() |
198 |
| - allAttrs = fProvider.attributeIndexes() |
199 |
| - fProvider.select(allAttrs) |
200 |
| - myFields = fProvider.fields() |
201 |
| - return myFields |
202 |
| - |
203 |
| - |
204 |
| - def randomize(self, inLayer, outPath, minimum, design, value, progressBar): |
205 |
| - outFeat = QgsFeature() |
206 |
| - if design == self.tr("unstratified"): |
207 |
| - ext = inLayer.extent() |
208 |
| - if inLayer.type() == inLayer.RasterLayer: bound = ext |
209 |
| - else: bound = self.createSinglePolygon(inLayer, progressBar) |
210 |
| - points = self.simpleRandom(int(value), bound, ext.xMinimum(), ext.xMaximum(), ext.yMinimum(), ext.yMaximum()) |
211 |
| - progressBar.setValue(70) |
212 |
| - else: points = self.loopThruPolygons(inLayer, value, design, progressBar) |
| 202 | + fProvider = vlayer.dataProvider() |
| 203 | + feat = QgsFeature() |
| 204 | + allAttrs = fProvider.attributeIndexes() |
| 205 | + fProvider.select(allAttrs) |
| 206 | + myFields = fProvider.fields() |
| 207 | + return myFields |
| 208 | + |
213 | 209 |
|
214 |
| - fields = { 0 : QgsField("ID", QVariant.Int) } |
215 |
| - check = QFile(self.shapefileName) |
216 |
| - if check.exists(): |
217 |
| - if not QgsVectorFileWriter.deleteShapeFile(self.shapefileName): |
218 |
| - return |
219 |
| - writer = QgsVectorFileWriter(self.shapefileName, self.encoding, fields, QGis.WKBPoint, None) |
220 |
| - idVar = 0 |
221 |
| - count = 70.00 |
222 |
| - add = 30.00 / len(points) |
223 |
| - for i in points: |
224 |
| - outFeat.setGeometry(i) |
225 |
| - outFeat.addAttribute(0, QVariant(idVar)) |
226 |
| - writer.addFeature(outFeat) |
227 |
| - idVar = idVar + 1 |
228 |
| - count = count + add |
229 |
| - progressBar.setValue(count) |
230 |
| - del writer |
231 |
| - |
| 210 | + def randomize(self, inLayer, outPath, minimum, design, value): |
| 211 | + outFeat = QgsFeature() |
| 212 | + if design == self.tr("unstratified"): |
| 213 | + ext = inLayer.extent() |
| 214 | + if inLayer.type() == inLayer.RasterLayer: bound = ext |
| 215 | + else: bound = self.createSinglePolygon(inLayer) |
| 216 | + points = self.simpleRandom(int(value), bound, ext.xMinimum(), ext.xMaximum(), ext.yMinimum(), ext.yMaximum()) |
| 217 | + else: points = self.loopThruPolygons(inLayer, value, design) |
| 218 | + crs = self.mapCanvas.mapRenderer().destinationSrs() |
| 219 | + if not crs.isValid(): crs = None |
| 220 | + fields = { 0 : QgsField("ID", QVariant.Int) } |
| 221 | + check = QFile(self.shapefileName) |
| 222 | + if check.exists(): |
| 223 | + if not QgsVectorFileWriter.deleteShapeFile(self.shapefileName): |
| 224 | + return |
| 225 | + writer = QgsVectorFileWriter(self.shapefileName, self.encoding, fields, QGis.WKBPoint, crs) |
| 226 | + idVar = 0 |
| 227 | + count = 70.00 |
| 228 | + add = ( 100.00 - 70.00 ) / len(points) |
| 229 | + for i in points: |
| 230 | + outFeat.setGeometry(i) |
| 231 | + outFeat.addAttribute(0, QVariant(idVar)) |
| 232 | + writer.addFeature(outFeat) |
| 233 | + idVar = idVar + 1 |
| 234 | + count = count + add |
| 235 | + self.progressBar.setValue(count) |
| 236 | + del writer |
| 237 | + |
232 | 238 | #
|
233 |
| - def loopThruPolygons(self, inLayer, numRand, design, progressBar): |
234 |
| - sProvider = inLayer.dataProvider() |
235 |
| - sAllAttrs = sProvider.attributeIndexes() |
236 |
| - sProvider.select(sAllAttrs) |
237 |
| - sFeat = QgsFeature() |
238 |
| - sGeom = QgsGeometry() |
239 |
| - sPoints = [] |
240 |
| - if design == "field": |
241 |
| - for (i, attr) in sProvider.fields().iteritems(): |
242 |
| - if (unicode(numRand) == attr.name()): index = i #get input field index |
243 |
| - count = 10.00 |
244 |
| - add = 60.00 / sProvider.featureCount() |
245 |
| - while sProvider.nextFeature(sFeat): |
246 |
| - sGeom = sFeat.geometry() |
247 |
| - if design == self.tr("density"): |
248 |
| - sDistArea = QgsDistanceArea() |
249 |
| - value = int(round(numRand * sDistArea.measure(sGeom))) |
250 |
| - elif design == self.tr("field"): |
251 |
| - sAtMap = sFeat.attributeMap() |
252 |
| - value = sAtMap[index].toInt()[0] |
253 |
| - else: |
254 |
| - value = numRand |
255 |
| - sExt = sGeom.boundingBox() |
256 |
| - sPoints.extend(self.simpleRandom(value, sGeom, sExt.xMinimum(), sExt.xMaximum(), sExt.yMinimum(), sExt.yMaximum())) |
257 |
| - count = count + add |
258 |
| - progressBar.setValue(count) |
259 |
| - return sPoints |
| 239 | + def loopThruPolygons(self, inLayer, numRand, design): |
| 240 | + sProvider = inLayer.dataProvider() |
| 241 | + sAllAttrs = sProvider.attributeIndexes() |
| 242 | + sProvider.select(sAllAttrs) |
| 243 | + sFeat = QgsFeature() |
| 244 | + sGeom = QgsGeometry() |
| 245 | + sPoints = [] |
| 246 | + if design == "field": |
| 247 | + for (i, attr) in sProvider.fields().iteritems(): |
| 248 | + if (unicode(numRand) == attr.name()): index = i #get input field index |
| 249 | + count = 10.00 |
| 250 | + add = 60.00 / sProvider.featureCount() |
| 251 | + while sProvider.nextFeature(sFeat): |
| 252 | + sGeom = sFeat.geometry() |
| 253 | + if design == self.tr("density"): |
| 254 | + sDistArea = QgsDistanceArea() |
| 255 | + value = int(round(numRand * sDistArea.measure(sGeom))) |
| 256 | + elif design == self.tr("field"): |
| 257 | + sAtMap = sFeat.attributeMap() |
| 258 | + value = sAtMap[index].toInt()[0] |
| 259 | + else: |
| 260 | + value = numRand |
| 261 | + sExt = sGeom.boundingBox() |
| 262 | + sPoints.extend(self.simpleRandom(value, sGeom, sExt.xMinimum(), sExt.xMaximum(), sExt.yMinimum(), sExt.yMaximum())) |
| 263 | + count = count + add |
| 264 | + self.progressBar.setValue(count) |
| 265 | + return sPoints |
0 commit comments