Aller au contenu

Generate MVT Tile

Generate MVT tiles for geographic model.

This script provides a Django management command to generate MVT (Mapbox Vector Tiles) for specified geographic models. It supports multi-threading for improved performance and allows for the deletion of existing tiles before generating new ones.

Command

Bases: BaseCommand

Source code in back/api/management/commands/generate_mvt.py
 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
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
class Command(BaseCommand):
    help = "Generate MVT file for a specif model."

    def add_arguments(self, parser):
        parser.add_argument(
            "--number_of_thread",
            type=int,
            default=1,
            help="Number of threads to use for generating tiles",
        )
        parser.add_argument(
            "--geolevel",
            type=str,
            required=True,
            choices=[choice for choice, _ in GeoLevel.choices],
            help=f"What geolevel to transform to MVT. Choices: {', '.join([choice for choice, _ in GeoLevel.choices])}",
        )
        parser.add_argument(
            "--datatype",
            type=str,
            required=True,
            choices=[choice for choice, _ in DataType.choices],
            help=f"What datatype to transform to MVT. Choices: {', '.join([choice for choice, _ in DataType.choices])}",
        )
        parser.add_argument(
            "--keep",
            action="store_true",
            help="Keep already existing tiles, do not delete them.",
        )

    def generate_tiles_for_model(
        self,
        model: Type[Model],
        queryset: QuerySet,
        zoom_levels: Tuple[int, int] = DEFAULT_ZOOM_LEVELS,
        number_of_thread: int = 1,
    ) -> None:
        """
        Generate MVT tiles for a geographic model.

        This method generates MVT (Mapbox Vector Tiles) for a specified geographic model
        based on the provided queryset and zoom levels. It utilizes multiple threads
        to enhance performance.

        Args:
            model (Type[Model]): The model class to generate MVT tiles for.
            queryset (QuerySet): The queryset of the model instances to process.
            zoom_levels (Tuple[int, int]): A tuple specifying the range of zoom levels
                                           to generate tiles for (inclusive).
            number_of_thread (int): The number of threads to use for generating tiles.

        Returns:
            None
        """
        mvt_generator = MVTGenerator(
            queryset=queryset,
            zoom_levels=zoom_levels,
            datatype=model.datatype,
            geolevel=model.geolevel,
            number_of_thread=number_of_thread,
        )

        mvt_generator.generate_tiles()
        self.stdout.write(self.style.SUCCESS("MVT tiles generated successfully!"))

    def handle(self, *args, **options):
        """Handle the command."""
        number_of_thread = options["number_of_thread"]
        geolevel = options["geolevel"]
        datatype = options["datatype"]
        if geolevel == GeoLevel.TILE.value:
            mdl = Tile
        elif geolevel == GeoLevel.LCZ.value and datatype == DataType.LCZ.value:
            mdl = Lcz
        elif (
            geolevel == GeoLevel.LCZ.value and datatype == DataType.VULNERABILITY.value
        ):
            mdl = Vulnerability
        elif (
            geolevel == GeoLevel.CADASTRE.value and datatype == DataType.CADASTRE.value
        ):
            mdl = Cadastre
        else:
            supported_levels = [
                GeoLevel.TILE.value,
                GeoLevel.LCZ.value,
                GeoLevel.CADASTRE.value,
            ]
            raise ValueError(
                f"Unsupported geolevel: {geolevel}. Currently supported: {', '.join(supported_levels)}"
            )

        if options["keep"] is False:
            print(f"Deleting existing MVTTile for model : {mdl._meta.model_name}.")
            print(
                MVTTile.objects.filter(
                    geolevel=geolevel, datatype=mdl.datatype
                ).delete()
            )
        # Generate new tiles
        self.generate_tiles_for_model(
            model=mdl,
            queryset=mdl.objects.all(),
            zoom_levels=DEFAULT_ZOOM_LEVELS,
            number_of_thread=number_of_thread,
        )

generate_tiles_for_model(model, queryset, zoom_levels=DEFAULT_ZOOM_LEVELS, number_of_thread=1)

Generate MVT tiles for a geographic model.

This method generates MVT (Mapbox Vector Tiles) for a specified geographic model based on the provided queryset and zoom levels. It utilizes multiple threads to enhance performance.

Parameters:

Name Type Description Default
model Type[Model]

The model class to generate MVT tiles for.

required
queryset QuerySet

The queryset of the model instances to process.

required
zoom_levels Tuple[int, int]

A tuple specifying the range of zoom levels to generate tiles for (inclusive).

DEFAULT_ZOOM_LEVELS
number_of_thread int

The number of threads to use for generating tiles.

1

Returns:

Type Description
None

None

Source code in back/api/management/commands/generate_mvt.py
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
def generate_tiles_for_model(
    self,
    model: Type[Model],
    queryset: QuerySet,
    zoom_levels: Tuple[int, int] = DEFAULT_ZOOM_LEVELS,
    number_of_thread: int = 1,
) -> None:
    """
    Generate MVT tiles for a geographic model.

    This method generates MVT (Mapbox Vector Tiles) for a specified geographic model
    based on the provided queryset and zoom levels. It utilizes multiple threads
    to enhance performance.

    Args:
        model (Type[Model]): The model class to generate MVT tiles for.
        queryset (QuerySet): The queryset of the model instances to process.
        zoom_levels (Tuple[int, int]): A tuple specifying the range of zoom levels
                                       to generate tiles for (inclusive).
        number_of_thread (int): The number of threads to use for generating tiles.

    Returns:
        None
    """
    mvt_generator = MVTGenerator(
        queryset=queryset,
        zoom_levels=zoom_levels,
        datatype=model.datatype,
        geolevel=model.geolevel,
        number_of_thread=number_of_thread,
    )

    mvt_generator.generate_tiles()
    self.stdout.write(self.style.SUCCESS("MVT tiles generated successfully!"))

handle(*args, **options)

Handle the command.

Source code in back/api/management/commands/generate_mvt.py
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
def handle(self, *args, **options):
    """Handle the command."""
    number_of_thread = options["number_of_thread"]
    geolevel = options["geolevel"]
    datatype = options["datatype"]
    if geolevel == GeoLevel.TILE.value:
        mdl = Tile
    elif geolevel == GeoLevel.LCZ.value and datatype == DataType.LCZ.value:
        mdl = Lcz
    elif (
        geolevel == GeoLevel.LCZ.value and datatype == DataType.VULNERABILITY.value
    ):
        mdl = Vulnerability
    elif (
        geolevel == GeoLevel.CADASTRE.value and datatype == DataType.CADASTRE.value
    ):
        mdl = Cadastre
    else:
        supported_levels = [
            GeoLevel.TILE.value,
            GeoLevel.LCZ.value,
            GeoLevel.CADASTRE.value,
        ]
        raise ValueError(
            f"Unsupported geolevel: {geolevel}. Currently supported: {', '.join(supported_levels)}"
        )

    if options["keep"] is False:
        print(f"Deleting existing MVTTile for model : {mdl._meta.model_name}.")
        print(
            MVTTile.objects.filter(
                geolevel=geolevel, datatype=mdl.datatype
            ).delete()
        )
    # Generate new tiles
    self.generate_tiles_for_model(
        model=mdl,
        queryset=mdl.objects.all(),
        zoom_levels=DEFAULT_ZOOM_LEVELS,
        number_of_thread=number_of_thread,
    )