def _mbr_orientation(mbr: QgsPolygon): ''' Compute the orientation of a minimum bounding rectangle (QgsPolygon) (in degrees) comparatively to the cartographic East (axis X). Its value is between 0 and 180 degrees. ''' # , except if the MBR is geometrically # null or empty. In that last case, the value -2.0 is returned. # if mbr.isNull() or mbr.isEmpty(): # return -2.0 # geom = mbr.geometry() mbr_vertices = _geometry_vertices(mbr, 2) v0 = QgsPoint(mbr_vertices[0].x(), mbr_vertices[0].y()) v1 = QgsPoint(mbr_vertices[1].x(), mbr_vertices[1].y()) v2 = QgsPoint(mbr_vertices[2].x(), mbr_vertices[2].y()) length = v0.distanceSquared(v1.x(), v1.y()) length2 = v1.distanceSquared(v2.x(), v2.y()) if length > length2: angle = math.atan2(v0.y() - v1.y(), v0.x() - v1.x()) else: angle = math.atan2(v1.y() - v2.y(), v1.x() - v2.x()) if angle < 0: angle += math.pi return angle * 180.0 / math.pi
def polygon_orientation(polygon: QgsPolygon): ''' Compute the orientation of a polygon (QgsPolygon) (in degrees) comparatively to the cartographic East (axis X). The orientation is based on the orientation of the associated minimum bounding rectangle. Its value is between 0 and 180 degrees, except if the MBR can not be defined. In that last case, the value -2.0 is returned. ''' # orientedMinimumBoundingBox(self) → Tuple[QgsGeometry, float, float, float, float] # angle (clockwise in degrees from North) (mbr, area, angle, width, height) = polygon.orientedMinimumBoundingBox() if mbr.isNull() or mbr.isEmpty(): return -2.0 # geom = mbr.geometry() v0 = QgsPoint(mbr[0]) v1 = QgsPoint(mbr[1]) v2 = QgsPoint(mbr[2]) length = v0.distanceSquared(v1.x(), v1.y()) length2 = v1.distanceSquared(v2.x(), v2.y()) if length > length2: angle = math.atan2(v0.y() - v1.y(), v0.x() - v1.x()) else: angle = math.atan2(v1.y() - v2.y(), v1.x() - v2.x()) if angle < 0: angle += math.pi return angle * 180.0 / math.pi