3 minute read

Simplex

3D ํฌ์ธํŠธ ํด๋ผ์šฐ๋“œ์—์„œ ์ž…์ฒด๋ฅผ ๋ชจ๋ธ๋งํ•  ๋•Œ๋Š” 3D Delaunay triangulation์„ ์‚ฌ์šฉํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค.

3D Delaunay triangulation์€ ์‚ฌ๋ฉด์ฒด(tetrahedra)๋ฅผ ์ƒ์„ฑํ•˜์ง€๋งŒ, ์šฐ๋ฆฌ๋Š” ํ‘œ๋ฉด ๋ฉ”์‹œ๋งŒ ํ•„์š”ํ•˜๋ฏ€๋กœ ์‚ฌ๋ฉด์ฒด์˜ ์™ธ๋ถ€ ๋ฉด(2D surfaces)๋งŒ ์ถ”์ถœํ•˜์—ฌ ์‚ฌ์šฉํ•  ๊ฒƒ์ž…๋‹ˆ๋‹ค.

์ด๋ฅผ ์œ„ํ•ด scipy.spatial import Delaunay๋กœ point cloud์— ๋Œ€ํ•œ Delaunay ๊ฐ์ฒด๋ฅผ tri ๋ณ€์ˆ˜๋กœ ์ƒ์„ฑํ•˜๊ณ , simplices๋ฅผ ์‚ฌ์šฉํ•ฉ๋‹ˆ๋‹ค.

simplices

In geometry, a simplex (plural: simplexes or simplices) is a generalization of the notion of a triangle or tetrahedron to arbitrary dimensions. The simplex is so-named because it represents the simplest possible polytope in any given dimension. For example,

  • a 0-dimensional simplex is a point,
  • a 1-dimensional simplex is a line segment,
  • a 2-dimensional simplex is a triangle,
  • a 3-dimensional simplex is a tetrahedron, and
  • a 4-dimensional simplex is a 5-cell.

image

The four simplexes that can be fully represented in 3D space.

โ€ฆ the word โ€œsimplexโ€ simply means any finite set of vertices. (์œ„ํ‚คํ”ผ๋””์•„์—์„œ ๋‹จ์ˆœํ•˜๊ฒŒ ํ‘œํ˜„)

โ€œsimplexโ€๋Š” ๋‹จ์ˆœํžˆ ์ ๋“ค์˜ ์ง‘ํ•ฉ์ด๋ผ๊ธฐ๋ณด๋‹ค๋Š”, ๊ทธ ์ ๋“ค์ด ์ด๋ฃจ๋Š” ๊ตฌ์ฒด์ ์ธ ๊ธฐํ•˜ํ•™์  ํ˜•์ƒ์„ ์˜๋ฏธํ•˜๋Š” ๊ฒƒ์ด ๋” ์ •ํ™•ํ•ฉ๋‹ˆ๋‹ค.

๋”ฐ๋ผ์„œ, Delaunay ๊ฐ์ฒด์˜ simplices๋Š” vertices(์ )๋กœ ์ด๋ฃจ์–ด์ง„ ์‚ผ๊ฐํ˜•(๋˜๋Š” 3D์˜ ๊ฒฝ์šฐ ์‚ฌ๋ฉด์ฒด)์„ ์˜๋ฏธํ•ฉ๋‹ˆ๋‹ค.

Faces are simplices themselves. (์œ„ํ‚คํ”ผ๋””์•„ ์„ค๋ช…)

๋ชจ๋“  simplex๋Š” ํ•˜์œ„ ์ฐจ์›์˜ simplex๋“ค์„ ํฌํ•จํ•˜๊ณ  ์žˆ์œผ๋ฉฐ, ์ด๋ฅผ face๋ผ๊ณ  ๋ถ€๋ฆ…๋‹ˆ๋‹ค.

