# NEw ST_Angle function, with test and doc #97

Closed
wants to merge 15 commits into
from

## Conversation

Projects
None yet
3 participants

### Remi-C commented Feb 25, 2016

 Hey, new function with 2 behaviours, ST_Angle(P1,P2,P3) returns the angle of P1P2P3 ST_ANgle(P1,P2,P3,P4) returns the angle of 2 vectors P1P2,P3P4 For an easy visual test, use the query in the doc to generate a few dozen angles, and display in qgis. Cheers

### strk reviewed Feb 25, 2016

 n_args = i ; if (n_args < 3) lwpgerror("Empty geometry"); break;

#### strk Feb 25, 2016

Member

Should this be a PG_RETURN_NULL() instead ?

#### strk Feb 25, 2016

Member

Sorry, I meant within the conditional block, not outside

### strk reviewed Feb 25, 2016

 ST_Angle Returns the angle in radian measured clokwise between 3 points, or the angle measured clockwise between 2 vectors.

#### strk Feb 25, 2016

Member

"clokwise" -> "clockwise" (first occurrence)

If I may suggest also keeping the "refpurpose" text small (may omit radian and clockwise, leaving it specified in the "description")

### strk reviewed Feb 25, 2016

 geometry point1 geometry point2 geometry point3 geometry point4

#### strk Feb 25, 2016

Member

Isn't the 4th point optional ? There should be a tag or attribute to specify that in the docs.

### strk reviewed Feb 25, 2016

 For 3 points, computes the angle measured clockwise of P1P2P3. For 4 points,compute the angle measured clockwise of P1P2,P3P4. Results are always positive, between 0 and 2*Pi radians. Uses ST_Azimuth.

#### strk Feb 25, 2016

Member

"Uses ST_Azimuth" isn't really true, it's using liblwgeom internal functions (on which ST_Azimuth is also based).

