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

Marcin Mionskowski mionskowskimarcin at gmail.com
Thu Feb 17 13:28:45 PST 2022

```Yes, but there are many more "ifs" in your two if sentences.
For example 'LINESTRING(0 0,0 1,180 1,179.5 0)' has a cumulative azimuth
change greater than 180, but I wouldn't say it is a U-turn, or that it is
doing circular motion.
And what about 'LINESTRING(1 0,1 1,-10 1,-10 2,1 2,1 30,2 30,2 2,30 2,30
1,2 1,2 0)'? Segment set [2,3,4] is looking like a U-turn, but when you add
1st segment it's not.
As usually, IMO, it's all about data and definitions :)

czw., 17 lut 2022 o 20:39 Shaozhong SHI <shishaozhong at gmail.com> napisał(a):

>
>
> 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
> _______________________________________________
> postgis-users mailing list
> postgis-users at lists.osgeo.org
> https://lists.osgeo.org/mailman/listinfo/postgis-users
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.osgeo.org/pipermail/postgis-users/attachments/20220217/9e73bef1/attachment.html>
```