mesh-avatar-studio
일러스트를 코딩 에이전트와 로컬 편집기로 2D 메쉬 애니메이션 아바타로 변환
극좌표에서 사인 모드로 변형된 원형 형태를 실시간으로 조작하고, SVG·PNG·LaTeX·Python으로 내보내는 인터랙티브 플롯터
Interactive plotter for pebble-like shapes: a circle perturbed by sine modes in polar coordinates, with live shape descriptors and export to SVG, PNG, LaTeX and Python.
디자인HTMLGitHub @shyam97온라인운영자 미확인
써 보셨어요? 한 번만 눌러 주세요. 로그인은 필요 없어요.
아직 감지된 업데이트가 없습니다. GitHub 릴리스가 나오면 여기에 보입니다.
개인 계정의 공개 저장소 소유자는 GitHub로 로그인해 운영자를 확인하고 소개를 직접 관리할 수 있습니다. 관리자 승인은 필요하지 않습니다.
로그인한 뒤 확인 파일을 만들어 이 저장소의 기본 브랜치에 30분 안에 커밋해 주세요. 다른 브랜치나 포크의 파일은 인정하지 않습니다. 파일을 올린 뒤 아래에서 확인하면 관리자 승인 없이 관리할 수 있습니다. 자격을 유지하려면 파일을 남겨 두세요.
로그인이 필요하면 로그인 화면으로 이동합니다. 로그인 후 이곳으로 돌아와 원하는 확인 버튼을 다시 눌러 주세요.
프로젝트 폴더에서 /nomorevibe verify를 실행하면 소유권을 확인하고 소개를 직접 관리할 수 있습니다.
1분 만에 확인하기README 전체를 불러오는 중입니다. 아래는 저장된 발췌입니다.
An interactive plotter for pebble-like shapes: a circle perturbed by a few low-order sine modes in polar coordinates. Drag the sliders and watch the shape, its equation and its shape descriptors update live. You can then export it as an image or copy it as LaTeX, Python, SVG or JSON.
The site is one self-contained index.html. It has no framework, build step or external requests.
The boundary is a polar curve $r(\theta)$ for $\theta \in [0, 2\pi)$: a unit circle plus three Fourier modes.README 전문 보기 ↗An interactive plotter for pebble-like shapes: a circle perturbed by a few low-order sine modes in polar coordinates. Drag the sliders and watch the shape, its equation and its shape descriptors update live. You can then export it as an image or copy it as LaTeX, Python, SVG or JSON.
The site is one self-contained index.html. It has no framework, build step or external requests.
The boundary is a polar curve $r(\theta)$ for $\theta \in [0, 2\pi)$: a unit circle plus three Fourier modes.
$$ r(\theta) = 1 + w_2,a\sin(2\theta + 2\pi b) + w_3,c\sin(3\theta + 2\pi d) + w_4,e\sin(4\theta + 2\pi f) $$
| Symbol | Meaning | Range |
|---|---|---|
| $a, c, e$ | amplitude multipliers for modes 2, 3, 4 | $[0, 1]$ |
| $b, d, f$ | phases, as a fraction of a full turn | $[0, 1]$ |
| $w_2, w_3, w_4$ | mode weights, which cap each mode's amplitude | $[0, 2]$, default $0.3, 0.2, 0.1$ |
Mode 2 stretches the circle into an oval, mode 3 makes it rounded-triangular and mode 4 rounded-square. The weights shrink with mode number, so the higher, bumpier modes add only fine detail.
Writing phases as fractions of a turn keeps all six sliders on the same $[0, 1]$ scale. Phase $0$ and phase $1$ give the same shape.
Validity. Each sine term is at least $-w_k \cdot \text{amplitude}$, so
$$ r_{\min} \ge 1 - (w_2 a + w_3 c + w_4 e). $$
With the default weights this bound is at least $0.4$, so the curve is always a simple closed shape. If you raise the weights far enough for $r(\theta)$ to reach $0$, the curve passes through the origin and folds over itself. The page shows a warning when that happens.
The curve is sampled at $N = 1440$ points $(x_i, y_i) = (r_i\cos\theta_i,\ r_i\sin\theta_i)$ and treated as a polygon. All lengths are in units of the base radius.
| Descriptor | How it is computed |
|---|---|
| Area $A$ | Shoelace formula: $A = \tfrac12 \left\lvert \sum_i (x_i y_{i+1} - x_{i+1} y_i) \right\rvert$ |
| Perimeter $P$ | Sum of segment lengths |
| Centroid | Polygon centroid, $c_x = \frac{1}{6A}\sum_i (x_i + x_{i+1})(x_i y_{i+1} - x_{i+1} y_i)$, likewise for $c_y$. The page shows its distance from the origin and marks it on the plot. |
| Circularity | $4\pi A / P^2$, which is $1$ for a circle and smaller for anything else |
| Equivalent diameter | $2\sqrt{A/\pi}$, the diameter of the circle with the same area |
| Solidity | $A / A_\text{hull}$. The convex hull comes from Andrew's monotone chain algorithm, so solidity is $1$ for a convex shape. |
| Aspect ratio | $F_\max / F_\min$, the ratio of the largest to smallest Feret (caliper) diameter. Each Feret diameter is the width of the hull projected onto a direction; 180 directions are checked, one degree apart. |
| $r_\min$ / $r_\max$ | Extremes of $r(\theta)$ over the samples |
Randomize draws $a, \dots, f$ uniformly from $[0, 1]$ and each weight $w_k$ uniformly from $[0, 0.4]$. If the weights add up to more than $0.8$, they are scaled down to sum to $0.8$, which keeps $r_\min \ge 0.2$ by the bound above, so a random shape never folds over.
Suggested shapes. The gallery shows 16 shapes, freshly drawn on every load or when you click "New set". Each one comes from rejection sampling: make the same random draw as Randomize and keep the shape if
$$ F_\max / F_\min \le 1.3 \quad\text{and}\quad r_\max / r_\min \le 2, $$
which keeps the suggestions compact and pebble-like. After 400 rejected draws it falls back to the closest candidate. These limits apply only to suggestions; the sliders can make any shape.
Everything lives in index.html: CSS in a <style> block and two inline <script> blocks.
Head script. This runs before first paint:
Main script. This is a single IIFE split into commented sections:
| Section | What it does |
|---|---|
| state | Parameters and preferences, saved to localStorage |
| theme, colour picker | Light/dark toggle that follows the system setting until you choose; ten pastel pebble colours |
| geometry | r(θ), point sampling, convex hull, polygon area and all the shape descriptors |
| shared SVG markup | Polar grid and per-mode overlays, shared by the live view and the exports |
| equation | The colour-coded equation and the live numeric form below it |
| controls | Slider and number inputs for each mode, built from a MODES table |
| live drawing | update(), which recomputes everything and redraws the SVG on each input |
| export | SVG download (the pebble alone); PNG/JPG download (the full figure with the equation, rendered at 2400 px wide through a canvas) |
| randomness, tweening, animation | Randomize, Reset, tweens and phase animation, using requestAnimationFrame |
| suggested shapes | The rejection-sampled gallery |
| copy | Clipboard export as LaTeX, Python/NumPy, SVG or JSON |
The "glass" pebble. The pebble is drawn as layered SVG:
Accessibility.
aria-live.prefers-reduced-motion is set.localStorage, the Clipboard API, matchMedia for theme and reduced motion, and requestAnimationFrame._headers sets security headers in the Netlify/Cloudflare Pages format, including a strict Content-Security-Policy that allows only inline scripts and styles and data:/blob: images. robots.txt and a noindex meta tag keep the site out of search engines.HANDOFF.txt is a short status note for whoever works on the project next, whether a person or an AI coding agent. It covers the current state, the design decisions made so far and the open items. It lives only in this repository: _redirects sends /HANDOFF.txt on the deployed site back to the home page.
Open index.html in a browser. To serve it the way a host would:
python3 -m http.server
Then visit http://localhost:8000.
Conceptualized by shyam97.