Aller au contenu

Réaliser une carte comme la couverture de l'album Unknow Pleasures de Joy Division#

📆 Date de publication initiale : 11 Juillet 2022

Introduction#

icône globe musique note

Dans cet article, nous allons voir comment créer une carte Post-punk à la mode Joy Division en utilisant les générateurs de géométrie de QGIS.

La couverture de l'album 'Unknow Pleasures' du groupe Joy Division est iconique et a inspiré bon nombre de cartographes. Ne vous fait-elle pas penser à des courbes de niveaux ?

Joy Division cover

Commenter cet article


Joy Division, Joy Maps et Joy Plots#

La couverture de l'album Unkown Pleasures du groupe Joy Division amuse beaucoup de cartographes. C'est un thème très repris dans la #gistribe.

Voici par exemple une carte de l'Islande :

Carte de l'Islande

Dans le monde de la dataviz, on nomme ce type de rendu des ridgelines.

Ridgeline plots

L'album Unknow Pleasures est paru en 1979. Sa couverture est assez bien ancrée dans l'époque des années 80 avec un air assez pixel art, rétro-futuriste. Elle rappelle un peu les écrans de contrôle dans Star Trek ou Star Wars, ou l'esthétique du film Tron.

Dancing Girl Dance

Quand on regarde la couverture, tous les férus de carto y voient des courbes de niveau, ou un paysage. Personnellement, ça me fait penser à la vidéo promotionnelle du logiciel GRASS (1987).

La couverture de l'album est en réalité la reproduction d'une image intitulée "100 consecutive pulses from the pulsar CP 1919" qui représente les émissions radio du tout premier pulsar découvert en 1967. Chaque ligne représente une impulsion. C'était donc déjà une dataviz.

Voici ce que dit Wikipedia sur cette image :

The image was originally created by radio astronomer Harold Craft at the Arecibo Observatory for his 1970 doctoral dissertation as a way to visualize smaller pulses within larger ones, which might help explain what had been causing the pulses. He was unaware for years that the image was associated with the album cover until a friend told him; afterwards he bought a copy because he felt he should have one as the creator of the image.

Voici d'ailleurs à quoi ressemble l'image originale :

Image originale des impulsions

Cette image n'est pas sans rappeler la musique, notamment les courbes de réponse fréquentielle qui servent aux ingénieurs du son à égaliser dans les basses, médiums et aigus. Voilà si l'on souhaite faire un lien avec le monde de la musique

courbe de réponse fréquentielle


Téléchargement du MNT#

Je ferai la carte Joy Division de la Montagne Sainte-Victoire. Celle-ci domine Aix-en-Provence où j'habite.

Voici le secteur sur Géoportail :

Sainte-Victoire sur Géoportail

Cette montagne a été souvent peinte par Cézanne.

La Sainte Victoire peinte par Cézanne

Le MNT BDALTI de l'IGN à une résolution de 25 mètres sera suffisant pour notre carte.

Téléchargez le MNT sur votre département (j'avoue que j'ai un faible pour le site de Christian Quest). Mon département étant les Bouches-du-Rhône, le zip à télécharger est https://data.cquest.org/ign/bdalti/BDALTIV2_2-0_25M_ASC_LAMB93-IGN69_D013_2019-10-01.7z.


Découpage du MNT selon votre zone#

Localisez-vous sur votre zone grâce à l'outil de localisation (plugin French Locator Filter)

Localisation d'Aix

Découpez le MNT selon votre zone de référence via Raster > Extraction > Découper un raster selon une emprise en choisissant le mode dessin :

Découpe avec QGIS

Vous obtiendrez alors :

MNT découpé

Création de la couche d'emprise#

Ensuite, créez une couche vectorielle selon l'étendue de votre MNT.

Allez sur Extraire l'emprise de la couche :

Extraction de l'emprise

Puis, extrayez l'emprise de votre modèle numérique de terrain via Vecteur > Outils de recherche > Extraire l'emprise de la couche.

Extraire l'emprise

Voici l'emprise :

Emprise


QGIS, générateur de joie#

Allez dans les Propriétés de la couche Emprise, dans Style, et choisissez Générateur de géométrie, et dans un premier temps, le rendu Multiligne / Multi-Polyligne. Nous allons enfin pouvoir faire joujou !

Générateur de géométries

Nous allons procéder pas à pas afin de comprendre les différentes fonctions.

