def test_barycentric_coordinate_map(dims): from random import Random rng = Random(17) n = 5 unit = np.empty((dims, n)) from modepy.tools import ( pick_random_simplex_unit_coordinate, unit_to_barycentric, barycentric_to_unit, barycentric_to_equilateral, equilateral_to_unit,) for i in range(n): unit[:, i] = pick_random_simplex_unit_coordinate(rng, dims) bary = unit_to_barycentric(unit) assert (np.abs(np.sum(bary, axis=0) - 1) < 1e-15).all() assert (bary >= 0).all() unit2 = barycentric_to_unit(bary) assert la.norm(unit-unit2) < 1e-14 equi = barycentric_to_equilateral(bary) unit3 = equilateral_to_unit(equi) assert la.norm(unit-unit3) < 1e-14
def warp_and_blend_nodes_2d(n, node_tuples=None): try: alpha = _alpha_opt_2d[n-1] except IndexError: alpha = 5/3 if node_tuples is None: from pytools import generate_nonnegative_integer_tuples_summing_to_at_most \ as gnitstam node_tuples = list(gnitstam(n, 2)) else: if len(node_tuples) != (n+1)*(n+2)//2: raise ValueError("node_tuples list does not have the correct length") # shape: (2, nnodes) unit_nodes = (np.array(node_tuples, dtype=np.float64)/n*2 - 1).T from modepy.tools import ( unit_to_barycentric, barycentric_to_equilateral, equilateral_to_unit) bary = unit_to_barycentric(unit_nodes) return equilateral_to_unit( barycentric_to_equilateral(bary) + _2d_equilateral_shift(n, bary, alpha))
def warp_and_blend_nodes_2d(n, node_tuples=None): try: alpha = _alpha_opt_2d[n - 1] except IndexError: alpha = 5 / 3 if node_tuples is None: from pytools import generate_nonnegative_integer_tuples_summing_to_at_most \ as gnitstam node_tuples = list(gnitstam(n, 2)) else: if len(node_tuples) != (n + 1) * (n + 2) // 2: raise ValueError( "node_tuples list does not have the correct length") # shape: (2, nnodes) unit_nodes = (np.array(node_tuples, dtype=np.float64) / n * 2 - 1).T from modepy.tools import (unit_to_barycentric, barycentric_to_equilateral, equilateral_to_unit) bary = unit_to_barycentric(unit_nodes) return equilateral_to_unit( barycentric_to_equilateral(bary) + _2d_equilateral_shift(n, bary, alpha))
def test_barycentric_coordinate_map(dims): n = 100 from modepy.tools import ( unit_to_barycentric, barycentric_to_unit, barycentric_to_equilateral, equilateral_to_unit, ) rng = np.random.Generator(np.random.PCG64(17)) unit = nd.random_nodes_for_shape(shp.Simplex(dims), n, rng=rng) bary = unit_to_barycentric(unit) assert (np.abs(np.sum(bary, axis=0) - 1) < 1e-15).all() assert (bary >= 0).all() unit2 = barycentric_to_unit(bary) assert la.norm(unit - unit2) < 1e-14 equi = barycentric_to_equilateral(bary) unit3 = equilateral_to_unit(equi) assert la.norm(unit - unit3) < 1e-14
def warp_and_blend_nodes_2d(n, node_tuples=None): try: alpha = _alpha_opt_2d[n - 1] except IndexError: alpha = 5 / 3 space = PN(2, n) if node_tuples is None: node_tuples = node_tuples_for_space(space) else: if len(node_tuples) != space.space_dim: raise ValueError( "'node_tuples' list does not have the correct length") # shape: (2, nnodes) unit_nodes = (np.array(node_tuples, dtype=np.float64) / n * 2 - 1).T from modepy.tools import (unit_to_barycentric, barycentric_to_equilateral, equilateral_to_unit) bary = unit_to_barycentric(unit_nodes) return equilateral_to_unit( barycentric_to_equilateral(bary) + _2d_equilateral_shift(n, bary, alpha))
def warp_and_blend_nodes_3d(n, node_tuples=None): try: alpha = _alpha_opt_3d[n-1] except IndexError: alpha = 1. if node_tuples is None: from pytools import generate_nonnegative_integer_tuples_summing_to_at_most \ as gnitstam node_tuples = list(gnitstam(n, 3)) else: if len(node_tuples) != (n+1)*(n+2)*(n+3)//6: raise ValueError("node_tuples list does not have the correct length") # shape: (3, nnodes) unit_nodes = (np.array(node_tuples, dtype=np.float64)/n*2 - 1).T from modepy.tools import ( unit_to_barycentric, barycentric_to_equilateral, equilateral_to_unit, EQUILATERAL_VERTICES) bary = unit_to_barycentric(unit_nodes) equi = barycentric_to_equilateral(bary) equi_vertices = EQUILATERAL_VERTICES[3] # total number of nodes and tolerance tol = 1e-8 shift = np.zeros_like(equi) for i1, i2, i3, i4, vertex_step in [ (0, 1, 2, 3, -1), (1, 2, 3, 0, -1), (2, 3, 0, 1, -1), (3, 0, 1, 2, -1), ]: vi2, vi3, vi4 = [(i1 + vertex_step*i) % 4 for i in range(1, 4)] # all vertices have the same distance from the origin tangent1 = equi_vertices[vi3] - equi_vertices[vi4] tangent1 /= la.norm(tangent1) tangent2 = equi_vertices[vi2] - equi_vertices[vi3] tangent2 -= np.dot(tangent1, tangent2)*tangent1 tangent2 /= la.norm(tangent2) sub_bary = bary[[i2, i3, i4]] warp1, warp2 = _2d_equilateral_shift(n, sub_bary, alpha) l1 = bary[i1] l2, l3, l4 = sub_bary blend = l2*l3*l4 denom = (l2+0.5*l1)*(l3+0.5*l1)*(l4+0.5*l1) denom_ok = denom > tol blend[denom_ok] = ( (1+(alpha*l1[denom_ok])**2) * blend[denom_ok] / denom[denom_ok]) shift = shift + (blend*warp1)[np.newaxis, :] * tangent1[:, np.newaxis] shift = shift + (blend*warp2)[np.newaxis, :] * tangent2[:, np.newaxis] is_face = (l1 < tol) & ((l2 > tol) | (l3 > tol) | (l4 > tol)) # assign face warp separately shift[:, is_face] = ( + warp1[is_face][np.newaxis, :] * tangent1[:, np.newaxis] + warp2[is_face][np.newaxis, :] * tangent2[:, np.newaxis] ) return equilateral_to_unit(equi + shift)
link_radius = 0.02 from pytools import generate_nonnegative_integer_tuples_summing_to_at_most \ as gnitstam node_tuples = list(gnitstam(n, 3)) faces = [ [nt for nt in node_tuples if nt[0] == 0], [nt for nt in node_tuples if nt[1] == 0], [nt for nt in node_tuples if nt[2] == 0], [nt for nt in node_tuples if sum(nt) == n] ] from modepy.tools import unit_to_barycentric, barycentric_to_equilateral nodes = [(n[0],n[2], n[1]) for n in barycentric_to_equilateral( unit_to_barycentric( mp.warp_and_blend_nodes(3, n, node_tuples))).T] id_to_node = dict(list(zip(node_tuples, nodes))) def get_ball_radius(nid): in_faces = len([f for f in faces if nid in f]) if in_faces >= 2: return ball_radius * 1.333 else: return ball_radius def get_ball_color(nid): in_faces = len([f for f in faces if nid in f]) if in_faces >= 2: return (1,0,1) else:
import matplotlib.pyplot as pt import numpy as np import modepy as mp dims = 3 n = 10 unit = mp.warp_and_blend_nodes(dims, n) if 0: from modepy.tools import estimate_lebesgue_constant lebesgue = estimate_lebesgue_constant(n, unit, visualize=True) from modepy.tools import unit_to_barycentric, barycentric_to_equilateral equi = barycentric_to_equilateral(unit_to_barycentric(unit)) if dims == 2: pt.plot(equi[0], equi[1], "o") from modepy.tools import EQUILATERAL_VERTICES uv = list(EQUILATERAL_VERTICES[2]) uv.append(uv[0]) uv = np.array(uv) pt.plot(uv[:, 0], uv[:, 1], "") pt.gca().set_aspect("equal") pt.show() elif dims == 3: import mayavi.mlab as mlab mlab.points3d(equi[0], equi[1], equi[2]) mlab.orientation_axes()
def warp_and_blend_nodes_3d(n, node_tuples=None): try: alpha = _alpha_opt_3d[n - 1] except IndexError: alpha = 1. if node_tuples is None: from pytools import generate_nonnegative_integer_tuples_summing_to_at_most \ as gnitstam node_tuples = list(gnitstam(n, 3)) else: if len(node_tuples) != (n + 1) * (n + 2) * (n + 3) // 6: raise ValueError( "node_tuples list does not have the correct length") # shape: (3, nnodes) unit_nodes = (np.array(node_tuples, dtype=np.float64) / n * 2 - 1).T from modepy.tools import (unit_to_barycentric, barycentric_to_equilateral, equilateral_to_unit, EQUILATERAL_VERTICES) bary = unit_to_barycentric(unit_nodes) equi = barycentric_to_equilateral(bary) equi_vertices = EQUILATERAL_VERTICES[3] # total number of nodes and tolerance tol = 1e-8 shift = np.zeros_like(equi) for i1, i2, i3, i4, vertex_step in [ (0, 1, 2, 3, -1), (1, 2, 3, 0, -1), (2, 3, 0, 1, -1), (3, 0, 1, 2, -1), ]: vi2, vi3, vi4 = [(i1 + vertex_step * i) % 4 for i in range(1, 4)] # all vertices have the same distance from the origin tangent1 = equi_vertices[vi3] - equi_vertices[vi4] tangent1 /= la.norm(tangent1) tangent2 = equi_vertices[vi2] - equi_vertices[vi3] tangent2 -= np.dot(tangent1, tangent2) * tangent1 tangent2 /= la.norm(tangent2) sub_bary = bary[[i2, i3, i4]] warp1, warp2 = _2d_equilateral_shift(n, sub_bary, alpha) l1 = bary[i1] l2, l3, l4 = sub_bary blend = l2 * l3 * l4 denom = (l2 + 0.5 * l1) * (l3 + 0.5 * l1) * (l4 + 0.5 * l1) denom_ok = denom > tol blend[denom_ok] = ((1 + (alpha * l1[denom_ok])**2) * blend[denom_ok] / denom[denom_ok]) shift = shift + (blend * warp1)[np.newaxis, :] * tangent1[:, np.newaxis] shift = shift + (blend * warp2)[np.newaxis, :] * tangent2[:, np.newaxis] is_face = (l1 < tol) & ((l2 > tol) | (l3 > tol) | (l4 > tol)) # assign face warp separately shift[:, is_face] = ( +warp1[is_face][np.newaxis, :] * tangent1[:, np.newaxis] + warp2[is_face][np.newaxis, :] * tangent2[:, np.newaxis]) return equilateral_to_unit(equi + shift)
n = 8 ball_radius = 0.05 link_radius = 0.02 from pytools import generate_nonnegative_integer_tuples_summing_to_at_most \ as gnitstam node_tuples = list(gnitstam(n, 3)) faces = [[nt for nt in node_tuples if nt[0] == 0], [nt for nt in node_tuples if nt[1] == 0], [nt for nt in node_tuples if nt[2] == 0], [nt for nt in node_tuples if sum(nt) == n]] from modepy.tools import unit_to_barycentric, barycentric_to_equilateral nodes = [(n[0], n[2], n[1]) for n in barycentric_to_equilateral( unit_to_barycentric(mp.warp_and_blend_nodes(3, n, node_tuples))).T] id_to_node = dict(list(zip(node_tuples, nodes))) def get_ball_radius(nid): in_faces = len([f for f in faces if nid in f]) if in_faces >= 2: return ball_radius * 1.333 else: return ball_radius def get_ball_color(nid): in_faces = len([f for f in faces if nid in f]) if in_faces >= 2: return (1, 0, 1)
from __future__ import absolute_import import matplotlib.pyplot as pt import numpy as np import modepy as mp dims = 3 n = 10 unit = mp.warp_and_blend_nodes(dims, n) if 0: from modepy.tools import estimate_lebesgue_constant lebesgue = estimate_lebesgue_constant(n, unit, visualize=True) from modepy.tools import unit_to_barycentric, barycentric_to_equilateral equi = barycentric_to_equilateral(unit_to_barycentric(unit)) if dims == 2: pt.plot(equi[0], equi[1], "o") from modepy.tools import EQUILATERAL_VERTICES uv = list(EQUILATERAL_VERTICES[2]) uv.append(uv[0]) uv = np.array(uv) pt.plot(uv[:, 0], uv[:, 1], "") pt.gca().set_aspect("equal") pt.show() elif dims == 3: import mayavi.mlab as mlab mlab.points3d(