/posts  ·   /talks  ·   /boat  ·   /#30DayMapChallenge 2020 | 2022  ·  /About

2022 / Day 17: A map without a computer

I have a scrapbook for plotting out ideas of SQL processing flows and for todays entry I decided to revisit some of the old ones. Found a bunch of sketch-ups for a little something I did about 1.5 years ago. And I must apologize - as it has been already some time then most probably I won’t remember all the fine print details.

But. The task was to find a way to create road areas (polygons around road centerlines) from cadastral point descriptions. Yes, sure the points had a specific location, but the main goal was to use a description like “5.5 meters from the centerline” to shift the points around so that if the geometry of the road centerline changes, the road surface area would be recalculatable on the fly.

As a side-note: the structure of this description with a point itself was not a concern. At least in that moment.

But I remember distinctly thinking that this is essentially a question of a variable width buffer for the road centerline geometry. Which, given that we know the desired width at a linestrings node ( which can be stored e.g either as m-coordinate and retrieved via st_m or z-coordinate and retrieved via st_z) can be calculated as a st_union over the linestrings identifier of all st_convexhull polygons created from st_dumppoints points of a segmentized linestrings st_firstpoints and st_lastpoints st_buffers to the required width. Or in a bitsy more simplified form

select
    oid, st_union(geom) as geom
from (
    select
        oid, ord,
        lag(ord) over (partition by oid order by ord) as lag_oid,
        st_convexhull(
            st_collect(
                array[
                    geom,
                    lag(geom) over (partition by oid order by ord)
                ]
            )
        ) as geom
    from (
        select
            oid,
            pts.path[1] as ord,
            st_buffer(pts.geom, st_z(pts.geom)) as geom
        from (
            select
                1 as oid,
                st_makeline(
                    array[
                        st_pointz(0,0,5),
                        st_pointz(10,10,1),
                        st_pointz(20,20,5),
                        st_pointz(20,10,3.5)
                    ]
                ) geom
            ) d
                join lateral
                    st_dumppoints(d.geom) pts on true
        ) e
) f
where
    lag_oid is not null
group by
    oid
;

Which returns something in the line of

A variable width buffer of a linestring using PostGIS

But there are a few issues to be solved here first (as I see from the notes):

In the end the solution I came up with is essentially to snap points to the road centerline st_closestpoint or st_linelocatepoint - I can’t remember any more which one I used. Create the required buffers as with the variable width buffer, st_split the buffer with the road centerline, figure out if I need to keep the left- or right-hand side one, and then union these over the road centerline together.

Some additional notes from here are the questions:

output image