Disabled external gits

This commit is contained in:
2022-04-07 18:46:57 +02:00
parent 88cb3426ad
commit 15e7120d6d
5316 changed files with 4563444 additions and 6 deletions

View File

@@ -0,0 +1,749 @@
{
"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
}

View File

@@ -0,0 +1,423 @@
import numpy as np
# -----------------------------------------------------------------------------
# DERIVATIVES OF PARABOLOID
# -----------------------------------------------------------------------------
def compute_paraboloid_points(P, a, b, c, d, e):
"""Computes the points of the paraboloid x(u,v) = (u, v, z(u,v)) with
z(u,v) = a*u^2 + b*v^2 + c*u*v + d*u + e*v.
Try to vectorize this function.
Parameters:
- P : np.array (n, 2)
Contains in i-th row the (u, v) coordinates of the i-th parameter point p_i.
- a, b, c, d, e : float
The parameters of the paraboloid.
Returns:
- x : np.array (n, 3)
The points x(P), where the i-th row contains the (x,y,z) coordinates
of the point x(p_i)
"""
n = a*P[:,0]**2 + \
b*P[:,1]**2 + \
c*P[:,0]*P[:,1] + \
d*P[:,0] + \
e*P[:,1]
x = np.dstack((P[:,0],P[:,1],n))[0]
return x
def compute_paraboloid_first_derivatives(P, a, b, c, d, e):
"""Computes the first derivatives of the paraboloid x(u,v) = (u, v, z(u,v))
with z(u,v) = a*u^2 + b*v^2 + c*u*v + d*u + e*v.
Try to vectorize this function.
Parameters:
- P : np.array (n, 2)
Contains in i-th row the (u, v) coordinates of the i-th parameter point p_i.
- a, b, c, d, e : float
The parameters of the paraboloid.
Returns:
- x_u : np.array (n, 3)
The vectors x_u(P), where the i-th row contains the (x,y,z) coordinates
of the vector x_u(p_i).
- x_v : np.array (n, 3)
The vectors x_v(P), where the i-th row contains the (x,y,z) coordinates
of the vector x_v(p_i).
"""
nu = 2*a*P[:,0] + \
c*P[:,1] + \
d
nv = 2*b*P[:,1] + \
c*P[:,0] + \
e
z = np.zeros(P.shape[0])
o = np.ones(P.shape[0])
x_u = np.dstack((o,z,nu))[0]
x_v = np.dstack((z,o,nv))[0]
return x_u, x_v
def compute_paraboloid_second_derivatives(P, a, b, c, d, e):
"""Computes the second derivatives of the paraboloid x(u,v) = (u, v, z(u,v))
with z(u,v) = a*u^2 + b*v^2 + c*u*v + d*u + e*v.
Try to vectorize this function.
Parameters:
- P : np.array (n, 2)
Contains in i-th row the (u, v) coordinates of the i-th parameter point p_i.
- a, b, c, d, e : float
The parameters of the paraboloid.
Returns:
- x_uu : np.array (n, 3)
The vectors x_uu(P), where the i-th row contains the (x,y,z) coordinates
of the vector x_uu(p_i).
- x_uv : np.array (n, 3)
The vectors x_uv(P), where the i-th row contains the (x,y,z) coordinates
of the vector x_uv(p_i).
- x_vv : np.array (n, 3)
The vectors x_vv(P), where the i-th row contains the (x,y,z) coordinates
of the vector x_vv(p_i).
"""
nuu = np.repeat(2*a, P.shape[0])
nuv = np.repeat( c, P.shape[0])
nvv = np.repeat(2*b, P.shape[0])
z = np.zeros(P.shape[0])
x_uu = np.dstack((z,z,nuu))[0]
x_uv = np.dstack((z,z,nuv))[0]
x_vv = np.dstack((z,z,nvv))[0]
return x_uu, x_uv, x_vv
# -----------------------------------------------------------------------------
# DERIVATIVES OF TORUS
# -----------------------------------------------------------------------------
def compute_torus_points(P, R, r):
"""Computes the second derivatives of a torus.
Try to vectorize this function.
Parameters:
- P : np.array (n, 2)
Contains in i-th row the (u, v) coordinates of the i-th parameter point p_i.
- R : float
The radius of revolution.
- r : float
The radius of the cross section.
Returns:
- x : np.array (n, 3)
The points x(P), where the i-th row contains the (x,y,z) coordinates
of the point x(p_i)
"""
cosu = np.cos(P[:,0])
sinu = np.sin(P[:,0])
cosv = np.cos(P[:,1])
sinv = np.sin(P[:,1])
fx = (r * cosu+ R) * cosv
fy = (r * cosu+ R) * sinv
fz = r * sinu
x = np.dstack((fx, fy, fz))[0]
return x
def compute_torus_first_derivatives(P, R, r):
"""Computes the second derivatives of a torus.
Try to vectorize this function.
Parameters:
- P : np.array (n, 2)
Contains in i-th row the (u, v) coordinates of the i-th parameter point p_i.
- R : float
The radius of revolution.
- r : float
The radius of the cross section.
Returns:
- x_u : np.array (n, 3)
The vectors x_u(P), where the i-th row contains the (x,y,z) coordinates
of the vector x_u(p_i).
- x_v : np.array (n, 3)
The vectors x_v(P), where the i-th row contains the (x,y,z) coordinates
of the vector x_v(p_i).
"""
cosu = np.cos(P[:,0])
sinu = np.sin(P[:,0])
cosv = np.cos(P[:,1])
sinv = np.sin(P[:,1])
z = np.zeros(P.shape[0])
fx_u = - r * sinu * cosv
fy_u = - r * sinu * sinv
fz_u = r * cosu
fx_v = -(r * cosu+ R) * sinv
fy_v = (r * cosu+ R) * cosv
fz_v = z
x_u = np.dstack((fx_u, fy_u, fz_u))[0]
x_v = np.dstack((fx_v, fy_v, fz_v))[0]
return x_u, x_v
def compute_torus_second_derivatives(P, R, r):
"""Computes the second derivatives of a torus.
Try to vectorize this function.
Parameters:
- P : np.array (n, 2)
Contains in i-th row the (u, v) coordinates of the i-th parameter point p_i.
- R : float
The radius of revolution.
- r : float
The radius of the cross section.
Returns:
- x_uu : np.array (n, 3)
The vectors x_uu(P), where the i-th row contains the (x,y,z) coordinates
of the vector x_uu(p_i).
- x_uv : np.array (n, 3)
The vectors x_uv(P), where the i-th row contains the (x,y,z) coordinates
of the vector x_uv(p_i).
- x_vv : np.array (n, 3)
The vectors x_vv(P), where the i-th row contains the (x,y,z) coordinates
of the vector x_vv(p_i).
"""
cosu = np.cos(P[:,0])
sinu = np.sin(P[:,0])
cosv = np.cos(P[:,1])
sinv = np.sin(P[:,1])
z = np.zeros(P.shape[0])
fx_uu = - r * cosu * cosv
fy_uu = - r * cosu * sinv
fz_uu = - r * sinu
fx_uv = (r * sinu) * sinv
fy_uv = -(r * sinu) * cosv
fz_uv = z
fx_vv = -(r * cosu+ R) * cosv
fy_vv = -(r * cosu+ R) * sinv
fz_vv = z
x_uu = np.dstack((fx_uu, fy_uu, fz_uu))[0]
x_uv = np.dstack((fx_uv, fy_uv, fz_uv))[0]
x_vv = np.dstack((fx_vv, fy_vv, fz_vv))[0]
return x_uu, x_uv, x_vv
# -----------------------------------------------------------------------------
# SHAPE OPERATOR
# -----------------------------------------------------------------------------
def compute_first_fundamental_form(x_u, x_v):
"""Computes the first fundamental form I.
Try to vectorize this function.
Parameters:
- x_u : np.array (n, 3)
The i-th row contains the (x,y,z) coordinates of the vector x_u(p_i).
- x_v : np.array (n, 3)
The i-th row contains the (x,y,z) coordinates of the vector x_v(p_i).
Returns:
- I : np.array (n, 2, 2)
The first fundamental forms.
The (i, j, k) position contains the (j, k) element of the first
fundamental form I(p_i).
"""
e00 = np.einsum('lm,ml->m',x_u.T,x_u)
e01 = np.einsum('lm,ml->m',x_u.T,x_v)
e10 = np.einsum('lm,ml->m',x_v.T,x_u)
e11 = np.einsum('lm,ml->m',x_v.T,x_v)
I = np.dstack((e00,e01,e10,e11))[0].reshape((x_u.shape[0],2,2))
return I
def compute_surface_normal(x_u, x_v):
"""Computes the surface normal n.
Try to vectorize this function.
Parameters:
- x_u : np.array (n, 3)
The i-th row contains the (x,y,z) coordinates of the vector x_u(p_i).
- x_v : np.array (n, 3)
The i-th row contains the (x,y,z) coordinates of the vector x_v(p_i).
Returns:
- n : np.array (n, 3)
The surface normals.
The i-th row contains the (x,y,z) coordinates of the vector n(p_i).
"""
exp = np.cross(x_u, x_v)
div = np.linalg.norm(exp, axis=1)
n = exp/div[:,None]
return n
def compute_second_fundamental_form(x_uu, x_uv, x_vv, n):
"""Computes the second fundamental form II.
Try to vectorize this function.
Parameters:
- x_uu : np.array (n, 3)
The i-th row contains the (x,y,z) coordinates of the vector x_uu(p_i).
- x_uv : np.array (n, 3)
The i-th row contains the (x,y,z) coordinates of the vector x_uv(p_i).
- x_vv : np.array (n, 3)
The i-th row contains the (x,y,z) coordinates of the vector x_vv(p_i).
- n : np.array (n, 3)
The surface normals.
The i-th row contains the (x,y,z) coordinates of the vector n(p_i).
Returns:
- II : np.array (n, 2, 2)
The second fundamental forms.
The (i, j, k) position contains the (j, k) element of the second
fundamental form II(p_i).
"""
e00 = np.einsum('lm,ml->m',n.T, x_uu)
e01 = np.einsum('lm,ml->m',n.T, x_uv)
e10 = np.einsum('lm,ml->m',n.T, x_uv)
e11 = np.einsum('lm,ml->m',n.T, x_vv)
II = np.dstack((e00,e01,e10,e11))[0].reshape((n.shape[0],2,2))
return II
def compute_shape_operator(I, II):
"""Computes the shape operator S.
Try to vectorize this function.
Parameters:
- I : np.array (n, 2, 2)
The first fundamental forms.
The (i, j, k) position contains the (j, k) element of the first
fundamental form I(p_i).
- II : np.array (n, 2, 2)
The second fundamental forms.
The (i, j, k) position contains the (j, k) element of the second
fundamental form II(p_i).
Returns:
- S : np.array (n, 2, 2)
The shape operators.
The (i, j, k) position contains the (j, k) element of the shape
operator S(p_i).
"""
Iinv = np.linalg.inv(I)
S = Iinv @ II
return S
# -----------------------------------------------------------------------------
# PRINCIPAL CURVATURES
# -----------------------------------------------------------------------------
def compute_principal_curvatures(S, x_u, x_v):
"""Computes principal curvatures and corresponding principal directions.
Try to vectorize this function.
Parameters:
- S : np.array (n, 2, 2)
The shape operators.
The (i, j, k) position contains the (j, k) element of the shape
operator S(p_i).
- x_u : np.array (n, 3)
The i-th row contains the (x,y,z) coordinates of the vector x_u(p_i).
- x_v : np.array (n, 3)
The i-th row contains the (x,y,z) coordinates of the vector x_v(p_i).
Returns:
- k_1 : np.array (n)
The min principal curvature. i-th element contains the curvature k_1(p_i).
- k_2 : np.array (n)
The max principal curvature. i-th element contains the curvature k_2(p_i).
- e_1 : np.array (n, 3)
The unitized principal curvature direction corresponding to k_1.
The i-th row contains the (x,y,z) coordinates of e_1(p_i).
- e_2 : np.array (n, 3)
The unitized principal curvature direction corresponding to k_2.
The i-th row contains the (x,y,z) coordinates of e_2(p_i).
"""
# this section computes the ordered eigenvalues and eigenvectors of S where
# k_1[i] = min eigenvalue at p_i, k_2[i] = max eigenvalue at p_i,
# bar_e_1[i] = [u, v] components of the eigenvector of k_1,
# bar_e_2[i] = [u, v] components of the eigenvector of k_2
eig = np.linalg.eig(S)
index = np.argsort(eig[0], axis=1)
k_1 = eig[0][np.arange(len(S)), index[:, 0]]
k_2 = eig[0][np.arange(len(S)), index[:, 1]]
bar_e_1 = eig[1][np.arange(len(S)), :, index[:, 0]]
bar_e_2 = eig[1][np.arange(len(S)), :, index[:, 1]]
# Compute the normalized 3D vectors e_1, e_2
J = np.concatenate((x_u,x_v), axis=1).reshape((S.shape[0],2,3))
Je1 = np.einsum('lnm,ln->lm',J, bar_e_1)
Je2 = np.einsum('lnm,ln->lm',J, bar_e_2)
e_1 = Je1/np.linalg.norm(Je1, axis=1)[:,None]
e_2 = Je2/np.linalg.norm(Je2, axis=1)[:,None]
return k_1, k_2, e_1, e_2
# -----------------------------------------------------------------------------
# ASYMPTOTIC DIRECTIONS
# -----------------------------------------------------------------------------
def compute_asymptotic_directions(k_1, k_2, e_1, e_2):
"""Computes principal curvatures and corresponding principal directions.
Try to vectorize this function.
Parameters:
- k_1 : np.array (n)
The min principal curvature. i-th element contains the curvature k_1(p_i).
- k_2 : np.array (n)
The max principal curvature. i-th element contains the curvature k_2(p_i).
- e_1 : np.array (n, 3)
The unitized principal curvature direction corresponding to k_1.
The i-th row contains the (x,y,z) coordinates of e_1(p_i).
- e_2 : np.array (n, 3)
The unitized principal curvature direction corresponding to k_2.
The i-th row contains the (x,y,z) coordinates of e_2(p_i).
Returns:
- a_1 : np.array (n, 3)
The first unitized asymptotic direction. The i-th row contains the
(x,y,z) coordinates of a_2(p_i) if it exists, (0, 0, 0) otherwise.
- a_2 : np.array (n, 3)
The second unitized asymptotic direction. The i-th row contains the
(x,y,z) coordinates of a_2(p_i) if it exists, (0, 0, 0) otherwise.
"""
a_1 = np.zeros((k_1.shape[0],3))
a_2 = np.zeros((k_1.shape[0],3))
k1k2 = k_1*k_2
v1 = np.where(k1k2<=0)
v2 = np.where(k1k2<0)
f = np.zeros((k_1.shape[0]))
ff = np.zeros((k_1.shape[0]))
v3 = np.where((k_1-k_2)!=0)
f[v3] = (k_1[v3]/((k_1 - k_2)[v3]))
ff[v1] = f[v1]
cosT = np.sqrt(1-f)
sinT = np.sqrt(f)
a_1[v1] =(e_1*cosT[:,None] + e_2*sinT[:,None])[v1]
a_2[v2] =(e_1*cosT[:,None] - e_2*sinT[:,None])[v2]
return a_1, a_2

