Skip to content

Commit c89fec8

Browse files
committed
[FEATURE] fTools: allow to calculate extent not only for whole layer but
for individual features too
1 parent 24a1fb9 commit c89fec8

File tree

2 files changed

+135
-9
lines changed

2 files changed

+135
-9
lines changed

python/plugins/fTools/tools/doGeometry.py

+116-4
Original file line numberDiff line numberDiff line change
@@ -81,7 +81,8 @@ def accept( self ):
8181
self.tr( "Please specify valid UID field" ) )
8282
else:
8383
self.outShape.clear()
84-
self.geometry( self.inShape.currentText(), self.lineEdit.value(), self.cmbField.currentText() )
84+
self.geometry( self.inShape.currentText(), self.lineEdit.value(),
85+
self.cmbField.currentText() )
8586

8687
def outFile( self ):
8788
self.outShape.clear()
@@ -97,6 +98,9 @@ def manageGui( self ):
9798
self.lblCalcType.setVisible( False )
9899
self.cmbCalcType.setVisible( False )
99100

101+
self.chkUseSelection.setVisible( False )
102+
self.chkByFeatures.setVisible( False )
103+
100104
self.chkWriteShapefile.setVisible( False )
101105
if self.myFunction == 1: # Singleparts to multipart
102106
self.setWindowTitle( self.tr( "Singleparts to multipart" ) )
@@ -167,6 +171,8 @@ def manageGui( self ):
167171
self.label_3.setText( self.tr( "Input layer" ) )
168172
self.label.setVisible( False )
169173
self.lineEdit.setVisible( False )
174+
self.chkByFeatures.setVisible( True )
175+
self.chkUseSelection.setVisible( True )
170176
self.lblOutputShapefile.setText( self.tr( "Output polygon shapefile" ) )
171177
self.resize( 381, 100 )
172178
self.populateLayers()
@@ -229,7 +235,8 @@ def geometry( self, myLayer, myParam, myField ):
229235
self.buttonOk.setEnabled( False )
230236
self.testThread = geometryThread( self.iface.mainWindow(), self, self.myFunction,
231237
vlayer, myParam, myField, self.shapefileName, self.encoding,
232-
self.cmbCalcType.currentIndex(), self.chkWriteShapefile.isChecked() )
238+
self.cmbCalcType.currentIndex(), self.chkWriteShapefile.isChecked(),
239+
self.chkByFeatures.isChecked(), self.chkUseSelection.isChecked() )
233240
QObject.connect( self.testThread, SIGNAL( "runFinished( PyQt_PyObject )" ), self.runFinishedFromThread )
234241
QObject.connect( self.testThread, SIGNAL( "runStatus( PyQt_PyObject )" ), self.runStatusFromThread )
235242
QObject.connect( self.testThread, SIGNAL( "runRange( PyQt_PyObject )" ), self.runRangeFromThread )
@@ -288,7 +295,8 @@ def runRangeFromThread( self, range_vals ):
288295

