"""
.. _wrap_in_bbox:

Bounding Box Wrapper
====================

This example demonstrates the various features of the
:any:`qtcad.builder.Builder.wrap_in_bbox` and
:any:`qtcad.builder.Builder.extrude_mask_bbox` operations using an
Xmon coupler layout.
"""

# %%
# Introduction
# ------------
#
# The :any:`qtcad.builder.Builder.wrap_in_bbox` method wraps the entire model
# or a specific group in a bounding box with a designated padding. This can
# be useful, for example, when wrapping a device in a surrounding
# dielectric such as air.
#
# Similarly, :any:`qtcad.builder.Builder.extrude_mask_bbox` allows for
# extruding the bounding box of a mask directly.
#
# First, we import the required module.

from qtcad.builder import Builder

# %%
# Base Model Factory
# ------------------
#
# We define a helper function to instantiate a :class:`qtcad.builder.Builder`,
# load the layout of the Xmon coupler, and extrude the metal
# layer. This allows us to demonstrate different wrapping features from a
# clean baseline.
#
# The layout contains three physical groups: ``"ground_plane"``, ``"xmon"``,
# and ``"coupler"``.


def make_xmon_base() -> Builder:
    return (
        Builder(name="xmon_coupler", length_unit_exponent=-6)
        .load_layout("./layouts/xmon_coupler.oas", cell_name="TOP")
        .set_mesh_size(50)
        .use_mask("layer_1")
        .extrude(0.1)
    )


# %%
# Case 1: Wrapping the Entire Model
# ---------------------------------
#
# To wrap the entire model, we use :meth:`~qtcad.builder.Builder.fill_mode` to ensure
# physical groups inherit intersecting regions, set the active group name to
# ``"wrapper_all"``, and call :meth:`~qtcad.builder.Builder.wrap_in_bbox`
# with a 3-tuple representing the padding in the x, y, and z directions.
#
# .. automethod:: qtcad.builder.Builder.wrap_in_bbox
#    :no-index:

builder_all = (
    make_xmon_base()
    .fill_mode()
    .set_group_name("wrapper_all")
    .wrap_in_bbox(padding=(200, 200, 300))
)

# %%
#
# We view the resulting model from a side view and save it as a PNG.

builder_all.view(
    save="figs/xmon_wrapped_all.png",
    angles=(-45, 0, 45),
    volume_labels=True,
    surfaces=True,
)

# %%
# Case 2: Wrapping a Specific Group
# ---------------------------------
#
# Rather than wrapping the entire model, we can wrap a single specific physical
# group. Here, we wrap only the coupler line (``"coupler"``) in a local
# bounding box named ``"wrapper_coupler"``.

builder_coupler = (
    make_xmon_base()
    .fill_mode()
    .set_group_name("wrapper_coupler")
    .wrap_in_bbox(padding=(50, 50, 20), group="coupler")
)

# %%
#
# Viewing the model with the local coupler wrapper.

builder_coupler.view(
    save="figs/xmon_wrapped_coupler.png",
    angles=(-45, 0, 45),
    volume_labels=True,
    surfaces=True,
)

# %%
# Case 3: Wrapping a List of Specific Groups
# ------------------------------------------
#
# The ``group`` argument also accepts a list of physical group names. Here, we
# wrap both the ``"xmon"`` and ``"coupler"`` in a single
# bounding box named ``"wrapper_active"``.

builder_active = (
    make_xmon_base()
    .fill_mode()
    .set_group_name("wrapper_active")
    .wrap_in_bbox(padding=(100, 100, 50), group=["xmon", "coupler"])
)

# %%
#
# Viewing the model with the combined active components wrapper.

builder_active.view(
    save="figs/xmon_wrapped_active.png",
    angles=(-45, 0, 45),
    volume_labels=True,
    surfaces=True,
)

# %%
# Case 4: Wrapping in a 2D Bounding Surface
# -----------------------------------------
#
# If a 3D bounding box is not desired, we can wrap the active device components in a 2D
# bounding surface using :meth:`~qtcad.builder.Builder.wrap_in_bbox_surface`.
#
# .. automethod:: qtcad.builder.Builder.wrap_in_bbox_surface
#    :no-index:
#
# We wrap only the ``"xmon"`` group in a 2D bounding surface at the central plane (z = 5)
# with 150 padding named ``"wrapper_surface"``.

builder_surf = (
    make_xmon_base()
    .set_z(5)
    .set_group_name("wrapper_surface")
    .wrap_in_bbox_surface(padding=150, group="xmon")
)

# %%
#
# Viewing the model with the 2D bounding surface wrapper.

builder_surf.view(
    save="figs/xmon_wrapped_surface.png",
    angles=(-45, 0, 45),
    volume_labels=True,
    surfaces=True,
)


# %%
# Case 5: Extruding a Mask Bounding Box
# -------------------------------------
#
# Finally, we demonstrate the :meth:`~qtcad.builder.Builder.extrude_mask_bbox`
# operation. This method extrudes the bounding box of a specified mask (or the
# current mask if none is specified) by a given height.
#
# .. automethod:: qtcad.builder.Builder.extrude_mask_bbox
#    :no-index:

builder_extrude_bbox = (
    make_xmon_base()
    .set_z(0)
    .set_group_name("wrapper_mask")
    .extrude_mask_bbox(height=-200, mask="layer_1")
)

# %%
#
# Viewing the model with the extruded mask bounding box.

builder_extrude_bbox.view(
    save="figs/xmon_extrude_mask_bbox.png",
    angles=(-45, 0, 45),
    volume_labels=True,
    surfaces=True,
)
