Created
March 31, 2020 18:32
-
-
Save deeplook/d9ac96508362ce5eb5015a7e449eb0b6 to your computer and use it in GitHub Desktop.
Explore seam on textures mapped to spheres
This file contains hidden or 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
| { | |
| "cells": [ | |
| { | |
| "cell_type": "markdown", | |
| "metadata": {}, | |
| "source": [ | |
| "# Explore texture seam on spheres" | |
| ] | |
| }, | |
| { | |
| "cell_type": "code", | |
| "execution_count": 1, | |
| "metadata": {}, | |
| "outputs": [], | |
| "source": [ | |
| "import numpy as np\n", | |
| "import ipyvolume as ipv\n", | |
| "from PIL import Image\n", | |
| "from ipywidgets import interact" | |
| ] | |
| }, | |
| { | |
| "cell_type": "markdown", | |
| "metadata": {}, | |
| "source": [ | |
| "## Define sphere" | |
| ] | |
| }, | |
| { | |
| "cell_type": "code", | |
| "execution_count": 2, | |
| "metadata": { | |
| "ExecuteTime": { | |
| "end_time": "2020-03-28T12:43:46.345724Z", | |
| "start_time": "2020-03-28T12:43:46.337716Z" | |
| } | |
| }, | |
| "outputs": [], | |
| "source": [ | |
| "def sphere(x, y, z, radius, color=\"red\", texture=None, num=100):\n", | |
| " \"\"\"Create a sphere mesh with origin at x, y, z and radius.\n", | |
| " \"\"\"\n", | |
| " assert num > 0\n", | |
| " \n", | |
| " # First compute the unit vectors and scale them:\n", | |
| " phi = np.linspace(0, 2 * np.pi, num)\n", | |
| " theta = np.linspace(0, np.pi, num)\n", | |
| " xu = np.outer(np.cos(phi), np.sin(theta))\n", | |
| " yu = np.outer(np.sin(phi), np.sin(theta))\n", | |
| " zu = np.outer(np.ones(np.size(phi)), np.cos(theta))\n", | |
| " X = x + radius * xu\n", | |
| " Y = y + radius * yu\n", | |
| " Z = z + radius * zu\n", | |
| " \n", | |
| " # Compute the lon and lat for a z-aligned sphere to change axis,\n", | |
| " # the math changes but is essentially the same.\n", | |
| " lon = np.arctan2(yu, xu)\n", | |
| " lat = np.arcsin(zu)\n", | |
| " \n", | |
| " # Get U, V and move them to proper values:\n", | |
| " u = 0.5 + lon / (2 * np.pi)\n", | |
| " v = 0.5 + lat / np.pi\n", | |
| "\n", | |
| " return ipv.plot_mesh(X, Y, Z, u=u, v=v, color=color, texture=texture, wireframe=False)" | |
| ] | |
| }, | |
| { | |
| "cell_type": "code", | |
| "execution_count": 3, | |
| "metadata": {}, | |
| "outputs": [ | |
| { | |
| "data": { | |
| "application/vnd.jupyter.widget-view+json": { | |
| "model_id": "cddeef0a52ac4e7c8cc0695c59a7d96b", | |
| "version_major": 2, | |
| "version_minor": 0 | |
| }, | |
| "text/plain": [ | |
| "VBox(children=(Figure(camera=PerspectiveCamera(fov=46.0, position=(0.0, 0.0, 2.0), quaternion=(0.0, 0.0, 0.0, …" | |
| ] | |
| }, | |
| "metadata": {}, | |
| "output_type": "display_data" | |
| } | |
| ], | |
| "source": [ | |
| "fig = ipv.figure()\n", | |
| "s = sphere(0, 0, 0, radius=1, color=\"blue\", num=15)\n", | |
| "ipv.show()" | |
| ] | |
| }, | |
| { | |
| "cell_type": "code", | |
| "execution_count": 4, | |
| "metadata": {}, | |
| "outputs": [], | |
| "source": [ | |
| "s.color = \"red\"" | |
| ] | |
| }, | |
| { | |
| "cell_type": "markdown", | |
| "metadata": {}, | |
| "source": [ | |
| "## Generate textures" | |
| ] | |
| }, | |
| { | |
| "cell_type": "code", | |
| "execution_count": 5, | |
| "metadata": {}, | |
| "outputs": [], | |
| "source": [ | |
| "def flat_image(width, height):\n", | |
| " data = 100 * np.ones((height, width)).astype(np.uint8)\n", | |
| " return Image.fromarray(data, \"L\")" | |
| ] | |
| }, | |
| { | |
| "cell_type": "code", | |
| "execution_count": 6, | |
| "metadata": {}, | |
| "outputs": [ | |
| { | |
| "data": { | |
| "image/png": "iVBORw0KGgoAAAANSUhEUgAAAIAAAABACAAAAAD3vSCjAAAAPklEQVR4nO3OMQEAAAjDsIFW/GtAxp7UQDOXblv+AwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAOQByggA5F96DpsAAAAASUVORK5CYII=\n", | |
| "text/plain": [ | |
| "<PIL.Image.Image image mode=L size=128x64 at 0x121628750>" | |
| ] | |
| }, | |
| "execution_count": 6, | |
| "metadata": {}, | |
| "output_type": "execute_result" | |
| } | |
| ], | |
| "source": [ | |
| "flat_image(128, 64)" | |
| ] | |
| }, | |
| { | |
| "cell_type": "code", | |
| "execution_count": 7, | |
| "metadata": {}, | |
| "outputs": [], | |
| "source": [ | |
| "def random_image(width, height):\n", | |
| " data = 255 * np.random.randint(0, 2, (height, width)).astype(np.uint8)\n", | |
| " return Image.fromarray(data, \"L\")" | |
| ] | |
| }, | |
| { | |
| "cell_type": "code", | |
| "execution_count": 8, | |
| "metadata": {}, | |
| "outputs": [ | |
| { | |
| "data": { | |
| "image/png": "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\n", | |
| "text/plain": [ | |
| "<PIL.Image.Image image mode=L size=128x64 at 0x1216A5790>" | |
| ] | |
| }, | |
| "execution_count": 8, | |
| "metadata": {}, | |
| "output_type": "execute_result" | |
| } | |
| ], | |
| "source": [ | |
| "random_image(128, 64)" | |
| ] | |
| }, | |
| { | |
| "cell_type": "code", | |
| "execution_count": 9, | |
| "metadata": {}, | |
| "outputs": [], | |
| "source": [ | |
| "def stripe_image(width, height):\n", | |
| " a0 = np.zeros(height)\n", | |
| " a1 = np.ones(height)\n", | |
| " data = 255 * np.array([[a0, a1][i % 2] for i in range(width)]).T.astype(np.uint8)\n", | |
| " return Image.fromarray(data, \"L\")" | |
| ] | |
| }, | |
| { | |
| "cell_type": "code", | |
| "execution_count": 10, | |
| "metadata": {}, | |
| "outputs": [ | |
| { | |
| "data": { | |
| "image/png": "iVBORw0KGgoAAAANSUhEUgAAAIAAAABACAAAAAD3vSCjAAAAPElEQVR4nO3OQREAAAzCMG7+PQ8ZfNIaSPLbL+MAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACkhAQD9DCv+KAAAAAElFTkSuQmCC\n", | |
| "text/plain": [ | |
| "<PIL.Image.Image image mode=L size=128x64 at 0x120A10490>" | |
| ] | |
| }, | |
| "execution_count": 10, | |
| "metadata": {}, | |
| "output_type": "execute_result" | |
| } | |
| ], | |
| "source": [ | |
| "stripe_image(128, 64)" | |
| ] | |
| }, | |
| { | |
| "cell_type": "markdown", | |
| "metadata": {}, | |
| "source": [ | |
| "## Map textures on sphere" | |
| ] | |
| }, | |
| { | |
| "cell_type": "code", | |
| "execution_count": 11, | |
| "metadata": { | |
| "ExecuteTime": { | |
| "end_time": "2020-03-28T12:43:49.970693Z", | |
| "start_time": "2020-03-28T12:43:46.702179Z" | |
| } | |
| }, | |
| "outputs": [ | |
| { | |
| "data": { | |
| "application/vnd.jupyter.widget-view+json": { | |
| "model_id": "d154b56cd91f4a32b5757a05eaa62904", | |
| "version_major": 2, | |
| "version_minor": 0 | |
| }, | |
| "text/plain": [ | |
| "VBox(children=(Figure(camera=PerspectiveCamera(fov=46.0, position=(0.0, 0.0, 2.0), quaternion=(0.0, 0.0, 0.0, …" | |
| ] | |
| }, | |
| "metadata": {}, | |
| "output_type": "display_data" | |
| } | |
| ], | |
| "source": [ | |
| "fig = ipv.figure()\n", | |
| "s = sphere(0, 0, 0, radius=1, num=24)\n", | |
| "ipv.show()" | |
| ] | |
| }, | |
| { | |
| "cell_type": "code", | |
| "execution_count": 12, | |
| "metadata": {}, | |
| "outputs": [], | |
| "source": [ | |
| "s.texture = flat_image(16, 8)" | |
| ] | |
| }, | |
| { | |
| "cell_type": "code", | |
| "execution_count": 13, | |
| "metadata": {}, | |
| "outputs": [ | |
| { | |
| "data": { | |
| "application/vnd.jupyter.widget-view+json": { | |
| "model_id": "2421309defd844fcaceced428a0ee50b", | |
| "version_major": 2, | |
| "version_minor": 0 | |
| }, | |
| "text/plain": [ | |
| "VBox(children=(Figure(camera=PerspectiveCamera(fov=46.0, position=(0.0, 0.0, 2.0), quaternion=(0.0, 0.0, 0.0, …" | |
| ] | |
| }, | |
| "metadata": {}, | |
| "output_type": "display_data" | |
| } | |
| ], | |
| "source": [ | |
| "fig = ipv.figure()\n", | |
| "img = stripe_image(64, 4)\n", | |
| "s = sphere(0, 0, 0, radius=1, num=24, texture=img)\n", | |
| "ipv.show()" | |
| ] | |
| }, | |
| { | |
| "cell_type": "markdown", | |
| "metadata": {}, | |
| "source": [ | |
| "## Add more interactivity" | |
| ] | |
| }, | |
| { | |
| "cell_type": "code", | |
| "execution_count": 15, | |
| "metadata": {}, | |
| "outputs": [ | |
| { | |
| "data": { | |
| "application/vnd.jupyter.widget-view+json": { | |
| "model_id": "24908e4bb19346ccad27143dadd0b882", | |
| "version_major": 2, | |
| "version_minor": 0 | |
| }, | |
| "text/plain": [ | |
| "VBox(children=(Figure(camera=PerspectiveCamera(fov=46.0, position=(0.0, 0.0, 2.0), quaternion=(0.0, 0.0, 0.0, …" | |
| ] | |
| }, | |
| "metadata": {}, | |
| "output_type": "display_data" | |
| } | |
| ], | |
| "source": [ | |
| "fig = ipv.figure()\n", | |
| "s = sphere(0, 0, 0, radius=1, num=12)\n", | |
| "ipv.show()" | |
| ] | |
| }, | |
| { | |
| "cell_type": "code", | |
| "execution_count": 21, | |
| "metadata": {}, | |
| "outputs": [ | |
| { | |
| "data": { | |
| "application/vnd.jupyter.widget-view+json": { | |
| "model_id": "5f027625f8e24e9c9e0a79981aa98f6c", | |
| "version_major": 2, | |
| "version_minor": 0 | |
| }, | |
| "text/plain": [ | |
| "interactive(children=(IntSlider(value=16, description='w', max=32, min=1), IntSlider(value=8, description='h',…" | |
| ] | |
| }, | |
| "metadata": {}, | |
| "output_type": "display_data" | |
| } | |
| ], | |
| "source": [ | |
| "tx = None\n", | |
| "\n", | |
| "@interact\n", | |
| "def retexture(w=(1, 32), h=(1, 16), typ=[\"stripe\", \"random\"]):\n", | |
| " global tx\n", | |
| " tx = stripe_image(w, h) if typ==\"stripe\" else random_image(w, h)\n", | |
| " s.texture = tx\n", | |
| " tx_norm = tx.resize((256, 128), Image.AFFINE)\n", | |
| " return tx_norm" | |
| ] | |
| } | |
| ], | |
| "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.7.6" | |
| } | |
| }, | |
| "nbformat": 4, | |
| "nbformat_minor": 4 | |
| } |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment