Our function is simple, KNN magic aside. As an input to the function, we allow geometry, as shown in the following query:
CREATE OR REPLACE FUNCTION chp04.angle_to_street (geometry) RETURNS double precision AS $$
The preceding function returns a floating-point value.
We then use a WITH statement to create a temporary table, which returns the five closest lines to our point of interest. Remember, as the index uses bounding boxes, we don't really know which line is the closest, so we gather a few extra points and then filter them based on distance. This idea is implemented in the following query:
WITH index_query as (SELECT ST_Distance($1,road.geom) as dist, degrees(ST_Azimuth($1, ST_ClosestPoint(road.geom, $1))) as azimuth FROM street_centerlines As road ORDER BY $1 <#> road.geom LIMIT 5)
Note that we are actually returning to columns. The first column is dist, in which we calculate the distance to the nearest five road lines. Note that this operation is performed after the ORDER BY and LIMIT functions have been used as filters, so this does not take much computation. Then, we use ST_Azimuth to calculate the angle from our point to the closest points (ST_ClosestPoint) on each of our nearest five lines. In summary, what returns with our temporary index_query table is the distance to the nearest five lines and the respective rotation angles to the nearest five lines.
If we recall, however, we were not looking for the angle to the nearest five but to the true nearest road line. For this, we order the results by distance and further use LIMIT 1:
SELECT azimuth FROM index_query ORDER BY dist LIMIT 1;