Tesserae
e‑ink 디스플레이용 무료 오픈소스 대시보드 서버, 브라우저에서 대시보드 구성·프레임 렌더링·MQTT·REST 전송, 자체 호스팅·추적 없음
케이지 손잡이를 함께 움직이고, 미리 계산된 희소 행렬 하나로 손실 없이 규칙적인 케이지와 부드러운 날개, 실제 주조 가능한 손끝 제공
Make cage handles move together. One precomputed sparse matrix, no extra losses: regular cages, smoother wings, fingertips you can actually cast.
개발 도구Python · JavaScriptGitHub @camral온라인운영자 미확인
써 보셨어요? 한 번만 눌러 주세요. 로그인은 필요 없어요.
아직 감지된 업데이트가 없습니다. GitHub 릴리스가 나오면 여기에 보입니다.
Project page: Structural Affinity — coherent cage-based shape design
README 전체를 불러오는 중입니다.
README 전문 보기 ↗Reference implementation of Structural Affinity: An Algorithm for Coherent Cage-Based Shape Design (Aviraj Newatia, Shengan Yang, Hantao Zhong, Rika Antonova, University of Cambridge).
Project page · arXiv · Paper (PDF)
In cage-based deformation (CBD), each handle of the control cage moves independently. This can cause spiky, distorted and self-intersecting shapes.
Structural Affinity couples the handle motion with a second cage:
The outer cage gives an affinity matrix C (N × N). C tells how much each handle follows the other handles and is calculated once, offline. At deformation time, the method does one sparse matrix product.
structural_affinity_torch.py. matplotlib, for the examples.The implementation is one file: structural_affinity.py. Copy this file into
your project. For a PyTorch pipeline, also copy structural_affinity_torch.py.
Make the outer cage from the inner cage:
import structural_affinity as sa
outer_verts, outer_faces = sa.icosahedral_outer_cage(cage_verts)
Calculate the affinity. Do this step one time for each inner cage:
affinity = sa.StructuralAffinity(cage_verts, outer_verts, outer_faces, alpha=0.3, density=0.4)
Apply the affinity to the handle displacements D (N, 3):
deformed_cage = cage_verts + affinity.propagate(D)
The outer cage must:
If the outer cage does not obey these rules, StructuralAffinity raises ValueError.
Three functions make an outer cage. Each function returns (outer_verts, outer_faces):
| function | vertices | paper experiment |
|---|---|---|
icosahedral_outer_cage(cage_verts, padding=0.1) | 12 in 3D, 7 in 2D | Neural Cages |
box_outer_cage(cage_verts, padding=0.05) | 8 in 3D, 4 in 2D | Robot fingertips |
convex_outer_cage(cage_verts, padding=0.05) | the hull vertices of the inner cage | Wing optimization |
A custom outer cage can also be made as long as it satisfies the requirements above, these are just our provided implementations.
Note: for a convex inner cage, convex_outer_cage keeps all inner handles. The outer cage is then not
coarser than the inner cage.
To use your own outer cage, supply the arrays directly:
affinity = sa.StructuralAffinity(cage_verts, my_outer_verts, my_outer_faces, alpha=0.3, density=0.4)
my_outer_verts: shape (M, 3).my_outer_faces: shape (F, 3). The faces must have a consistent orientation.The outer cage controls which handles move together. The result of the method depends on this choice.
| parameter | range | effect |
|---|---|---|
alpha | ≥ 0 | Affinity strength. 0 gives plain CBD. A larger value makes the handles move more together. |
density | [0, 1] | Fraction of off-diagonal pairs in C to keep, largest values first. 0 removes all coupling. 1 keeps C dense. |
Start with alpha in [0.1, 0.45] and density in [0.2, 0.7].
Values in the paper:
| experiment | alpha | density | outer cage |
|---|---|---|---|
| Neural Cages (chair / table / car) | 0.3 / 0.2 / 0.4 | 0.4 | icosahedral_outer_cage |
| Robot fingertips | 0.35 | 0.15 | box_outer_cage, padding 0.05 |
| Wing, perturbed starts | 0.05 | 0.025 | convex_outer_cage |
Structural Affinity changes only the step that adds the displacements to the inner cage:
# before
deformed_cage = cage_verts + D
# after
deformed_cage = cage_verts + affinity.propagate(D)
propagate also accepts a batch with shape (B, N, d).
To save C and use it again, use StructuralAffinity.from_affinity_matrix(C, alpha).
AffinityPropagation is a torch.nn.Module. Its gradients go through the propagation to the offsets.
from structural_affinity_torch import AffinityPropagation
propagate = AffinityPropagation(affinity.C, alpha=affinity.alpha).to(device)
deformed_cage = cage + propagate(net(x)) # net(x) gives the offsets, shape (B, N, 3)
| step | time | operation | function |
|---|---|---|---|
| 1 | offline | Make a convex outer cage that strictly encloses the inner cage. | icosahedral_outer_cage, box_outer_cage, convex_outer_cage |
| 2 | offline | Calculate the mean-value coordinates W (N, M) of each inner handle in the outer cage. | mvc |
| 3 | offline | Calculate C_ij = Σ_k min(w_ik, w_jk). C is symmetric, in [0, 1], with a diagonal of 1. | affinity_matrix |
| 4 | offline | Keep the diagonal and the largest off-diagonal entries of C. | sparsify |
| 5 | each step | Calculate ΔV = A D, with A = (1 − α) I + α Cᵀ. | propagate |
Steps 2 to 4 are performed in the constructor of StructuralAffinity constructor.
Properties:
D_i moves by D_i.j also moves by α · C_ij · D_i.여기까지가 README 앞부분입니다. 나머지는 원문에서 읽을 수 있습니다. README 전문 보기 ↗