
.. DO NOT EDIT.
.. THIS FILE WAS AUTOMATICALLY GENERATED BY SPHINX-GALLERY.
.. TO MAKE CHANGES, EDIT THE SOURCE PYTHON FILE:
.. "auto_examples/15_solid_flagging.py"
.. LINE NUMBERS ARE GIVEN BELOW.

.. only:: html

    .. note::
        :class: sphx-glr-download-link-note

        :ref:`Go to the end <sphx_glr_download_auto_examples_15_solid_flagging.py>`
        to download the full example code.

.. rst-class:: sphx-glr-example-title

.. _sphx_glr_auto_examples_15_solid_flagging.py:


Solid Flagging (3D Volume)
==========================

This example demonstrates end-to-end solid-based flagging:

1. Build a regular block model from geometry.
2. Create a closed triangulated ellipsoid mesh in PyVista.
3. Load the mesh as a ``MeshSolid``.
4. Evaluate a boolean inside/outside mask for all block centroids.
5. Visualise centroid classification in 3D with a mesh wireframe.
6. Encode the result as a categorical block-model attribute.

.. GENERATED FROM PYTHON SOURCE LINES 14-25

.. code-block:: Python


    import tempfile
    from pathlib import Path

    import numpy as np
    import pandas as pd
    import pyvista as pv

    from parq_blockmodel import MeshSolid, ParquetBlockModel, RegularGeometry









.. GENERATED FROM PYTHON SOURCE LINES 26-28

Create a geometry-backed block model
------------------------------------

.. GENERATED FROM PYTHON SOURCE LINES 28-41

.. code-block:: Python


    temp_dir = Path(tempfile.gettempdir()) / "solid_flagging_example"
    temp_dir.mkdir(parents=True, exist_ok=True)
    pbm_path = temp_dir / "solid_flagging.pbm"

    geometry = RegularGeometry(
        corner=(0.0, 0.0, 0.0),
        block_size=(1.0, 1.0, 1.0),
        shape=(20, 16, 6),
    )
    pbm = ParquetBlockModel.from_geometry(geometry=geometry, path=pbm_path)
    blocks = pbm.read(index=None)








.. GENERATED FROM PYTHON SOURCE LINES 42-44

Build and ingest a named ellipsoid solid from PyVista
-----------------------------------------------------

.. GENERATED FROM PYTHON SOURCE LINES 44-59

.. code-block:: Python


    ellipsoid_surface = pv.Sphere(
        radius=1.0,
        center=(0.0, 0.0, 0.0),
        theta_resolution=40,
        phi_resolution=28,
    ).triangulate()
    ellipsoid_surface.points[:, 0] = 9.0 + 5.0 * ellipsoid_surface.points[:, 0]
    ellipsoid_surface.points[:, 1] = 7.5 + 4.0 * ellipsoid_surface.points[:, 1]
    ellipsoid_surface.points[:, 2] = 2.5 + 2.0 * ellipsoid_surface.points[:, 2]

    solid = MeshSolid.from_pyvista(ellipsoid_surface, name="ore_shell")

    print("Solid name:", solid.name)





.. rst-class:: sphx-glr-script-out

 .. code-block:: none

    Solid name: ore_shell




.. GENERATED FROM PYTHON SOURCE LINES 60-64

Evaluate centroid-in-solid and visualise in 3D
----------------------------------------------
We plot all block centroids and overlay the ellipsoid as a wireframe.
Inside and outside centroids use distinct colors.

.. GENERATED FROM PYTHON SOURCE LINES 64-105

.. code-block:: Python


    mask = solid.evaluate(pbm.geometry)
    block_ids = blocks["block_id"].to_numpy(dtype=np.int64)
    centroids = blocks[["x", "y", "z"]].to_numpy(dtype=float)
    inside_points = centroids[mask[block_ids]]
    outside_points = centroids[~mask[block_ids]]

    plotter = pv.Plotter()
    plotter.add_points(
        outside_points,
        color="#bdbdbd",
        point_size=5,
        render_points_as_spheres=True,
        label="outside",
    )
    plotter.add_points(
        inside_points,
        color="#2c7fb8",
        point_size=12,
        render_points_as_spheres=True,
        label="inside",
    )
    plotter.add_mesh(
        ellipsoid_surface,
        color="#6baed6",
        opacity=0.14,
        smooth_shading=True,
    )
    plotter.add_mesh(
        ellipsoid_surface,
        style="wireframe",
        color="#222222",
        line_width=0.9,
        opacity=0.9,
        label=f"{solid.name} wireframe",
    )
    plotter.add_legend()
    plotter.show_grid()
    plotter.show_axes()
    plotter.show()




.. image-sg:: /auto_examples/images/sphx_glr_15_solid_flagging_001.png
   :alt: 15 solid flagging
   :srcset: /auto_examples/images/sphx_glr_15_solid_flagging_001.png
   :class: sphx-glr-single-img





.. GENERATED FROM PYTHON SOURCE LINES 106-108

Encode the mask as a categorical block-model attribute
------------------------------------------------------

.. GENERATED FROM PYTHON SOURCE LINES 108-118

.. code-block:: Python


    inside_label = solid.name or "inside"
    domain = np.full(len(blocks), pd.NA, dtype=object)
    domain[mask[blocks["block_id"].to_numpy(dtype=np.int64)]] = inside_label
    blocks["solid_domain"] = pd.Categorical(domain, categories=[inside_label], ordered=False)

    pbm.write(blocks[["block_id", "solid_domain"]], merge=True)
    print("solid_domain (NA-aware):")
    print(pbm.read(columns=["solid_domain"], index=None)["solid_domain"].value_counts(dropna=False))





.. rst-class:: sphx-glr-script-out

 .. code-block:: none

    solid_domain (NA-aware):
    solid_domain
    NaN          1766
    ore_shell     154
    Name: count, dtype: int64




.. GENERATED FROM PYTHON SOURCE LINES 119-121

Plot the final 3D block model using the encoded categorical domain
------------------------------------------------------------------

.. GENERATED FROM PYTHON SOURCE LINES 121-124

.. code-block:: Python


    plotter: pv.Plotter = pbm.plot(scalar="solid_domain", threshold=True, enable_picking=True, grid_type="image")
    plotter.show()



.. image-sg:: /auto_examples/images/sphx_glr_15_solid_flagging_002.png
   :alt: 15 solid flagging
   :srcset: /auto_examples/images/sphx_glr_15_solid_flagging_002.png
   :class: sphx-glr-single-img






.. rst-class:: sphx-glr-timing

   **Total running time of the script:** (0 minutes 1.258 seconds)


.. _sphx_glr_download_auto_examples_15_solid_flagging.py:

.. only:: html

  .. container:: sphx-glr-footer sphx-glr-footer-example

    .. container:: sphx-glr-download sphx-glr-download-jupyter

      :download:`Download Jupyter notebook: 15_solid_flagging.ipynb <15_solid_flagging.ipynb>`

    .. container:: sphx-glr-download sphx-glr-download-python

      :download:`Download Python source code: 15_solid_flagging.py <15_solid_flagging.py>`

    .. container:: sphx-glr-download sphx-glr-download-zip

      :download:`Download zipped: 15_solid_flagging.zip <15_solid_flagging.zip>`


.. only:: html

 .. rst-class:: sphx-glr-signature

    `Gallery generated by Sphinx-Gallery <https://sphinx-gallery.github.io>`_
