Prerequisite
For this solution to work, the point layer must have a field (in this example called buffer_id
) that contains the id of the joined buffer polygon. The solution was implemented in QGIS 3.30.3.
Label values
The values for the labels are generated with this expression:
to_int( -- optional cast to integer
length(
make_line(
$geometry,
centroid(
geometry(
get_feature( -- get the centroid of the buffer that matches the buffer_id of the joined point.
layer:='buffers',
attribute:='id', -- 'id' in single quotes is the `id` field name in the buffers layer
value:="buffer_id" -- "buffer_id" in double quotes is the field value of the **current point** in the joined layer
)
)
)
)
)
)
The expression finds the feature in the buffers
layer where the buffer_id matches the joined field in the points layer, makes a line from the buffer centroid to the current point and gets the length of that line.
The expression is entered by clicking the button next to the Value text edit. The mode is changed to Offset from point
and the lower center quadrant is selected.
Label placement
The labels are placed at the midpoint of the connecting lines using this expression:
centroid( -- get the centroid (mid-point) of the line joining the point with the centroid of its associated buffer
make_line(
$geometry,
centroid(
geometry(
get_feature(
layer:='buffers',
attribute:='id', -- 'id' in single quotes is the `id` field name in the buffers layer
value:="buffer_id"
)
)
)
)
)
The expression is entered by checking Geometry Generator and clicking on the ... button next to the text edit area. Point / MultiPoint
is chosen as the geometry type.
Label rotation
The labels are rotated parallel to the line using this expression:
main_angle( -- get the angle of the line joining the point with the centroid of its associated buffer
make_line(
$geometry,
centroid(
geometry(
get_feature(
layer:='buffers',
attribute:='id', -- 'id' in single quotes is the `id` field name in the buffers layer
value:="buffer_id"
)
)
)
)
) + 90 -- add 90 to make the label text parallel to the line
The expression is entered as a Data defined override by clicking the button next to Rotation in the Data defined
section
Unfortunately, it is not a desirable Geometry Generator, however, I can suggest a PyQGIS approach. It is primarily based on the segmentizeArc()
method of the QgsGeometryUtils
class. Perhaps this tool would be a nice add-on to QGIS functions.
Let's assume there is a polyline layer (five features), see the image below. Line visualization imitates OP's example.
Proceed with Plugins > Python Console > Show Editor
(Ctrl+Alt+P) and paste the script below:
# imports
from qgis.core import (QgsProject, QgsVectorLayer, QgsGeometryUtils,
QgsFeature, QgsGeometry, QgsPoint)
# getting the original polyline layer by its name
layer = QgsProject.instance().mapLayersByName("YOUR_LAYER_NAME")[0]
# creating a polyline layer for the output
vl = QgsVectorLayer(f"LineString?crs={layer.crs().authid()}&index=yes", "arrows_like", "memory")
provider = vl.dataProvider()
# adding all fields from the original layer
provider.addAttributes(layer.fields())
vl.updateFields()
# looping over each original feature
for feat in layer.getFeatures():
# initiating a new feature
new_feat = QgsFeature()
# accessing original polyline geometry as a list of QgsPointXY
geom_points = feat.geometry().asPolyline()
# converting each QgsPointXY to QgsPoint in the list
points = list(map(lambda point: QgsPoint(point), geom_points))
# building arcs from three points
arc_as_points_seq = QgsGeometryUtils.segmentizeArc(points[0], points[1], points[2])
# converting a sequence of points to a polyline
new_geom = QgsGeometry.fromPolyline(arc_as_points_seq)
# setting up new geometry
new_feat.setGeometry(new_geom)
# setting up initial attributes
new_feat.setAttributes(feat.attributes())
# finalizing a new feature
provider.addFeature(new_feat)
QgsProject.instance().addMapLayer(vl)
Press Run script
and get the output that will look like:
Best Answer
Edit: new version
Use this expression:
Screenshot: point X is inside polygon X and polygon Y, but only polygon X is created with Geoemtry generator, based on the common attribute value
X
:Old version
Use this expression: