A common way is to collapse multi-dimensional observations into low-dimensional realms that can be handled with simpler algorithms - in this case could try to find a coefficient for your 4 dimensions (x, y, length, azimuth) to project onto the 2 dimensions (x, y) needed for the cluster functionality in PostGIS.
The general idea is to create a surrogate table with Point geom
s having their coordinates augmented by a given coefficient derived off the 4 line predicates (x, y, length, azimuth); a simple starting point could be to use the ST_Centroid
of your segments as positional indicator and work in weighted factors of the predicates:
SELECT
line_id,
ST_MakePoint(
1 / ( <positional_weight> * x + <length_weight> * len + <directional_weight> * azm ),
1 / ( <positional_weight> * y + <length_weight> * len + <directional_weight> * azm )
) AS geom
FROM
<lines>,
LATERAL ST_Length(geom) AS len,
LATERAL ST_Centroid(geom) AS ctr,
LATERAL ST_X(ctr) AS x,
LATERAL ST_Y(ctr) AS y,
LATERAL ST_StartPoint(geom) AS sp,
LATERAL ST_EndPoint(geom) AS ep,
LATERAL DEGREES(ST_Azimuth(sp, ep)) AS azm
;
This is a simplistic weighting: you can and should normalize/enhance the factorization to suit your needs; the idea is to be able to weight all predicates individually based on their importance for the actual clustering.
On a table like the one above you can apply ST_ClusterDBSCAN
(or ST_ClusterKMEANS
) with the eps
parameter referencing the 'observation distance' of the surrogate Point coordinates. You can link back to your original lines by their line_id
.