16

In QGIS there are two shapefiles representing the moving data between cells and one additional layer, see image below

Example_of_shapefiles

Moving data defined by:

  1. A polygon 'LayerA' (transparent squares with red outline). Besides it also relates to circles representing the movements within cells, visualized on the position of 'LayerA' geocentroids.

    LayerA_AT

  2. A polyline layer 'Flows' (yellow/grey arrows), convey values via connections between geocentroids of 'LayerA' features

    Flows_AT

Target layer:

  • Polygon 'LayerB' (light lilac features with dark grey outline).

    LayerB_AT

Additionally, I have already transferred "FLUX" and movement values within cells from 'LayerA' into 'LayerB' polygons, see my previous question: Inherited values between polygons in QGIS. It was done using the % of $area calculation.


There might be a meaningful solution/approach of transferring/transmitting/transforming flow connections represented by 'Flows' and its values from relations of 'LayerA' into relations of 'LayerB'.

How can I achieve those connections as polylines?

Additionally, new flows will inherit a similar style to 'Flows'.

By the request, I can provide a sample of the data.

Flows will exist not between features of 'LayerA', but between features of 'LayerB'. The main aim is to achieve the attribute "FLUX" (i.e. from/to) for connections between 'LayerB' possible as table/Origin-Destination Matrix.


There are some requirements/criteria that should be adhered:

  1. There are no flow connections between features' parts (selected in yellow) in the same cell

    condition_1

  2. There are no connections between the same feature even its parts are in different cells

    condition_2

  3. Connections exist between parts of features 'LayerB' (based on "Union" output) if they are entirely within two distinct 'LayerA' cell features

    condition_3

  4. New "FLUX"-value that is conveying, will be calculated as shown on the image below.

    For instance, there is a connection between two cells I and II, where "FLUX" is 100. Assuming other values, the "NEW_FLUX" between A' and B'' will be around 1.5625. 100 is only a single example.

    condition_4


References:

3
  • 1
    Thanks for the edit, I begin to understand but not very sure. Can you edit your original post one more time to add the expected result ? (for example : Line layer between polygon_b centroids with this fields below : - "field1" : explanation, attempted datas, etc.) Commented Apr 5, 2019 at 11:27
  • 1
    For clarify, can we discuss more freely on this GSE chat room : chat.stackexchange.com/rooms/92038/… ? Commented Apr 5, 2019 at 11:49
  • 2
    From a technical standpoint everything is doable, but what are you actually trying to achieve? Seems to me that you are trying to interpolate data from a generalize grid to a more finely grained geography. Unless i got you wrong, this can lead to very misleading results. If you don't have data about flows at the "layer B" level, no mathematic trickery can recreate them. It's the equivalent of zooming under pixel level and do a 3D rotation using a low resolution picture in an inaccurate cops movie.
    – MarHoff
    Commented Apr 9, 2019 at 12:14

2 Answers 2

5
+200

With the Virtual Layers, theoretically, it's possible (with shapefiles, the process will be extra long, but if the layers are in a Spatial Database, I think it is a lot faster).

Here the code :

-- create intersection between LayerA and LayerB 
WITH inter_ab AS ( 
    SELECT
        LayerA.id || '_' || LayerB.FLAECHEID AS id, 
        LayerA.id AS id_a, 
        ST_AREA(LayerA.geometry) AS area_a, 
        LayerB.FLAECHEID AS id_b, 
        ST_INTERSECTION(LayerB.geometry, LayerA.geometry) AS geom 
    FROM
        LayerA,
        LayerB 
    WHERE
        ST_INTERSECTION(layerB.geometry, layerA.geometry) IS NOT NULL 
    ),

-- calculation of the new flux value 
new_flux AS (
    SELECT
        t1.id_b AS origine, 
        t2.id_b AS dest, 
        SUM(Flows.flux * ST_AREA(t1.geom) / t1.area_a * ST_AREA(t2.geom) / t2.area_a) AS value  
    FROM
        inter_ab t1,
        inter_ab t2,
        flows 
    -- no connection between the same feature 
    WHERE
        t1.id <> t2.id 
        -- rule 1 
        AND t1.id_a <> t2.id_a 
        -- rule 2 
        AND t1.id_b <> t2.id_b 
        -- get flow data 
        AND flows.origine = t1.id_a 
        AND flows.dest = t2.id_a 
    GROUP BY
        t1.id_b,
        t2.id_b
    )

--create flows between original layerB features
SELECT
    new_flux.origine,
    new_flux.dest,
    new_flux.value AS flux,
     --ST_MakeLine under postGIS
    make_line(ST_CENTROID(t3.geometry), ST_CENTROID(t4.geometry)) AS geom
FROM
    LayerB t3,
    LayerB t4,
    new_flux
WHERE
    t3.FLAECHEID = new_flux.origine
    AND t4.FLAECHEID = new_flux.dest

The graphical output will look like

Output

The result was tested manually. The difference in "FLUX" values is neglectable.

The final output will inherit styles from "Flow" and look like

Output_Final

I recommend to test it with a few data, and if it takes too long for large data sets, execute step by step the queries ("inter_ab", "new_flux") and save the result and execute the next query.

3
  • 1
    Sorry, I'm french and I use an open french township database as Polygon_b layer, and it's key field is id_geofla. I made the correction. Commented Apr 4, 2019 at 11:31
  • 1
    I have added explanations, hope that helps. Commented Apr 5, 2019 at 8:11
  • 1
    Yes its correct to have polygons. I've made corrections for have the whole polygon_b layers and polygon_a.**value** if a flow make a connection. For me, the result is not a line layer, but directly polygon_b layer with the polygon_a value imported by flow layer. Commented Apr 5, 2019 at 9:04
4

You could do a join between the three layers, then aggregate by layerB. Virtual layers can likely be used. I am not sure if the important data is in layerA or in the flow layer.. Here is an (untested) possibility:

SELECT b.id, b.geometry, sum(a.myVar)
FROM layerB b
LEFT JOIN flow f
   ON ST_Intersects(ST_EndPoint(f.geometry),b.geometry)
 JOIN layerA a
   ON ST_Intersects(ST_StartPoint(f.geometry),a.geometry)
GROUP BY b.id
2
  • I have tried this solution it works. The important data is in "Flows".
    – Taras
    Commented Apr 4, 2019 at 10:42
  • @Taras Great! You can also use aggregates such as sum(f.flow_var) or even sum(fl.flow_var * a.poly_var)
    – JGH
    Commented Apr 4, 2019 at 12:12

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.