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

.. only:: html

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

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

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

.. _sphx_glr_examples_01_readers_read_fcstd.py:


Read a FreeCAD document
=======================

``.FCStd`` is FreeCAD's native document format: a zip archive carrying
``Document.xml`` plus one BREP per part. ``pyvista_cad.read_fcstd``
parses the manifest and tessellates the BREPs via OCP, no FreeCAD
binary required.

This example reads a real part straight from the FreeCAD parts library
(CC-BY 3.0, FreeCAD-library contributors): an M3 nyloc lock nut, and
walks the resulting :class:`pyvista.MultiBlock`.

Why this matters: FreeCAD is the dominant open-source MCAD package.
Reading FCStd without a FreeCAD install lets analysis pipelines pick
up community parts directly.

.. GENERATED FROM PYTHON SOURCE LINES 20-26

.. code-block:: Python


    import pyvista as pv

    import pyvista_cad
    from pyvista_cad.examples import downloads








.. GENERATED FROM PYTHON SOURCE LINES 27-28

Read the real FCStd document.

.. GENERATED FROM PYTHON SOURCE LINES 28-32

.. code-block:: Python


    mb = pyvista_cad.read_fcstd(downloads.fcstd_nut_path())
    mb






.. raw:: html

    <div class="output_subarea output_html rendered_html output_result">
    <div><style>/* PyVista HTML repr stylesheet.
     * Uses pv- prefix to avoid conflicts with other libraries.
     */

    :root {
      --pv-font-color0: var(--jp-content-font-color0, rgba(0, 0, 0, 1));
      --pv-font-color2: var(--jp-content-font-color2, rgba(0, 0, 0, 0.54));
      --pv-font-color3: var(--jp-content-font-color3, rgba(0, 0, 0, 0.38));
      --pv-border-color: var(--jp-border-color2, #e0e0e0);
      --pv-disabled-color: var(--jp-layout-color3, #bdbdbd);
      --pv-background-color-row-even: var(--jp-layout-color1, #f5f5f5);
      --pv-background-color-row-odd: var(--jp-layout-color2, #eeeeee);
      --pv-badge-active: #1b5e20;
      --pv-badge-normals: #0d47a1;
      --pv-badge-vectors: #00695c;
      --pv-badge-tcoords: #4527a0;
    }

    body[data-jp-theme-light="false"] {
      --pv-font-color0: var(--jp-content-font-color0, rgba(255, 255, 255, 1));
      --pv-font-color2: var(--jp-content-font-color2, rgba(255, 255, 255, 0.54));
      --pv-font-color3: var(--jp-content-font-color3, rgba(255, 255, 255, 0.38));
      --pv-border-color: var(--jp-border-color2, #424242);
      --pv-disabled-color: var(--jp-layout-color3, #616161);
      --pv-background-color-row-even: var(--jp-layout-color1, #1a1a1a);
      --pv-background-color-row-odd: var(--jp-layout-color2, #252525);
      --pv-badge-active: #66bb6a;
      --pv-badge-normals: #64b5f6;
      --pv-badge-vectors: #4db6ac;
      --pv-badge-tcoords: #b39ddb;
    }

    html[theme="dark"],
    html[data-theme="dark"],
    body[data-theme="dark"],
    body.vscode-dark {
      --pv-font-color0: rgba(255, 255, 255, 1);
      --pv-font-color2: rgba(255, 255, 255, 0.54);
      --pv-font-color3: rgba(255, 255, 255, 0.38);
      --pv-border-color: #424242;
      --pv-disabled-color: #616161;
      --pv-background-color-row-even: #1a1a1a;
      --pv-background-color-row-odd: #252525;
      --pv-badge-active: #66bb6a;
      --pv-badge-normals: #64b5f6;
      --pv-badge-vectors: #4db6ac;
      --pv-badge-tcoords: #b39ddb;
    }

    /* OS-level dark mode fallback: applies when no explicit data-theme is set */
    @media (prefers-color-scheme: dark) {
      html:not([data-theme="light"]) {
        --pv-font-color0: rgba(255, 255, 255, 1);
        --pv-font-color2: rgba(255, 255, 255, 0.54);
        --pv-font-color3: rgba(255, 255, 255, 0.38);
        --pv-border-color: #424242;
        --pv-disabled-color: #616161;
        --pv-background-color-row-even: #1a1a1a;
        --pv-background-color-row-odd: #252525;
        --pv-badge-active: #66bb6a;
        --pv-badge-normals: #64b5f6;
        --pv-badge-vectors: #4db6ac;
        --pv-badge-tcoords: #b39ddb;
      }
    }

    .pv-wrap {
      display: block !important;
      min-width: 300px;
      max-width: 700px;
      line-height: 1.6;
      padding-bottom: 4px;
      font-family: var(--jp-ui-font-family, sans-serif);
      font-size: var(--jp-ui-font-size1, 13px);
      color: var(--pv-font-color0);
    }

    .pv-text-repr-fallback {
      display: none;
    }

    /* Header */
    .pv-header {
      display: flex;
      align-items: center;
      gap: 8px;
      padding-top: 6px;
      padding-bottom: 6px;
      border-bottom: solid 1px var(--pv-border-color);
      margin-bottom: 4px;
    }

    .pv-header-text {
      display: flex;
      flex-direction: column;
      gap: 1px;
      min-width: 0;
      flex: 1;
    }

    .pv-obj-type {
      font-weight: 600;
      color: var(--pv-font-color0);
    }

    .pv-header-badge {
      display: inline-block;
      font-size: 0.75em;
      font-weight: 600;
      padding: 2px 7px;
      border-radius: 3px;
      color: var(--pv-font-color2);
      border: 1px solid var(--pv-border-color);
      white-space: nowrap;
    }

    /* Metadata (always-visible key-value rows) */
    .pv-metadata {
      margin: 4px 0 6px 0;
      font-size: 0.92em;
      line-height: 1.5;
    }

    .pv-meta-row {
      display: flex;
      flex-wrap: wrap;
      gap: 1px 14px;
      padding: 1px 0;
    }

    .pv-meta-row-label {
      color: var(--pv-font-color2);
      font-weight: 500;
      white-space: nowrap;
      min-width: 60px;
    }

    .pv-meta-entry {
      white-space: nowrap;
    }

    /* Copy-to-clipboard button */
    .pv-copy-btn {
      display: inline-block;
      cursor: pointer;
      opacity: 0.5;
      font-size: 0.85em;
      padding: 0 3px;
      vertical-align: middle;
      transition: opacity 0.15s;
      user-select: none;
      border: none;
      background: none;
      color: var(--pv-font-color3);
    }

    .pv-copy-btn:hover {
      opacity: 1;
      color: var(--pv-font-color0);
    }

    .pv-meta-label {
      color: var(--pv-font-color3);
      font-weight: 400;
      padding-right: 2px;
    }

    /* Sections grid */
    .pv-sections {
      padding-left: 0 !important;
      display: grid;
      grid-template-columns: 150px auto auto auto 1fr 20px 20px;
      margin-block-start: 0;
      margin-block-end: 0;
      list-style: none;
    }

    .pv-section-item {
      display: contents;
    }

    /* Hidden checkbox for expand/collapse */
    .pv-section-item > input {
      display: block;
      opacity: 0;
      height: 0;
      margin: 0;
    }

    .pv-section-item > input + label {
      color: var(--pv-disabled-color);
    }

    .pv-section-item > input:enabled + label {
      cursor: pointer;
      color: var(--pv-font-color2);
    }

    .pv-section-item > input:enabled + label:hover {
      color: var(--pv-font-color0);
    }

    /* Section summary (left column label) */
    .pv-section-summary {
      grid-column: 1;
      color: var(--pv-font-color2);
      font-weight: 500;
      white-space: nowrap;
    }

    .pv-section-summary > span {
      display: inline-block;
      padding-left: 0.3em;
    }

    .pv-section-summary-in:disabled + label {
      color: var(--pv-font-color2);
    }

    /* Expand/collapse arrows */
    .pv-section-summary-in + label:before {
      display: inline-block;
      content: "\25b6";
      font-size: 11px;
      width: 15px;
      text-align: center;
    }

    .pv-section-summary-in:disabled + label:before {
      color: var(--pv-disabled-color);
    }

    .pv-section-summary-in:checked + label:before {
      content: "\25bc";
    }

    .pv-section-summary-in:checked + label > span {
      display: none;
    }

    .pv-section-summary,
    .pv-section-inline-details {
      padding-top: 4px;
    }

    .pv-section-inline-details {
      grid-column: 2 / -1;
    }

    .pv-section-details {
      grid-column: 1 / -1;
      margin-top: 4px;
      margin-bottom: 5px;
    }

    .pv-section-summary-in ~ .pv-section-details {
      display: none;
    }

    .pv-section-summary-in:checked ~ .pv-section-inline-details {
      display: none;
    }

    .pv-section-summary-in:checked ~ .pv-section-details {
      display: block;
    }

    .pv-section-summary-in:checked ~ .pv-section-details:has(.pv-var-list) {
      display: contents;
    }

    /* Variable (array) list */
    .pv-var-list,
    .pv-var-item {
      display: contents;
    }

    .pv-var-item > div,
    .pv-var-item label,
    .pv-var-item > .pv-var-name span {
      background-color: var(--pv-background-color-row-even);
      border-color: var(--pv-background-color-row-odd);
      margin-bottom: 0;
      padding-top: 2px;
    }

    .pv-var-list > li:nth-child(odd) > div,
    .pv-var-list > li:nth-child(odd) > label,
    .pv-var-list > li:nth-child(odd) > .pv-var-name span {
      background-color: var(--pv-background-color-row-odd);
      border-color: var(--pv-background-color-row-even);
    }

    .pv-var-name {
      grid-column: 1;
    }

    .pv-var-dims {
      grid-column: 2;
    }

    .pv-var-dtype {
      grid-column: 3;
      text-align: right;
      color: var(--pv-font-color2);
    }

    .pv-var-range {
      grid-column: 4;
      color: var(--pv-font-color3);
      font-size: 0.92em;
    }

    .pv-var-badges {
      grid-column: 5;
      padding-left: 8px;
    }

    .pv-var-name,
    .pv-var-dims,
    .pv-var-dtype,
    .pv-var-range {
      white-space: nowrap;
      overflow: hidden;
      text-overflow: ellipsis;
      padding-right: 10px;
    }

    .pv-var-name:hover,
    .pv-var-dims:hover,
    .pv-var-dtype:hover,
    .pv-var-range:hover {
      overflow: visible;
      width: auto;
      z-index: 1;
    }

    .pv-var-name span {
      padding-left: 25px !important;
    }

    .pv-var-name-active span {
      font-weight: 600;
    }

    /* Badges */
    .pv-badge {
      display: inline-block;
      font-size: 0.75em;
      font-weight: 600;
      padding: 1px 5px;
      border-radius: 3px;
      vertical-align: middle;
      line-height: 1.4;
    }

    .pv-badge-active {
      color: var(--pv-badge-active);
      border: 1px solid var(--pv-badge-active);
    }

    .pv-badge-normals {
      color: var(--pv-badge-normals);
      border: 1px solid var(--pv-badge-normals);
    }

    .pv-badge-vectors {
      color: var(--pv-badge-vectors);
      border: 1px solid var(--pv-badge-vectors);
    }

    .pv-badge-tcoords {
      color: var(--pv-badge-tcoords);
      border: 1px solid var(--pv-badge-tcoords);
    }

    /* Logo and Icons */
    .pv-logo {
      display: flex;
      align-items: center;
      flex-shrink: 0;
    }

    .pv-logo svg {
      width: 28px;
      height: 28px;
    }

    .pv-brand-logo {
      display: flex;
      align-items: center;
      flex-shrink: 0;
    }

    .pv-brand-logo svg {
      height: 20px;
      width: auto;
    }

    /* Children list (MultiBlock / PartitionedDataSet) */
    .pv-children-list {
      padding-left: 25px !important;
      list-style: none;
    }

    .pv-children-list li {
      padding: 1px 0;
    }

    .pv-child-name {
      font-weight: 500;
    }

    .pv-child-type {
      color: var(--pv-font-color2);
      font-style: italic;
    }

    .pv-child-type:before {
      content: "\00b7";
      padding: 0 6px;
      font-style: normal;
    }

    .pv-child-detail {
      color: var(--pv-font-color3);
      font-size: 0.9em;
    }

    .pv-child-detail:not(:empty):before {
      content: "\00b7";
      padding: 0 6px;
    }
    </style><pre class='pv-text-repr-fallback'>MultiBlock (0x7f6faf5e69e0)
      N Blocks:   16
      X Bounds:   -3.175e+00, 3.175e+00
      Y Bounds:   -3.175e+00, 3.175e+00
      Z Bounds:   -2.000e-01, 3.856e+00</pre><div class='pv-wrap' style='display:none'><div class='pv-header'><span class='pv-logo'><svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 32 32">
      <defs>
        <linearGradient id="pv-mb-top1" x1="0" y1="0" x2="1" y2="1">
          <stop offset="0%" stop-color="#ffd040"/>
          <stop offset="100%" stop-color="#376fa0"/>
        </linearGradient>
        <linearGradient id="pv-mb-top2" x1="0" y1="0" x2="1" y2="1">
          <stop offset="0%" stop-color="#376fa0"/>
          <stop offset="100%" stop-color="#ffd040"/>
        </linearGradient>
      </defs>
      <polygon points="13,2 22,6 13,10 4,6" fill="url(#pv-mb-top1)" opacity="0.9"/>
      <polygon points="4,6 13,10 13,17 4,13" fill="#1a4a70" opacity="0.9"/>
      <polygon points="22,6 13,10 13,17 22,13" fill="#376fa0" opacity="0.85"/>
      <g stroke="rgba(255,255,255,0.4)" stroke-width="0.35" fill="none">
        <polygon points="13,2 22,6 13,10 4,6"/>
        <line x1="13" y1="10" x2="13" y2="17"/>
        <line x1="4" y1="6" x2="4" y2="13"/>
        <line x1="22" y1="6" x2="22" y2="13"/>
        <line x1="4" y1="13" x2="13" y2="17"/>
        <line x1="22" y1="13" x2="13" y2="17"/>
      </g>
      <polygon points="17,7 26,11 17,15 8,11" fill="url(#pv-mb-top2)" opacity="0.9"/>
      <polygon points="8,11 17,15 17,22 8,18" fill="#1a4a70" opacity="0.85"/>
      <polygon points="26,11 17,15 17,22 26,18" fill="#376fa0" opacity="0.85"/>
      <g stroke="rgba(255,255,255,0.4)" stroke-width="0.35" fill="none">
        <polygon points="17,7 26,11 17,15 8,11"/>
        <line x1="17" y1="15" x2="17" y2="22"/>
        <line x1="8" y1="11" x2="8" y2="18"/>
        <line x1="26" y1="11" x2="26" y2="18"/>
        <line x1="8" y1="18" x2="17" y2="22"/>
        <line x1="26" y1="18" x2="17" y2="22"/>
      </g>
      <polygon points="19,13 28,17 19,21 10,17" fill="url(#pv-mb-top1)" opacity="0.95"/>
      <polygon points="10,17 19,21 19,28 10,24" fill="#1a4a70" opacity="0.9"/>
      <polygon points="28,17 19,21 19,28 28,24" fill="#376fa0" opacity="0.9"/>
      <g stroke="rgba(255,255,255,0.45)" stroke-width="0.35" fill="none">
        <polygon points="19,13 28,17 19,21 10,17"/>
        <line x1="19" y1="21" x2="19" y2="28"/>
        <line x1="10" y1="17" x2="10" y2="24"/>
        <line x1="28" y1="17" x2="28" y2="24"/>
        <line x1="10" y1="24" x2="19" y2="28"/>
        <line x1="28" y1="24" x2="19" y2="28"/>
      </g>
    </svg>
    </span><div class='pv-header-text'><div class='pv-obj-type'>MultiBlock <span class='pv-header-badge'>16 blocks</span> <span class='pv-header-badge'>562 KiB</span></div></div><span class='pv-brand-logo'><svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 90 24">
      <text x="0" y="18" font-family="system-ui,-apple-system,sans-serif" font-size="18" font-weight="700" font-style="italic" letter-spacing="-0.5">
        <tspan fill="#3776AB" opacity="0.7">P</tspan><tspan fill="#FFD43B" opacity="0.7">y</tspan><tspan fill="#008c9e">Vista</tspan>
      </text>
    </svg>
    </span></div><div class='pv-metadata'><div class='pv-meta-row pv-copyable'><span class='pv-meta-row-label'>Bounds</span><button class='pv-copy-btn' title='Copy to clipboard' data-copy='(-3.1750000000000003, 3.175, -3.1749999904483475, 3.1749999904483506, -0.2, 3.8563544370490277)' onclick="navigator.clipboard.writeText(this.dataset.copy)">⧉</button><span class='pv-meta-entry'><span class='pv-meta-label'>X</span> [-3.175e+00, 3.175e+00]</span><span class='pv-meta-entry'><span class='pv-meta-label'>Y</span> [-3.175e+00, 3.175e+00]</span><span class='pv-meta-entry'><span class='pv-meta-label'>Z</span> [-2.000e-01, 3.856e+00]</span></div></div><ul class='pv-sections'><li class='pv-section-item'><input id='section-6f0b6ec6-88aa-4008-b721-d6dcf9cc77f4' class='pv-section-summary-in' type='checkbox' checked /><label for='section-6f0b6ec6-88aa-4008-b721-d6dcf9cc77f4' class='pv-section-summary' title='Expand/collapse section'>Blocks: <span>(16)</span></label><div class='pv-section-inline-details'></div><div class='pv-section-details'><ul class='pv-children-list'><li><span class='pv-child-name'>Sketch</span><span class='pv-child-type'>PolyData</span><span class='pv-child-detail'>0 pts · 0 cells · 3 KiB</span></li><li><span class='pv-child-name'>Revolution</span><span class='pv-child-type'>PolyData</span><span class='pv-child-detail'>214 pts · 204 cells · 19 KiB</span></li><li><span class='pv-child-name'>Hexagon</span><span class='pv-child-type'>PolyData</span><span class='pv-child-detail'>0 pts · 0 cells · 3 KiB</span></li><li><span class='pv-child-name'>Sketch002</span><span class='pv-child-type'>PolyData</span><span class='pv-child-detail'>0 pts · 0 cells · 3 KiB</span></li><li><span class='pv-child-name'>Pocket</span><span class='pv-child-type'>PolyData</span><span class='pv-child-detail'>424 pts · 372 cells · 33 KiB</span></li><li><span class='pv-child-name'>Pocket001</span><span class='pv-child-type'>PolyData</span><span class='pv-child-detail'>530 pts · 480 cells · 36 KiB</span></li><li><span class='pv-child-name'>neck-sketch</span><span class='pv-child-type'>PolyData</span><span class='pv-child-detail'>0 pts · 0 cells · 3 KiB</span></li><li><span class='pv-child-name'>neck</span><span class='pv-child-type'>PolyData</span><span class='pv-child-detail'>538 pts · 832 cells · 56 KiB</span></li><li><span class='pv-child-name'>nut-with-neck</span><span class='pv-child-type'>PolyData</span><span class='pv-child-detail'>1,068 pts · 1,312 cells · 77 KiB</span></li><li><span class='pv-child-name'>Chamfer</span><span class='pv-child-type'>PolyData</span><span class='pv-child-detail'>1,122 pts · 1,364 cells · 78 KiB</span></li><li><span class='pv-child-name'>Cylinder</span><span class='pv-child-type'>PolyData</span><span class='pv-child-detail'>106 pts · 100 cells · 11 KiB</span></li><li><span class='pv-child-name'>Cylinder001</span><span class='pv-child-type'>PolyData</span><span class='pv-child-detail'>106 pts · 100 cells · 11 KiB</span></li><li><span class='pv-child-name'>nylon-ring</span><span class='pv-child-type'>PolyData</span><span class='pv-child-detail'>212 pts · 208 cells · 18 KiB</span></li><li><span class='pv-child-name'>nut-base</span><span class='pv-child-type'>PolyData</span><span class='pv-child-detail'>1,122 pts · 1,364 cells · 78 KiB</span></li><li><span class='pv-child-name'>nylon-neck</span><span class='pv-child-type'>PolyData</span><span class='pv-child-detail'>212 pts · 208 cells · 18 KiB</span></li><li><span class='pv-child-name'>Nyloc-nut-M3</span><span class='pv-child-type'>PolyData</span><span class='pv-child-detail'>1,334 pts · 1,572 cells · 115 KiB</span></li></ul></div></li></ul></div></div>
    </div>
    <br />
    <br />

.. GENERATED FROM PYTHON SOURCE LINES 33-34

Render the nut.

.. GENERATED FROM PYTHON SOURCE LINES 34-41

.. code-block:: Python


    for _, part in mb.cad.walk():
        part['elevation'] = part.points[:, 2]

    pl = pv.Plotter()
    pl.cad.add(mb, scalars='elevation', cmap='cividis')
    pl.show()







.. tab-set::



   .. tab-item:: Static Scene



            
     .. image-sg:: /examples/01_readers/images/sphx_glr_read_fcstd_001.png
        :alt: read fcstd
        :srcset: /examples/01_readers/images/sphx_glr_read_fcstd_001.png
        :class: sphx-glr-single-img
     


   .. tab-item:: Interactive Scene



       .. offlineviewer:: /home/runner/work/pyvista-cad/pyvista-cad/doc/examples/01_readers/images/sphx_glr_read_fcstd_001.vtksz







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

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


.. _sphx_glr_download_examples_01_readers_read_fcstd.py:

.. only:: html

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

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

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

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

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

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

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