<jupyter_start><jupyter_text>Distance Between Two Surfaces=============================Compute the average thickness between two surfaces.For example, you might have two surfaces that represent the boundariesof lithological layers in a subsurface geological model and you want toknow the average thickness of a unit between those boundaries.We can compute the thickness between the two surfaces using a fewdifferent methods. First, we will demo a method where we compute thenormals of the bottom surface, and then project a ray to the top surfaceto compute the distance along the surface normals. Second, we will use aKDTree to compute the distance from every point in the bottom mesh toit\'s closest point in the top mesh.<jupyter_code>import numpy as np

import pyvista as pv


# A helper to make a random surface
def hill(seed):
    mesh = pv.ParametricRandomHills(randomseed=seed, u_res=50, v_res=50,
                                    hillamplitude=0.5)
    mesh.rotate_y(-10, inplace=True) # give the surfaces some tilt

    return mesh

h0 = hill(1).elevation()
h1 = hill(10)
# Shift one surface
h1.points[:,-1] += 5
h1 = h1.elevation()
p = pv.Plotter()
p.add_mesh(h0, smooth_shading=True)
p.add_mesh(h1, smooth_shading=True)
p.show_grid()
p.show()<jupyter_output><empty_output><jupyter_text>Ray Tracing Distance====================Compute normals of lower surface<jupyter_code>h0n = h0.compute_normals(point_normals=True, cell_normals=False,
                         auto_orient_normals=True)<jupyter_output><empty_output><jupyter_text>Travel along normals to the other surface and compute the thickness oneach vector.<jupyter_code>h0n["distances"] = np.empty(h0.n_points)
for i in range(h0n.n_points):
    p = h0n.points[i]
    vec = h0n["Normals"][i] * h0n.length
    p0 = p - vec
    p1 = p + vec
    ip, ic = h1.ray_trace(p0, p1, first_point=True)
    dist = np.sqrt(np.sum((ip - p)**2))
    h0n["distances"][i] = dist

# Replace zeros with nans
mask = h0n["distances"] == 0
h0n["distances"][mask] = np.nan
np.nanmean(h0n["distances"])
p = pv.Plotter()
p.add_mesh(h0n, scalars="distances", smooth_shading=True)
p.add_mesh(h1, color=True, opacity=0.75, smooth_shading=True)
p.show()<jupyter_output><empty_output><jupyter_text>Nearest Neighbor Distance=========================You could also use a KDTree to compare the distance between each pointof the upper surface and the nearest neighbor of the lower surface. Thiswon\'t be the exact surface to surface distance, but it will benoticeably faster than a ray trace, especially for large surfaces.<jupyter_code>from scipy.spatial import KDTree

tree = KDTree(h1.points)
d, idx = tree.query(h0.points )
h0["distances"] = d
np.mean(d)
p = pv.Plotter()
p.add_mesh(h0, scalars="distances", smooth_shading=True)
p.add_mesh(h1, color=True, opacity=0.75, smooth_shading=True)
p.show()<jupyter_output><empty_output>
{'fraction_non_alphanumeric': 0.12234227953990938, 'fraction_numerical': 0.01812478215406065, 'mean_word_length': 4.991649269311065, 'pattern_counts': {'":': 0, '<': 17, '<?xml version=': 0, '>': 17, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 1, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'chain_length': '4', 'dir': 'jupyter-structured-clean-dedup', 'id': '564648', 'license': 'MIT', 'n_tokens_mistral': 975, 'n_tokens_neox': 940, 'n_words': 288, 'path': 'distance-between-surfaces.ipynb', 'repo_name': 'UttamBasu/ipygany_examples', 'size': '2869'}