{
 "cells": [
  {
   "cell_type": "markdown",
   "id": "665d9cda",
   "metadata": {},
   "source": [
    "# Distances and their cell IDs\n",
    "## This notebook shows Mesh.distance(other_mesh), which returns a tuple with an array of distances and the corresponding point or cell ids nearest the closest points.  "
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "c5c5dd98",
   "metadata": {},
   "outputs": [],
   "source": [
    "import shapeworks as sw\n",
    "import numpy as np\n",
    "import pyvista as pv\n",
    "import math"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "2ae4a8ef",
   "metadata": {},
   "outputs": [],
   "source": [
    "pv.set_jupyter_backend('static')"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "ed9c43e0",
   "metadata": {},
   "outputs": [],
   "source": [
    "DATA = \"../Data/\""
   ]
  },
  {
   "cell_type": "markdown",
   "id": "eb0d562c",
   "metadata": {},
   "source": [
    "## Example of Mesh.distance results\n",
    "Receives array of distances and their associated cell/point ids in target"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "fc44676c",
   "metadata": {},
   "outputs": [],
   "source": [
    "filename1 = DATA + \"ellipsoid_05.vtk\"\n",
    "filename2 = DATA + \"ellipsoid_07.vtk\""
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "530ef785",
   "metadata": {},
   "outputs": [],
   "source": [
    "mesh1 = sw.Mesh(filename1)\n",
    "mesh2 = sw.Mesh(filename2)"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "e084ce38",
   "metadata": {},
   "source": [
    "### point to cell distance"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "3bfce1aa",
   "metadata": {},
   "outputs": [],
   "source": [
    "distances_and_cell_ids_1to2 = mesh1.distance(mesh2)\n",
    "distances_and_cell_ids_2to1 = mesh2.distance(mesh1)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "8cc6c6d4",
   "metadata": {},
   "outputs": [],
   "source": [
    "distances_and_cell_ids_1to2"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "d4566aed",
   "metadata": {},
   "outputs": [],
   "source": [
    "distances_and_cell_ids_2to1"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "c39c3261",
   "metadata": {},
   "outputs": [],
   "source": [
    "distances_and_cell_ids_1to2[0].size"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "f7b5f3cc",
   "metadata": {},
   "outputs": [],
   "source": [
    "distances_and_cell_ids_1to2[1].size"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "adbf8f57",
   "metadata": {},
   "source": [
    "#### validate data ownership, ensuring no copying from C++ to Python"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "b69eb7ba",
   "metadata": {},
   "outputs": [],
   "source": [
    "distances_and_cell_ids_1to2[0].flags\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "fd6a288a",
   "metadata": {},
   "outputs": [],
   "source": [
    "distances_and_cell_ids_2to1[1].flags\n"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "0804b5f6",
   "metadata": {},
   "source": [
    "### point to point distance"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "75e76d96",
   "metadata": {},
   "outputs": [],
   "source": [
    "distances_and_point_ids_1to2 = mesh1.distance(mesh2, sw.Mesh.DistanceMethod.PointToPoint)\n",
    "distances_and_point_ids_2to1 = mesh2.distance(mesh1, sw.Mesh.DistanceMethod.PointToPoint)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "08d67236",
   "metadata": {},
   "outputs": [],
   "source": [
    "distances_and_point_ids_1to2"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "d15386e3",
   "metadata": {},
   "outputs": [],
   "source": [
    "distances_and_point_ids_2to1"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "43ad78e4",
   "metadata": {},
   "outputs": [],
   "source": [
    "distances_and_point_ids_1to2[0].size"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "e1c9d919",
   "metadata": {},
   "outputs": [],
   "source": [
    "distances_and_point_ids_1to2[1].size"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "cbf1c02a",
   "metadata": {},
   "source": [
    "#### validate distance of first point in mesh1 to specified closest point in mesh2\n",
    "distance 1to2[0]: 43.43859498"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "5a5f4e87",
   "metadata": {},
   "outputs": [],
   "source": [
    "p0 = mesh1.getPoint(0)\n",
    "p0"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "e0abcb13",
   "metadata": {},
   "outputs": [],
   "source": [
    "p1 = mesh2.getPoint(458)\n",
    "p1"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "18bf01f3",
   "metadata": {},
   "outputs": [],
   "source": [
    "v = p1 - p0\n",
    "v"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "60358b77",
   "metadata": {},
   "outputs": [],
   "source": [
    "math.sqrt(v.dot(v))"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "0c2e0b33",
   "metadata": {},
   "source": [
    "### plot distances as scalar field on meshes"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "81383ed6",
   "metadata": {},
   "outputs": [],
   "source": [
    "pv_mesh1 = sw.sw2vtkMesh(mesh1)\n",
    "pv_mesh2 = sw.sw2vtkMesh(mesh2)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "81e1e291",
   "metadata": {},
   "outputs": [],
   "source": [
    "# used to maintain bounds even when meshes' positions change\n",
    "a = pv.UniformGrid()\n",
    "a.dimensions = np.array([9,8,8])\n",
    "a.origin = (-15,-5,-15)\n",
    "a.spacing = (10, 10, 10)\n",
    "outline = a.outline()\n",
    "\n",
    "p = pv.Plotter(shape=(1,1), border=False)\n",
    "\n",
    "p.subplot(0,0)\n",
    "p.add_text(\"distances\")\n",
    "p.add_mesh(outline)\n",
    "p.add_mesh(pv_mesh1, scalars=distances_and_cell_ids_1to2[0], show_scalar_bar=True, opacity=1.0)\n",
    "p.add_mesh(pv_mesh2, scalars=distances_and_cell_ids_2to1[0], show_scalar_bar=True, opacity=1.0)\n",
    "p.camera_position = 'xy'\n",
    "\n",
    "p.show()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "66eeab2c",
   "metadata": {},
   "outputs": [],
   "source": []
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3 (ipykernel)",
   "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.7.8"
  },
  "toc": {
   "base_numbering": 1,
   "nav_menu": {},
   "number_sections": true,
   "sideBar": true,
   "skip_h1_title": false,
   "title_cell": "Table of Contents",
   "title_sidebar": "Contents",
   "toc_cell": false,
   "toc_position": {},
   "toc_section_display": true,
   "toc_window_display": false
  }
 },
 "nbformat": 4,
 "nbformat_minor": 5
}
