{
 "cells": [
  {
   "cell_type": "markdown",
   "id": "c699eec9",
   "metadata": {},
   "source": [
    "# Transforms can also be used to align two meshes"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "e7deff83",
   "metadata": {},
   "outputs": [],
   "source": [
    "import shapeworks as sw\n",
    "import numpy as np\n",
    "import pyvista as pv\n",
    "import matplotlib"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "0702c8cb",
   "metadata": {},
   "outputs": [],
   "source": [
    "pv.set_jupyter_backend('static')"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "3a5b8b37",
   "metadata": {},
   "outputs": [],
   "source": [
    "DATA = \"../Data\""
   ]
  },
  {
   "cell_type": "markdown",
   "id": "58adbaa4",
   "metadata": {},
   "source": [
    "## Mesh alignment\n",
    "A mesh transformation can be computed rigidly, using similarity, or as an affine matrix. The alignment is computed using the iterative closest point (ICP) method for the specified number of iterations (default: a similarity transform with 10 iterations)."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "e7469337",
   "metadata": {},
   "outputs": [],
   "source": [
    "filename1 = DATA + \"/ellipsoid_1mode/meshes/ellipsoid_05.vtk\"\n",
    "filename2 = DATA + \"/ellipsoid_1mode/meshes/ellipsoid_07.vtk\""
   ]
  },