Nous allons créer des lignes horizontales :

Rendu en lignes

Voici le code associé :

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
collect_geometries(
    array_foreach(
        generate_series(
            y_min($geometry),
            y_max($geometry),
            200 -- Espace vertical entre les lignes
        ),
        with_variable(
            'y',
            @element,
            make_line(
                make_point(x_min($geometry), @y),
                make_point(x_max($geometry), @y)
            )
        )
    )
)

Ce dernier génère une séries de coordonnées Y :

1
2
3
4
5
generate_series(
    y_min($geometry),
    y_max($geometry),
    200 -- Espace vertical entre les lignes
)

Et crée une ligne entre le X min et le X max de l'étendue pour chaque Y

1
2
3
4
make_line(
  make_point(x_min($geometry), @y),
  make_point(x_max($geometry), @y)
)

Ensuite, nous densifions les lignes avec des points, ce qui laisse apparaître une grille de points. Ces points constitueront plus tard les noeuds de nos lignes.

Rendu en points

Voici le code associé :

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
collect_geometries(
    -- Collecte toutes les lignes de points
    array_foreach(
        generate_series(
            y_min($geometry),
            y_max($geometry),
            200 -- Espace vertical entre les lignes
        ),
        collect_geometries(
            -- Collecte une ligne de points
            with_variable(
                'y',
                @element,
                array_foreach(
                    generate_series(
                        x_min($geometry),
                        x_max($geometry),
                        50
                    ),
                    -- Espace horizontal entre les points
                    with_variable(
                        'x',
                        @element,
                        make_point(@x, @y)
                    )
                )
            )
        )
    )
)

Nous utilisons collect_geometries deux fois :

  1. une fois pour agréger les points d'une ligne horizontale
  2. une autre fois pour agréger toutes les lignes horizontales de points

Si nous ne mettions pas collect_geometries et que nous nous arrêtions seulement à array_foreach, nous n'obtiendrions pas de rendu graphique.

En commentant collect_geometries, nous pouvons débugger le code en laissant apparaître l'"ADN géométrique" du rendu :

Commenter le code

Maintenant, ce que l'on va faire, c'est déplacer chaque point vers le haut en fonction de la valeur du MNT qui se situe en dessous.
C'est-à-dire ceci :

Déplacement des points

Voici le code associé :

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
collect_geometries(
    --Collecte toutes les lignes de points
    array_foreach(
        generate_series(
            y_min($ geometry) + 200,
            y_max($ geometry) - 200,
            200 -- Espace vertical entre les lignes
        ),
        collect_geometries(
            -- Collecte une ligne de points
            with_variable(
                'y',
                @element,
                array_foreach(
                    generate_series(
                        x_min($ geometry) + 1,
                        x_max($ geometry) - 1,
                        50
                    ),
                    -- Espace horizontal entre les points
                    with_variable(
                        'x',
                        @element,
                        with_variable(
                            'point',
                            make_point(@x, @y),
                            with_variable(
                                'shift',
                                raster_value('dem', 1, @point) * 2,
                                translate(@point, 0, @shift)
                            )
                        )
                    )
                )
            )
        )
    )
)

Pour trouver la valeur du MNT, nous utilisons la fonction raster_value qui permet de croiser un point avec un raster.

1
raster_value('dem', 1, @point)

Nous exagérons la hauteur au point, en la doublant, comme ceci :

1
raster_value('dem', 1, @point) * 2

Pour déplacer le point en fonction de l'altitude au point, nous utilisons la fonction translate

1
2
3
4
5
translate(
    @point,
    0, -- Pas de translation en X
    raster_value('dem', 1, @point)*2
)

Si aucune valeur n'est trouvée sur un point, alors aucune géométrie ne sera retournée. On a dû affecter un petit offset aux X pour que les points croisent correctement le MNT.

1
2
3
4
5
generate_series(
    x_min($geometry) + 1, -- offset de 1 m
    x_max($geometry) - 1,
    50
)

Enfin, nous construisons une ligne qui relie chaque point qui a été déplacé.

Le rendu sera le suivant :

Rendu basique

St Patricks Day Rainbow GIF

