Based on @kazuhito's answer I put together a single, hacky expression in the QGIS Field Calculator that should do the same thing in one step.
However I can imagine this will be very resource-intensive on larger datasets. I think the problem is best suited to a Python implementation, which obviously handles referencing and iteration far better than the Field Calculator.
This first creates an 'array' of node numbers using
generate_series(), specifying the maximum as the number of nodes in each polygon - this is
num_points($geometry), minus 1 to skip the repeated first/last node.
You can then pass the values of this array through a function to generate another array using
array_foreach(). Here we pass the polygon node number (represented as
point_n(), which returns the actual geometry of that node, then we feed that into
line_locate_point() to determine its length along the specified line (see Important Note below).
The resulting array is then sorted in ascending order using
array_sort() which then lets us get the "leftmost" and "rightmost" distances along the line using
array_first(). Subtract the two and the result is the "length" of the polygon along the line.
See below for an example of the above expression shown as a label in the polygons (plus "leftmost" and "rightmost" line distances split off from the above expression). For comparison I have also included extracted vertices and relevant line distance values. Green vertices are the "leftmost" and "rightmost" vertices along the line. Note the top-left polygon where the green point is actually further along the line than the point to the right below it, due to the angle of the line...
The line layer geometry is referenced here using
aggregate(). You will need to change the layer name (
'lines') as required, and if you have multiple lines, you should add a filter to specify which line you want to compare it with, e.g.:
aggregate('lines','collect',$geometry,"name"='TrainLine1') . To make this automatically work on the closest line I really recommend SQL or Python over Field Calc.
Also, this calculates the "length" of the Polygon ALONG the line, including if the line is kinked per my example. If you want the straight-line distance... maybe calculate the
distance() between the relevant nodes?