
  {
   "cell_type": "markdown",
   "id": "36c06d3a",
   "metadata": {},
   "source": [
    "#### Load meshes"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "02316262",
   "metadata": {},
   "outputs": [],
   "source": [
    "mesh1 = sw.Mesh(filename1)\n",
    "mesh2 = sw.Mesh(filename2)"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "33d6c374",
   "metadata": {},
   "source": [
    "#### Visualize original meshes"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "d575c06c",
   "metadata": {},
   "outputs": [],
   "source": [
    "pv_mesh1_orig = sw.sw2vtkMesh(mesh1)\n",
    "pv_mesh2_orig = sw.sw2vtkMesh(mesh2)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "8f420ade",
   "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=(2,2), border=False)\n",
    "\n",
    "p.subplot(0,0)\n",
    "p.add_text(\"xy\")\n",
    "p.add_mesh(outline)\n",
    "p.add_mesh(pv_mesh1_orig, show_scalar_bar=False, color='#4fb080', opacity=1.0)\n",
    "p.add_mesh(pv_mesh2_orig, show_scalar_bar=False, color='#ced175', opacity=1.0)\n",
    "p.camera_position = 'xy'\n",
    "\n",
    "p.subplot(0,1)\n",
    "p.add_text(\"yz\")\n",
    "p.add_mesh(outline)\n",
    "p.add_mesh(pv_mesh1_orig, show_scalar_bar=False, color='#4fb080', opacity=1.0)\n",
    "p.add_mesh(pv_mesh2_orig, show_scalar_bar=False, color='#ced175', opacity=1.0)\n",
    "p.camera_position = 'yz'\n",
    "\n",
    "p.subplot(1,0)\n",
    "p.add_text(\"zx\")\n",
    "p.add_mesh(outline)\n",
    "p.add_mesh(pv_mesh1_orig, show_scalar_bar=False, color='#4fb080', opacity=1.0)\n",
    "p.add_mesh(pv_mesh2_orig, show_scalar_bar=False, color='#ced175', opacity=1.0)\n",
    "p.camera_position = 'zx'\n",
    "\n",
    "p.add_text(\"Original Meshes\", position='lower_edge')\n",
    "\n",
    "p.subplot(1,1)\n",
    "p.add_text(\"persp\")\n",
    "p.add_mesh(outline)\n",
    "p.add_mesh(pv_mesh1_orig, show_scalar_bar=False, color='#4fb080', opacity=1.0)\n",
    "p.add_mesh(pv_mesh2_orig, show_scalar_bar=False, color='#ced175', opacity=1.0)\n",
    "p.camera_position = [100,35,70]\n",
    "p.set_viewup([0,1,0])\n",
    "p.show_bounds(grid='front', location='outer', all_edges=False, )\n",
    "\n",
    "p.show()"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "ee67bcc5",
   "metadata": {},
   "source": [
    "### Rigid transformation"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "0ff39975",
   "metadata": {},
   "source": [
    "#### create transforms"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "1df14486",
   "metadata": {},
   "outputs": [],
   "source": [
    "xform_1_to_2 = mesh1.createTransform(mesh2, sw.Mesh.AlignmentType.Rigid)\n",
    "xform_2_to_1 = mesh2.createTransform(mesh1, sw.Mesh.AlignmentType.Rigid)"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "985f9e8d",
   "metadata": {},
   "source": [
    "#### apply transforms"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "aee68933",
   "metadata": {},
   "outputs": [],
   "source": [
    "mesh1.applyTransform(xform_1_to_2)\n",
    "mesh2.applyTransform(xform_2_to_1)"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "bb5b88d4",
   "metadata": {},
   "source": [
    "#### visualize results\n",
    "Notice how the original meshes do not change shape. This is very different from affine transformations below."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "f33bc5ee",
   "metadata": {},
   "outputs": [],
   "source": [
    "pv_mesh1 = sw.sw2vtkMesh(mesh1)\n",
    "pv_mesh2 = sw.sw2vtkMesh(mesh2)"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "18c49bd1",
   "metadata": {},
   "source": [
    "#### Mesh 1 -> Mesh 2"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "55a57b58",
   "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=(2,2), border=False)\n",
    "\n",
    "p.subplot(0,0)\n",
    "p.add_text(\"xy\")\n",
    "p.add_mesh(outline)\n",
    "p.add_mesh(pv_mesh1, show_scalar_bar=False, color='#4fb080', opacity=1.0)\n",
    "p.add_mesh(pv_mesh2_orig, show_scalar_bar=False, color='#ced175', style='wireframe', opacity=0.5)\n",
    "p.camera_position = 'xy'\n",
    "\n",
    "p.subplot(0,1)\n",
    "p.add_text(\"yz\")\n",
    "p.add_mesh(outline)\n",
    "p.add_mesh(pv_mesh1, show_scalar_bar=False, color='#4fb080', opacity=1.0)\n",
    "p.add_mesh(pv_mesh2_orig, show_scalar_bar=False, color='#ced175', style='wireframe', opacity=0.5)\n",
    "p.camera_position = 'yz'\n",
    "\n",
    "p.subplot(1,0)\n",
    "p.add_text(\"zx\")\n",
    "p.add_mesh(outline)\n",
    "p.add_mesh(pv_mesh1, show_scalar_bar=False, color='#4fb080', opacity=1.0)\n",
    "p.add_mesh(pv_mesh2_orig, show_scalar_bar=False, color='#ced175', style='wireframe', opacity=0.5)\n",
    "p.camera_position = 'zx'\n",
    "\n",
    "p.add_text(\"Rigid Transforms\", position='lower_edge')\n",
    "\n",
    "p.subplot(1,1)\n",
    "p.add_text(\"persp\")\n",
    "p.add_mesh(outline)\n",
    "p.add_mesh(pv_mesh1, show_scalar_bar=False, color='#4fb080', opacity=1.0)\n",
    "p.add_mesh(pv_mesh2_orig, show_scalar_bar=False, color='#ced175', style='wireframe', opacity=0.75)\n",
    "p.camera_position = [100,35,70]\n",
    "p.set_viewup([0,1,0])\n",
    "p.show_bounds(grid='front', location='outer', all_edges=False, )\n",
    "\n",
    "p.show()"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "dcc725ac",
   "metadata": {},
   "source": [
    "#### Mesh 2 -> Mesh 1"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "6cbd3d32",
   "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=(2,2), border=False)\n",
    "\n",
    "p.subplot(0,0)\n",
    "p.add_text(\"xy\")\n",
    "p.add_mesh(outline)\n",
    "p.add_mesh(pv_mesh2, show_scalar_bar=False, color='#4fb080', opacity=1.0)\n",
    "p.add_mesh(pv_mesh1_orig, show_scalar_bar=False, color='#ced175', style='wireframe', opacity=0.5)\n",
    "p.camera_position = 'xy'\n",
    "\n",
    "p.subplot(0,1)\n",
    "p.add_text(\"yz\")\n",
    "p.add_mesh(outline)\n",
    "p.add_mesh(pv_mesh2, show_scalar_bar=False, color='#4fb080', opacity=1.0)\n",
    "p.add_mesh(pv_mesh1_orig, show_scalar_bar=False, color='#ced175', style='wireframe', opacity=0.5)\n",
    "p.camera_position = 'yz'\n",
    "\n",
    "p.subplot(1,0)\n",
    "p.add_text(\"zx\")\n",
    "p.add_mesh(outline)\n",
    "p.add_mesh(pv_mesh2, show_scalar_bar=False, color='#4fb080', opacity=1.0)\n",
    "p.add_mesh(pv_mesh1_orig, show_scalar_bar=False, color='#ced175', style='wireframe', opacity=0.5)\n",
    "p.camera_position = 'zx'\n",
    "\n",
    "p.add_text(\"Rigid Transforms\", position='lower_edge')\n",
    "\n",
    "p.subplot(1,1)\n",
    "p.add_text(\"persp\")\n",
    "p.add_mesh(outline)\n",
    "p.add_mesh(pv_mesh2, show_scalar_bar=False, color='#4fb080', opacity=1.0)\n",
    "p.add_mesh(pv_mesh1_orig, show_scalar_bar=False, color='#ced175', style='wireframe', opacity=0.75)\n",
    "p.camera_position = [100,35,70]\n",
    "p.set_viewup([0,1,0])\n",
    "p.show_bounds(grid='front', location='outer', all_edges=False, )\n",
    "\n",
    "p.show()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "7cea142c",
   "metadata": {},
   "outputs": [],
   "source": []
  },