{
  "cells": [
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {
        "collapsed": false
      },
      "outputs": [],
      "source": [
        "%matplotlib inline"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "# Extract Edges {#extract_edges_example}\n\nExtract edges from a surface.\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {
        "collapsed": false
      },
      "outputs": [],
      "source": [
        "import pyvista as pv\nfrom pyvista import examples"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "From vtk documentation, the edges of a mesh are one of the following:\n\n1.  boundary (used by one polygon) or a line cell\n2.  non-manifold (used by three or more polygons)\n3.  feature edges (edges used by two triangles and whose dihedral angle\n    \\> feature_angle)\n4.  manifold edges (edges used by exactly two polygons).\n\nThe\n`extract_feature_edges() <pyvista.DataSetFilters.extract_feature_edges>`{.interpreted-text\nrole=\"func\"} filter will extract those edges given a feature angle and\nreturn a dataset with lines that represent the edges of the original\nmesh.\n\nTo demonstrate, we will first extract the edges around a sample CAD\nmodel:\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {
        "collapsed": false
      },
      "outputs": [],
      "source": [
        "# Download the example CAD model and extract all feature edges above 45 degrees\nmesh = examples.download_cad_model()\nedges = mesh.extract_feature_edges(45)\n\n# Render the edge lines on top of the original mesh.  Zoom in to provide a better figure.\np = pv.Plotter()\np.add_mesh(mesh, color=True)\np.add_mesh(edges, color=\"red\", line_width=5)\np.camera.zoom(1.5)\np.show()"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "We can do this analysis for any `pyvista.PolyData`{.interpreted-text\nrole=\"class\"} object. Let\\'s try the cow mesh example:\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {
        "collapsed": false
      },
      "outputs": [],
      "source": [
        "mesh = examples.download_cow()\nedges = mesh.extract_feature_edges(20)\n\np = pv.Plotter()\np.add_mesh(mesh, color=True)\np.add_mesh(edges, color=\"red\", line_width=5)\np.camera_position = [(9.5, 3.0, 5.5), (2.5, 1, 0), (0, 1, 0)]\np.show()"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "We can leverage the `pyvista.PolyData.n_open_edges`{.interpreted-text\nrole=\"any\"} property and\n`pyvista.DataSetFilters.extract_feature_edges`{.interpreted-text\nrole=\"func\"} filter to count and extract the open edges on a\n`pyvista.PolyData`{.interpreted-text role=\"class\"} mesh.\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {
        "collapsed": false
      },
      "outputs": [],
      "source": [
        "# Download a sample surface mesh with visible open edges\nmesh = examples.download_bunny()\nmesh"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "We can get a count of the open edges with:\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {
        "collapsed": false
      },
      "outputs": [],
      "source": [
        "mesh.n_open_edges"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "And we can extract those edges with the `boundary_edges` option of\n`pyvista.DataSetFilters.extract_feature_edges`{.interpreted-text\nrole=\"func\"}:\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {
        "collapsed": false
      },
      "outputs": [],
      "source": [
        "edges = mesh.extract_feature_edges(boundary_edges=True, feature_edges=False, manifold_edges=False)\n\np = pv.Plotter()\np.add_mesh(mesh, color=True)\np.add_mesh(edges, color=\"red\", line_width=5)\np.camera_position = [(-0.2, -0.13, 0.12), (-0.015, 0.10, -0.0), (0.28, 0.26, 0.9)]\np.show()"
      ]
    }
  ],
  "metadata": {
    "kernelspec": {
      "display_name": "Python 3",
      "language": "python",
      "name": "python3"
    },
    "language_info": {
      "codemirror_mode": {
        "name": "ipython",
        "version": 3
      },
      "file_extension": ".py",
      "mimetype": "text/x-python",
      "name": "python",
      "nbconvert_exporter": "python",
      "pygments_lexer": "ipython3",
      "version": "3.12.2"
    }
  },
  "nbformat": 4,
  "nbformat_minor": 0
}