3

In QGIS I have a point feature with "Rotation" field. Using the geometry builder I am trying to build square geometries based on the XY as centre and rotated based on the "Rotation" field using the expression below.

geom_from_wkt( 
'POLYGON(('|| 
(((x( centroid( $geometry) ) + 0.5)*(cos(radians("Rotation"))))-((y( centroid( $geometry) ) + 0.5)*(sin(radians("Rotation")))))||' '||(((x( centroid( $geometry) ) + 0.5)*(sin(radians("Rotation"))))+((y( centroid( $geometry) ) + 0.5)*(cos(radians("Rotation")))))||','||
(((x( centroid( $geometry) ) + 0.5)*(cos(radians("Rotation"))))-((y( centroid( $geometry) ) - 0.5)*(sin(radians("Rotation")))))||' '||(((x( centroid( $geometry) ) + 0.5)*(sin(radians("Rotation"))))+((y( centroid( $geometry) ) - 0.5)*(cos(radians("Rotation")))))||','||
(((x( centroid( $geometry) ) - 0.5)*(cos(radians("Rotation"))))-((y( centroid( $geometry) ) - 0.5)*(sin(radians("Rotation")))))||' '||(((x( centroid( $geometry) ) - 0.5)*(sin(radians("Rotation"))))+((y( centroid( $geometry) ) - 0.5)*(cos(radians("Rotation")))))||','||
(((x( centroid( $geometry) ) - 0.5)*(cos(radians("Rotation"))))-((y( centroid( $geometry) ) + 0.5)*(sin(radians("Rotation")))))||' '||(((x( centroid( $geometry) ) - 0.5)*(sin(radians("Rotation"))))+((y( centroid( $geometry) ) + 0.5)*(cos(radians("Rotation")))))||','||
(((x( centroid( $geometry) ) + 0.5)*(cos(radians("Rotation"))))-((y( centroid( $geometry) ) + 0.5)*(sin(radians("Rotation")))))||' '||(((x( centroid( $geometry) ) + 0.5)*(sin(radians("Rotation"))))+((y( centroid( $geometry) ) + 0.5)*(cos(radians("Rotation")))))||','||
'))')

My rotation values are in degrees hence the conversion to radians but any feature with a rotation does not show up at all, features with no rotation value set show up as squares aligned North to South. Can someone tell me where I went wrong?

0

I would suggest using [shapely](http://toblerity.org/shapely/shapely.html#module-shapely.affinity which is provided as a python package. You would interested in the rotate function:

shapely.affinity.rotate(geom, angle, origin='center', use_radians=False)¶
Returns a rotated geometry on a 2D plane.  
The angle of rotation can be specified in either degrees (default) or   radians by setting use_radians=True. Positive angles are counter-clockwise and   negative are clockwise rotations.  
The point of origin can be a keyword ‘center’ for the bounding box center   (default), ‘centroid’ for the geometry’s centroid, a Point object or a   coordinate tuple (x0, y0).  
The affine transformation matrix for 2D rotation is:  
/ cos(r) -sin(r) xoff | sin(r) cos(r) yoff | 0 0 1 /
where the offsets are calculated from the origin Point(x0, y0)
0

This is what I come up with to do the transformation using geometry generator;

geom_from_wkt( 
'POLYGON(('|| 
(x( centroid( $geometry) ) + ((( "length" /2)*(cos(radians("azimuth"))))-(( "width" /2)*(sin(radians("azimuth"))))))||' '||(y( centroid( $geometry) ) + ((( "length" /2)*(sin(radians("azimuth"))))+(( "width" /2)*(cos(radians("azimuth"))))))||','||
(x( centroid( $geometry) ) + ((( "length" /2)*(cos(radians("azimuth"))))-(-( "width" /2)*(sin(radians("azimuth"))))))||' '||(y( centroid( $geometry) ) + ((( "length" /2)*(sin(radians("azimuth"))))+(-( "width" /2)*(cos(radians("azimuth"))))))||','||
(x( centroid( $geometry) ) + ((-( "length" /2)*(cos(radians("azimuth"))))-(-( "width" /2)*(sin(radians("azimuth"))))))||' '||(y( centroid( $geometry) ) + ((-( "length" /2)*(sin(radians("azimuth"))))+(-( "width" /2)*(cos(radians("azimuth"))))))||','||
(x( centroid( $geometry) ) + ((-( "length" /2)*(cos(radians("azimuth"))))-(( "width" /2)*(sin(radians("azimuth"))))))||' '||(y( centroid( $geometry) )  + ((-( "length" /2)*(sin(radians("azimuth"))))+(( "width" /2)*(cos(radians("azimuth"))))))||','||
(x( centroid( $geometry) ) + ((( "length" /2)*(cos(radians("azimuth"))))-(( "width" /2)*(sin(radians("azimuth"))))))||' '||(y( centroid( $geometry) )  + ((( "length" /2)*(sin(radians("azimuth"))))+(( "width" /2)*(cos(radians("azimuth"))))))||','||
'))')

I started with the solution from this post Using QGIS Geometry Generator to get rectangle from point?

The solution basically adds to the x,y, coordinate dimensions so that the geometry generator can build a bounding box around a point feature making the point it's centre. However if you rotate the point the bounding box will not rotate it stays North South Oriented. So starting there I added the required math to find the new coordinates for each corner of a square or rectangle after a rotation is applied and imputing those coordinates into a WKT geometry type. Essentially each line is taking the x,y, coordinate of each feature for example 0.5,0.5, and applying the rotation math (for X x=x1cos@-y1sin@ and for Y y=x1sin@ + y1cos@) then adding the results to the original centroid XY.

To rotate a feature in a Cartesian coordinate system the rotate point needs to be set to 0,0, before the math can be applied. For my purposes I am rotating at the centroid (XY coordinate of the point feature). so I would need to subtract the x,y, of the point from the coordinates, but to bring the feature back to its location I would then need to add the x,y, coordinate back to the rotated results. Since the 2 procedures cancel each other out I instead only applied the rotation math to the fields and then added the results to the original x,y, coordinate of the point feature at the end. The result is a number of rectangles of varying dimensions rotated accordingly based on attribute field values. Using CASE WHEN and a shape identification code you could apply this to multiple different shape types. Things to note; since my data had Length and Width I had to divide those fields by 2, otherwise the resulting features would have been 2x larger. The "azimuth" field is my rotation in degrees but QGIS cos() function expects radians that is why I use (cos(radians("azimuth") this converts the degrees to radians. Also the math works out where -degrees are clockwise rotations and +degrees are counter clockwise rotations. In my final code I put a "-" on my azimuths so that rotations would be clockwise (cos(radians(-("azimuth")), of course you could use -Degrees in the fields to fix this as well.

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.