
  {
   "cell_type": "markdown",
   "id": "61fcd4bf",
   "metadata": {},
   "source": [
    "### Similarity transformation\n",
    "This type of transformation is very similar to rigid transformations above."
   ]
  },
  {
   "cell_type": "markdown",
   "id": "339de861",
   "metadata": {},
   "source": [
    "#### Reload meshes"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "908aeea1",
   "metadata": {},
   "outputs": [],
   "source": [
    "mesh1 = sw.Mesh(filename1)\n",
    "mesh2 = sw.Mesh(filename2)"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "e19a65ce",
   "metadata": {},
   "source": [
    "#### create transforms"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "38c7773a",
   "metadata": {},
   "outputs": [],
   "source": [
    "xform_1_to_2 = mesh1.createTransform(mesh2, sw.Mesh.AlignmentType.Similarity)\n",
    "xform_2_to_1 = mesh2.createTransform(mesh1, sw.Mesh.AlignmentType.Similarity)"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "49264791",
   "metadata": {},
   "source": [
    "#### apply transforms"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "33186077",
   "metadata": {},
   "outputs": [],
   "source": [
    "mesh1.applyTransform(xform_1_to_2)\n",
    "mesh2.applyTransform(xform_2_to_1)"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "6d9e607f",
   "metadata": {},
   "source": [
    "#### visualize results\n",
    "Notice how the original meshes do not change shape (or orientation wrt the origin? How are these different from affine?)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "35803394",
   "metadata": {},
   "outputs": [],
   "source": [
    "pv_mesh1 = sw.sw2vtkMesh(mesh1)\n",
    "pv_mesh2 = sw.sw2vtkMesh(mesh2)"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "2d7723ef",
   "metadata": {},
   "source": [
    "#### Mesh 1 -> Mesh 2"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "0b3a713e",
   "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=(2,2), border=False)\n",
    "\n",
    "p.subplot(0,0)\n",
    "p.add_text(\"xy\")\n",
    "p.add_mesh(outline)\n",
    "p.add_mesh(pv_mesh1, show_scalar_bar=False, color='#4fb080', opacity=1.0)\n",
    "p.add_mesh(pv_mesh2_orig, show_scalar_bar=False, color='#ced175', style='wireframe', opacity=0.5)\n",
    "p.camera_position = 'xy'\n",
    "\n",
    "p.subplot(0,1)\n",
    "p.add_text(\"yz\")\n",
    "p.add_mesh(outline)\n",
    "p.add_mesh(pv_mesh1, show_scalar_bar=False, color='#4fb080', opacity=1.0)\n",
    "p.add_mesh(pv_mesh2_orig, show_scalar_bar=False, color='#ced175', style='wireframe', opacity=0.5)\n",
    "p.camera_position = 'yz'\n",
    "\n",
    "p.subplot(1,0)\n",
    "p.add_text(\"zx\")\n",
    "p.add_mesh(outline)\n",
    "p.add_mesh(pv_mesh1, show_scalar_bar=False, color='#4fb080', opacity=1.0)\n",
    "p.add_mesh(pv_mesh2_orig, show_scalar_bar=False, color='#ced175', style='wireframe', opacity=0.5)\n",
    "p.camera_position = 'zx'\n",
    "\n",
    "p.add_text(\"Similarity Transforms\", position='lower_edge')\n",
    "\n",
    "p.subplot(1,1)\n",
    "p.add_text(\"persp\")\n",
    "p.add_mesh(outline)\n",
    "p.add_mesh(pv_mesh1, show_scalar_bar=False, color='#4fb080', opacity=1.0)\n",
    "p.add_mesh(pv_mesh2_orig, show_scalar_bar=False, color='#ced175', style='wireframe', opacity=0.75)\n",
    "p.camera_position = [100,35,70]\n",
    "p.set_viewup([0,1,0])\n",
    "p.show_bounds(grid='front', location='outer', all_edges=False, )\n",
    "\n",
    "p.show()"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "f7839267",
   "metadata": {},
   "source": [
    "#### Mesh 2 -> Mesh 1"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "a06eb485",
   "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=(2,2), border=False)\n",
    "\n",
    "p.subplot(0,0)\n",
    "p.add_text(\"xy\")\n",
    "p.add_mesh(outline)\n",
    "p.add_mesh(pv_mesh2, show_scalar_bar=False, color='#4fb080', opacity=1.0)\n",
    "p.add_mesh(pv_mesh1_orig, show_scalar_bar=False, color='#ced175', style='wireframe', opacity=0.5)\n",
    "p.camera_position = 'xy'\n",
    "\n",
    "p.subplot(0,1)\n",
    "p.add_text(\"yz\")\n",
    "p.add_mesh(outline)\n",
    "p.add_mesh(pv_mesh2, show_scalar_bar=False, color='#4fb080', opacity=1.0)\n",
    "p.add_mesh(pv_mesh1_orig, show_scalar_bar=False, color='#ced175', style='wireframe', opacity=0.5)\n",
    "p.camera_position = 'yz'\n",
    "\n",
    "p.subplot(1,0)\n",
    "p.add_text(\"zx\")\n",
    "p.add_mesh(outline)\n",
    "p.add_mesh(pv_mesh2, show_scalar_bar=False, color='#4fb080', opacity=1.0)\n",
    "p.add_mesh(pv_mesh1_orig, show_scalar_bar=False, color='#ced175', style='wireframe', opacity=0.5)\n",
    "p.camera_position = 'zx'\n",
    "\n",
    "p.add_text(\"Similarity Transforms\", position='lower_edge')\n",
    "\n",
    "p.subplot(1,1)\n",
    "p.add_text(\"persp\")\n",
    "p.add_mesh(outline)\n",
    "p.add_mesh(pv_mesh2, show_scalar_bar=False, color='#4fb080', opacity=1.0)\n",
    "p.add_mesh(pv_mesh1_orig, show_scalar_bar=False, color='#ced175', style='wireframe', opacity=0.75)\n",
    "p.camera_position = [100,35,70]\n",
    "p.set_viewup([0,1,0])\n",
    "p.show_bounds(grid='front', location='outer', all_edges=False, )\n",
    "\n",
    "p.show()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "8cb3bfd3",
   "metadata": {},
   "outputs": [],
   "source": []
  },