5

I am working on a protected areas map. The label layer is from the mapping authority. The one I am using is point based.

Unfortunately some of the points carry the same name leading to duplicate names for mountain areas, glaciers and other. I am for several reasons bound to use this layer, so finding a different layer or making changes to the layer is not within the scope of this question.

Result of duplicate label names, point layer

Is there a way to remove duplicate labels when labels are within a certain distance of each other?

If so, can such a rule be enforced within one of the categories when rule-based labelling is used?

enter image description here

2
  • 1
    Have you considered using multipolyons to represent the features? That you have this problem suggests you have redundancy in your data schema. Using multipolygons to represent these kinds of geographic objects would address the labelling issue (although it could make placement a lot harder). Apr 1, 2016 at 21:52
  • @RichardLaw The underlying data model is sound. The Norwegian Mapping authority has allways done a good job in modelling their data. I am using one of their derived data products where names are represented associated with points. An idea from your input: If the data were stored in a spatial database I guess point buffering and subsequent dissolve over name could be a way to solve this. Not sure if I can query an eesri gdb-file that way. Other than that the solution provided by detlev looks very good.
    – ragnvald
    Apr 2, 2016 at 7:34

2 Answers 2

4

Fast forward into 2020 and QGIS 3.10. There are now dedicated tools to do the accepted answer methodology.

In the labels properties, select the Placement tab. Select the Offset from point option and use the center quadrant.

In the Geometry generator, use the following expression:

centroid(collect( $geometry,  "UWI" ))

enter image description here

3

If you do not want to build a different layer just for labeling and do not want to make changes to the layer, then data defined properties may be what you need.

The idea: get the feature to be labeled and create a geometry collection of all features having the same attribute value (no matter which attributes). Retrieve the centroid of this collection, get its x and y coordinate, and use this for labeling.

In default setting QGIS doesn't show colliding labels. This way you see all labels only once, right in the center of objects with same names.

To use this approach, you need to use data defined overriding of y and y coordinate, on tab Layer Properties -> Labeling -> Placement.

Define following function in functions editor, and press Load.

@qgsfunction(args='auto', group='Custom')
def getAgglomerationCenter(layername, attribute, feature, parent):
    layer  = QgsMapLayerRegistry.instance().mapLayersByName(layername)[0]
    geom = QgsGeometry().fromWkt('GEOMETRYCOLLECTION()')
    for feat in layer.getFeatures():
        if feat[attribute] == feature[attribute]:
            geom.addPart(QgsPointV2(feat.geometry().asPoint()))
    return geom.centroid()

As expression in case of x coordinate give:

x(getAgglomerationCenter( 'YOUR LAYER NAME', 'ATTRIBUTE NAME' ))

and for y coordinate:

y(getAgglomerationCenter( 'YOUR LAYER NAME', 'ATTRIBUTE NAME' ))

Tested situation:

Test case

Disclaimer: this implementation is not optimized in any way, eg instead of looping over all features, using QgsFeatureRequest() is preferable. And probably memoizing results is possible, to prevent build the same collection several times.

3
  • The layer has around 2.4 million points. I get a certain lag when applying your function. This might point to issuwes with QGIS. Seems like QGIS is doing requests to the layer continously when I am working in the expression window. But your solution looks great. Take a look at my comment to @RichardLaw though. Could it point to a better solution? Will require some "on-the-fly" spatial sql queries to be available even for esri geodatabases though.
    – ragnvald
    Apr 2, 2016 at 18:59
  • 1
    The possible way I suggested is defacto building a multigeometry object on the fly. Given 2.4 mio points all ways of optimizing should be used. I am interested in this, and will experiment a bit, and extend my answer. Building such a permanent layer once of cause will be the fastest solution.
    – Detlev
    Apr 2, 2016 at 20:30
  • Tried out your procedure and it worked. But QGIS has an issue with rendering stuff while it is being entered. So I ended up with a system which looked like it had stopped completely. And the number of objects did not help. So preprocessing data in postGIS could be an other approach to be tested out.
    – ragnvald
    Apr 5, 2016 at 13:33

Your Answer

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

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