์˜ˆ๋ฅผ ๋“ค์–ด:

  • ์‚ผ๊ฐํ˜•(2์ฐจ์› simplex)์˜ face๋Š” ๊ทธ ์‚ผ๊ฐํ˜•์„ ์ด๋ฃจ๋Š” ๋ณ€(1์ฐจ์› simplex)์ž…๋‹ˆ๋‹ค.
  • ์‚ฌ๋ฉด์ฒด(3์ฐจ์› simplex)์˜ face๋Š” ๊ทธ ์‚ฌ๋ฉด์ฒด๋ฅผ ์ด๋ฃจ๋Š” ์‚ผ๊ฐํ˜•(2์ฐจ์› simplex)์ž…๋‹ˆ๋‹ค.

์‚ฌ๋ฉด์ฒด(3์ฐจ์› simplex)์—์„œ ์‚ผ๊ฐํ˜•(2์ฐจ์› simplex)๊ฐ€ face์ž…๋‹ˆ๋‹ค.

์‚ฌ๋ฉด์ฒด(3์ฐจ์› simplex)๋Š” ๋„ค ๊ฐœ์˜ ๊ผญ์ง“์ ์œผ๋กœ ๊ตฌ์„ฑ๋œ ์ž…์ฒด ๋„ํ˜•์ด๋ฉฐ, ์ด ์‚ฌ๋ฉด์ฒด๋Š” ๋„ค ๊ฐœ์˜ ์‚ผ๊ฐํ˜• ๋ฉด์„ ๊ฐ€์ง‘๋‹ˆ๋‹ค. ๊ฐ๊ฐ์˜ ์‚ผ๊ฐํ˜• ๋ฉด์€ ์‚ฌ๋ฉด์ฒด์˜ face๋ฅผ ๊ตฌ์„ฑํ•˜๋ฉฐ, ์ด ์‚ผ๊ฐํ˜• ๋ฉด๋“ค์ด ๋ชจ์—ฌ ์‚ฌ๋ฉด์ฒด์˜ ํ‘œ๋ฉด ๋ฉ”์‹œ(surface mesh)๋ฅผ ํ˜•์„ฑํ•ฉ๋‹ˆ๋‹ค.


์‹ค์ „ ์ฝ”๋“œ

image

Triangulation of a set of points:

import numpy as np
points = np.array([[0, 0], [0, 1.1], [1, 0], [1, 1]])
from scipy.spatial import Delaunay
tri = Delaunay(points)

points๋Š” 4๊ฐœ์˜ ์ขŒํ‘œ๊ฐ€ ๋“ค์–ด์žˆ๋Š” 2์ฐจ์› NumPy ๋ฐฐ์—ด์ž…๋‹ˆ๋‹ค. ๊ฐ๊ฐ์˜ ์ขŒํ‘œ๋Š” (x, y) ํ˜•ํƒœ๋กœ ๋˜์–ด ์žˆ์ฃ .

  • points[:, 0]์€ ๋ชจ๋“  ํ–‰์—์„œ ์ฒซ ๋ฒˆ์งธ ์—ด(์ฆ‰, x ์ขŒํ‘œ๋“ค)์„ ์„ ํƒํ•ฉ๋‹ˆ๋‹ค.
  • points[:, 1]์€ ๋ชจ๋“  ํ–‰์—์„œ ๋‘ ๋ฒˆ์งธ ์—ด(์ฆ‰, y ์ขŒํ‘œ๋“ค)์„ ์„ ํƒํ•ฉ๋‹ˆ๋‹ค.

์˜ˆ๋ฅผ ๋“ค์–ด:

  • points[:, 0]์€ [0, 0, 1, 1]์ด ๋˜๊ณ , ์ด๋Š” x ์ขŒํ‘œ๋“ค์ž…๋‹ˆ๋‹ค.
  • points[:, 1]์€ [0, 1.1, 0, 1]์ด ๋˜๊ณ , ์ด๋Š” y ์ขŒํ‘œ๋“ค์ž…๋‹ˆ๋‹ค.

