Here is an example using QGIS 3.24.2-Tisler and data from a PostGIS (PG:14-3.2) database.
First create some dummy data in a PostGIS database:
-- DROP TABLE IF EXISTS public.measurement;
CREATE TABLE IF NOT EXISTS public.measurement
( id INT GENERATED ALWAYS AS IDENTITY PRIMARY KEY,
house TEXT,
geom GEOMETRY(MULTIPOINT,4326));
INSERT INTO measurement (house, geom) VALUES
('house1',
ST_SetSrid(
ST_Collect(ARRAY[
ST_GeomFromText('POINT(8.5050 47.3032)'), -- northern most
ST_GeomFromText('POINT(8.5054 47.3030)'), -- eastern most
ST_GeomFromText('POINT(8.5050 47.3028)'), -- southern most
ST_GeomFromText('POINT(8.5046 47.3030)') -- western most
]), 4326 )),
('house2',
ST_SetSrid(
ST_Collect(ARRAY[
ST_GeomFromText('POINT(8.4050 48.2032)'), -- northern most
ST_GeomFromText('POINT(8.4054 48.2030)'), -- eastern most
ST_GeomFromText('POINT(8.4050 48.2028)'), -- southern most
ST_GeomFromText('POINT(8.4046 48.2030)') -- western most
]), 4326 )),
('house3',
ST_SetSrid(
ST_Collect(ARRAY[
ST_GeomFromText('POINT(8.6050 49.7032)'), -- northern most
ST_GeomFromText('POINT(8.6054 49.7030)'), -- eastern most
ST_GeomFromText('POINT(8.6050 49.7028)'), -- southern most
ST_GeomFromText('POINT(8.6046 49.7030)') -- western most
]), 4326 ));
SELECT id, house, ST_AsText(geom) AS geom FROM measurement;
id | house | geom
----+--------+---------------------------------------------------------------------
1 | house1 | MULTIPOINT(8.505 47.3032,8.5054 47.303,8.505 47.3028,8.5046 47.303)
2 | house2 | MULTIPOINT(8.405 48.2032,8.4054 48.203,8.405 48.2028,8.4046 48.203)
3 | house3 | MULTIPOINT(8.605 49.7032,8.6054 49.703,8.605 49.7028,8.6046 49.703)
(3 rows)
Open QGIS, connect to the DB in the DB manager and load the layer in a new project.
In the layer styling window, select "Single Symbol" and "Edit" the color using the drop down menu:
In the "Expression String Builder" window which should normally have opened, use a CASE
expression and the geometry_part_num
as follow:
CASE
WHEN @geometry_part_num = 1 THEN '#aa0055de'
WHEN @geometry_part_num = 2 THEN '#aa0ecc22'
WHEN @geometry_part_num = 3 THEN '#aaf0f00a'
WHEN @geometry_part_num = 4 THEN '#aaed8b1a'
END
Finally click "OK" and "Apply" the changes:
You may have to play a bit to find the right order but here, the the sub-parts order used in the "Expression String Builder" window (using the geometry_part_num
variable) seems to follow the same as the one used when building the geometry in PostGIS.
Each of the 3 defined MultiPoints will have the same style.
For a GeoJSON, for example the first house, when dumped using ST_AsGeoJSON()
:
$ cat house1.geojson
{
"type": "MultiPoint",
"coordinates": [
[
8.505,
47.3032
],
[
8.5054,
47.303
],
[
8.505,
47.3028
],
[
8.5046,
47.303
]
]
}
If you copy paste the style from your previous layer, you will normally notice that the colors stay the same for each of the 4 sub-points. It seems to simply rely on the logical order of each point inside the GeoJSON structure.
So, now if for example you flip the coordinates of the subpoint 2 (east) <-> subpoint 4 (west):
$ cat house1_flip24.geojson
{
"type": "MultiPoint",
"coordinates": [
[
8.505,
47.3032
],
[
8.505,
47.3028
],
[
8.5046,
47.303
],
[
8.5054,
47.303
]
]
}
You will then notice that the eastern point (2) is now orange (because it became the 4th point), the western one (4) yellow (because it became the second point):
And the same style actually applies if you load such same ordered MutiPoint from PostGIS:
INSERT INTO measurement (house, geom) VALUES
('house1_flip24',
ST_SetSrid(
ST_Collect(ARRAY[
ST_GeomFromText('POINT(7.5050 47.3032)'), -- northern most
ST_GeomFromText('POINT(7.5046 47.3030)'), -- western most
ST_GeomFromText('POINT(7.5050 47.3028)'), -- southern most
ST_GeomFromText('POINT(7.5054 47.3030)') -- eastern most
]), 4326 ));
->