View File

@@ -0,0 +1,72 @@
import numpy as np
# -----------------------------------------------------------------------------
# UTILITIES
# -----------------------------------------------------------------------------
def uv_grid(u_domain, v_domain, n_u, n_v):
"""Computes a triangulation of a u-v patch.
Parameters:
- u_domain : list of floats [u_min, u_max]
The u domain.
- v_domain : list of floats [v_min, v_max]
The v domain.
- n_u : int
The number of samplings in u direction.
- n_v : int
The number of samplings in v direction.
Returns:
- P : np.array (n_u * n_v, 2)
The sample points. The i-th row contains the (u, v) coordinates of
point p_i.
- F : np.array (2 * (n_u - 1) * (n_v - 1), 3)
Triangular mesh faces of the points P. This can be used for
visualization.
"""
G = np.arange(n_u * n_v).reshape(n_v, n_u)
v1 = G[:-1, :-1].flatten()
v2 = G[:-1, 1:].flatten()
v3 = G[1:, 1:].flatten()
v4 = G[1:, :-1].flatten()
F1 = np.column_stack((v1, v3, v4))
F2 = np.column_stack((v1, v2, v3))
F = np.vstack((F1, F2))
u, v = np.meshgrid(np.linspace(u_domain[0], u_domain[1], n_u),
np.linspace(v_domain[0], v_domain[1], n_v))
P = np.column_stack((u.flatten(), v.flatten()))
return P, F
def bgr_color(values):
"""Computes bgr colors of some values.
Parameters:
- values * np.array (#values, )
Returns:
- rgb : np.array(#values, 3)
"""
val = np.array(values)
expansion = .5
X = np.linspace(0, 1, 64)
increase = 255 * (X ** expansion)
decrease = increase[::-1]
one = 255 * np.ones(64)
zero = np.zeros(64)
lut = np.ones((256, 3)).astype(float)
B = np.hstack((one, decrease, zero, zero))
G = np.hstack((increase, one, one, decrease))
R = np.hstack((zero, zero, increase, one))
lut[:, 0] = R / 255
lut[:, 1] = G / 255
lut[:, 2] = B / 255
lut[-1, :] = [255, 0, 255]
max_val = np.max(np.abs(values))
if max_val == 0:
max_val = 1
val = np.round(val / max_val * 127).astype('i') + 127
return lut[val]

