"""
.. _clip_closed_surface_example:

Clip and Cap a Closed Surface
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

Compare a standard planar clip, which leaves an open boundary, with
:func:`pyvista.PolyDataFilters.clip_closed_surface`, which seals the cut face.
"""

import pyvista as pv
from pyvista import examples

# sphinx_gallery_thumbnail_number = 2

# %%
# Load a closed surface
# ~~~~~~~~~~~~~~~~~~~~~
# The :func:`~pyvista.examples.downloads.download_lucy` scan is a watertight,
# manifold PolyData surface with no open edges.

surface = examples.download_lucy().triangulate()
surface


# %%
# Define an oblique cutting plane
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# The same plane is reused for both the open and the closed-surface clip.

plane_origin = surface.center
plane_normal = (1, 0.3, 0)
plane_size = surface.length * 1.2
plane = pv.Plane(
    center=plane_origin, direction=plane_normal, i_size=plane_size, j_size=plane_size
)

pl = pv.Plotter()
pl.add_mesh(surface, color='wheat', smooth_shading=True)
pl.add_mesh(plane, style='wireframe', color='black', line_width=2)
pl.view_xz()
pl.camera.azimuth = 35
pl.show()


# %%
# Compare an open cut to a capped cut
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# A standard clip leaves a boundary loop along the cut. The closed-surface
# clip caps that loop with new triangles and stays watertight.

open_clip = surface.clip(normal=plane_normal, origin=plane_origin)
closed_clip = surface.clip_closed_surface(normal=plane_normal, origin=plane_origin)

open_boundary = open_clip.extract_feature_edges(
    boundary_edges=True,
    feature_edges=False,
    manifold_edges=False,
    non_manifold_edges=False,
)

pl = pv.Plotter(shape=(1, 2))
pl.subplot(0, 0)
pl.add_mesh(open_clip, color='wheat', smooth_shading=True)
pl.add_mesh(open_boundary, color='tomato', line_width=6)
pl.add_mesh(plane, style='wireframe', color='black', line_width=2)
pl.view_xz()
pl.camera.azimuth = 35
pl.subplot(0, 1)
pl.add_mesh(closed_clip, color='wheat', smooth_shading=True)
pl.add_mesh(plane, style='wireframe', color='black', line_width=2)
pl.view_xz()
pl.camera.azimuth = 35
pl.link_views()
pl.show()


# %%
# Confirm that the capped result is watertight
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# The open clip carries hundreds of boundary edges; the capped result has none.

open_boundary.n_cells, closed_clip.n_open_edges
# %%
# .. tags:: filter
