7

I'm not quite sure how to phrase this so apologies if it is a duplicate. I have a project that uses a series of lines created from the boundaries of polygons overlaid onto a map in QGIS. I understand how to use QGIS to create a point layer with the centroid of the initial polygon before it is converted to a line. How can I move a polygon or line layer to a new location based on the centroid placement?

To try to explain it more clearly, imagine 2 buildings on a map, both in separate locations. Each is expressed as a polygon layer in QGIS. What I am trying to do is calculate the centroid of each and then move building A so that it sits in the position of B, using the centroids of each to ensure that they are positioned in the same place, even though they are different shapes. All I can think of is there might be a way to lock the centroid layer to the line layer and then move them both by editing the coordinates of the centroid? I am fairly new to GIS in general though so I'm not sure how to approach the problem.

8
+50

A translation is an affine transformation. Next code includes this kind of transformation and it works well at the Python Console of QGIS for creating a memory layer with the displaced layer (building1).

registry = QgsMapLayerRegistry.instance()

n = registry.count()

layers = registry.mapLayers().values() 

layers_names = [ layers[i].name() for i in range(n) ]

name1 = 'building1'
name2 = 'building2'

idx1 = layers_names.index(name1)
idx2 = layers_names.index(name2)

#features
feat1 = layers[idx1].getFeatures().next()
feat2 = layers[idx2].getFeatures().next()

#polygons geometry
pol1 = feat1.geometry().asPolygon() #polygon1
pol2 = feat2.geometry().asPolygon() #polygon2

#centroid coordinates
c1 = feat1.geometry().centroid().asPoint() #centroid1
c2 = feat2.geometry().centroid().asPoint() #centroid2

n = len(pol_t[0])

pol_t = pol1

#calculating displacement based in centroids
px = c2.x() - c1.x()
py = c2.y() - c1.y()

#translation as an affine transformation
for i in range(n):
    pol_t[0][i].setX(pol1[0][i].x() + px)
    pol_t[0][i].setY(pol1[0][i].y() + py)

#creating a memory layer for displaced polygon (building1)
crs = layers[1].crs()
epsg = crs.postgisSrid()

uri = "Polygon?crs=epsg:" + str(epsg) + "&field=id:integer""&index=yes"

mem_layer = QgsVectorLayer(uri,
                           "building1_displaced",
                           "memory")

QgsMapLayerRegistry.instance().addMapLayer(mem_layer)

mem_layer.startEditing()

feat = QgsFeature()

#Set geometry
feat.setGeometry(QgsGeometry.fromPolygon(pol_t))

#set attributes values
feat.setAttributes([1])
mem_layer.addFeature(feat, True)

#stop editing and save changes
mem_layer.commitChanges()

I tried out the code with these vector layers:

enter image description here

After running the code:

enter image description here

centroid of building1 was successfully displaced to centroid of building2.

Editing Note:

I also created a plugin (see next image) that it can move any kind of layer. At next image, I took the points on layers (approximately at the centroid of the grid) and the targets points (all different) by using the "Where Am I" plugin of Gary Sherman. It works quick and nicely.

enter image description here

  • Works well thanks. I ended up achieving the same through exporting the layer as a csv file, calculating the difference between the centroids of the two polygons and then altering each coordinate by the difference.Then it was just a matter of reimporting the new csv to QGIS. Achieved the same result but yours is more elegant for repeated use. Mine however requires zero knowledge of Python. Horses for courses but I am marking yours as the answer. – Tatone Oct 9 '15 at 21:33
  • You're welcome. – xunilk Oct 9 '15 at 21:38
  • I've used your code and works a treat, awarding you a bounty! – Joseph Oct 12 '15 at 9:27
4

The move plugin works in a similar way.

  1. calculate the centroids using Vector -> Geometry Tools -> Polygon Centroids for both layers,
  2. turn the layer to be moved into edit mode
  3. select the feature to be moved
  4. activate the plugin with its icon
  5. draw a line from the first centroid to the second
  6. With right-click, move the object
  7. Save the layer
  8. turn off the edit mode

Unfortuantely, snapping to the points does not seem to work.

  • I also created a plugin. Later, I will think in the snapping. – xunilk Oct 12 '15 at 22:05
  • @xunilk I hope you will write a good user documentation for your plugin too. Some other plugins should do almost the same thing, but I can't get them to work properly. – AndreJ Oct 13 '15 at 7:46

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.