View File

@@ -0,0 +1,281 @@
import time
import pytest
import json
import sys
import igl
import numpy as np
sys.path.append('../')
sys.path.append('../src')
from smooth_surfaces import *
eps = 1E-6
with open('test_data.json', 'r') as infile:
homework_datas = json.load(infile)
# Derivatives of a paraboloid
@pytest.mark.timeout(0.5)
@pytest.mark.parametrize("data", homework_datas[0])
def test_paraboloid_points(data):
P, a, b, c, d, e, x = data
P = np.array(P, dtype=float)
x = np.array(x, dtype=float)
x_student = compute_paraboloid_points(P, a, b, c, d, e)
assert np.linalg.norm(x_student - x) < eps
@pytest.mark.timeout(0.5)
@pytest.mark.parametrize("data", homework_datas[1])
def test_paraboloid_first_derivatives(data):
P, a, b, c, d, e, x_u, x_v = data
P = np.array(P, dtype=float)
x_u = np.array(x_u, dtype=float)
x_v = np.array(x_v, dtype=float)
x_u_student, x_v_student = compute_paraboloid_first_derivatives(P, a, b, c, d, e)
assert np.linalg.norm(x_u_student - x_u) < eps
assert np.linalg.norm(x_v_student - x_v) < eps
@pytest.mark.timeout(0.5)
@pytest.mark.parametrize("data", homework_datas[2])
def test_paraboloid_second_derivatives(data):
P, a, b, c, d, e, x_uu, x_uv, x_vv = data
P = np.array(P, dtype=float)
x_uu = np.array(x_uu, dtype=float)
x_uv = np.array(x_uv, dtype=float)
x_vv = np.array(x_vv, dtype=float)
student_x_uu, student_x_uv, student_x_vv = compute_paraboloid_second_derivatives(P, a, b, c, d, e)
assert np.linalg.norm(student_x_uu - x_uu) < eps
assert np.linalg.norm(student_x_uv - x_uv) < eps
assert np.linalg.norm(student_x_vv - x_vv) < eps
##############################
# Derivatives of a torus
@pytest.mark.timeout(0.5)
@pytest.mark.parametrize("data", homework_datas[3])
def test_torus_points(data):
P, R, r, x = data
P = np.array(P, dtype=float)
x = np.array(x, dtype=float)
x_student = compute_torus_points(P, R, r)
assert np.linalg.norm(x_student - x) < eps
@pytest.mark.timeout(0.5)
@pytest.mark.parametrize("data", homework_datas[4])
def test_torus_first_derivatives(data):
P, R, r, x_u, x_v = data
P = np.array(P, dtype=float)
x_u = np.array(x_u, dtype=float)
x_v = np.array(x_v, dtype=float)
x_u_student, x_v_student = compute_torus_first_derivatives(P, R, r)
assert np.linalg.norm(x_u_student - x_u) < eps
assert np.linalg.norm(x_v_student - x_v) < eps
@pytest.mark.timeout(0.5)
@pytest.mark.parametrize("data", homework_datas[5])
def test_torus_second_derivatives(data):
P, R, r, x_uu, x_uv, x_vv = data
P = np.array(P, dtype=float)
x_uu = np.array(x_uu, dtype=float)
x_uv = np.array(x_uv, dtype=float)
x_vv = np.array(x_vv, dtype=float)
student_x_uu, student_x_uv, student_x_vv = compute_torus_second_derivatives(P, R, r)
assert np.linalg.norm(student_x_uu - x_uu) < eps
assert np.linalg.norm(student_x_uv - x_uv) < eps
assert np.linalg.norm(student_x_vv - x_vv) < eps
##############################
# Shape Operator
@pytest.mark.timeout(0.5)
@pytest.mark.parametrize("data", homework_datas[6])
def test_paraboloid_first_fundamental_form(data):
P, a, b, c, d, e, I, x_u, x_v = data
P = np.array(P, dtype=float)
I = np.array(I, dtype=float)
x_u = np.array(x_u, dtype=float)
x_v = np.array(x_v, dtype=float)
I_student = compute_first_fundamental_form(x_u, x_v)
assert np.linalg.norm(I_student - I) < eps
@pytest.mark.timeout(0.5)
@pytest.mark.parametrize("data", homework_datas[7])
def test_torus_first_fundamental_form(data):
P, R, r, I, x_u, x_v = data
P = np.array(P, dtype=float)
I = np.array(I, dtype=float)
x_u = np.array(x_u, dtype=float)
x_v = np.array(x_v, dtype=float)
I_student = compute_first_fundamental_form(x_u, x_v)
assert np.linalg.norm(I_student - I) < eps
@pytest.mark.timeout(0.5)
@pytest.mark.parametrize("data", homework_datas[8])
def test_paraboloid_surface_normal(data):
P, a, b, c, d, e, n, x_u, x_v = data
P = np.array(P, dtype=float)
n = np.array(n, dtype=float)
x_u = np.array(x_u, dtype=float)
x_v = np.array(x_v, dtype=float)
n_student = compute_surface_normal(x_u, x_v)
assert np.linalg.norm(n_student - n) < eps
@pytest.mark.timeout(0.5)
@pytest.mark.parametrize("data", homework_datas[9])
def test_torus_surface_normal(data):
P, R, r, n, x_u, x_v = data
P = np.array(P, dtype=float)
n = np.array(n, dtype=float)
x_u = np.array(x_u, dtype=float)
x_v = np.array(x_v, dtype=float)
n_student = compute_surface_normal( x_u, x_v)
assert np.linalg.norm(n_student - n) < eps
@pytest.mark.timeout(0.5)
@pytest.mark.parametrize("data", homework_datas[10])
def test_paraboloid_second_fundamental_form(data):
P, a, b, c, d, e, II, x_uu, x_uv, x_vv, n = data
P = np.array(P, dtype=float)
II = np.array(II, dtype=float)
x_uu = np.array(x_uu, dtype=float)
x_uv = np.array(x_uv, dtype=float)
x_vv = np.array(x_vv, dtype=float)
n = np.array(n, dtype=float)
II_student = compute_second_fundamental_form(x_uu, x_uv, x_vv, n )
assert np.linalg.norm(II_student - II) < eps
@pytest.mark.timeout(0.5)
@pytest.mark.parametrize("data", homework_datas[11])
def test_torus_second_fundamental_form(data):
P, R, r, II, x_uu, x_uv, x_vv, n = data
P = np.array(P, dtype=float)
II = np.array(II, dtype=float)
x_uu = np.array(x_uu, dtype=float)
x_uv = np.array(x_uv, dtype=float)
x_vv = np.array(x_vv, dtype=float)
n = np.array(n, dtype=float)
II_student = compute_second_fundamental_form(x_uu, x_uv, x_vv, n)
assert np.linalg.norm(II_student - II) < eps
@pytest.mark.timeout(0.5)
@pytest.mark.parametrize("data", homework_datas[12])
def test_paraboloid_shape_operator(data):
P, a, b, c, d, e, S, I, II = data
P = np.array(P, dtype=float)
S = np.array(S, dtype=float)
I = np.array(I, dtype=float)
II = np.array(II, dtype=float)
S_student = compute_shape_operator(I, II)
assert np.linalg.norm(S_student - S) < eps
@pytest.mark.timeout(0.5)
@pytest.mark.parametrize("data", homework_datas[13])
def test_torus_shape_operator(data):
P, R, r, S, I, II = data
P = np.array(P, dtype=float)
S = np.array(S, dtype=float)
I = np.array(I, dtype=float)
II = np.array(II, dtype=float)
S_student = compute_shape_operator(I, II)
assert np.linalg.norm(S_student - S) < eps
##############################
# Principal Curvatures
@pytest.mark.timeout(0.5)
@pytest.mark.parametrize("data", homework_datas[14])
def test_paraboloid_principal_curvatures(data):
P, a, b, c, d, e, k1, k2, e1, e2, S, x_u, x_v = data
P = np.array(P, dtype=float)
k1 = np.array(k1, dtype=float)
k2 = np.array(k2, dtype=float)
e1 = np.array(e1, dtype=float)
e2 = np.array(e2, dtype=float)
S = np.array(S, dtype=float)
x_u = np.array(x_u, dtype=float)
x_v = np.array(x_v, dtype=float)
k_1_student, k_2_student, e_1_student, e_2_student = compute_principal_curvatures(S, x_u, x_v)
assert np.linalg.norm(k_1_student - k1) < eps
assert np.linalg.norm(k_2_student - k2) < eps
assert np.linalg.norm(e_1_student - e1) < eps
assert np.linalg.norm(e_2_student - e2) < eps
@pytest.mark.timeout(0.5)
@pytest.mark.parametrize("data", homework_datas[15])
def test_torus_principal_curvatures(data):
P, R, r, k1, k2, e1, e2, S, x_u, x_v = data
P = np.array(P, dtype=float)
k1 = np.array(k1, dtype=float)
k2 = np.array(k2, dtype=float)
e1 = np.array(e1, dtype=float)
e2 = np.array(e2, dtype=float)
S = np.array(S, dtype=float)
x_u = np.array(x_u, dtype=float)
x_v = np.array(x_v, dtype=float)
k_1_student, k_2_student, e_1_student, e_2_student = compute_principal_curvatures(S, x_u, x_v)
assert np.linalg.norm(k_1_student - k1) < eps
assert np.linalg.norm(k_2_student - k2) < eps
assert np.linalg.norm(e_1_student - e1) < eps
assert np.linalg.norm(e_2_student - e2) < eps
##############################
# Asymptotic Directions
@pytest.mark.timeout(0.5)
@pytest.mark.parametrize("data", homework_datas[16])
def test_paraboloid_asymptotic_direction(data):
P, a, b, c, d, e, a1, a2, k1, k2, e1, e2 = data
P = np.array(P, dtype=float)
a1 = np.array(a1, dtype=float)
a2 = np.array(a2, dtype=float)
k1 = np.array(k1, dtype=float)
k2 = np.array(k2, dtype=float)
e1 = np.array(e1, dtype=float)
e2 = np.array(e2, dtype=float)
a_1_student, a_2_student = compute_asymptotic_directions(k1, k2, e1, e2)
assert (np.linalg.norm(a_1_student - a1) < eps and np.linalg.norm(a_2_student - a2) < eps) or (np.linalg.norm(a_1_student - a2) < eps and np.linalg.norm(a_2_student - a1) < eps)
@pytest.mark.timeout(0.5)
@pytest.mark.parametrize("data", homework_datas[17])
def test_torus_asymptotic_direction(data):
P, R, r, a1, a2, k1, k2, e1, e2 = data
P = np.array(P, dtype=float)
a1 = np.array(a1, dtype=float)
a2 = np.array(a2, dtype=float)
k1 = np.array(k1, dtype=float)
k2 = np.array(k2, dtype=float)
e1 = np.array(e1, dtype=float)
e2 = np.array(e2, dtype=float)
a_1_student, a_2_student = compute_asymptotic_directions(k1, k2, e1, e2)
assert (np.linalg.norm(a_1_student - a1) < eps and np.linalg.norm(a_2_student - a2) < eps) or (np.linalg.norm(a_1_student - a2) < eps and np.linalg.norm(a_2_student - a1) < eps)
##############################

File diff suppressed because one or more lines are too long