This solution might be not the best one in terms of time consumption and performance because of the data size (calculating for the whole world). However, if you want to achieve a "rapid" result (here you do not need to set up anything) IMHO this is what you need. Nevertheless, handling large data sets will be much more efficient by means of PostgreSQL with PostGIS extension. Perhaps writing a PyQGIS script is even better or as was suggested by @csk via using the Field Calculator.
I can suggest using a "Virtual Layer" through Layer > Add Layer > Add/Edit Virtual Layer...
Let's assume we have the following layers 'boundaries'
, 'coastlines'
, and 'rivers'
, see image below. Numbers over the lines represent the 'scalerank'
. I did not use the data provided in the question, because of the large volume.
Question I. For a boundary layer
With the following query, it is possible to create a dummy variable being 1
if a district lies on the coast and 0
if not, including a distance from the district to the closest coast (this will only give a value when a district does not intersect the coastline).
SELECT "boundaries".*,
(CASE
WHEN "boundaries".id IN
(SELECT "boundaries".id
FROM "boundaries", "coastlines"
WHERE st_intersects("boundaries".geometry, "coastlines".geometry))
THEN '1'
ELSE '0'
END) AS dummy_var,
ROUND(ST_Length(ST_ShortestLine("boundaries".geometry, "coastlines".geometry)),2) AS distance
FROM "boundaries", "coastlines"
GROUP BY "boundaries".id
ORDER BY MIN(ST_Length(ST_ShortestLine("boundaries".geometry, "coastlines".geometry)))
The output Virtual Layer with its Attribute table will look as following
In this case, be careful with geometric predicates since 'boundaries'
and 'coastlines'
cannot only intersect, as well as touch etc. Hence, you may extend the query with the OR
operator, i.e.
WHERE st_intersects("boundaries".geometry, "coastlines".geometry) OR st_touches("boundaries".geometry, "coastlines".geometry)
Moreover, mind the CRS. Work with one that provides a distance in miles, meters etc.
Question II. For a river layer
With the following query, it is possible to create a dummy variable 1
if a river crosses a district and 0
otherwise and for rivers with scale ranks between 1
and 5
.
WITH "rivers_1_5" AS (
SELECT *
FROM "rivers"
WHERE "scalerank" >= 1 AND "scalerank" <= 5
)
SELECT "boundaries".*,
(CASE
WHEN "boundaries".id IN
(SELECT "boundaries".id
FROM "boundaries", "rivers_1_5"
WHERE st_intersects("boundaries".geometry, "rivers_1_5" .geometry))
THEN '1'
ELSE '0'
END) AS dummy_var
FROM "boundaries"
GROUP BY "boundaries".id
The output Virtual Layer with its Attribute table will look as follows.
Answering the question in comments: "Where/How can I enter the code?"
In QGIS 3 paste the code and then run Add
In QGIS 2 paste the code and then run Ok