์ด ๊ฐ’๋“ค์€ ๊ทธ๋ž˜ํ”„๋ฅผ ๊ทธ๋ฆด ๋•Œ x์ถ•๊ณผ y์ถ• ์ขŒํ‘œ๋กœ ์‚ฌ์šฉ๋ฉ๋‹ˆ๋‹ค. plt.triplot๊ณผ plt.plot์—์„œ ๊ฐ๊ฐ x ์ขŒํ‘œ์™€ y ์ขŒํ‘œ๋ฅผ ์ง€์ •ํ•˜๋Š” ์—ญํ• ์„ ํ•ฉ๋‹ˆ๋‹ค.

We can plot it:

import matplotlib.pyplot as plt
plt.triplot(points[:,0], points[:,1], tri.simplices)
plt.plot(points[:,0], points[:,1], 'o')
plt.show()

image

Point indices and coordinates for the two triangles forming the triangulation:

tri.simplices
array([[2, 3, 0],                 # may vary
       [3, 1, 0]], dtype=int32)

Note that depending on how rounding errors go, the simplices may be in a different order than above.

points[tri.simplices]
array([[[ 1. ,  0. ],            # may vary
        [ 1. ,  1. ],
        [ 0. ,  0. ]],
       [[ 1. ,  1. ],
        [ 0. ,  1.1],
        [ 0. ,  0. ]]])

open3d.utility.Vector3iVector

import open3d
import numpy as np

# Example mesh
# x, y coordinates:
# [0: (-1, 2)]__________[1: (1, 2)]
#             \        /\
#              \  (0) /  \
#               \    / (1)\
#                \  /      \
#      [2: (0, 0)]\/________\[3: (2, 0)]
#
# z coordinate: 0

mesh = open3d.geometry.TriangleMesh()
np_vertices = np.array([[-1, 2, 0],
                        [1, 2, 0],
                        [0, 0, 0],
                        [2, 0, 0]])
np_triangles = np.array([[0, 2, 1],
                         [1, 2, 3]]).astype(np.int32)
mesh.vertices = open3d.Vector3dVector(np_vertices)

# From numpy to Open3D
mesh.triangles = open3d.Vector3iVector(np_triangles)

# From Open3D to numpy
np_triangles = np.asarray(mesh.triangles)

Code ๊ตฌํ˜„

import open3d as o3d
import numpy as np
from scipy.spatial import Delaunay

def extract_surface_mesh(tetra):
    # ๊ฐ ์‚ฌ๋ฉด์ฒด์˜ ๋ฉด์„ ์ถ”์ถœ
    faces = np.vstack((
        tetra[:, [0, 1, 2]],
        tetra[:, [0, 2, 3]],
        tetra[:, [0, 1, 3]],
        tetra[:, [1, 2, 3]]
    ))
    
    # ์ค‘๋ณต ๋ฉด ์ œ๊ฑฐ (ํ‘œ๋ฉด ๋ฉด๋งŒ ๋‚จ๊น€)
    faces = np.sort(faces, axis=1)
    faces, counts = np.unique(faces, return_counts=True, axis=0)
    surface_faces = faces[counts == 1]
    
    return surface_faces

def barycentric_deformation(GT, BP, GT_colors, BP_colors):
    print("\n Processing Barycentric Deformation.. \n")
    
    gt_pcd = o3d.geometry.PointCloud()
    gt_pcd.points = o3d.utility.Vector3dVector(GT)
    gt_pcd.colors = o3d.utility.Vector3dVector(GT_colors / 255.0)
    
    bp_pcd = o3d.geometry.PointCloud()
    bp_pcd.points = o3d.utility.Vector3dVector(BP)
    bp_colors = o3d.utility.Vector3dVector(BP_colors / 255.0)
    
    # Create a mesh from BP using 3D Delaunay triangulation
    bp_points = np.asarray(bp_pcd.points)
    tri = Delaunay(bp_points)
    surface_faces = extract_surface_mesh(tri.simplices)

Leave a comment