[postgis-users] Are there script examples for determine where vertices run clockwise or anti-clockwise?

Shaozhong SHI shishaozhong at gmail.com
Thu Feb 17 11:39:35 PST 2022

```On Thu, 17 Feb 2022 at 18:10, Marcin Mionskowski <
mionskowskimarcin at gmail.com> wrote:

> "The terms clockwise and counterclockwise can only be applied to a
> rotational motion once a side of the rotational plane is specified, from
> which the rotation is observed."
> https://en.wikipedia.org/wiki/Clockwise
> So, you need some kind of rotation (direction change) and some reference.
> In case of a polygon (or a closed line representing boundary of a polygon)
> both are obvious -> boundary direction and interior of a polygon.
> In case of a line the reference part is missing.
> What seams reasonable to me is to:
> - divide LINESTRING into segments,
> - combine consecutive segments into pairs,
> - chose 1st segment as a reference,
> - calculate the angle between segments (with respect to its direction OFC)
> using ST_Angle.
> The problem is, that one LINESTRING can have different "orientations". The
> CW/CCW is a property of {segment pair|the middle vertex of a pair of
> segments}.
> You can also use some direction as a reference (north in your example),
> but it has the same disadvantages and gives no additional information
> other than the azimuth/azimuth class.
>
> Anyway, the SQL could look like:
>
> with
> a_line as (
> select 1 gid,ST_geomfromtext('LINESTRING(0 0,1 1,2 0,3 1)') a_line
> union all
> select 2 gid,ST_geomfromtext('LINESTRING(0 0,0.5 1,2 0.5,3.5 1)') a_line
> )
> , points as (
> select gid,(ST_DumpPoints(a_line)).*
> from a_line
> )
> , segments as (
> select p1.gid,p1.path||p2.path
> start_end_points,ST_MakeLine(p1.geom,p2.geom) seg_geom
> from points p1, points p2
> where p1.gid=p2.gid and p1.path[1]+1=p2.path[1]
> )
> select s1.gid
> , s1.start_end_points||s2.start_end_points[2] points
> , case floor(st_angle(s1.seg_geom,s2.seg_geom)/pi()) when 0 then 'CW' else
> 'CCW' end
> from segments s1,segments s2
> where s1.gid=s2.gid and s1.start_end_points[2]=s2.start_end_points[1];
>
> If you insist on using the azimuth, replace the part from ", segments as
> (" with:
>
> select p1.gid,p1.path||p2.path start_end_points,ST_Azimuth(p1.geom,p2.geom)
> from points p1, points p2
> where p1.gid=p2.gid and p1.path[1]+1=p2.path[1]
>
> You can use LEAD() to optimize performance, but the SQL above is more
> readable in my opinion (it explains the logic better, I think).
>
>
> This looks very interesting.  Perhaps, if using ST_Azimuth, it can be used
to do the following:

divide linestring into segments,
combine consecutive segments into pairs
chose previous segment as a reference
calculate the azimuth change (positive or negative)
calculate the accumulative change
If the accumulative change is greater than 180, the line is doing a U-turn
If the accumulative change is greater than 180, the line is doing a
circular motion

Potentially, it can also be adapted for determine whether a line is doing
zig-zagging.

Am I right?

Regards,

David
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.osgeo.org/pipermail/postgis-users/attachments/20220217/2d6b9ffa/attachment.html>
```