.. SPDX-FileCopyrightText: 2025 Kohei Yoshida
..
.. SPDX-License-Identifier: MIT

.. highlight:: cpp

Visualize R-tree structure
==========================

In this section we will illustrate a way to visualize the structure of an R-tree
via :cpp:func:`~mdds::rtree::export_tree()`, which can be useful when you need
to visually inspect the tree structure to see how well balanced it is (or not).

We will be using the following set of 2-dimensional rectangles as the bounding
rectangles for input values.

.. figure:: ../_static/images/rtree_bounds_src.png
   :align: center

For input values, we'll simply use linearly increasing series of integer values,
but the values themselves are not the focus of this section, so we'll not focus
much on that.  We will also intentionally make the capacity of the directory
nodes smaller so that the tree will split more frequently during insertion even
with smaller number of inputs.

First, we need to talk about how the concrete rtree type is defined:

.. literalinclude:: ../../example/rtree_medium.cpp
   :language: C++
   :start-after: //!code-start: tree-type
   :end-before: //!code-end: tree-type

The first and second template arguments specify the key and value types to be
both ``int``.  This time around, however, we are specifying the third template
argument to be a struct containing several static constant values.  These
constant values define various traits of your R-tree, and there are some
constraints you need to be aware of in case you need to define your own custom
traits.  Refer to :cpp:class:`~mdds::detail::rtree::default_rtree_traits`, which
is the default traits used when you don't specify a custom one, for the
descriptions of the individual constants that your traits struct is expected to
include as well as their constraints.

Also be aware that these constants must all be constant expressions with
``constexpr`` specifiers, as some of them are used within ``static_assert``
declarations, and even those that are currently not used within
``static_assert`` may be used in ``static_assert`` in the future.

The only part of the custom traits we need to highlight in our current example
is that we are setting the directory node size to 2 to 5 instead of the default
size of 40 to 100, to trigger more node splits and make the tree artificially
deeper.

Let's move on to the next part of the code:

.. literalinclude:: ../../example/rtree_medium.cpp
   :language: C++
   :start-after: //!code-start: input-data
   :end-before: //!code-end: input-data
   :dedent: 4

This ``rects`` variable holds an array of 2-dimensional rectangle data that
represent the positions and sizes of rectangles shown earlier in this section.
This will be used as bounding rectangles for the input values in the next part
of the code:

.. literalinclude:: ../../example/rtree_medium.cpp
   :language: C++
   :start-after: //!code-start: insert
   :end-before: //!code-end: insert
   :dedent: 4

Here, the tree is instantiated, and the input rectangles are inserted with their
associated values one at a time.  Once the tree is populated, the code that
follows will export the structure of the tree as an SVG string, which will
then be saved to a file on disk:

.. literalinclude:: ../../example/rtree_medium.cpp
   :language: C++
   :start-after: //!code-start: export
   :end-before: //!code-end: export
   :dedent: 4

When you open the exported SVG file named **bounds.svg** in a SVG viewer,
you'll see something similar to this:

.. figure:: ../_static/images/rtree_bounds_tree.png
   :align: center

which depicts not only the bounding rectangles of the inserted values
(the red rectangles), but also the bounding rectangles of the directory
nodes as well (the light green rectangles).
