3

I am creating annotations using Python script in QGIS 3.40. They newly created Annotations belong to the class QgsAnnotationPointTextItem.

Here is an example of what it looks like in QGIS. example Annotation

With another script, I want to modify some of the annotations with a mouse click. The problem is that the method boundingBox only returns a QgsRectangle Object with two Coordinates which are the same-> <QgsRectangle: 391239.10772885562619194 5737021.05845910217612982, 391239.10772885562619194 5737021.05845910217612982>

So if I press on the map canvas I need to click exactly on the point, to modify the annotation.

If I use the modify annotations tool to modify them manually, the annotations are highlighted via a perfect bounding box. example annotation, highlighted via the modify annotation tool

So my question is there another method or way to get 4 coordinates or a QgsRectangle object, that is actually a rectangle around my annotations?

2
  • 1
    In <QgsRectangle: 391239.10772885562619194 5737021.05845910217612982, 391239.10772885562619194 5737021.05845910217612982> the two pair of coordinates are exactly the same, so it is actually a point, not a line. Isn't it? Commented Jan 3 at 10:48
  • yes you are right, i somehow thought it was a line. i changed the question, but the problem is still the same Commented Jan 3 at 10:56

1 Answer 1

1

So i have found a way to get an approximation of the bounding box. First you have to know the scale of the map, that the annotations are for and set them. setSymbologyReferenceScale

After that you use following code to get the approximation.

from qgis import core # creating memory vector layer for the visualation of the bounding box Prj = QgsProject().instance() lyr = QgsVectorLayer('Polygon?crs=epsg:25832','bounding_box',"memory") # change the epsg to your coordinate system Prj.addMapLayers([lyr]) # get all rendered items in the current canvas rendered_annot_list = iface.mapCanvas().renderedItemResults().renderedItems() # list of all annotation layer, length should be one for this code anno_layer_list= [x for x in iface.mapCanvas().layers() if isinstance(x, QgsAnnotationLayer)] if len(anno_layer_list) != 1: raise ValueError("There has to be only one ") # get a list of all items in the annotation layer annot_layer = anno_layer_list[0] list_annot_layer = annot_layer.items() # write all the annotation in a list that are visible in the current canvas annot_list = [] for ren_annot in rendered_annot_list: annot_list.append(list_annot_layer[ren_annot.itemId()]) # loop over all the annotations in the current canvas and get their bounding box for anno in annot_list: map_setting = core.QgsMapSettings() render_context = core.QgsRenderContext.fromMapSettings(map_setting) b_box = anno.boundingBox(render_context) print(b_box) # visualize the bounding box feature = QgsFeature() feature.setGeometry(QgsGeometry.fromRect(b_box)) lyr.startEditing() lyr.addFeature(feature) lyr.commitChanges(True) 

After that you get the bounding box for the scale you set up beforehand. If you visualize it, it will look something like this:bounding box inside the annotation

As you see the bounding box is not perfect, but it is the best approximation i have found until now.

2
  • 1
    For now I am getting TypeError: QgsRenderedItemDetails.boundingBox(): too many arguments Commented Jan 6 at 14:44
  • 1
    changed the code. Thought that the bounding box method of QgsRenderedItemDetails would work the same as the QgsAnnotationPointTextItem method and i could save some line of code. Commented Jan 7 at 9:26

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.