### strk reviewed Feb 25, 2016

 lwpoint = lwgeom_as_lwpoint(geom_unser); if ( ! lwpoint ) { PG_FREE_IF_COPY(geom, i);

#### strk Feb 25, 2016

Member

These memory releases should really affect all the previous geometry inputs, or only the last one would be released.

### strk reviewed Feb 25, 2016

 if ( ! getPoint2d_p(lwpoint->point, 0, &points[i]) ) { PG_FREE_IF_COPY(geom, i); lwpgerror("Error extracting point");

#### strk Feb 25, 2016

Member

This should really only happen when the point is empty (hint hint [ for reducing complexity ])

### strk reviewed Feb 25, 2016

 if (n_args == 3) { if ( ! azimuth_pt_pt(&points[0], &points[1], &az1) ) PG_RETURN_NULL();

#### strk Feb 25, 2016

Member

I guess the code here expects azimuth_pt_pt to call lwerror itself, better specify it with a comment, or a reader would be wondering why no error message is printed.

An lwpgerror could even be left to be even ready shall liblwgeom stop reporting errors in such a primitive way :)

### strk reviewed Feb 25, 2016

 ST_Angle_4_pts|4.71238898038469 ST_Angle_4_pts|0.785398163397448 ST_Angle_3_pts|1.5707963267949 ERROR: Operation on mixed SRID geometries

#### strk Feb 25, 2016

Member

The EMPTY case is missing a test

#### Remi-C Feb 25, 2016

Hey,
I removed the empty test case because ST_Azimuth is failing it.
(it returns another error than the one expected)
it returns `ERROR: getPoint2d_p: point offset out of range`

#### Remi-C Feb 25, 2016

hm never mind its ok I added the missing test, thanks

Member

### Remi-C commented Feb 25, 2016

 Hey @strk , thanks for the review! I don't get the PG_RETURN_NULL stuff, what do you mean exactly? (I don't get either the error you mention, are you pointing to a line in perticular (I don't know how to see it if this is the case)) I corrected the other things you mention, now working on the memory stuff. Cheers
Member

### strk commented Feb 25, 2016

 I just meant that any "lwpgerror" call should be followed by a PG_RETURN_NULL(), which wasn't done in the n_args < 3 check (btw, on re-reading that check is probably bogus and the source of your problems with empty ?)

### Remi-C commented Feb 25, 2016

 @strk I don't get the memory issue you mention. `POINT2D points[4];` doesn't need to be freed manually I guess. Other variables are freed in each loop, so no need to free those in case of error some loop after? Do you mean I should free `geom_unser` and / or `lwpoint` before each `PG_RETURN_NULL` ? Cheers
Member

### strk commented Feb 25, 2016

 I mean the PG_FREE_IF_COPY calls you add. They are inconsistent. Ideally you'd have a PG_FREE_IF_COPY call for each and every parameter, before exiting or raising an error.

### Remi-C commented Feb 26, 2016

 Hey @strk, here is a rewrite, with better separation of exception and actual computing. Exception are tried on serialized geometry. About `PG_FREE_IF_COPY`, from what I understand there is no need to use it on a parameter if you havn't used `PG_GETARG_GSERIALIZED_P`. If this is true, it should be ok as it is now (only one arg is in memory at a time, being cleaned at the end of the loop anyway) Cheers, Remi-C
Member

### strk commented Feb 26, 2016

 Ok so I see you're detoasting/free-if-copying once for checking and again for actual using. Could you avoid the duplication ?

### strk reviewed Feb 26, 2016

 if (!lwpoint) { lwpgerror("Error unserializing geometry"); PG_RETURN_NULL() ;

#### strk Feb 26, 2016

Member

Also this misses a PG_FREE_IF_COPY...

#### Remi-C Feb 26, 2016

@strk Ok as you suggested I stored the serialized pointers to keep getting
those twice.
Now `PG_FREE_IF_COPY` is always executed if exceptions or in regular
operations.

2016-02-26 14:47 GMT+01:00 Sandro Santilli notifications@github.com:

In postgis/lwgeom_functions_basic.c
#97 (comment):

• ``````      case 3:
``````
• ``````      lwpgerror("Operation on mixed SRID geometries");
``````
• ``````      PG_RETURN_NULL();
``````
• ``````      break;
``````
• ``````  }
``````
• /* extract points */
• for(i=0; i<n_args; i++)
• {
• ``````  geom = PG_GETARG_GSERIALIZED_P(i);
``````
• ``````  geom_unser = lwgeom_from_gserialized(geom) ;
``````
• ``````  lwpoint = lwgeom_as_lwpoint(geom_unser);
``````
• ``````  if (!lwpoint)
``````
• ``````  {
``````
• ``````      lwpgerror("Error unserializing geometry");
``````
• ``````      PG_RETURN_NULL() ;
``````

Also this misses a PG_FREE_IF_COPY...

Reply to this email directly or view it on GitHub
https://github.com/postgis/postgis/pull/97/files#r54244102.

### Remi-C commented Feb 26, 2016

 Hey @strk , here the pointers are stored to avoid calling twice the functions. Cheers

### strk reviewed Feb 26, 2016

 /* dont do lwpoint_free(lwpoint); , this memory is needed ! */ } for (j=0;j

#### strk Feb 26, 2016

Member

It is not safe to release the serialized format after deserializing, because LWGEOM can still refer to the serialized POINTLIST.

### Remi-C commented Feb 26, 2016

 @strk : thanks to help me learn all of this. Cheers, RemiC
Member

### robe2 commented May 20, 2017

 @Remi-C looks like this isn't ready yet as @strk had one last note doesn't look like you addressed. Also this needs to be rebased if to be committed for PostGIS 2.4.
Member

### robe2 commented Aug 10, 2017

 @Remi-C can you rebase and I'll test and commit for PostGIS 2.4

### Remi-C commented Sep 5, 2017

 Hey Regina, @strk, I removed the serialized memory freeing. About my rebasing, I think I messed something, I rebased so my branch st_angle is updated and contains all the latest postgis commits. What I don't understand is why now the pull request contains also all the postgis commits? Shall we drop this pull request and make a new one? Cheers, Rémi-C 2017-08-10 12:09 GMT+02:00 Regina Obe : … @Remi-C can you rebase and I'll test and commit for PostGIS 2.4 — You are receiving this because you were mentioned. Reply to this email directly, view it on GitHub <#97 (comment)>, or mute the thread .
Member

### strk commented Sep 5, 2017

 Try this (assuming "origin" points to the official mirror): git rebase origin git push -f
Member

### robe2 commented Sep 5, 2017

 keep in mind it's too late for this to go into 2.4. Has to wait for 2.5

### Remi-C added some commits Feb 25, 2016

``` Adding test for ST_Azimuth ```
``` b2ece5c ```
``` new st_angle function with test and doc ```
`2 behaviours, depending on 3 points or 4 points input`
``` 0f2c23a ```
``` Slight change on doc and typos ```
``` 814d280 ```
``` adding a wrapper st_angle(line1,line2) ```
``` 37d3c8b ```
``` adding missing pg_return_null and a comment about error ```
``` 7bfb66c ```
``` rewrite of st_angle so it doesn't deserialize for check, better memor… ```
`…y management`
``` e1f7645 ```
``` storing serialized arg to not ask for theim twice ```
``` 9fb5aad ```

### Remi-C and others added some commits Feb 26, 2016

``` dont free unserialized memory , cast to point might need it ```
``` 8857ad9 ```
``` removing freeing of serialized memory after it has been deserialized … ```
`…because lw could need this memory`
``` 8d751ca ```
``` Adding test for ST_Azimuth ```
``` 4b054ef ```
``` new st_angle function with test and doc ```
`2 behaviours, depending on 3 points or 4 points input`
``` e88d706 ```
``` Slight change on doc and typos ```
``` 0959a78 ```
``` adding a wrapper st_angle(line1,line2) ```
``` 3396b7c ```
``` availability changed to 2.5 ```
``` ee76121 ```
``` sql function declaration was dupliquated, updated to 2.5 ```
``` 87401b4 ```

### Remi-C commented Sep 7, 2017

 Hey @robe2, no problem, it'll be for 2.5 with any luck. Thanks @strk, this fixed it (after some awkward manual edits) Minor typos

### pramsey pushed a commit to pramsey/postgis-gh that referenced this pull request Oct 16, 2017

``` ST_Angle function from Rémi Cura ```
```Closes postgis/postgis#97
Closes #3876

git-svn-id: https://svn.osgeo.org/postgis/trunk@15884 b70326c6-7e19-0410-871a-916f4a2858ee```
``` 9b5a673 ```

Closed