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

.. only:: html

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

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

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

.. _sphx_glr_examples_04_metadata_units_and_conversion.py:


Units and unit conversion
=========================

The ``cad.units`` field-data slot records the document unit on read
and write. ``units_conversion_factor`` returns the scalar to multiply
points by to reach a target unit, so an mm-defined part can move into
meters (for FEA) or inches (for US-customary CAM) without leaving the
pipeline.

This example reads a real mm-defined STEP part, the NIST AM Bench
2022 LPBF bridge specimen (public domain,
https://doi.org/10.18434/mds2-2607), converts it to inches, and
confirms the bounding box and volume scale accordingly.

.. GENERATED FROM PYTHON SOURCE LINES 18-27

.. code-block:: Python


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

    import pyvista_cad
    from pyvista_cad._metadata import units_conversion_factor
    from pyvista_cad.examples import downloads








.. GENERATED FROM PYTHON SOURCE LINES 28-29

Read the real part. Verify the source unit.

.. GENERATED FROM PYTHON SOURCE LINES 29-35

.. code-block:: Python


    mb = pyvista_cad.read_step(downloads.step_part_path())
    mesh = mb.combine().extract_surface()
    src_unit = str(mesh.cad.units) if mesh.cad.units else 'mm'
    pd.DataFrame({'source_unit': [src_unit], 'bounds': [mesh.bounds]})





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

 .. code-block:: none

    /home/runner/work/pyvista-cad/pyvista-cad/examples/04_metadata/units_and_conversion.py:31: PyVistaFutureWarning: The default value of `algorithm` for the filter
    `UnstructuredGrid.extract_surface` will change in the future. It currently defaults to
    `'dataset_surface'`, but will change to `None`. Explicitly set the `algorithm` keyword to
    silence this warning.
      mesh = mb.combine().extract_surface()


.. raw:: html

    <div class="output_subarea output_html rendered_html output_result">
    <div>
    <style scoped>
        .dataframe tbody tr th:only-of-type {
            vertical-align: middle;
        }

        .dataframe tbody tr th {
            vertical-align: top;
        }

        .dataframe thead th {
            text-align: right;
        }
    </style>
    <table border="1" class="dataframe">
      <thead>
        <tr style="text-align: right;">
          <th></th>
          <th>source_unit</th>
          <th>bounds</th>
        </tr>
      </thead>
      <tbody>
        <tr>
          <th>0</th>
          <td>mm</td>
          <td>(0.0, 75.00000000000003, -2.445960101127298e-1...</td>
        </tr>
      </tbody>
    </table>
    </div>
    </div>
    <br />
    <br />

.. GENERATED FROM PYTHON SOURCE LINES 36-37

Convert mm -> inch. The scalar factor is 1/25.4.

.. GENERATED FROM PYTHON SOURCE LINES 37-51

.. code-block:: Python


    factor = units_conversion_factor(src_unit, 'inch')

    converted = mesh.copy()
    converted.points = converted.points * factor
    converted.field_data['cad.units'] = np.array(['inch'])
    pd.DataFrame(
        {
            'factor': [factor],
            'bounds_source': [mesh.bounds],
            'bounds_inch': [converted.bounds],
        }
    )






.. raw:: html

    <div class="output_subarea output_html rendered_html output_result">
    <div>
    <style scoped>
        .dataframe tbody tr th:only-of-type {
            vertical-align: middle;
        }

        .dataframe tbody tr th {
            vertical-align: top;
        }

        .dataframe thead th {
            text-align: right;
        }
    </style>
    <table border="1" class="dataframe">
      <thead>
        <tr style="text-align: right;">
          <th></th>
          <th>factor</th>
          <th>bounds_source</th>
          <th>bounds_inch</th>
        </tr>
      </thead>
      <tbody>
        <tr>
          <th>0</th>
          <td>0.03937</td>
          <td>(0.0, 75.00000000000003, -2.445960101127298e-1...</td>
          <td>(0.0, 2.952755905511812, -9.629764177666528e-1...</td>
        </tr>
      </tbody>
    </table>
    </div>
    </div>
    <br />
    <br />

.. GENERATED FROM PYTHON SOURCE LINES 52-54

Verify volumes scale by ``factor**3`` (the volume invariant for
isotropic scaling).

.. GENERATED FROM PYTHON SOURCE LINES 54-62

.. code-block:: Python


    pd.DataFrame(
        {
            'volume_ratio': [converted.volume / mesh.volume if mesh.volume > 0 else float('nan')],
            'expected': [factor**3],
        }
    )






.. raw:: html

    <div class="output_subarea output_html rendered_html output_result">
    <div>
    <style scoped>
        .dataframe tbody tr th:only-of-type {
            vertical-align: middle;
        }

        .dataframe tbody tr th {
            vertical-align: top;
        }

        .dataframe thead th {
            text-align: right;
        }
    </style>
    <table border="1" class="dataframe">
      <thead>
        <tr style="text-align: right;">
          <th></th>
          <th>volume_ratio</th>
          <th>expected</th>
        </tr>
      </thead>
      <tbody>
        <tr>
          <th>0</th>
          <td>0.000061</td>
          <td>0.000061</td>
        </tr>
      </tbody>
    </table>
    </div>
    </div>
    <br />
    <br />

.. GENERATED FROM PYTHON SOURCE LINES 63-64

Render the converted mesh.

.. GENERATED FROM PYTHON SOURCE LINES 64-69

.. code-block:: Python


    converted['Z (in)'] = converted.points[:, 2]
    pl = pv.Plotter()
    pl.cad.add(converted, scalars='Z (in)', cmap='viridis')
    pl.show()







.. tab-set::



   .. tab-item:: Static Scene



            
     .. image-sg:: /examples/04_metadata/images/sphx_glr_units_and_conversion_001.png
        :alt: units and conversion
        :srcset: /examples/04_metadata/images/sphx_glr_units_and_conversion_001.png
        :class: sphx-glr-single-img
     


   .. tab-item:: Interactive Scene



       .. offlineviewer:: /home/runner/work/pyvista-cad/pyvista-cad/doc/examples/04_metadata/images/sphx_glr_units_and_conversion_001.vtksz







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

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


.. _sphx_glr_download_examples_04_metadata_units_and_conversion.py:

.. only:: html

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

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

      :download:`Download Jupyter notebook: units_and_conversion.ipynb <units_and_conversion.ipynb>`

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

      :download:`Download Python source code: units_and_conversion.py <units_and_conversion.py>`

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

      :download:`Download zipped: units_and_conversion.zip <units_and_conversion.zip>`
