I try to make a Perpilou's map on QGIS, I managed to get a working code but it is not generic at all, so I am looking for ways to improve it.
A Perpillou map is a (old-fashioned) cartographic method of representing multivariate quantitative data quite effectively. Its general operation is as follows: We start with a set of quantitative variables whose proportions we want to represent and we use these values to generate a filling pattern (see figure 1). These patterns are always similar, we represent each variable by a band whose width is proportional to the value of the variable and we juxtapose all these bands. It is important to note that the total width of the figure (e.g. Band A + B + C) must always be the same size (manualy choosed). It is only the part occupied by each of the different bands that should vary. Figure 1 illustrates what this representation would look like if variable A represented 50% of the total, variable B 10% and variable C 40%.
This pattern, must then be applied for each polygon (fig 2). As the polygons are not necessarily the same size as the pattern, they are repeated and if they are larger than the pattern, they are cut off (as shown on the right in fig 2). The only constraint is that the strips must be aligned vertically to avoid shifts that are painful to read.
I managed to approach this result on a regular mesh using the geometry generator. In this case the size of pattern is the size of polygon (ei. xmax _xmin). I generate the geometry of each band (A, B or C on the example) with this functions :
Geometry for the first band (A) :
make_polygon(
make_line(
# Point below left
make_point(
x_min($geometry),
y_min($geometry)),
# Point Up left
make_point(
x_min($geometry),
y_max($geometry)),
# Point Up right
make_point(
x_min($geometry) + ("A" / ("A" + "B" + "C"))*(x_max($geometry)-x_min($geometry))),
y_max($geometry)),
# Point Up below
make_point(
x_min($geometry) + ("A" / ("A" + "B" + "C"))*(x_max($geometry)-x_min($geometry))),
y_min($geometry)),
# First point to close the polygon
make_point(
x_min($geometry),
y_min($geometry))
)
)
Geometry for the second band (B) :
make_polygon(
make_line(
# Point below left
make_point(
x_min($geometry) + ("A" / ("A" + "B" + "C")) *(x_max($geometry)-x_min($geometry)),
y_min($geometry)),
# Point Up left
make_point(
x_min($geometry) + ("A" / ("A" + "B" + "C")) *(x_max($geometry)-x_min($geometry)),
y_max($geometry)),
# Point Up right
make_point(
x_min($geometry) + ("B" / ("A" + "B" + "C"))*(x_max($geometry)-x_min($geometry))),
y_max($geometry)),
# Point Up below
make_point(
x_min($geometry) + ("B" / ("A" + "B" + "C"))*(x_max($geometry)-x_min($geometry))),
y_min($geometry)),
# First point to close the polygon
make_point(
x_min($geometry) + ("A" / ("A" + "B" + "C")) *(x_max($geometry)-x_min($geometry)),
y_min($geometry))
)
)
Geometry for the last band (C) :
make_polygon(
make_line(
# Point below left
make_point(
x_min($geometry) + (("A" + "B") / ("A" + "B" + "C")) *(x_max($geometry)-x_min($geometry)),
y_min($geometry)),
# Point Up left
make_point(
x_min($geometry) + (("A" + "B")) / ("A" + "B" + "C")) *(x_max($geometry)-x_min($geometry)),
y_max($geometry)),
# Point Up right
make_point(
x_min($geometry) + ("C" / ("A" + "B" + "C"))*(x_max($geometry)-x_min($geometry))),
y_max($geometry)),
# Point Up below
make_point(
x_min($geometry) + ("C" / ("A" + "B" + "C"))*(x_max($geometry)-x_min($geometry))),
y_min($geometry)),
# First point to close the polygon
make_point(
x_min($geometry) + (("A" + "B") / ("A" + "B" + "C")) *(x_max($geometry)-x_min($geometry)),
y_min($geometry))
)
)
This results in the following rendering :
I am quite satisfied with the result, but not with the method to produce it. Indeed :
- This code can only works when the polygons have the same size
- It's necessary to modify the function as soon as the variables (or their number) change
Is there a way to correct these problems and do better in QGIS using only the symbology tools ?
xmin
of the right triangle will be at the middle of the left triangle.