.. SPDX-FileCopyrightText: 2025 Kohei Yoshida .. .. SPDX-License-Identifier: MIT .. highlight:: cpp Bulk-loading data ================= In this section we will explore on how to bulk-load data into an :cpp:class:`~mdds::rtree` instance via rtree's own :cpp:class:`~mdds::rtree::bulk_loader` class. In this example, we'll be using the same custom trait we've used in the previous section in order to artificially promote the rate of node splits. The first part of the code: .. literalinclude:: ../../example/rtree_medium_bulkload.cpp :language: C++ :start-after: //!code-start: tree-type :end-before: //!code-end: tree-type is pretty much identical to the example in the last section. The next part of the code defines what bounding rectangles to be inserted. Here, we are using a somewhat larger rectangle set than the one used in the previous example to better highlight the difference between normal insertions and bulk-loading: .. literalinclude:: ../../example/rtree_medium_bulkload.cpp :language: C++ :start-after: //!code-start: input-data :end-before: //!code-end: input-data As with the previous example, each line in the ``rects`` initialization block contains the top-left position of a rectangle (``x`` and ``y``) as well as its size (``w`` and ``h``). But unlike the previous example, We are going to insert them in two different ways. First, we are going to insert them via normal :cpp:func:`~mdds::rtree::insert()` method: .. literalinclude:: ../../example/rtree_medium_bulkload.cpp :language: C++ :start-after: //!code-start: normal-load :end-before: //!code-end: normal-load :dedent: 4 This code should look familiar since it's nearly identical to the code in the previous example. After the insertion is done, we export the tree as an SVG to visualize its structure. Next, we insert the same set of rectangles via :cpp:class:`~mdds::rtree::bulk_loader`: .. literalinclude:: ../../example/rtree_medium_bulkload.cpp :language: C++ :start-after: //!code-start: bulkload :end-before: //!code-end: bulkload :dedent: 4 Inserting via :cpp:class:`~mdds::rtree::bulk_loader` shouldn't be too different than inserting via rtree's own insert methods. The only difference is that you instantiate a :cpp:class:`~mdds::rtree::bulk_loader` instance to insert all your data to it first, then call its :cpp:func:`~mdds::rtree::bulk_loader::pack()` method at the end to construct the final :cpp:class:`~mdds::rtree` instance. When the insertion is done and the tree instance created, we are once again exporting its structure to an SVG file for visualization. There are primarily two advantages to using :cpp:class:`~mdds::rtree::bulk_loader` to load data. First, unlike the normal insertion, bulk-loading does not trigger dynamic re-insertion nor node splits during insertion. Second, a tree created from the bulk loader is typically well balanced than if you insert the same data through normal insertion. That is because the bulk loader sorts the data with respect to their bounding rectangles ahead of time to partition them evenly. The tree is then populated from the bottom-up. You can visually see the effect of this when comparing the two trees built in our current example. The first one is from the tree built via normal insertion: .. figure:: ../_static/images/rtree_bounds2_tree.png :align: center The top part of the picture looks very "busy" indicated by a darker green area indicative of more directory nodes overlaping with each other. In general, the bounding rectangles look bigger and are more overlapped. The one below, on the other hand, is from the tree built with the same data set but through bulk-loading: .. figure:: ../_static/images/rtree_bounds2_tree_bulkload.png :align: center The bounding rectangles generally look smaller and show much less overlaps than the previous tree - traits indicative of a more balanced R-tree structure.