QGIS – Move a Layer to a Precise Position Based on Centroid

alignmentlayerspolygonqgis

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.

Best Answer

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

Related Question