-
-
Notifications
You must be signed in to change notification settings - Fork 404
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
73bd2fd
commit f19bdd6
Showing
13 changed files
with
946 additions
and
62 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,181 @@ | ||
{ | ||
"cells": [ | ||
{ | ||
"cell_type": "markdown", | ||
"metadata": {}, | ||
"source": [ | ||
"<div class=\"contentcontainer med left\" style=\"margin-left: -50px;\">\n", | ||
"<dl class=\"dl-horizontal\">\n", | ||
" <dt>Title</dt> <dd> TriMesh Element</dd>\n", | ||
" <dt>Dependencies</dt> <dd>Bokeh</dd>\n", | ||
" <dt>Backends</dt> <dd><a href='./TriMesh.ipynb'>Bokeh</a></dd> <dd><a href='../matplotlib/TriMesh.ipynb'>Matplotlib</a></dd>\n", | ||
"</dl>\n", | ||
"</div>" | ||
] | ||
}, | ||
{ | ||
"cell_type": "code", | ||
"execution_count": null, | ||
"metadata": {}, | ||
"outputs": [], | ||
"source": [ | ||
"import numpy as np\n", | ||
"import pandas as pd\n", | ||
"import holoviews as hv\n", | ||
"from scipy.spatial import Delaunay\n", | ||
"\n", | ||
"hv.extension('bokeh')" | ||
] | ||
}, | ||
{ | ||
"cell_type": "markdown", | ||
"metadata": {}, | ||
"source": [ | ||
"A ``TriMesh`` represents a mesh of triangles represented as the simplexes and vertexes. The simplexes represent the indices into the vertex data, made up of three indices per triangle. The mesh therefore follows a datastructure very similar to a graph, with the abstract connectivity between nodes stored on the ``TriMesh`` element itself, the node or vertex positions stored on a ``Nodes`` element and the concrete ``EdgePaths`` making up each triangle generated when required by accessing the edgepaths attribute.\n", | ||
"\n", | ||
"Unlike a Graph each simplex is represented as the node indices of the three corners of each triangle rather than the usual source and target node.\n", | ||
"\n", | ||
"We will begin with a simple random mesh, generated by sampling some random integers and then applying Delaunay triangulation, which is available in SciPy. We can then construct the ``TriMesh`` by passing it the **simplexes** and the **vertices** (or **nodes**)." | ||
] | ||
}, | ||
{ | ||
"cell_type": "code", | ||
"execution_count": null, | ||
"metadata": {}, | ||
"outputs": [], | ||
"source": [ | ||
"n_verts = 100\n", | ||
"pts = np.random.randint(1, n_verts, (n_verts, 2))\n", | ||
"tris = Delaunay(pts)\n", | ||
"\n", | ||
"trimesh = hv.TriMesh((tris.simplices, pts))\n", | ||
"trimesh" | ||
] | ||
}, | ||
{ | ||
"cell_type": "markdown", | ||
"metadata": {}, | ||
"source": [ | ||
"To make this easier TriMesh also provides a convenient ``from_vertices`` method, which will apply the Delaunay triangulation and construct the ``TriMesh`` for us:" | ||
] | ||
}, | ||
{ | ||
"cell_type": "code", | ||
"execution_count": null, | ||
"metadata": {}, | ||
"outputs": [], | ||
"source": [ | ||
"hv.TriMesh.from_vertices(np.random.randn(100, 2))" | ||
] | ||
}, | ||
{ | ||
"cell_type": "markdown", | ||
"metadata": {}, | ||
"source": [ | ||
"Just like the ``Graph`` element we can access the ``Nodes`` and ``EdgePaths`` via the ``.nodes`` and ``.edgepaths`` attributes respectively." | ||
] | ||
}, | ||
{ | ||
"cell_type": "code", | ||
"execution_count": null, | ||
"metadata": {}, | ||
"outputs": [], | ||
"source": [ | ||
"trimesh.nodes + trimesh.edgepaths" | ||
] | ||
}, | ||
{ | ||
"cell_type": "markdown", | ||
"metadata": {}, | ||
"source": [ | ||
"Now let's make a slightly more interesting example by generating a more complex geometry. Here we will compute a geometry, then apply Delaunay triangulation again and finally apply a mask to drop nodes in the center." | ||
] | ||
}, | ||
{ | ||
"cell_type": "code", | ||
"execution_count": null, | ||
"metadata": {}, | ||
"outputs": [], | ||
"source": [ | ||
"# First create the x and y coordinates of the points.\n", | ||
"n_angles = 36\n", | ||
"n_radii = 8\n", | ||
"min_radius = 0.25\n", | ||
"radii = np.linspace(min_radius, 0.95, n_radii)\n", | ||
"\n", | ||
"angles = np.linspace(0, 2*np.pi, n_angles, endpoint=False)\n", | ||
"angles = np.repeat(angles[..., np.newaxis], n_radii, axis=1)\n", | ||
"angles[:, 1::2] += np.pi/n_angles\n", | ||
"\n", | ||
"x = (radii*np.cos(angles)).flatten()\n", | ||
"y = (radii*np.sin(angles)).flatten()\n", | ||
"z = (np.cos(radii)*np.cos(angles*3.0)).flatten()\n", | ||
"nodes = np.column_stack([x, y, z])\n", | ||
"\n", | ||
"# Apply Delaunay triangulation\n", | ||
"delauney = Delaunay(np.column_stack([x, y]))\n", | ||
"\n", | ||
"# Mask off unwanted triangles.\n", | ||
"xmid = x[delauney.simplices].mean(axis=1)\n", | ||
"ymid = y[delauney.simplices].mean(axis=1)\n", | ||
"mask = np.where(xmid*xmid + ymid*ymid < min_radius*min_radius, 1, 0)\n", | ||
"simplices = delauney.simplices[np.logical_not(mask)]" | ||
] | ||
}, | ||
{ | ||
"cell_type": "markdown", | ||
"metadata": {}, | ||
"source": [ | ||
"Once again we can simply supply the simplices and nodes to the ``TriMesh``." | ||
] | ||
}, | ||
{ | ||
"cell_type": "code", | ||
"execution_count": null, | ||
"metadata": {}, | ||
"outputs": [], | ||
"source": [ | ||
"nodes = hv.Points(nodes, vdims='z')\n", | ||
"hv.TriMesh((simplices, nodes))" | ||
] | ||
}, | ||
{ | ||
"cell_type": "markdown", | ||
"metadata": {}, | ||
"source": [ | ||
"We can also do something more interesting, e.g. by adding a value dimension to the vertices and coloring the edges by the vertex averaged value using the ``edge_color_index`` plot option:" | ||
] | ||
}, | ||
{ | ||
"cell_type": "code", | ||
"execution_count": null, | ||
"metadata": {}, | ||
"outputs": [], | ||
"source": [ | ||
"%%opts TriMesh [filled=True edge_color_index='z' width=400 height=400 tools=['hover'] inspection_policy='edges'] (cmap='viridis')\n", | ||
"hv.TriMesh((simplices, nodes))" | ||
] | ||
} | ||
], | ||
"metadata": { | ||
"kernelspec": { | ||
"display_name": "Python 3", | ||
"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.6.3" | ||
} | ||
}, | ||
"nbformat": 4, | ||
"nbformat_minor": 2 | ||
} |
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,180 @@ | ||
{ | ||
"cells": [ | ||
{ | ||
"cell_type": "markdown", | ||
"metadata": {}, | ||
"source": [ | ||
"<div class=\"contentcontainer med left\" style=\"margin-left: -50px;\">\n", | ||
"<dl class=\"dl-horizontal\">\n", | ||
" <dt>Title</dt> <dd> TriMesh Element</dd>\n", | ||
" <dt>Dependencies</dt> <dd>Bokeh</dd>\n", | ||
" <dt>Backends</dt> <dd><a href='./TriMesh.ipynb'>Matplotlib</a></dd> <dd><a href='../bokeh/TriMesh.ipynb'>Bokeh</a></dd>\n", | ||
"</dl>\n", | ||
"</div>" | ||
] | ||
}, | ||
{ | ||
"cell_type": "code", | ||
"execution_count": null, | ||
"metadata": {}, | ||
"outputs": [], | ||
"source": [ | ||
"import numpy as np\n", | ||
"import pandas as pd\n", | ||
"import holoviews as hv\n", | ||
"from scipy.spatial import Delaunay\n", | ||
"\n", | ||
"hv.extension('matplotlib')" | ||
] | ||
}, | ||
{ | ||
"cell_type": "markdown", | ||
"metadata": {}, | ||
"source": [ | ||
"A ``TriMesh`` represents a mesh of triangles represented as the simplexes and vertexes. The simplexes represent the indices into the vertex data, made up of three indices per triangle. The mesh therefore follows a datastructure very similar to a graph, with the abstract connectivity between nodes stored on the ``TriMesh`` element itself, the node or vertex positions stored on a ``Nodes`` element and the concrete ``EdgePaths`` making up each triangle generated when required by accessing the edgepaths attribute.\n", | ||
"\n", | ||
"Unlike a Graph each simplex is represented as the node indices of the three corners of each triangle rather than the usual source and target node.\n", | ||
"\n", | ||
"We will begin with a simple random mesh, generated by sampling some random integers and then applying Delaunay triangulation, which is available in SciPy. We can then construct the ``TriMesh`` by passing it the **simplexes** and the **vertices** (or **nodes**)." | ||
] | ||
}, | ||
{ | ||
"cell_type": "code", | ||
"execution_count": null, | ||
"metadata": {}, | ||
"outputs": [], | ||
"source": [ | ||
"n_verts = 100\n", | ||
"pts = np.random.randint(1, n_verts, (n_verts, 2))\n", | ||
"tris = Delaunay(pts)\n", | ||
"\n", | ||
"trimesh = hv.TriMesh((tris.simplices, pts))\n", | ||
"trimesh" | ||
] | ||
}, | ||
{ | ||
"cell_type": "markdown", | ||
"metadata": {}, | ||
"source": [ | ||
"To make this easier TriMesh also provides a convenient ``from_vertices`` method, which will apply the Delaunay triangulation and construct the ``TriMesh`` for us:" | ||
] | ||
}, | ||
{ | ||
"cell_type": "code", | ||
"execution_count": null, | ||
"metadata": {}, | ||
"outputs": [], | ||
"source": [ | ||
"hv.TriMesh.from_vertices(np.random.randn(100, 2))" | ||
] | ||
}, | ||
{ | ||
"cell_type": "markdown", | ||
"metadata": {}, | ||
"source": [ | ||
"Just like the ``Graph`` element we can access the ``Nodes`` and ``EdgePaths`` via the ``.nodes`` and ``.edgepaths`` attributes respectively." | ||
] | ||
}, | ||
{ | ||
"cell_type": "code", | ||
"execution_count": null, | ||
"metadata": {}, | ||
"outputs": [], | ||
"source": [ | ||
"trimesh.nodes + trimesh.edgepaths" | ||
] | ||
}, | ||
{ | ||
"cell_type": "markdown", | ||
"metadata": {}, | ||
"source": [ | ||
"Now let's make a slightly more interesting example by generating a more complex geometry. Here we will compute a geometry, then apply Delaunay triangulation again and finally apply a mask to drop nodes in the center." | ||
] | ||
}, | ||
{ | ||
"cell_type": "code", | ||
"execution_count": null, | ||
"metadata": {}, | ||
"outputs": [], | ||
"source": [ | ||
"# First create the x and y coordinates of the points.\n", | ||
"n_angles = 36\n", | ||
"n_radii = 8\n", | ||
"min_radius = 0.25\n", | ||
"radii = np.linspace(min_radius, 0.95, n_radii)\n", | ||
"\n", | ||
"angles = np.linspace(0, 2*np.pi, n_angles, endpoint=False)\n", | ||
"angles = np.repeat(angles[..., np.newaxis], n_radii, axis=1)\n", | ||
"angles[:, 1::2] += np.pi/n_angles\n", | ||
"\n", | ||
"x = (radii*np.cos(angles)).flatten()\n", | ||
"y = (radii*np.sin(angles)).flatten()\n", | ||
"z = (np.cos(radii)*np.cos(angles*3.0)).flatten()\n", | ||
"nodes = np.column_stack([x, y, z])\n", | ||
"\n", | ||
"# Apply Delaunay triangulation\n", | ||
"delauney = Delaunay(np.column_stack([x, y]))\n", | ||
"\n", | ||
"# Mask off unwanted triangles.\n", | ||
"xmid = x[delauney.simplices].mean(axis=1)\n", | ||
"ymid = y[delauney.simplices].mean(axis=1)\n", | ||
"mask = np.where(xmid*xmid + ymid*ymid < min_radius*min_radius, 1, 0)\n", | ||
"simplices = delauney.simplices[np.logical_not(mask)]" | ||
] | ||
}, | ||
{ | ||
"cell_type": "markdown", | ||
"metadata": {}, | ||
"source": [ | ||
"Once again we can simply supply the simplices and nodes to the ``TriMesh``." | ||
] | ||
}, | ||
{ | ||
"cell_type": "code", | ||
"execution_count": null, | ||
"metadata": {}, | ||
"outputs": [], | ||
"source": [ | ||
"hv.TriMesh((simplices, nodes))" | ||
] | ||
}, | ||
{ | ||
"cell_type": "markdown", | ||
"metadata": {}, | ||
"source": [ | ||
"We can also do something more interesting, e.g. by adding a value dimension to the vertices and coloring the edges by the vertex averaged value using the ``edge_color_index`` plot option:" | ||
] | ||
}, | ||
{ | ||
"cell_type": "code", | ||
"execution_count": null, | ||
"metadata": {}, | ||
"outputs": [], | ||
"source": [ | ||
"%%opts TriMesh [filled=True edge_color_index='z' fig_size=200] (cmap='viridis')\n", | ||
"hv.TriMesh((simplices, hv.Points(nodes, vdims='z')))" | ||
] | ||
} | ||
], | ||
"metadata": { | ||
"kernelspec": { | ||
"display_name": "Python 3", | ||
"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.6.3" | ||
} | ||
}, | ||
"nbformat": 4, | ||
"nbformat_minor": 2 | ||
} |
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
Oops, something went wrong.