16

With QGIS 2.12.2, how can I set up layer labeling to avoid placing labels where features from another layer already exist?

For example, if I have a stream/river polyline layer that contains lake "centerlines", and I place a "lake" polygon layer above it in the drawing order, I don't want the river layer to place a label inside the lake. Instead, I would rather have the river labeled outside of the lake (as needed). That way, I can place labels from the lakes layer and I don't run into label collisions.

Here is an example, where (I have intentionally put the lines on top for visual purposes) what I am hoping to achieve is no river center-line labels shown inside the lake polygon: Lines are labeling inside polygon

  • 4
    How is your data stored and served? Working with PostGIS, I'd be tempted to define my rivers with a view, where the parts of the rivers intersecting lakes are clipped out entirely. Good automated labelling is a hard problem, geometry less so. – alphabetasoup Jan 12 '16 at 8:58
  • These were shapefiles, but your idea of moving to PostGIS and managing the data issues on the fly is a really good one. I would suggest you move your comment to an Answer, since I could make a pretty valid argument that this is a good resolution. – RyanDalton Jan 12 '16 at 22:14
9
+200

Automated labelling is a really hard problem, but feature geometry is not so bad.

Even if you can get placement to work adequately most of the time, there are likely to be exceptions. Some of these you will notice and may be able to address. Others you won't notice when making a large map or tileset because you can't pour over every inch of your map at a variety of scales. Almost always you will have the urge to move some automatically-placed labels manually, from a cartographic perspective.

As I suggested in my comment, I'd make the problem easier for the labelling engine. In this case, I would do this by defining my rivers as a table view*, with river geometries clipped to respect lake boundaries. That way, there are no river features inside lakes to be labelled, and no label collisions.

* I assume the use of a RDBMS here, like PostgreSQL/PostGIS, for convenience and the ability to only update your authoritative source of data and have the view work itself out without your intervention. But you can also do some work upfront with static files to clip and delete features, but I don't recommend this if you ever plan to revisit a map.

Example:

Starting with two shapefiles (could be database tables) of rivers and lakes, with rivers intersecting lakes and causing labelling issues that are hard to resolve completely and confidently:

enter image description here

Bring these into Postgres if you need to with shp2pgsql:

shp2pgsql -s 4326 /data/lake public.lakes | psql -d mydb

shp2pgsql -s 4326 /data/river public.rivers | psql -d mydb

Then define a view with ST_Difference:

CREATE OR REPLACE VIEW rivers_clipped AS
SELECT r.id, ST_Difference(r.geom, l.geom) AS geom, r.name
FROM public.rivers AS r, public.lakes AS l;

Add the view to your layout:

enter image description here

Although the problem in my example is deliberately fabricated, the styles in the two river layers (original and view) are the same, and they are placed on top of the lake in the drawing order. When you update the lakes or rivers geometries, you won't need to do much more than refresh the rendering.

enter image description here

  • 2
    While I wasn't working with a DB layer directly, this solution made the most sense to me, as it did not require editing the geometry of the initial data sources (other than loading them into the DB). This is a great example of thinking outside the box of shapefiles and application limitations, and finding a creative solution to the problem by combining both application and DB logic. – RyanDalton Jan 19 '16 at 15:48
13

In QGIS >= 2.12 you can set the "lake" polygon layer as a label obstacle. This is done through the layer properties of the "lake" layer, under the 'Labels' section. Change the combo box at the top from "No labels" to "Discourage other labels from covering features in this layer".

  • 1
    Thanks. I was looking for something like that, and had not noticed that drop-down option before. However, I would say this was only moderately successful. 1) It only "kind-of-sort-of" discouraged labels from the River layer (they still show up in within the lake, but less-so), and 2) now I don't have my Lake name labels :( I have also tried setting the River labels > Obstacles "Discourage labels from covering features" (no success) and setting weights Low & High (no success), and setting Placement > Priority = Low & High (no success). – RyanDalton Jan 6 '16 at 22:52
  • Ah, maybe I misunderstood. If you have labels on the lake layer then make sure the "discourage labels from covering features" check box under the rendering tab is ticked. You may need to play with the "weight" slider and other options in this group to get the desired results. – ndawson Jan 6 '16 at 23:18
  • 1
    No, you were definitely on the right track. I played around with the weights (high weight on lake polygons + "minimize placing labels over the features interior, low weight on rivers) and got closer, but never really got to the point where the river labels were not on the lake. The issue appears to be associated with lines that are both inside and outside of the polygon. – RyanDalton Jan 7 '16 at 17:13
  • 4
    why don't you remove (or split) those lines when it come to labelling ? They are not usefull for your map anyway. – radouxju Jan 12 '16 at 7:46
4

I find labeling in general quite hard, at least to generate labels that please my cartographer's senses. While the automatic labelling feature works fine 80% of the time, there are cases like your river/lake labeling problem where it doesn't generate nice labeling. The automatic labeling is often tied to the geometry of the feature, e.g. how many parts are in a line so that at first all parts are being labeled. Of course QGIS has means to prevent repeated labeling, which also depends on the scale of the current map view.

Well anyway, my tip isn't a quick solution. I often create a specialised layer just for labelling, so that my labels are more easily controlled. And often the features geometry for cartographic representation can collide with a good geometry for labeling. So I would propose to create a new layer where the streams do not cross the lakes, so that you can circumvent the problem altogether. Having an extra labeling-layer can also help to prevent problems where the labeling direction is not in the intended one because it is tied to how the geometry was created.

Well, I fear that my tip is not what you expected, but I hope that my alternative approach my help you somehow.

  • You make a valid point that I could create a new dataset (which would be easy to do in this case... just erase out the line features under polygons), doubling up datasets doesn't sound too appealing or manageable, unless you use a database-driven method like @Richard Law mentioned. – RyanDalton Jan 12 '16 at 22:19
  • I see your point and I understand your hesitation to create a similar dataset twice. In my experience the label layer is frequently more different than the original data layer. For example, to stick with your river example, you might want to change the river's geometry further to join or split feature parts in order to create a nicer labeling which is repeated more reguarly. At least this is often the case for me when dealing with OSM roads for example which are sometimes quite arbitrarily organized. – Frank Jan 13 '16 at 19:06
3

there is a plugin called "Mask" which can be used to filter labels based on polygons.

As mentioned in my previous comment, however, it would be a lot easier if you could split your lines at intersection with the lakes (see different methods here). Then you can define a zero sized label for segments that are within the lakes ( "Layer" > "Labeling" > "Data Defined Settings" > "Size" then select the column where you store label size). Splitting keeps most of the properties of your river network and is reversible with dissolve, so you can continue to work with a single layer (store the total length in a specific attribute table if needed).

  • Thanks, the plugin sounds promising, so I will give it a try. – RyanDalton Jan 12 '16 at 22:20

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.