{ "cells": [ { "cell_type": "markdown", "id": "ac87e6fb-030a-4c57-8cdc-20a9450c0a4f", "metadata": { "tags": [] }, "source": [ "# Assignment 3.1: Differential Geometry of smooth surfaces" ] }, { "cell_type": "code", "execution_count": 1, "id": "eb14a5c8-13ce-4d21-8167-ddbb674225e2", "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "/opt/conda/bin/python\n" ] } ], "source": [ "import numpy as np\n", "import sys\n", "print(sys.executable)\n", "import meshplot as mp\n", "sys.path.append('../src/')\n", "from smooth_surfaces import *\n", "from utils import *" ] }, { "cell_type": "markdown", "id": "4949242e-7532-4744-836c-3da903f42ea9", "metadata": {}, "source": [ "## Paraboloid surface" ] }, { "cell_type": "markdown", "id": "5290233d-e1c7-464f-b116-63917aaa8df3", "metadata": {}, "source": [ "To evaluate the paraboloid surface, we first sample the domain $\\Omega$ with a regular grid. For that, we specify the $u$ and $v$ intervals, and the sampling in the two directions:" ] }, { "cell_type": "code", "execution_count": 2, "id": "b06d705d-1164-496f-9f58-00267da59e81", "metadata": {}, "outputs": [], "source": [ "u_interval = [-1, 1]\n", "v_interval = [-1, 1]\n", "u_sampling = 21\n", "v_sampling = 21" ] }, { "cell_type": "markdown", "id": "23442be0-a0bc-42ea-83bd-23693de97a49", "metadata": {}, "source": [ "We use now the following provided function that creates the points $p\\in\\Omega\\subseteq\\mathbb R^2$, collected in the array `P`, and a triangulation `F` for visualization:" ] }, { "cell_type": "code", "execution_count": 3, "id": "ae541330-6a57-46d4-a8cd-7005fe8cd70e", "metadata": {}, "outputs": [], "source": [ "P, F = uv_grid(u_interval, v_interval, u_sampling, v_sampling)" ] }, { "cell_type": "markdown", "id": "600fbd25-4295-4074-a979-9d2a7aac8b45", "metadata": {}, "source": [ "We can now choose the parameters of the paraboloid:" ] }, { "cell_type": "code", "execution_count": 164, "id": "a0169d4c-ae67-4e23-92ec-798a7012e649", "metadata": {}, "outputs": [], "source": [ "a = 0.2\n", "b = 0.2\n", "c = -0.2\n", "d = -0.2\n", "e = 0" ] }, { "cell_type": "markdown", "id": "35a40d7a-2ac8-4248-b497-39dafac57078", "metadata": {}, "source": [ "Try to change the parameters to get and then compute the corresponding paraboloid points $\\mathbf x(p)\\in\\mathbb R^3$ and the derivatives of the parametrization at that points:" ] }, { "cell_type": "code", "execution_count": 165, "id": "75d4933e-2a64-4c01-91d7-3c9c47ace5a1", "metadata": {}, "outputs": [], "source": [ "x = compute_paraboloid_points(P, a, b, c, d, e)\n", "\n", "x_u, x_v = compute_paraboloid_first_derivatives(P, a, b, c, d, e)\n", "\n", "x_uu, x_uv, x_vv = compute_paraboloid_second_derivatives(P, a, b, c, d, e)" ] }, { "cell_type": "markdown", "id": "e41fefc0-dbd9-4fb7-bf4a-ae0e034bfb9b", "metadata": {}, "source": [ "### Principal curvatures" ] }, { "cell_type": "markdown", "id": "bc4a49ce-a517-4a5b-a6bb-18aad4be33fc", "metadata": {}, "source": [ "We define now a function that computes the principal curvatures of the surface at the points by using your functions:" ] }, { "cell_type": "code", "execution_count": 166, "id": "0577a574-95c2-4d0b-97a2-b5ca04235552", "metadata": {}, "outputs": [], "source": [ "def principal_curvatures(x_u, x_v, x_uu, x_uv, x_vv):\n", "\n", " n = compute_surface_normal(x_u, x_v)\n", "\n", " I = compute_first_fundamental_form(x_u, x_v)\n", "\n", " II = compute_second_fundamental_form(x_uu, x_uv, x_vv, n)\n", "\n", " S = compute_shape_operator(I, II)\n", "\n", " return compute_principal_curvatures(S, x_u, x_v)" ] }, { "cell_type": "markdown", "id": "064c8eba-7b20-4b30-8064-40db7a2e3e4d", "metadata": {}, "source": [ "and use it to evaluate the principal curvatures $\\kappa_1$ and $\\kappa_2$ with the corresponding principal directions $\\mathbf e_1$ and $\\mathbf e_2$ at each surface point:" ] }, { "cell_type": "code", "execution_count": 167, "id": "26483943-2117-4b33-b13f-54351ea4ee1e", "metadata": {}, "outputs": [], "source": [ "k_1, k_2, e_1, e_2 = principal_curvatures(x_u, x_v, x_uu, x_uv, x_vv)" ] }, { "cell_type": "markdown", "id": "0ae42813-cd7f-4b27-b9c4-9407a5a79e44", "metadata": {}, "source": [ "We can compute now the Gaussian curvature $K$ and the mean curvature $H$ as" ] }, { "cell_type": "code", "execution_count": 168, "id": "d365f3c0-c069-4645-a360-ba4f2219f3c3", "metadata": {}, "outputs": [], "source": [ "K = k_1 * k_2\n", "\n", "H = (k_1 + k_2)/2" ] }, { "cell_type": "markdown", "id": "34710736-2847-42e3-9468-3d620bb82d4b", "metadata": {}, "source": [ "To display the surface and the curvature, we define a plot function that colors points according to the curvature values with a blue-green-red color scale, with blue for negative values, green for zero, and red for positive values." ] }, { "cell_type": "code", "execution_count": 169, "id": "4ac8a92c-ded6-485b-b0d0-9d692fc96a73", "metadata": {}, "outputs": [], "source": [ "def plot_curvature(x, F, values):\n", " color = bgr_color(values)\n", " shading_options = {\n", " \"flat\":False,\n", " \"wireframe\":False,\n", " \"metalness\": 0,\n", " }\n", " mp.plot(x, F, c=color, shading=shading_options)" ] }, { "cell_type": "markdown", "id": "97dfabad-89d6-4d16-a028-5809aa4d3d22", "metadata": {}, "source": [ "and use it to visualize the Gaussian curvature of the surface" ] }, { "cell_type": "code", "execution_count": 170, "id": "ccb2dde3-cf23-4c0f-81bc-1de8f0910eb3", "metadata": {}, "outputs": [ { "data": { "application/vnd.jupyter.widget-view+json": { "model_id": "fd0f312ceca0422583d581083529866e", "version_major": 2, "version_minor": 0 }, "text/plain": [ "Renderer(camera=PerspectiveCamera(children=(DirectionalLight(color='white', intensity=0.6, position=(3.1415927…" ] }, "metadata": {}, "output_type": "display_data" } ], "source": [ "plot_curvature(x, F, K)" ] }, { "cell_type": "markdown", "id": "1d166a4e-04dd-4d0d-a248-b5baf5e7dcf8", "metadata": {}, "source": [ "and the mean curvature" ] }, { "cell_type": "code", "execution_count": 171, "id": "400c14b0-e551-4363-ac36-a71d8bd74fb8", "metadata": {}, "outputs": [ { "data": { "application/vnd.jupyter.widget-view+json": { "model_id": "b0f1ccdc2b3c43dcb18857be4c6d7083", "version_major": 2, "version_minor": 0 }, "text/plain": [ "Renderer(camera=PerspectiveCamera(children=(DirectionalLight(color='white', intensity=0.6, position=(3.1415927…" ] }, "metadata": {}, "output_type": "display_data" } ], "source": [ "plot_curvature(x, F, H)" ] }, { "cell_type": "markdown", "id": "afcb4e17-7677-4bb5-acc4-2548e77cd8f9", "metadata": {}, "source": [ "We want now to visualize directions on the surface. For that define the plot function" ] }, { "cell_type": "code", "execution_count": 172, "id": "75c72db5-cd8a-4a73-9c4b-ed17f6a870a2", "metadata": {}, "outputs": [], "source": [ "def plot_directions(x, F, d_1, d_2, scale=0.1):\n", " color = np.ones((len(x), 3))\n", " shading_options = {\n", " \"flat\": False,\n", " \"wireframe\":False,\n", " \"metalness\": 0.05,\n", " }\n", " p = mp.plot(x, F, c=color, shading=shading_options)\n", " p.add_lines(x+d_1*scale, x-d_1*scale, shading={\"line_color\": \"red\"})\n", " p.add_lines(x+d_2*scale, x-d_2*scale, shading={\"line_color\": \"blue\"})\n", " p.update_object()" ] }, { "cell_type": "markdown", "id": "94fc28d4-795d-440a-9c86-373186989d81", "metadata": {}, "source": [ "We can now display the principal curvature directions." ] }, { "cell_type": "code", "execution_count": 173, "id": "8435ea44-6114-4d96-9483-9b4d6ea1c36f", "metadata": {}, "outputs": [ { "data": { "application/vnd.jupyter.widget-view+json": { "model_id": "851bbfdf30f44a228f72b790a8fb6a88", "version_major": 2, "version_minor": 0 }, "text/plain": [ "Renderer(camera=PerspectiveCamera(children=(DirectionalLight(color='white', intensity=0.6, position=(3.1415927…" ] }, "metadata": {}, "output_type": "display_data" } ], "source": [ "plot_directions(x, F, e_1, e_2, scale=0.08)" ] }, { "cell_type": "markdown", "id": "efc58d26-2eae-490c-b8f0-a0226c63b978", "metadata": {}, "source": [ "### Asymptotic directions" ] }, { "cell_type": "markdown", "id": "22d70cd0-c1c1-496d-8513-e6f35a715be5", "metadata": {}, "source": [ "We estimate now the asymptotic directions" ] }, { "cell_type": "code", "execution_count": 174, "id": "9f872d92-2dea-41fc-a273-f3e65d4e5086", "metadata": {}, "outputs": [], "source": [ "a_1, a_2 = compute_asymptotic_directions(k_1, k_2, e_1, e_2)" ] }, { "cell_type": "markdown", "id": "dd7f02ac-825c-4ed4-bc88-8569cd7696e2", "metadata": { "tags": [] }, "source": [ "and display them" ] }, { "cell_type": "code", "execution_count": 175, "id": "98b09cbb-b742-4457-99d2-8c59b9ec40c5", "metadata": {}, "outputs": [ { "data": { "application/vnd.jupyter.widget-view+json": { "model_id": "8091f6dfb14e4c2398bb2d503c8c12a3", "version_major": 2, "version_minor": 0 }, "text/plain": [ "Renderer(camera=PerspectiveCamera(children=(DirectionalLight(color='white', intensity=0.6, position=(3.1415927…" ] }, "metadata": {}, "output_type": "display_data" } ], "source": [ "plot_directions(x, F, a_1, a_2, scale=0.08)" ] }, { "cell_type": "markdown", "id": "cd635566-05e4-48fc-93ec-0cee724e7751", "metadata": {}, "source": [ "## Torus surface" ] }, { "cell_type": "markdown", "id": "238ae4db-5c65-41fc-b5f5-cbea30683c9c", "metadata": {}, "source": [ "We display now the same quantities for thr torus surface, and start defining the domain interval and sampling" ] }, { "cell_type": "code", "execution_count": 16, "id": "4e1aa125-23ca-42f8-b846-7c9d8f7444bb", "metadata": {}, "outputs": [], "source": [ "u_interval = [0, 2*np.pi]\n", "v_interval = [0, 2*np.pi]\n", "u_sampling = 33\n", "v_sampling = 33" ] }, { "cell_type": "markdown", "id": "4fd11272-b041-4880-88f0-398987b360da", "metadata": {}, "source": [ "We now create an $u$-$v$ grid" ] }, { "cell_type": "code", "execution_count": 17, "id": "d298045e-3294-4ec4-ab22-28a9670c2ce2", "metadata": {}, "outputs": [], "source": [ "P, F = uv_grid(u_interval, v_interval, u_sampling, v_sampling)" ] }, { "cell_type": "markdown", "id": "da8fb757-e162-463b-9226-46ff6c6ab90c", "metadata": {}, "source": [ "and choose the torus radii" ] }, { "cell_type": "code", "execution_count": 18, "id": "aa3a5ac0-06ea-446a-ab6c-917265487c29", "metadata": {}, "outputs": [], "source": [ "R = 2\n", "\n", "r = 1" ] }, { "cell_type": "markdown", "id": "40dda590-2553-4a8a-a2f7-e0242eb5fec7", "metadata": {}, "source": [ "We can now proceed as for the paraboloid:" ] }, { "cell_type": "code", "execution_count": 19, "id": "870c5ee0-dd7e-4a87-9a64-2820513ff38e", "metadata": {}, "outputs": [], "source": [ "x = compute_torus_points(P, R, r)\n", "\n", "x_u, x_v = compute_torus_first_derivatives(P, R, r)\n", "\n", "x_uu, x_uv, x_vv = compute_torus_second_derivatives(P, R, r)" ] }, { "cell_type": "markdown", "id": "63c523f3-7db0-4bd1-8b04-8d7ddc66cfa9", "metadata": {}, "source": [ "### Principal curvatures" ] }, { "cell_type": "code", "execution_count": 20, "id": "f8da5db4-74c3-4c68-ac58-f123ce75c446", "metadata": {}, "outputs": [], "source": [ "k_1, k_2, e_1, e_2 = principal_curvatures(x_u, x_v, x_uu, x_uv, x_vv)" ] }, { "cell_type": "code", "execution_count": 21, "id": "d0a4bab6-d7e8-46ee-a0e3-fbf32a4c12c5", "metadata": {}, "outputs": [], "source": [ "K = k_1 * k_2\n", "\n", "H = (k_1 + k_2)/2" ] }, { "cell_type": "markdown", "id": "bc627815-58fd-40a7-afe8-a68adc8bac04", "metadata": {}, "source": [ "We plot now the Gaussian curvature $K$" ] }, { "cell_type": "code", "execution_count": 22, "id": "2cea4c46-a698-4a3e-91ad-a86cd2484b54", "metadata": {}, "outputs": [ { "data": { "application/vnd.jupyter.widget-view+json": { "model_id": "cccde70c2ddb4a7896fe694fdd3f4f9a", "version_major": 2, "version_minor": 0 }, "text/plain": [ "Renderer(camera=PerspectiveCamera(children=(DirectionalLight(color='white', intensity=0.6, position=(0.0, 0.0,…" ] }, "metadata": {}, "output_type": "display_data" } ], "source": [ "plot_curvature(x, F, K)" ] }, { "cell_type": "markdown", "id": "e05c34b0-770f-42fb-abd9-c8e790c2033a", "metadata": {}, "source": [ "the mean curvature $H$" ] }, { "cell_type": "code", "execution_count": 23, "id": "727be3f1-02b1-4db1-842d-c2ca5f619694", "metadata": {}, "outputs": [ { "data": { "application/vnd.jupyter.widget-view+json": { "model_id": "5cfec29c275e4ad09fd9ed50ca3e1048", "version_major": 2, "version_minor": 0 }, "text/plain": [ "Renderer(camera=PerspectiveCamera(children=(DirectionalLight(color='white', intensity=0.6, position=(0.0, 0.0,…" ] }, "metadata": {}, "output_type": "display_data" } ], "source": [ "plot_curvature(x, F, H)" ] }, { "cell_type": "markdown", "id": "4e2e4c3f-1a8c-4120-befc-1f7a3ea377b0", "metadata": {}, "source": [ "and the principal curvature directions $\\mathbf e_1$ and $\\mathbf e_2$" ] }, { "cell_type": "code", "execution_count": 24, "id": "6255e260-df73-4d4a-b8ec-2cd922d9942f", "metadata": {}, "outputs": [ { "data": { "application/vnd.jupyter.widget-view+json": { "model_id": "ef10f31b1d7d41c4a45129198f1a5ba4", "version_major": 2, "version_minor": 0 }, "text/plain": [ "Renderer(camera=PerspectiveCamera(children=(DirectionalLight(color='white', intensity=0.6, position=(0.0, 0.0,…" ] }, "metadata": {}, "output_type": "display_data" } ], "source": [ "plot_directions(x, F, e_1, e_2, scale=0.12)" ] }, { "cell_type": "markdown", "id": "5be26065-90f5-4fba-9dc4-80e283117dc9", "metadata": {}, "source": [ "### Asymptotic directions\n", "\n", "Finally, we can plot the asymptotic directions" ] }, { "cell_type": "code", "execution_count": 25, "id": "7c9161e6-7ef0-42ea-b1ec-fc9dd49533e0", "metadata": {}, "outputs": [ { "name": "stderr", "output_type": "stream", "text": [ "../src/smooth_surfaces.py:418: RuntimeWarning: invalid value encountered in sqrt\n", " sinT = np.sqrt(f)\n" ] } ], "source": [ "a_1, a_2 = compute_asymptotic_directions(k_1, k_2, e_1, e_2)" ] }, { "cell_type": "code", "execution_count": 26, "id": "ac71ac02-d0c0-4dd1-94af-227b3636ed9f", "metadata": {}, "outputs": [ { "data": { "application/vnd.jupyter.widget-view+json": { "model_id": "3f3da2e0f0474e4aaac9e29e11068f4f", "version_major": 2, "version_minor": 0 }, "text/plain": [ "Renderer(camera=PerspectiveCamera(children=(DirectionalLight(color='white', intensity=0.6, position=(0.0, 0.0,…" ] }, "metadata": {}, "output_type": "display_data" } ], "source": [ "plot_directions(x, F, a_1, a_2, scale=0.12)" ] }, { "cell_type": "code", "execution_count": null, "id": "a64403c3", "metadata": {}, "outputs": [], "source": [] }, { "cell_type": "code", "execution_count": null, "id": "87a49e59", "metadata": {}, "outputs": [], "source": [] }, { "cell_type": "code", "execution_count": null, "id": "6f639996", "metadata": {}, "outputs": [], "source": [] }, { "cell_type": "code", "execution_count": null, "id": "483b637b", "metadata": {}, "outputs": [], "source": [] }, { "cell_type": "code", "execution_count": null, "id": "99069ff6", "metadata": {}, "outputs": [], "source": [] } ], "metadata": { "kernelspec": { "display_name": "gc_course_env", "language": "python", "name": "gc_course_env" }, "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.8.8" } }, "nbformat": 4, "nbformat_minor": 5 }