-
Notifications
You must be signed in to change notification settings - Fork 6
Expand file tree
/
Copy pathformulas.html
More file actions
304 lines (284 loc) · 14.2 KB
/
Copy pathformulas.html
File metadata and controls
304 lines (284 loc) · 14.2 KB
1
2
3
4
5
6
7
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
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8" />
<!-- REMOVED 2026-08-15: the Ezoic Incubator integration-detection scripts and their
Gatekeeper CMP. See index.html for the reason - it rendered a real consent banner
with no working reject-all, reported live on Hacker News. -->
<meta name="viewport" content="width=device-width, initial-scale=1" />
<title>Writing a drum as an equation: polar and parametric outlines</title>
<meta
name="description"
content="A reference for Eigendrum's equation input: polar r(t), parametric x(t) and y(t), the full function list, worked examples, and the three kinds of formula that get refused."
/>
<link rel="canonical" href="https://eigendrum.com/formulas" />
<meta name="robots" content="index, follow, max-image-preview:large, max-snippet:-1" />
<meta name="author" content="Basel Ashraf" />
<meta name="color-scheme" content="light" />
<meta name="theme-color" content="#f0ede6" />
<!-- REMOVED 2026-08-15: Monetag and Google AdSense site-ownership verification tags.
All advertising is paused site-wide; see index.html for the fuller note. -->
<meta property="og:type" content="article" />
<meta property="og:site_name" content="Eigendrum" />
<meta property="og:url" content="https://eigendrum.com/formulas" />
<meta property="og:title" content="Writing a drum as an equation: polar and parametric outlines" />
<meta
property="og:description"
content="Type r(t) or a parametric x(t), y(t) pair and hear the shape it traces. Full function reference and worked examples."
/>
<meta property="og:image" content="https://eigendrum.com/docs/hero.png" />
<meta name="twitter:card" content="summary_large_image" />
<meta name="twitter:image" content="https://eigendrum.com/docs/hero.png" />
<script type="application/ld+json">
{
"@context": "https://schema.org",
"@type": "TechArticle",
"headline": "Writing a drum as an equation: polar and parametric outlines",
"description": "Reference for Eigendrum's expression language: notation, operators, available functions, worked examples, and the validity rules that cause a formula to be refused.",
"author": { "@type": "Person", "name": "Basel Ashraf" },
"publisher": { "@type": "Person", "name": "Basel Ashraf" },
"datePublished": "2026-08-02",
"mainEntityOfPage": "https://eigendrum.com/formulas",
"inLanguage": "en",
"proficiencyLevel": "Beginner"
}
</script>
<link rel="stylesheet" href="styles/font.css" />
<link rel="stylesheet" href="styles/app.css?v=2" />
<link rel="stylesheet" href="styles/page.css" />
<link
rel="icon"
href="data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 32 32'%3E%3Crect width='32' height='32' fill='%23f0ede6'/%3E%3Ccircle cx='16' cy='16' r='10' fill='%23d8321c'/%3E%3Cpath d='M0 16h32' stroke='%2314120f' stroke-width='3'/%3E%3C/svg%3E"
/>
</head>
<body>
<header class="masthead">
<a class="mark-link" href="/" aria-label="Eigendrum home">
<svg class="mark" viewBox="0 0 40 40" aria-hidden="true" focusable="false">
<circle cx="20" cy="20" r="13" fill="#d8321c" />
<path d="M0 20h40" stroke="#14120f" stroke-width="3" />
<rect x="17" y="17" width="6" height="6" fill="#14120f" />
</svg>
</a>
<div class="masthead-titles">
<p class="masthead-eyebrow"><a href="/">eigendrum</a></p>
<p>a study of the vibrating plane</p>
</div>
<div class="masthead-actions">
<a class="chip chip-solid" href="/#f=p:1 + 0.3cos(5t)">try an equation</a>
</div>
</header>
<main class="doc">
<article class="doc-inner">
<p class="doc-kicker">reference</p>
<h1>Writing a drum as an equation</h1>
<p class="doc-standfirst">
Besides tracing an outline with a pointer, you can write one. This reaches
shapes no hand traces accurately, and it makes a shape something you can
<em>vary</em>: change one number and hear what moved.
</p>
<p>
There are two notations. In both, <span class="tex">t</span> sweeps from 0 to
<span class="tex">tau</span> - one full turn, in radians.
</p>
<table>
<thead>
<tr><th>notation</th><th>meaning</th><th>example</th></tr>
</thead>
<tbody>
<tr>
<td>polar</td>
<td><span class="tex">r(t)</span>, the radius at angle <span class="tex">t</span></td>
<td><span class="tex">1 + 0.3cos(5t)</span></td>
</tr>
<tr>
<td>parametric</td>
<td><span class="tex">x(t)</span>, <span class="tex">y(t)</span></td>
<td><span class="tex">3cos(t) − cos(3t)</span></td>
</tr>
</tbody>
</table>
<p>
Size is irrelevant. Every outline is scaled to unit area before solving, because
what you are meant to hear is the shape and not the size - so
<span class="tex">r = 0.001</span> and <span class="tex">r = 5000</span> are the
same drum, and produce the same frequency ratios.
</p>
<h2>Operators</h2>
<p>
<span class="tex">+ − * / % ^</span> with the usual precedence, and
<span class="tex">^</span> is right associative. Brackets group.
<span class="tex">|x|</span> is absolute value. Implicit multiplication is
accepted, so <span class="tex">2t</span>,
<span class="tex">3cos(t)</span> and <span class="tex">2(1 + t)</span> all mean
what they look like.
</p>
<p>
One exception, and it is worth knowing because it will bite you. A bar is both an
opening and a closing delimiter, so <span class="tex">|</span> cannot also start
an implicit product. Write <span class="tex">2|t|</span> as
<span class="tex">2*|t|</span>. Ordinary written mathematics has the same
ambiguity and resolves it by context; a parser with one token of lookahead does
not have that luxury.
</p>
<h2>Available functions and constants</h2>
<p>
Constants: <span class="tex">pi</span>, <span class="tex">tau</span>,
<span class="tex">e</span>, <span class="tex">phi</span>.
</p>
<p>
Functions: <span class="tex">sin cos tan asin acos atan atan2 sinh cosh tanh exp
log ln log2 log10 sqrt cbrt abs sign floor ceil round hypot pow mod min max
clamp</span>.
</p>
<p>
Plus two that are not standard library functions but earn their place:
<span class="tex">square</span> and <span class="tex">tri</span>, a square wave
and a triangle wave of period <span class="tex">tau</span>. They are how you get
teeth and facets without needing a piecewise notation.
</p>
<div class="ad ad-article" data-ad="article-top" data-ad-format="auto">
<span class="ad-label">advertisement</span>
<div class="ad-frame"></div>
</div>
<h2>Worked examples</h2>
<h3>A five-lobed flower</h3>
<p class="equation">r = 1 + 0.3cos(5t)</p>
<p>
The classic starting point. The <span class="tex">5</span> sets the number of
lobes and the <span class="tex">0.3</span> sets how deep they are. Change the 5
to an 11 and you get eleven even lobes - a shape that is essentially impossible
to trace accurately by hand, and one whose spectrum is visibly different.
</p>
<h3>A superellipse, part way between a circle and a square</h3>
<p class="equation">r = (|cos(t)|^4 + |sin(t)|^4)^(−0.25)</p>
<p>
Raise the exponent and it approaches a square; lower it and it relaxes toward a
circle. This is the most direct way to hear what "cornerness" does to a spectrum,
because you can move continuously between two shapes that both have closed-form
answers.
</p>
<h3>A nephroid, parametric</h3>
<p class="equation">x = 3cos(t) − cos(3t) · y = 3sin(t) − sin(3t)</p>
<p>
Parametric reaches closed curves that polar cannot express at all - anything
where the radius is not a single-valued function of angle. Kidney shapes, eggs,
and lopsided blobs live here.
</p>
<h3>A toothed wheel</h3>
<p class="equation">r = 1 + 0.12square(9t)</p>
<p>
Sharp steps rather than smooth lobes. Worth comparing directly against
<span class="tex">1 + 0.12cos(9t)</span>, which has the same number of features
and the same amplitude but no corners - the difference in the high end of the
spectrum is the corners talking.
</p>
<h2>Three kinds of formula it won't take</h2>
<p>
Each one gets its own message explaining which problem it hit. None of these are
arbitrary limits - they're places where the maths genuinely breaks down.
</p>
<ul>
<li>
<strong>Undefined somewhere on the sweep.</strong> If the expression has no
value at some <span class="tex">t</span>, there's no curve to solve on.
</li>
<li>
<strong>Self-crossing.</strong> A crossing outline doesn't have a clean inside,
so the underlying problem isn't well posed. Usually it's a negative
<span class="tex">r</span> folding the curve back through the origin, and the
message calls that out directly since it's almost always what happened.
</li>
<li>
<strong>Too thin to mesh accurately.</strong> This is the one that actually
matters. A hair-thin sliver has no interior nodes across its narrow direction, so
solving it would hand back eigenvalues that look like real numbers but are wrong.
Refusing is the only honest option here. Freehand drawing never runs into this,
because nobody can draw a shape with a 1-in-10,000 aspect ratio by hand -
<span class="tex">x = cos(t)</span>, <span class="tex">y = 0.0004sin(t)</span>
does it instantly.
</li>
</ul>
<p>
An implicit form <span class="tex">F(x, y) = 0</span> is deliberately absent. It
needs marching squares, contour tracing, and a rule for deciding which contour
you meant - a different job from parsing an expression, and a much larger one.
</p>
<h2>Formulas travel as text</h2>
<p>
A written shape is stored in the URL as its own source, not as encoded geometry:
</p>
<p class="equation">eigendrum.com/#f=p:1 + 0.3cos(5t)</p>
<p>
So a shared link is something you can read, retype, and edit in the address bar,
rather than a few hundred characters of base64. It also means the link survives
any later change to how curves are sampled, which an encoded outline would not.
Editing the hash directly works - the page listens for it.
</p>
<h2>Why expressions are never evaluated as JavaScript</h2>
<p>
Expressions are compiled by a recursive-descent parser. There is no
<span class="tex">eval</span>, no <span class="tex">new Function</span>, and no
template-driven code generation anywhere in the path.
</p>
<p>
That is not stylistic preference. Shapes travel in the URL fragment, which means
an expression is untrusted input arriving from a link somebody else wrote. Handing
that to a JavaScript evaluator would turn every shared drum into a
script-injection vector. A parser over a closed vocabulary of about thirty
functions cannot execute anything - the worst a hostile formula can do is fail to
parse.
</p>
<p>
There is a related subtlety worth recording. The lookup tables for functions and
constants are created with a null prototype. Before that, an expression
containing the identifier <span class="tex">constructor</span> would find a match
on <span class="tex">Object.prototype</span> and resolve as though it were a
defined constant. Nothing executable escaped, because the evaluator only ever
does arithmetic and the result was simply <span class="tex">NaN</span> - but "the
layer above happens to be harmless" is not a security property.
</p>
<div class="ad ad-article" data-ad="article-foot" data-ad-format="auto">
<span class="ad-label">advertisement</span>
<div class="ad-frame"></div>
</div>
<a class="doc-cta" href="/#f=p:1 + 0.3cos(5t)">
<strong>Open the five-lobed flower</strong>
<span>Then change the 5 to an 11 and listen to what moved.</span>
</a>
</article>
</main>
<footer class="colophon">
<nav class="colophon-nav" aria-label="Site">
<h2>Read more</h2>
<ul>
<li>
<a href="/how-it-works">How Eigendrum works</a>
<span>Meshing, finite elements, and why a nodal strike is silent</span>
</li>
<li>
<a href="/hearing-the-shape-of-a-drum">Can one hear the shape of a drum?</a>
<span>Two different shapes, identical spectra</span>
</li>
<li>
<a href="https://github.com/BaselAshraf81/eigendrum" rel="noopener">Source and tests</a>
<span>Including the expression parser and its hostile-input tests</span>
</li>
</ul>
</nav>
<div>
<h2>Eigendrum</h2>
<p class="colophon-meta">
Built by Basel Ashraf. Free to use. Source available, non-commercial licence.
<a href="/privacy">Privacy</a> ·
<a href="mailto:u2679054@uel.ac.uk">Contact</a> ·
<a href="https://ko-fi.com/baselashraf" rel="noopener">Support</a>
</p>
</div>
</footer>
<script type="module">
import { mountAds } from './src/app/ads.js';
mountAds();
</script>
</body>
</html>