-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
e2f91ec
commit b2d7e4d
Showing
1 changed file
with
329 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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 | ||
} |