Si vous êtes un puriste de l'album, vous pouvez choisir de n'afficher que 100 lignes, comme les 100 impulsions du pulsar, et de conserver les proportions du graphique au maximum en augmentant la marge (ou l'offset) sur les bords droit et gauche (soit en X) :

Rendu puriste

Voici le code associé :

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
smooth(
    collect_geometries(
        array_foreach(
            generate_series(
                y_min($ geometry) + 200,
                y_max($ geometry) - 200,
                (bounds_height($ geometry) - 400) / 100
            ),
            with_variable(
                'y',
                @element,
                make_line(
                    array_foreach(
                        generate_series(
                            x_min($ geometry) + 4000,
                            -- offset de 1 m
                            x_max($ geometry) - 4000,
                            50
                        ),
                        -- Un point tous les 50 m
                        with_variable(
                            'x',
                            @element,
                            with_variable(
                                'point',
                                make_point(@x, @y),
                                with_variable(
                                    'shift',
                                    raster_value('dem', 1, @point) * 2,
                                    translate(
                                        @point,
                                        0,
                                        -- Pas de translation en X
                                        @shift
                                    )
                                )
                            )
                        )
                    )
                )
            )
        )
    ),
    1000 -- Valeur de lissage pour les lignes
)

Pour créer une ligne depuis les points ou noeuds déplacés, on utilise la fonction make_line

1
make_line([point1, point2, point3, ...])

Pour avoir cent lignes, comme les 100 impulsions du pulsar, on utilise l'expression :

1
2
3
4
5
generate_series(
    y_min($geometry) + 200,
    y_max($geometry) - 200,
    (bounds_height($geometry) - 400) / 100
)

Enfin, nous avons ajouté un petit smoothing aux lignes pour un rendu plus doux.

1
smooth(..., 1000)

Voilà, le tutoriel est fini. On voit qu'il y a pas mal de choses intéressantes et possibles à faire en utilisant seulement les geometry generators. Après le design génératif, voici venue l'ère de la carto générative.

A vous de jouer !

Dance Dancing GIF

Mon T-Shirt Joy Division

Pas mal de variations sont possibles sur la base de ces lignes. Voici une petite variation avec Blender accomplie par Steven Kay :


Petit livret de cuisine#

Pour résumer, voici les ingrédients utilisés pour cette carte :

  • Raster > Extraction > Découper un raster selon une emprise
  • Vecteur > Outils de recherche > Extraire l'emprise de la couche

Les fonctions :

  • array_foreach
  • bounds_height
  • collect_geometries
  • generate_series
  • make_line
  • make_point
  • raster_value
  • smooth
  • translate

Crédits#


Auteur#

Mathieu Rajerison#

Mathieu Rajerison

Agronome de formation, je travaille actuellement au Cerema, un centre d'études et d'expertise associé au Ministère de l'Ecologie en tant qu'ingénieur de données géomaticien.

Je m'intéresse particulièrement aux statistiques spatiales, ainsi qu'aux "contorsions" cartographiques.

J'ai rejoint la GéoTribu en 2013. Les revues de presse m'ont permis de partager au plus grand nombre les pépites géomatiques trouvées sur la Toile.

Selon l'humeur du moment, j'alimente un blog appelé datagistips et il m'arrive, aussi, de diffuser des choses sur twitter.

Licence #

Ce contenu est sous licence Creative Commons International 4.0 BY-NC-SA, avec attribution et partage dans les mêmes conditions, sauf dans le cadre d'une utilisation commerciale.
Les médias d'illustration sont potentiellement soumis à d'autres conditions d'utilisation.

Détails

Vous êtes autorisé(e) à :

  • Partager : copier, distribuer et communiquer le matériel par tous moyens et sous tous formats
  • Adapter : remixer, transformer et créer à partir du matériel pour toute utilisation, exceptée commerciale.

Citer cet article :

"Réaliser une carte comme la couverture de l'album Unknow Pleasures de Joy Division" publié par Mathieu RAJERISON sur Geotribu sous CC BY-NC-SA - Source : https://static.geotribu.fr/articles/2022/2022-07-11_qgis_joy_division/


Contributions à cette page : Julien Moura (42.73%), Mathieu Rajerison (56.36%), Geotribot (0.91%)

Ce contenu est sous licence Creative Commons BY-NC-SA 4.0 International Pictogramme Creative Commons Pictogramme Creative Commons BY Pictogramme Creative Commons NC Pictogramme Creative Commons SA


Commentaires

Une version minimale de la syntaxe markdown est acceptée pour la mise en forme des commentaires.
Propulsé par Isso.