
  {
   "cell_type": "markdown",
   "id": "ea11d04b",
   "metadata": {},
   "source": [
    "### Affine transformation\n",
    "This type of transformation warps the points of one mesh into the other as well as translating its position."
   ]
  },
  {
   "cell_type": "markdown",
   "id": "55e5b572",
   "metadata": {},
   "source": [
    "#### Reload meshes"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "febbed2f",
   "metadata": {},
   "outputs": [],
   "source": [
    "mesh1 = sw.Mesh(filename1)\n",
    "mesh2 = sw.Mesh(filename2)"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "5d44047e",
   "metadata": {},
   "source": [
    "#### create transforms"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "8dd5af3b",
   "metadata": {},
   "outputs": [],
   "source": [
    "xform_1_to_2 = mesh1.createTransform(mesh2, sw.Mesh.AlignmentType.Affine)\n",
    "xform_2_to_1 = mesh2.createTransform(mesh1, sw.Mesh.AlignmentType.Affine)"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "08f84670",
   "metadata": {},
   "source": [
    "#### apply transforms"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "6cd462b9",
   "metadata": {},
   "outputs": [],
   "source": [
    "mesh1.applyTransform(xform_1_to_2)\n",
    "mesh2.applyTransform(xform_2_to_1)"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "7bc65477",
   "metadata": {},
   "source": [
    "#### visualize results\n",
    "Notice how the original meshes do not change shape (or orientation wrt the origin? How are these different from affine?)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "5888b216",
   "metadata": {},
   "outputs": [],
   "source": [
    "pv_mesh1 = sw.sw2vtkMesh(mesh1)\n",
    "pv_mesh2 = sw.sw2vtkMesh(mesh2)"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "8a8428b0",
   "metadata": {},
   "source": [
    "#### Mesh 1 -> Mesh 2"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "7fbd3ee4",
   "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=(2,2), border=False)\n",
    "\n",
    "p.subplot(0,0)\n",
    "p.add_text(\"xy\")\n",
    "p.add_mesh(outline)\n",
    "p.add_mesh(pv_mesh1, show_scalar_bar=False, color='#4fb080', opacity=1.0)\n",
    "p.add_mesh(pv_mesh2_orig, show_scalar_bar=False, color='#ced175', style='wireframe', opacity=0.5)\n",
    "p.camera_position = 'xy'\n",
    "\n",
    "p.subplot(0,1)\n",
    "p.add_text(\"yz\")\n",
    "p.add_mesh(outline)\n",
    "p.add_mesh(pv_mesh1, show_scalar_bar=False, color='#4fb080', opacity=1.0)\n",
    "p.add_mesh(pv_mesh2_orig, show_scalar_bar=False, color='#ced175', style='wireframe', opacity=0.5)\n",
    "p.camera_position = 'yz'\n",
    "\n",
    "p.subplot(1,0)\n",
    "p.add_text(\"zx\")\n",
    "p.add_mesh(outline)\n",
    "p.add_mesh(pv_mesh1, show_scalar_bar=False, color='#4fb080', opacity=1.0)\n",
    "p.add_mesh(pv_mesh2_orig, show_scalar_bar=False, color='#ced175', style='wireframe', opacity=0.5)\n",
    "p.camera_position = 'zx'\n",
    "\n",
    "p.add_text(\"Affine Transforms\", position='lower_edge')\n",
    "\n",
    "p.subplot(1,1)\n",
    "p.add_text(\"persp\")\n",
    "p.add_mesh(outline)\n",
    "p.add_mesh(pv_mesh1, show_scalar_bar=False, color='#4fb080', opacity=1.0)\n",
    "p.add_mesh(pv_mesh2_orig, show_scalar_bar=False, color='#ced175', style='wireframe', opacity=0.75)\n",
    "p.camera_position = [100,35,70]\n",
    "p.set_viewup([0,1,0])\n",
    "p.show_bounds(grid='front', location='outer', all_edges=False, )\n",
    "\n",
    "p.show()"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "81361e77",
   "metadata": {},
   "source": [
    "#### Mesh 2 -> Mesh 1"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "afbb0fdb",
   "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=(2,2), border=False)\n",
    "\n",
    "p.subplot(0,0)\n",
    "p.add_text(\"xy\")\n",
    "p.add_mesh(outline)\n",
    "p.add_mesh(pv_mesh2, show_scalar_bar=False, color='#4fb080', opacity=1.0)\n",
    "p.add_mesh(pv_mesh1_orig, show_scalar_bar=False, color='#ced175', style='wireframe', opacity=0.5)\n",
    "p.camera_position = 'xy'\n",
    "\n",
    "p.subplot(0,1)\n",
    "p.add_text(\"yz\")\n",
    "p.add_mesh(outline)\n",
    "p.add_mesh(pv_mesh2, show_scalar_bar=False, color='#4fb080', opacity=1.0)\n",
    "p.add_mesh(pv_mesh1_orig, show_scalar_bar=False, color='#ced175', style='wireframe', opacity=0.5)\n",
    "p.camera_position = 'yz'\n",
    "\n",
    "p.subplot(1,0)\n",
    "p.add_text(\"zx\")\n",
    "p.add_mesh(outline)\n",
    "p.add_mesh(pv_mesh2, show_scalar_bar=False, color='#4fb080', opacity=1.0)\n",
    "p.add_mesh(pv_mesh1_orig, show_scalar_bar=False, color='#ced175', style='wireframe', opacity=0.5)\n",
    "p.camera_position = 'zx'\n",
    "\n",
    "p.add_text(\"Affine Transforms\", position='lower_edge')\n",
    "\n",
    "p.subplot(1,1)\n",
    "p.add_text(\"persp\")\n",
    "p.add_mesh(outline)\n",
    "p.add_mesh(pv_mesh2, show_scalar_bar=False, color='#4fb080', opacity=1.0)\n",
    "p.add_mesh(pv_mesh1_orig, show_scalar_bar=False, color='#ced175', style='wireframe', opacity=0.75)\n",
    "p.camera_position = [100,35,70]\n",
    "p.set_viewup([0,1,0])\n",
    "p.show_bounds(grid='front', location='outer', all_edges=False, )\n",
    "\n",
    "p.show()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "64318dae",
   "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
}
