Skip to content

bad_quad_mesh_from_quadtree

bad_quad_mesh_from_quadtree(C, W, CH)

Builds a mesh of a quadtree or octree for visualization purposes.

From a proper quadtree, builds a vertex-connected but degenerate quad mesh containing only the leaf nodes, to be used for visualizing the quadtree and quantities defined on its leaf nodes.

Parameters:

Name Type Description Default
C numpy double array

Matrix of cell centers

required
W numpy double array

Vector of half cell widths

required
CH numpy int array

Matrix of child indices (-1 if leaf node)

required

Returns:

Name Type Description
V numpy double array

Matrix of mesh vertices

Q numpy int array

Matrix of quad mesh indices

H numpy int array

Matrix of hexahedral mesh indices if input is octree (empty if quadtree)

See Also

initialize_quadtree, quadtree_children.

Examples:

# Build a quadtree from a random set of points
P = 2*np.random.rand(100,2) - 1
C,W,CH,PAR,D,A = gpytoolbox.initialize_quadtree(P,graded=True,max_depth=8,min_depth=2,vmin=np.array([-1,-1]),vmax=np.array([1,1]))
# Make it into a mesh
V,Q,_ = bad_quad_mesh_from_quadtree(C,W,CH)
# V is a list of vertices and Q is a list of quad indices into V
# Plotting this with polyscope
import polyscope as ps
ps.init()
ps.register_surface_mesh(V,Q)
ps.show()
Source code in src/gpytoolbox/bad_quad_mesh_from_quadtree.py
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
def bad_quad_mesh_from_quadtree(C,W,CH):
    """Builds a mesh of a quadtree or octree for visualization purposes.

    From a proper quadtree, builds a vertex-connected but degenerate quad mesh
    containing only the leaf nodes, to be used for visualizing the quadtree and quantities defined on its leaf nodes.

    Parameters
    ----------
    C : numpy double array
        Matrix of cell centers
    W : numpy double array
        Vector of half cell widths
    CH : numpy int array
        Matrix of child indices (-1 if leaf node)

    Returns
    -------
    V : numpy double array
        Matrix of mesh vertices
    Q : numpy int array
        Matrix of quad mesh indices
    H : numpy int array
        Matrix of hexahedral mesh indices if input is octree (empty if quadtree)

    See Also
    --------
    initialize_quadtree, quadtree_children.

    Examples
    --------
    ```python
    # Build a quadtree from a random set of points
    P = 2*np.random.rand(100,2) - 1
    C,W,CH,PAR,D,A = gpytoolbox.initialize_quadtree(P,graded=True,max_depth=8,min_depth=2,vmin=np.array([-1,-1]),vmax=np.array([1,1]))
    # Make it into a mesh
    V,Q,_ = bad_quad_mesh_from_quadtree(C,W,CH)
    # V is a list of vertices and Q is a list of quad indices into V
    # Plotting this with polyscope
    import polyscope as ps
    ps.init()
    ps.register_surface_mesh(V,Q)
    ps.show()
    ```
    """
    dim = C.shape[1]
    is_child = (CH[:,1]==-1)
    W = W[is_child][:,None]
    C = C[is_child,:]
    H = None
    # translate this
    Q = np.linspace(0,W.shape[0]-1,W.shape[0],dtype=int)[:,None]
    if dim==2:
        V = np.vstack((
            C + 0.5*np.tile(W,(1,2))*np.tile(np.array([[-1,-1]]),(W.shape[0],1)),
            C + 0.5*np.tile(W,(1,2))*np.tile(np.array([[-1,1]]),(W.shape[0],1)),
            C + 0.5*np.tile(W,(1,2))*np.tile(np.array([[1,1]]),(W.shape[0],1)),
            C + 0.5*np.tile(W,(1,2))*np.tile(np.array([[1,-1]]),(W.shape[0],1)),
            ))
        Q = np.hstack((
            Q,
            Q + W.shape[0],
            Q + 2*W.shape[0],
            Q + 3*W.shape[0]
        ))
    else:
        V = np.vstack((
            C + 0.5*np.tile(W,(1,3))*np.tile(np.array([[-1,-1,-1]]),(W.shape[0],1)),
            C + 0.5*np.tile(W,(1,3))*np.tile(np.array([[-1,1,-1]]),(W.shape[0],1)),
            C + 0.5*np.tile(W,(1,3))*np.tile(np.array([[1,1,-1]]),(W.shape[0],1)),
            C + 0.5*np.tile(W,(1,3))*np.tile(np.array([[1,-1,-1]]),(W.shape[0],1)),
            C + 0.5*np.tile(W,(1,3))*np.tile(np.array([[-1,-1,1]]),(W.shape[0],1)),
            C + 0.5*np.tile(W,(1,3))*np.tile(np.array([[-1,1,1]]),(W.shape[0],1)),
            C + 0.5*np.tile(W,(1,3))*np.tile(np.array([[1,1,1]]),(W.shape[0],1)),
            C + 0.5*np.tile(W,(1,3))*np.tile(np.array([[1,-1,1]]),(W.shape[0],1))
            ))
        H = np.hstack((Q + 0*W.shape[0],Q + 1*W.shape[0], Q + 2*W.shape[0],Q + 3*W.shape[0],Q + 4*W.shape[0],Q + 5*W.shape[0], Q + 6*W.shape[0],Q + 7*W.shape[0])) # polyscope convention
        Q = np.vstack((
            np.hstack((Q + 0*W.shape[0],Q + W.shape[0], Q + 2*W.shape[0],Q + 3*W.shape[0])),
            np.hstack((Q + 4*W.shape[0],Q + 5*W.shape[0], Q + 6*W.shape[0],Q + 7*W.shape[0])),
            np.hstack((Q + 2*W.shape[0],Q + 1*W.shape[0], Q + 5*W.shape[0],Q + 6*W.shape[0])),
            np.hstack((Q + 3*W.shape[0],Q + 0*W.shape[0], Q + 4*W.shape[0],Q + 7*W.shape[0])),
            np.hstack((Q + 1*W.shape[0],Q + 0*W.shape[0], Q + 4*W.shape[0],Q + 5*W.shape[0])),
            np.hstack((Q + 3*W.shape[0],Q + 2*W.shape[0], Q + 6*W.shape[0],Q + 7*W.shape[0])),
            ))

    # remap faces
    V, _, SVJ, Q = remove_duplicate_vertices(V,faces=Q,epsilon=np.amin(W)/100)
    H = SVJ[H]
    return V,Q,H