2

I have an unreferenced point layer that is rectangular in shape. It is made out of rows of unequally spaced points, with spacing between the rows of either 1 or 3 meters.

point layer

I also have a multipolygon layer that corresponds with the mentioned point layer in size, but the multipolygon layer is georeferenced (the four corner coordinates are known). I also have a column that indicates where is the Zero/Start corner, with the following values: East, West, North, or South.

attribute table

polygon layer Is there a way in pyqgis to obtain the Zero/Start coordinate of the corner vertex from the polygon layer based on the value in the Zero/Start column? In the example shown, the value of the Zero/Start column is South. I would also like to know if there is a way to get the angle of rotation between two layers. My idea is to first rotate the point layer with the following code:

vector_layer_edit_utils = QgsVectorLayerEditUtils(lyr)
rotation_angle = 0 # angle that is needed
zero_start = QgsPointXY(0, 0) # start coordinate of the unreferenced point layer
lyr = QgsProject.instance().mapLayersByName("point_layer")[0]
feats = lyr.getFeatures()
lyr.startEditing()
for feat in feats:
    geom = feat.geometry()
    geom.rotate(rotation_angle, zero_start)
    lyr.changeGeometry(feat.id(), geom)
lyr.commitChanges()

It's not clear to me what is the direction of the rotation, clockwise or counterclockwise. I would then translate the rotated layer to the coordinate obtained from the polygon vertex with the following code:

feats = lyr.getFeatures()
zero_coordinate = QgsPointXY(0, 0) # replace with the coordinate from the polygon layer
lyr.startEditing()
for feat in feats:
    vector_layer_edit_utils.translateFeature(feat.id(), zero_coordinate.x(), zero_coordinate.y())
lyr.commitChanges()
1
  • There is Affine transform in the Processing Toolbox. There is also rotation. Do you want to use Numpy and Scipy to rotate the point-matrix or loop?
    – Cary H
    Commented Oct 13, 2023 at 13:02

1 Answer 1

1

You can get the angle you need from the points of the rectangle using arctangent (Numpy arctan2)

import numpy
layer = iface.activeLayer()
features = layer.getFeatures()
top_left = [999999,9999999]
bot_left = [999999,9999999]
bot_right = [0,0]
rot_point = QgsPoint(0,0)
for feature in features:
    print("Type",feature.geometry().type(), QgsWkbTypes.PolygonGeometry)
    #these will be 2 if polygon.
    geom = feature.geometry()
    if geom.isMultipart():
        print("This is a multi polygon")
        multipolygon = geom.asMultiPolygon()
        polygon = multipolygon[0] #only get the first polygon in the list
    else:
        print("This is a single polygon")
        polygon = geom.asPolygon()
        
    n = len(polygon[0])
    for i in range(n-1): #first and last point the same
        this_x = polygon[0][i].x()
        this_y = polygon[0][i].y()
        print( this_x , this_y)
        if this_x < top_left[0]:
            top_left = [this_x , this_y]
        if this_x > bot_right[0]:
            bot_right = [this_x , this_y]
        if this_y < bot_left[1]:
            bot_left = [this_x , this_y]
            rot_point = polygon[0][i]
            
            
    #vertices = multipolygon[0].asPolygon()

# Get the vertices of the first polygon
    print(f"Top Left point {top_left}")
    print(f"Bottom Right point {bot_right}")
    print(f"Bottom Left point {bot_left} = Zero Start")
    delta_x = bot_right[0] - bot_left[0]
    delta_y = bot_right[1] - bot_left[1]
    tilt_ang = numpy.arctan2(delta_y, delta_x)
    print(f"Radians {tilt_ang}")
    print(f"Degrees {numpy.degrees(tilt_ang)}")
    print(f"Rotation Point = {rot_point}")

rotation_angle = numpy.degrees(tilt_ang) * -1
#rot_point =QgsPointXY(78009.613,2945880.6889)
plyr = QgsProject.instance().mapLayersByName("point_layer")[0]
feats = plyr.getFeatures()
plyr.startEditing()
for feat in feats:
    geom = feat.geometry()
    geom.rotate(rotation_angle, rot_point)
    plyr.changeGeometry(feat.id(), geom)
plyr.commitChanges()
9
  • Thank you for the answer. Unfortunately, I get an error: Traceback (most recent call last): File "C:\PROGRA~1\QGIS 3.32.3\apps\Python39\lib\code.py", line 90, in runcode exec(code, self.locals) File "<input>", line 1, in <module> File "<string>", line 8, in <module> TypeError: MultiPolygon geometry cannot be converted to a polygon. Only single polygon or curve polygon types are permitted. I can't test your suggestion, sorry. I can't find a working way to convert multipolygon to single, I tried geopandas and ogr, with zero effect. Commented Oct 16, 2023 at 6:40
  • 1
    OK - if you only have a single polygon stored as a multi, you can export it as a single using QGIS. Right click the layer and select export then save features as. Check here on how to determine if a feature is MultiType. opensourceoptions.com/pyqgis-get-feature-geometry
    – Cary H
    Commented Oct 16, 2023 at 14:33
  • If you post your data, it would help to determine what you are working with.
    – Cary H
    Commented Oct 16, 2023 at 14:37
  • Thank you so much! Is there a way I can use the Zero column in the multlipolygon shapefile to position the zero vertex? It has East, West, North, or South for every feature's zero point. The rectangular polygon is always rotated differently. Commented Oct 17, 2023 at 7:47
  • Also degrees needs to be -(numpy.degrees(tilt_ang)), I am guessing because of the rotation direction. Commented Oct 17, 2023 at 8:18

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

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