0

I have three layers. 1 point data with slaughterhouses, 1 point data with stores, and 1 line layer connecting the two (I connected them using the plugin "Connect points"). I want the lines with a slight curve, rather than straight. But I am only able to either have them straight, or with an insane curve, but no in between. Using the geometry generator so far just makes the lines dissapear.

With insane curves

straight lines

Vince
  • 20,017
  • 15
  • 45
  • 64
tina
  • 17
  • 1
  • 2
    Does this answer your question? Making lines curvy in QGIS – Comrade Che Nov 14 '23 at 12:56
  • I saw that post, but sadly does not answer my question. Since I created the lines instead of drawing them, I cannot add a vertex (as far as I know), so that solution does not work for me. – tina Nov 14 '23 at 13:10
  • This might be of help: https://gis.stackexchange.com/questions/457913/qgis-how-to-combine-a-single-line-and-a-centered-short-and-constant-offset-arrow/457930#457930 – Matt Nov 14 '23 at 13:53

1 Answers1

1

Curved lines can be achieved using line type arrow (if you set arrow head/length to 0, you in fact get a pure line style). To work, however, you need a third point that is not on the connecting line from start- to endpoint.

The trick to get a curved geometry now is to use Geometry Generator to create a line from start- to end point, but with an additional intermediate point somewhere offset off this line: create a new point in the middle of start/end of the line and shift this point perpendicular to the line. The distance of the shift can be adapted in the following expression (on line 15) to change the "radius" of the curve.

If you already have the lines, apply the following expression on the line layer with Geometry Generator:

Initial line (black dotted) and curved lines, created based on this, in red: enter image description here

make_line (
    start_point ($geometry),
    project (
        centroid (make_line (start_point($geometry), end_point($geometry))),
        length ($geometry)*0.19, --change here 
        radians (90+line_interpolate_angle ($geometry, length (@geometry)/2))
    ),
    end_point($geometry)
)

My first solution was based on directly creating the lines based on the points:

The expression here connects blue points to the four closest red points; adapt the expression to include the points you want to connect.

Connecting blue points (start) to the four closest points of layer "slaughter" (red), using the expression from below and setting the Geometry Generator's Geometry type to LineString and the line's Symbol layer type to Arrow (and in the arrow settings make sure to have checked the box Curved arrows). I set a line width of 0 at the start and 1.4 at the end, but you could style it as a simple line: enter image description here

This is the expression to use. In line 15, you can change the distance ("radius") of the curve:

collect_geometries(
    array_foreach (
        overlay_nearest (
            'slaughter',
            $geometry,
            limit:=4
        ),
        with_variable(
            'line',
            make_line ($geometry, @element),
            make_line (
                $geometry,
                project (
                    centroid (@line),
                    length(@line)*0.3, --change here 
                    line_interpolate_angle( 
                        @line,
                        length (@line)/2
                    )
                ),
                @element
            )
        )
    )
)
Babel
  • 71,072
  • 14
  • 78
  • 208
  • Thank you. However, my layer is already a line, not point data (see my first photo). I also do not want to create lines between the "nearest data". Some slaughterhouses provide meat to the 2 stores, others to 11 stores. So this will not work sadly – tina Nov 14 '23 at 16:01
  • You could still use the solution, changing only the part with overlay_nearest(), replacing it with the exact criteria you have. If already have the lines, however, it's even easier: use the same approach to create an additional point in the midde and shift it perpendically. See adapted answer. – Babel Nov 14 '23 at 16:19