Skip to content

Commit afa2a02

Browse files
committed
add FWA_SegmentAlongInterval, tweak LocateAlongInterval parameter order to match- fix #168
1 parent 9500b61 commit afa2a02

File tree

3 files changed

+168
-4
lines changed

3 files changed

+168
-4
lines changed

db/sql/functions/FWA_LocateAlongInterval.sql

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
CREATE OR REPLACE FUNCTION whse_basemapping.FWA_LocateAlongInterval(blue_line_key integer, start_measure integer DEFAULT 0, interval_length integer DEFAULT 1000, end_measure integer DEFAULT NULL)
1+
CREATE OR REPLACE FUNCTION whse_basemapping.FWA_LocateAlongInterval(blue_line_key integer, interval_length integer DEFAULT 1000, start_measure integer DEFAULT 0, end_measure integer DEFAULT NULL)
22

33
RETURNS TABLE
44
(
@@ -90,4 +90,4 @@ END;
9090
$$
9191
LANGUAGE 'plpgsql' IMMUTABLE PARALLEL SAFE;
9292

93-
COMMENT ON FUNCTION whse_basemapping.FWA_LocateAlongInterval IS 'Return a table (index, measure, geom), representing points along a stream between specified locations at specified interval'
93+
COMMENT ON FUNCTION whse_basemapping.FWA_LocateAlongInterval IS 'Return a table (index, measure, geom), representing points along a stream at a specified interval between specified locations'
Lines changed: 103 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,103 @@
1+
CREATE OR REPLACE FUNCTION whse_basemapping.FWA_SegmentAlongInterval(
2+
blue_line_key integer,
3+
start_measure integer DEFAULT 0,
4+
interval_length integer DEFAULT 100,
5+
end_measure integer DEFAULT NULL
6+
)
7+
8+
-- note that multipart geometries are returned in order to support non-contiguous stream geoms
9+
-- (ie, cross border or similar)
10+
11+
RETURNS TABLE
12+
(
13+
index integer,
14+
downstream_route_measure double precision,
15+
upstream_route_measure double precision,
16+
geom geometry(MultiLineString, 3005)
17+
)
18+
19+
AS
20+
21+
$$
22+
23+
DECLARE
24+
25+
v_blkey integer := blue_line_key;
26+
v_interval integer := interval_length;
27+
v_measure_start integer := start_measure;
28+
v_measure_end integer := end_measure;
29+
v_measure_max numeric;
30+
v_measure_min numeric;
31+
32+
BEGIN
33+
34+
-- find min and max measures of the stream
35+
-- (round measures to avoid floating point issues)
36+
SELECT
37+
min(round(s.downstream_route_measure::numeric, 3)) as min_measure,
38+
max(round(s.upstream_route_measure::numeric, 3)) as max_measure
39+
FROM whse_basemapping.fwa_stream_networks_sp s
40+
WHERE s.blue_line_key = v_blkey
41+
INTO v_measure_min, v_measure_max;
42+
43+
-- Check that the provided measure actually falls within the min/max measures of stream
44+
-- (if portions of the stream do not exist in the db there will simply be gaps in returned points)
45+
IF v_measure_start < v_measure_min OR v_measure_start > v_measure_max THEN
46+
RAISE EXCEPTION 'Input start_measure value does not exist in FWA';
47+
END IF;
48+
49+
IF v_measure_end > v_measure_max THEN
50+
RAISE EXCEPTION 'Input end_measure value does not exist in FWA';
51+
END IF;
52+
53+
IF v_measure_end <= v_measure_start THEN
54+
RAISE EXCEPTION 'Input end_measure value must be more than input start_measure value';
55+
END IF;
56+
57+
IF (v_measure_end - v_measure_start) < v_interval THEN
58+
RAISE EXCEPTION 'Distance between start_measure and end_measure is less than input interval_length';
59+
END IF;
60+
61+
-- if no end point provided, process the entire stream
62+
IF v_measure_end IS NULL THEN
63+
v_measure_end := v_measure_max;
64+
END IF;
65+
66+
RETURN QUERY
67+
68+
69+
WITH start_pts as
70+
(
71+
SELECT
72+
generate_series(0, v_measure_end / v_interval) as n,
73+
v_blkey as blue_line_key,
74+
generate_series(v_measure_start, v_measure_end, v_interval) as downstream_route_measure
75+
),
76+
77+
intervals as (
78+
SELECT
79+
n,
80+
s.blue_line_key,
81+
s.downstream_route_measure,
82+
coalesce(lead(s.downstream_route_measure) OVER (ORDER BY n), v_measure_end) AS upstream_route_measure
83+
FROM start_pts s
84+
)
85+
86+
select
87+
i.n::integer as index,
88+
i.downstream_route_measure::double precision,
89+
i.upstream_route_measure::double precision,
90+
ST_Multi(st_union(ST_LocateBetween(s.geom, i.downstream_route_measure, i.upstream_route_measure))) as geom
91+
FROM intervals i
92+
inner join whse_basemapping.fwa_stream_networks_sp s on s.blue_line_key = i.blue_line_key
93+
AND s.downstream_route_measure <= i.downstream_route_measure
94+
AND s.upstream_route_measure > i.downstream_route_measure
95+
GROUP BY i.n, i.blue_line_key, i.downstream_route_measure, i.upstream_route_measure
96+
ORDER BY i.n;
97+
98+
END;
99+
100+
$$
101+
LANGUAGE 'plpgsql' IMMUTABLE PARALLEL SAFE;
102+
103+
COMMENT ON FUNCTION whse_basemapping.FWA_SegmentAlongInterval IS 'Return a table (index, downstream_route_measure, upstream_route_measure, geom), representing segments along a stream between specified locations at specified interval'

docs/04_functions.md

Lines changed: 63 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -256,8 +256,8 @@ Create a point geometry at measure 25,000 on the Skeena River:
256256
```sql
257257
FWA_LocateAlongInterval(
258258
blue_line_key integer,
259-
start_measure integer DEFAULT 0,
260259
interval_length integer DEFAULT 1000,
260+
start_measure integer DEFAULT 0,
261261
end_measure integer DEFAULT NULL
262262
)
263263
```
@@ -283,8 +283,8 @@ Return points at a 1km interval along the Peace between Site C and Bennet dams:
283283
ST_AsText(geom)
284284
FROM FWA_LocateAlongInterval(
285285
359572348,
286-
1597489,
287286
1000,
287+
1597489,
288288
1706733
289289
);
290290
```
@@ -309,6 +309,67 @@ Make the same request as the example above, but
309309
[at 10km](https://features.hillcrestgeo.ca/fwa/functions/fwa_locatealonginterval/items.html?blue_line_key=359572348&start_measure=1597489&interval_length=10000&end_measure=1706733&limit=100)
310310

311311

312+
## FWA_SegmentAlongInterval
313+
314+
### Synopsis
315+
316+
```sql
317+
FWA_SegmentAlongInterval(
318+
blue_line_key integer,
319+
interval_length integer DEFAULT 100,
320+
start_measure integer DEFAULT 0,
321+
end_measure integer DEFAULT NULL
322+
)
323+
```
324+
325+
### Description
326+
327+
Return a table representing segments of given equal interval along a stream, between input locations.
328+
Note that final stream segment is the remainder of the stream under the given interval.
329+
330+
| field | type | description |
331+
| :-------------------------| --------------------- |-------------------------------------------- |
332+
| `index` | integer | 0 based index of returned features |
333+
| `downstream_route_measure`| double precision | measure value of start point of segment |
334+
| `upstream_route_measure` | double precision | measure value of end point of segment |
335+
| `geom` | geometry(MultiLineString, 3005) | Geometry of stream between the given measures |
336+
337+
### Example
338+
339+
Return stream segments at a 100m interval along the entire Goldstream river:
340+
341+
```sql
342+
SELECT
343+
index as id,
344+
downstream_route_measure,
345+
upstream_route_measure,
346+
ST_AsText(geom)
347+
FROM FWA_SegmentAlongInterval(
348+
354152425,
349+
100
350+
);
351+
```
352+
```
353+
id | downstream_route_measure | upstream_route_measure | st_astext
354+
-----+--------------------------+------------------------+-------------------
355+
0 | 100 | 200 | MULTILINESTRING Z ((
356+
1 | 200 | 300 | MULTILINESTRING Z ((
357+
2 | 300 | 400 | MULTILINESTRING Z ((
358+
359+
...
360+
```
361+
Mapping the returned features:
362+
363+
![watershed](images/segmentalonginterval.png)
364+
365+
### Web service
366+
367+
[FWA_SegmentAlongInterval](https://features.hillcrestgeo.ca/fwa/functions/fwa_segmentalonginterval.html)
368+
369+
Make the same request as the example above, but
370+
[at 1km](https://features.hillcrestgeo.ca/fwa/functions/fwa_segmentalonginterval/items.html?blue_line_key=354152425&interval_length=1000&limit=100)
371+
372+
312373
## FWA_StreamsAsMVT
313374

314375
### Synopsis

0 commit comments

Comments
 (0)