Skip to content

Commit

Permalink
Add simplification notebook
Browse files Browse the repository at this point in the history
  • Loading branch information
danshapero committed Jan 2, 2025
1 parent e2f91ec commit b2d7e4d
Showing 1 changed file with 329 additions and 0 deletions.
329 changes: 329 additions & 0 deletions demo/simplification.ipynb
Original file line number Diff line number Diff line change
@@ -0,0 +1,329 @@
{
"cells": [
{
"cell_type": "code",
"execution_count": null,
"id": "ab42d932-a5a1-46c5-9f4b-ce2e309761e5",
"metadata": {},
"outputs": [],
"source": [
"%matplotlib ipympl\n",
"import numpy as np\n",
"import matplotlib.pyplot as plt\n",
"from mpl_toolkits.mplot3d import Axes3D\n",
"from plyfile import PlyData\n",
"import zmsh"
]
},
{
"cell_type": "markdown",
"id": "7abcbb6d-e82a-4658-bd8e-4e8c5d6be479",
"metadata": {},
"source": [
"Download the Stanford bunny image."
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "48c2a0fe-431f-4c8e-a0ad-3c4830c5e880",
"metadata": {},
"outputs": [],
"source": [
"!wget --no-clobber http://graphics.stanford.edu/pub/3Dscanrep/bunny.tar.gz\n",
"!tar -zxvf bunny.tar.gz --wildcards --no-anchored '*bun_zipper_res2.ply'"
]
},
{
"cell_type": "markdown",
"id": "9c30d229-f61c-4ce8-bb2f-487b21a57491",
"metadata": {},
"source": [
"Load in the model using the `plyfile` package and extract the points and triangles."
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "8617dba1-aa69-46ff-b112-7b649d8ee902",
"metadata": {},
"outputs": [],
"source": [
"filename = \"bunny/reconstruction/bun_zipper_res2.ply\"\n",
"with open(filename, \"r\") as bunny_file:\n",
" model = PlyData.read(bunny_file)\n",
"\n",
"vertices = model.elements[0]\n",
"x, y, z = vertices[\"x\"], vertices[\"y\"], vertices[\"z\"]\n",
"points = np.column_stack((x, y, z))\n",
"triangles = np.array([tuple(elt) for elt in model.elements[1].data[\"vertex_indices\"]])"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "a89b3c09-e538-46ec-adf0-00bc5b0f65fc",
"metadata": {},
"outputs": [],
"source": [
"fig, ax = plt.subplots(subplot_kw={\"projection\": \"3d\"})\n",
"ax.view_init(elev=120)\n",
"ax.plot_trisurf(x, y, z, triangles=triangles);"
]
},
{
"cell_type": "markdown",
"id": "92a22bce-27f7-4396-a721-0768a6379394",
"metadata": {},
"source": [
"Make a mapping from vertices to triangles."
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "fbd901c3-d0b5-49d4-80d0-a02090f869d7",
"metadata": {},
"outputs": [],
"source": [
"cotriangles = [[] for index in range(len(points))]\n",
"for index, triangle in enumerate(triangles):\n",
" for vertex in triangle:\n",
" cotriangles[vertex].append(index)"
]
},
{
"cell_type": "markdown",
"id": "7eb35dd3-d30e-4156-b69c-edb8cbdb7ada",
"metadata": {},
"source": [
"We'll pick out the first two vertices of triangle 0 to focus on."
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "1cf603d6-1b36-4de2-9429-d778c4cda395",
"metadata": {},
"outputs": [],
"source": [
"triangles[0]"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "f4b441a6-8b13-48cc-be04-07872cda1ff1",
"metadata": {},
"outputs": [],
"source": [
"vertex0, vertex1 = triangles[0][:2]\n",
"vertex0, vertex1"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "5ef63b08-a646-4efc-879c-20c18fc24b0b",
"metadata": {},
"outputs": [],
"source": [
"triangle_ids = list(set(cotriangles[vertex0]).union(cotriangles[vertex1]))\n",
"patch = triangles[triangle_ids]\n",
"patch"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "13821956-e72d-496d-9d0d-2fcfc8eb5f2a",
"metadata": {},
"outputs": [],
"source": [
"vertex_ids = np.unique(patch.flatten())\n",
"vertex_ids"
]
},
{
"cell_type": "markdown",
"id": "3e5a0d86-f5bf-4d82-ab09-14427ba4b9b1",
"metadata": {},
"source": [
"To simplify things, we'll renumber the vertices on this patch."
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "1a8d8024-8772-4f11-a587-00e844ffe7f2",
"metadata": {},
"outputs": [],
"source": [
"id_map = np.vectorize({idx: val for val, idx in enumerate(vertex_ids)}.get)"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "ac1df793-570f-4817-ab92-224111f7330c",
"metadata": {},
"outputs": [],
"source": [
"patch = id_map(patch)\n",
"vtx0 = id_map(vertex0)\n",
"vtx1 = id_map(vertex1)"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "50fe653e-0f5f-46d6-85e1-eb20c3bb8261",
"metadata": {},
"outputs": [],
"source": [
"fig, ax = plt.subplots(subplot_kw={\"projection\": \"3d\"})\n",
"colors = [\"tab:green\" for index in range(len(vertex_ids))]\n",
"colors[vtx0] = \"tab:orange\"\n",
"colors[vtx1] = \"tab:orange\"\n",
"ax.plot_trisurf(x[vertex_ids], y[vertex_ids], z[vertex_ids], triangles=patch)\n",
"ax.scatter(x[vertex_ids], y[vertex_ids], z[vertex_ids], color=colors);"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "8a107f56-2ff8-4fd6-88ad-7575846fb360",
"metadata": {},
"outputs": [],
"source": [
"copatch = [[] for index in range(len(vertex_ids))]\n",
"for index, triangle in enumerate(patch):\n",
" for vertex in triangle:\n",
" copatch[vertex].append(index)\n",
"\n",
"copatch"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "db782eb7-f6d3-4f80-8398-5ac1d88a4181",
"metadata": {},
"outputs": [],
"source": [
"Q0 = zmsh.simplification.compute_qmatrix(points[vertex_ids[patch[copatch[vtx0]]]])\n",
"Q1 = zmsh.simplification.compute_qmatrix(points[vertex_ids[patch[copatch[vtx1]]]])\n",
"Q0, Q1"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "fe136419-7682-4557-a6b4-ddb1ad062169",
"metadata": {},
"outputs": [],
"source": [
"Q = Q0 + Q1\n",
"Q[0, 0] = 1\n",
"Q[0, 1:] = 0\n",
"f = np.array([1, 0, 0, 0])\n",
"r = np.linalg.solve(Q, f)[1:]\n",
"r, points[triangles[0][0]]"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "f3a012fa-56e3-4f03-ae26-2defa19ad949",
"metadata": {},
"outputs": [],
"source": [
"fig, ax = plt.subplots(subplot_kw={\"projection\": \"3d\"})\n",
"colors = [\"tab:green\" for index in range(len(vertex_ids))]\n",
"colors[vtx0] = \"tab:orange\"\n",
"colors[vtx1] = \"tab:orange\"\n",
"ax.plot_trisurf(x[vertex_ids], y[vertex_ids], z[vertex_ids], triangles=patch)\n",
"ax.scatter(x[vertex_ids], y[vertex_ids], z[vertex_ids], color=colors)\n",
"ax.scatter([r[0]], [r[1]], [r[2]], color=\"black\");"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "f22ef651-af3b-455c-8483-f410e07c6d10",
"metadata": {},
"outputs": [],
"source": [
"d0, d1, d2 = zmsh.polytopal.from_simplicial(patch)"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "e451bdec-1d96-4558-aeb5-db06e7e0ddda",
"metadata": {},
"outputs": [],
"source": [
"P0 = np.eye(len(vertex_ids), dtype=np.int8)\n",
"P0[vtx0, [vtx0, vtx1]] = (+1, +1)\n",
"P0[vtx1, :] = 0\n",
"P0"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "bc0e2b8c-b2fe-466d-a90c-3c87c2f73139",
"metadata": {},
"outputs": [],
"source": [
"e1 = P0 @ d1\n",
"e1.T"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "67f584cf-f121-47b6-8fa7-35b45710e4c9",
"metadata": {},
"outputs": [],
"source": [
"for index0, col0 in enumerate(e1.T):\n",
" for index1, col1 in enumerate(e1.T):\n",
" if (np.array_equal(col0, col1) or np.array_equal(col0, -col1)) and (index0 != index1) and (not np.all(col0 == 0)):\n",
" print(index0, index1)"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "42db5da8-937c-418f-8112-02cbc4a49918",
"metadata": {},
"outputs": [],
"source": [
"zmsh.polytopal.merge([e1, d2], face_ids=[3, 13])"
]
}
],
"metadata": {
"kernelspec": {
"display_name": "topomesh",
"language": "python",
"name": "topomesh"
},
"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.11.9"
}
},
"nbformat": 4,
"nbformat_minor": 5
}

0 comments on commit b2d7e4d

Please sign in to comment.