289296
class geometryThread( QThread ):
290297
def __init__( self, parentThread, parentObject, function, vlayer, myParam,
291-
myField, myName, myEncoding, myCalcType, myNewShape ):
298+
myField, myName, myEncoding, myCalcType, myNewShape, myByFeatures,
299+
myUseSelection ):
292300
QThread.__init__( self, parentThread )
293301
self.parent = parentObject
294302
self.running = False
@@ -300,6 +308,8 @@ def __init__( self, parentThread, parentObject, function, vlayer, myParam,
300308
self.myEncoding = myEncoding
301309
self.myCalcType = myCalcType
302310
self.writeShape = myNewShape
311+
self.byFeatures = myByFeatures
312+
self.useSelection = myUseSelection
303313

304314
def run( self ):
305315
self.running = True
@@ -319,7 +329,10 @@ def run( self ):
319329
elif self.myFunction == 8: # Delaunay triangulation
320330
success = self.delaunay_triangulation()
321331
elif self.myFunction == 9: # Polygon from layer extent
322-
success = self.layer_extent()
332+
if self.byFeatures:
333+
success = self.feature_extent()
334+
else:
335+
success = self.layer_extent()
323336
elif self.myFunction == 10: # Voronoi Polygons
324337
success = self.voronoi_polygons()
325338
elif self.myFunction == 11: # Lines to polygons
@@ -860,6 +873,105 @@ def layer_extent( self ):
860873

861874
return True
862875

876+
def feature_extent( self, ):
877+
vprovider = self.vlayer.dataProvider()
878+
vprovider.select( [] )
879+
880+
self.emit( SIGNAL( "runStatus( PyQt_PyObject )" ), 0 )
881+
882+
fields = { 0 : QgsField( "MINX", QVariant.Double ),
883+
1 : QgsField( "MINY", QVariant.Double ),
884+
2 : QgsField( "MAXX", QVariant.Double ),
885+
3 : QgsField( "MAXY", QVariant.Double ),
886+
4 : QgsField( "CNTX", QVariant.Double ),
887+
5 : QgsField( "CNTY", QVariant.Double ),
888+
6 : QgsField( "AREA", QVariant.Double ),
889+
7 : QgsField( "PERIM", QVariant.Double ),
890+
8 : QgsField( "HEIGHT", QVariant.Double ),
891+
9 : QgsField( "WIDTH", QVariant.Double ) }
892+
893+
writer = QgsVectorFileWriter( self.myName, self.myEncoding, fields,
894+
QGis.WKBPolygon, self.vlayer.crs() )
895+
inFeat = QgsFeature()
896+
outFeat = QgsFeature()
897+
nElement = 0
898+
899+
if self.useSelection:
900+
self.emit( SIGNAL( "runRange( PyQt_PyObject )" ), (0, self.vlayer.selectedFeatureCount() ) )
901+
for inFeat in self.vlayer.selectedFeatures():
902+
self.emit( SIGNAL( "runStatus( PyQt_PyObject )" ), nElement )
903+
nElement += 1
904+
905+
rect = inFeat.geometry().boundingBox()
906+
minx = rect.xMinimum()
907+
miny = rect.yMinimum()
908+
maxx = rect.xMaximum()
909+
maxy = rect.yMaximum()
910+
height = rect.height()
911+
width = rect.width()
912+
cntx = minx + ( width / 2.0 )
913+
cnty = miny + ( height / 2.0 )
914+
area = width * height
915+
perim = ( 2 * width ) + ( 2 * height )
916+
rect = [ QgsPoint( minx, miny ),
917+
QgsPoint( minx, maxy ),
918+
QgsPoint( maxx, maxy ),
919+
QgsPoint( maxx, miny ),
920+
QgsPoint( minx, miny ) ]
921+
geometry = QgsGeometry().fromPolygon( [ rect ] )
922+
923+
outFeat.setGeometry( geometry )
924+
outFeat.setAttributeMap( { 0 : QVariant( minx ),
925+
1 : QVariant( miny ),
926+
2 : QVariant( maxx ),
927+
3 : QVariant( maxy ),
928+
4 : QVariant( cntx ),
929+
5 : QVariant( cnty ),
930+
6 : QVariant( area ),
931+
7 : QVariant( perim ),
932+
8 : QVariant( height ),
933+
9 : QVariant( width ) } )
934+
writer.addFeature( outFeat )
935+
else:
936+
self.emit( SIGNAL( "runRange( PyQt_PyObject )" ), ( 0, vprovider.featureCount() ) )
937+
while vprovider.nextFeature( inFeat ):
938+
self.emit( SIGNAL( "runStatus( PyQt_PyObject )" ), nElement )
939+
nElement += 1
940+
941+
rect = inFeat.geometry().boundingBox()
942+
minx = rect.xMinimum()
943+
miny = rect.yMinimum()
944+
maxx = rect.xMaximum()
945+
maxy = rect.yMaximum()
946+
height = rect.height()
947+
width = rect.width()
948+
cntx = minx + ( width / 2.0 )
949+
cnty = miny + ( height / 2.0 )
950+
area = width * height
951+
perim = ( 2 * width ) + ( 2 * height )
952+
rect = [ QgsPoint( minx, miny ),
953+
QgsPoint( minx, maxy ),
954+
QgsPoint( maxx, maxy ),
955+
QgsPoint( maxx, miny ),
956+
QgsPoint( minx, miny ) ]
957+
geometry = QgsGeometry().fromPolygon( [ rect ] )
958+
959+
outFeat.setGeometry( geometry )
960+
outFeat.setAttributeMap( { 0 : QVariant( minx ),
961+
1 : QVariant( miny ),
962+
2 : QVariant( maxx ),
963+
3 : QVariant( maxy ),
964+
4 : QVariant( cntx ),
965+
5 : QVariant( cnty ),
966+
6 : QVariant( area ),
967+
7 : QVariant( perim ),
968+
8 : QVariant( height ),
969+
9 : QVariant( width ) } )
970+
writer.addFeature( outFeat )
971+
972+
del writer
973+
return True
974+
863975
def simpleMeasure( self, inGeom, calcType, ellips, crs ):
864976
if inGeom.wkbType() in ( QGis.WKBPoint, QGis.WKBPoint25D ):
865977
pt = QgsPoint()

python/plugins/fTools/tools/frmGeometry.ui

+19-5
Original file line numberDiff line numberDiff line change
@@ -47,7 +47,7 @@
4747
<widget class="QComboBox" name="cmbField"/>
4848
</widget>
4949
</item>
50-
<item row="4" column="0">
50+
<item row="6" column="0">
5151
<spacer>
5252
<property name="orientation">
5353
<enum>Qt::Vertical</enum>
@@ -60,7 +60,7 @@
6060
</property>
6161
</spacer>
6262
</item>
63-
<item row="5" column="0" colspan="2">
63+
<item row="7" column="0" colspan="2">
6464
<layout class="QVBoxLayout">
6565
<item>
6666
<widget class="QCheckBox" name="chkWriteShapefile">
@@ -96,7 +96,7 @@
9696
</item>
9797
</layout>
9898
</item>
99-
<item row="6" column="0">
99+
<item row="8" column="0">
100100
<spacer>
101101
<property name="orientation">
102102
<enum>Qt::Vertical</enum>
@@ -109,7 +109,7 @@
109109
</property>
110110
</spacer>
111111
</item>
112-
<item row="7" column="0">
112+
<item row="9" column="0">
113113
<widget class="QProgressBar" name="progressBar">
114114
<property name="value">
115115
<number>0</number>
@@ -122,7 +122,7 @@
122122
</property>
123123
</widget>
124124
</item>
125-
<item row="7" column="1">
125+
<item row="9" column="1">
126126
<widget class="QDialogButtonBox" name="buttonBox_2">
127127
<property name="orientation">
128128
<enum>Qt::Horizontal</enum>
@@ -189,6 +189,20 @@
189189
</item>
190190
</layout>
191191
</item>
192+
<item row="5" column="0" colspan="2">
193+
<widget class="QCheckBox" name="chkByFeatures">
194+
<property name="text">
195+
<string>Calculate extent for each feature separately</string>
196+
</property>
197+
</widget>
198+
</item>
199+
<item row="4" column="0" colspan="2">
200+
<widget class="QCheckBox" name="chkUseSelection">
201+
<property name="text">
202+
<string>Use only selected features</string>
203+
</property>
204+
</widget>
205+
</item>
192206
</layout>
193207
</widget>
194208
<resources/>

0 commit comments

Comments
 (0)