← All projects

Project archive · 2018-07

Self Drawing Equation

A high-school experiment in encoding an equation into a number and making the equation draw itself.

  • Mathematics
  • Matlab
  • Desmos

This page records a small mathematical toy project I made in high school: an equation that tries to draw its own written representation on the Cartesian plane.

It is mostly an encoding trick wrapped inside an implicit equation. Still, I like it as an old experiment

Drawing an alphabet

The project started with two goals: have fun, and create a 2D equation that could draw something resembling its own source text on a Cartesian plane.

The motivating thought was deliberately impractical: if a simple enough equation described the whole universe, then a written copy of that equation would also exist inside the universe it describes. This project was a tiny, playful version of that idea: can I write an equation that contains enough information to draw itself as text?

The first step was to define equations for every symbol required by the final expression:

0123456789+*-/^=()xyteansigfwhrdlo.b,

Each symbol became a small implicit curve. A selector function could then enable the appropriate curve for every encoded character.

Equation alphabet in Desmos. This is the actual Desmos instance that I used to define the equations for each symbol. It renders badly because Desmos is not a great tool for this kind of implicit-curve text rendering and mainly detects zero-crossings.

General approach

The construction is quine-like. In programming, a quine is a program that prints its own source code. Here the goal was similar, but with an implicit equation: when plotted, the equation should render a textual representation of itself.

The trick I used was to encode the equation text into a large number a, then decode that same number in two different ways:

  1. On the left half of the plane (x < 0), the equation decodes a in base 38. This reconstructs the symbolic part of the equation: the alphabet, operators, variables, and drawing machinery.
  2. On the right half of the plane (x > 0), the equation decodes a in base 10. This displays the decimal digits of a itself.

So the equation does not only draw a formula while hiding its data somewhere else. It also draws the large number used to encode the formula. That is the small self-reference trick at the core of the project.

Why does the equation contain “where a =”? This choice forced me to include a “where a = ” part in the rendered text. It would have been theoretically possible to avoid it by splitting the equation rendering into three regions instead of two, but that would have made the equation more complex without making the idea more interesting.

Encoding the equation

The expression had to contain both the drawing machinery and its own encoded text. I associated each character with a digit and concatenated those digits into a very large base-38 integer.

A decoder inside the equation extracts the character at each horizontal position. The corresponding curve is enabled and shifted into place, turning one large number back into a line of mathematical text.

Visual representation of the numeric decoding in Desmos.

Plotting it

A conventional plotter could not handle the resulting expression well. I wrote a MATLAB plotter that scanned the plane pixel by pixel, checking where the implicit curve was satisfied.

Each character’s shape is defined using atan, sign, and exponential functions to create smooth, enclosed curves. The equation evaluates to zero at points that lie on any of the active letter shapes.

The renderer was stupidly slow. It used fmincon on every pixel, processed the plane in blocks, and even with parallel execution it only got about 3% of the way through the full range before I gave up.

What it produced shows the first few characters of the equation peeking out from the left edge.

Partial plot of the self-drawing equation
Partial plot of the self-drawing equation. Part of the left half of the equation is visible, showing the first few characters of the encoded text.
Note

I never completed the full render. Months later I discovered Tupper’s self-referential formula 1, which is a more famous construction. Tupper’s formula is usually described as “drawing itself”, although the famous version works by decoding a huge bitmap stored in a constant.

My experiment is much rougher is a real mathematical quine.

The original source is preserved in this Google Drive folder.

Full equation

f(1,x,0)+f(atan(((x-floor(x))-0.5)^2*2.75+(y-1.05)^2-0.25),x,1)+f((atan((x-floor(x))-0.5)+4*(sign((y-1.05)^2-0.24)+1))*(atan(y-(x-floor(x))*0.4-1.34)+4*(sign(((x-floor(x))-0.35)^2-0.025)+1))*(atan(y-0.57)+4*(sign(((x-floor(x))-0.5)^2-0.1)+1)),x,2)+f((atan((y-0.57-e^(((x-floor(x))-0.8)*100))*(y-(x-floor(x))-0.43))+4*((sign(((x-floor(x))-0.48)^2-0.087))+1))*(atan(((x-floor(x))-0.5)^2+(y-1.3)^2-0.08)+4*(sign(y+((x-floor(x)))/(5)-1.35)-1)),x,3)+f(atan((((x-floor(x))-0.5)^2*0.6+(y-0.82)^2-0.07)*(((x-floor(x))-0.5)^2*0.6+(y-1.3)^2-0.05))+4*(sign(((x-floor(x))+(y*1.3-1.4)^2-0.45))-1),x,4)+f((atan(y-1.8*(x-floor(x))-0.4)+4*(sign((y-1.2)^2-0.115)+1))*(atan(y-0.85)+4*(sign(((x-floor(x))-0.55)^2-0.08)+1))*(atan((x-floor(x))-0.67)+4*(sign((y-1.05)^2-0.23)+1))*(atan(y-0.56)+4*(sign(((x-floor(x))-0.65)^2-0.03)+1)),x,5)+f((atan(y-1.55)+4*(sign(((x-floor(x))-0.5)^2-0.055)+1))*(atan((x-floor(x))-0.30)+4*(sign((y-1.32)^2-0.055)+1))*(atan(((x-floor(x))-0.5)^2+(y-0.85)^2-0.1)+4*(sign(5*(x-floor(x))-y-0.4)-1)),x,6)+f((atan(((x-floor(x))-0.57)^2+(y-0.84)^2-0.08))*(atan(((x-floor(x))-0.6)^2+((y-1.05)^2)/(2)-0.12)+4*(sign(1.15*(x-floor(x))-y+0.5)+1)),x,7)+f((atan((y+e^((0.2-(x-floor(x)))*100)-1.55)*(y-3*(x-floor(x))+0.9))+4*(sign(((x-floor(x))-0.52)^2-0.09)+sign(0.5-y)+2)),x,8)+f(atan((((x-floor(x))-0.5)^2+(y-0.81)^2-0.075)*(((x-floor(x))-0.5)^2+(y-1.32)^2-0.06)),x,9)+f(atan(((x-floor(x))-0.53)^2+(y-1.26)^2-0.08)*(atan(((x-floor(x))-0.5)^2+((y-0.85-((x-floor(x)))/(3))^2)/(2)-0.1)+4*(sign(y-1.1*(x-floor(x))-0.3)+1)),x,10)+f(atan(((x-floor(x))-0.5)*(y-1.02))+4*(sign(((x-floor(x))-0.5)^2+(y-1.02)^2-0.15)+1),x,11)+f(atan((((abs((x-floor(x))-0.5)))/((y-1.23))-0.01)*(((abs((x-floor(x))-0.5)))/((y-1.23))-4)*(((abs((x-floor(x))-0.5)))/((y-1.23))+0.7))+4*(sign(((x-floor(x))-0.5)^2+(y-1.23)^2-0.1)+1),x,12)+f(atan(y-1)+4*(sign(((x-floor(x))-0.5)^2-0.1)+1),x,13)+f(atan(y-2.1*(x-floor(x)))+4*(sign(((x-floor(x))-0.5)^2-0.1)+1),x,14)+f(atan(y+1.3*abs(((x-floor(x))-0.5))-1.5)+4*(sign(((x-floor(x))-0.5)^2-0.1)+1),x,15)+f(atan((y-1)^2-0.015)+4*(sign(((x-floor(x))-0.5)^2-0.16)+1),x,16)+f(atan(((x-floor(x))-1.5)^2+(y-0.95)^2-0.9)+4*(sign((x-floor(x))-0.8)+1),x,17)+f(atan(((x-floor(x))+0.5)^2+(y-0.95)^2-0.9)+4*(sign((x-floor(x))-0.2)-1),x,18)+f((atan(abs((x-floor(x))-0.5)-abs(y-0.9))+4*(sign(((x-floor(x))-0.5)^2+(y-0.9)^2-0.22)+1))*(atan((y-0.9)^2-0.105)+4*(sign((abs((x-floor(x))-0.5)-0.25)^2-0.01)+1)),x,19)+f((atan(y-1.23)+4*(sign((abs((x-floor(x))-0.52)-0.29)^2-0.01)+1))*(atan(y-2*(x-floor(x))+0.5)+4*(sign(((x-floor(x))-0.62)^2-0.06)+1))*(atan(y+2*(x-floor(x))-1.6)+4*(sign(((x-floor(x))-0.36)^2-0.03)+1))*(atan(y-0.25)+4*(sign(((x-floor(x))-0.35)^2-0.03)+1)),x,20)+f((atan((x-floor(x))-0.34)+4*(sign((y-1.05)^2-0.18)+1))*(atan(y-1.23)+4*(sign(((x-floor(x))-0.45)^2-0.1)+1))*(atan((((x-floor(x))-0.6)^2)/(2)+(y-0.75)^2-0.05)+4*(sign(y-0.63)+1)),x,21)+f((atan(((x-floor(x))-0.5)^2+(y-0.88)^2-0.13)+4*(sign(y-3*(x-floor(x))+1.65)-1))*(atan(y-0.92)+4*(sign(((x-floor(x))-0.5)^2-0.125)+1)),x,22)+f(((((x-floor(x))-0.4)^2)/(e^(x-floor(x)))+(y-0.1*(x-floor(x))-0.69)^2-0.05)*(atan((x-floor(x))-0.73)+4*(sign((y-0.83)^2-0.08)+1))*(atan((((x-floor(x))-0.5)^2)/(1.5)+(y-1.05)^2-0.04)+4*(sign(y-1.11)-1))*(atan(y-0.55)+4*(sign(((x-floor(x))-0.8)^2-0.008)+1)),x,23)+f((atan(((x-floor(x))-0.51)^2-0.07)+4*(sign((y-0.56)*(y+0.3*(x-floor(x))-1.3))+1))*(atan(y-0.57)+4*(sign(((abs((x-floor(x))-0.5)-0.27)^2-0.01))+1))*(atan(y-1.22)+4*(sign(((x-floor(x))-0.2)^2-0.005)+1))*(atan((((x-floor(x))-0.5)^2)/(1.5)+(y-0.95-0.1*(x-floor(x)))^2-0.05)+4*(sign(y-1.05)-1)),x,24)+f((atan(((((x-floor(x))-0.5)^2)/(2)+(y-0.72)^2-0.04)*((((x-floor(x))-0.5)^2)/(2)+(y-1.08)^2-0.03))+4*(sign((y-(x-floor(x))-0.4)*(y-0.9))-1))*(atan(abs((x-floor(x))-0.5)-0.27)+4*(sign((y-0.9*(x-floor(x))-0.45)^2-0.008)+1)),x,25)+f((atan((x-floor(x))-0.5)+4*(sign(((y-1.07)^2-0.27)*((y-1.35)^2-0.01))+1))*(atan(y-0.56)+4*(sign(((x-floor(x))-0.5)^2-0.1)+1))*(atan(y-1.23)+4*(sign(((x-floor(x))-0.4)^2-0.012)+1)),x,26)+f(atan(((x-floor(x))-0.45)^2+((y-0.9)^2)/(1.2)-0.09)*(atan((x-floor(x))+e^((-20*y+4))-0.76)+4*(sign((y-0.75)^2-0.26)+1))*(atan(y-1.23)+4*(sign(((x-floor(x))-0.83)^2-0.01)+1)),x,27)+f((atan((x-floor(x))-0.43)+4*(sign((y-1)^2-0.18)+1))*(atan((y-0.9)^2-0.11)+4*(sign(((x-floor(x))-0.5)^2-0.08)+1))*(atan((((x-floor(x))-0.67)^2)/(2)+(y-1.4)^2-0.03)+4*(sign(y-0.2*(x-floor(x))-1.3)-1)),x,28)+f((atan(y-abs(3*abs((x-floor(x))-0.52)-0.5)-0.55)+4*(sign(((x-floor(x))-0.52)^2-0.155)+1))*(atan(y-1.22)+4*(sign(((abs((x-floor(x))-0.52)-0.35)^2-0.01))+1)),x,29)+f((atan(((x-floor(x))-0.51)^2-0.07)+4*(sign((y-0.56)*(y+0.9*(x-floor(x))-1.76))+1))*(atan(y-0.57)+4*(sign(((abs((x-floor(x))-0.5)-0.27)^2-0.01))+1))*(atan(y-1.55)+4*(sign(((x-floor(x))-0.2)^2-0.005)+1))*(atan((((x-floor(x))-0.5)^2)/(1.5)+(y-0.95-0.1*(x-floor(x)))^2-0.05)+4*(sign(y-1.05)-1)),x,30)+f((atan((x-floor(x))-0.4)+4*(sign(((y-0.9)^2-0.12))+1))*(atan(y-0.56)+4*(sign(((x-floor(x))-0.45)^2-0.1)+1))*(atan(y-1.23)+4*(sign(((x-floor(x))-0.3)^2-0.012)+1))*(atan(5*y-sin(5*(x-floor(x))-2)-5)+4*(sign(((x-floor(x))-0.65)^2-0.07)+1)),x,31)+f((atan(((x-floor(x))-0.47)^2+(y-0.88)^2-0.11))*(atan((x-floor(x))-0.8)+4*(sign((y-1.05)^2-0.26)+1))*(atan(y-0.55)+4*(sign(((x-floor(x))-0.88)^2-0.01)+1))*(atan(y-1.55)+4*(sign(((x-floor(x))-0.72)^2-0.01)+1)),x,32)+f((atan((x-floor(x))-0.5)+4*(sign(((y-1.07)^2-0.27))+1))*(atan(y-0.56)+4*(sign(((x-floor(x))-0.5)^2-0.1)+1))*(atan(y-1.55)+4*(sign(((x-floor(x))-0.4)^2-0.012)+1)),x,33)+f(atan(((x-floor(x))-0.5)^2+(y-0.87)^2-0.13),x,34)+f(atan(sign(((x-floor(x))-0.5)^2+(y-0.6)^2-0.01)+1),x,35)+f((atan((0.53-(x-floor(x)))^2+(y-0.88)^2-0.11))*(atan(0.2-(x-floor(x)))+4*(sign((y-1.05)^2-0.26)+1))*(atan((y-0.55)*(y-1.55))+4*(sign((0.12-(x-floor(x)))^2-0.01)+1)),x,36)+f(atan(sign(((x-floor(x))-0.4)^2+(y-2*(x-floor(x))+0.3)^2-0.01)+1),x,37) = 0 where f(t,x,n)=(sign((g(x)-n)^2-0.1)-1)*t and g(x)=((floor(a/(38^floor(-x)))-floor(a/(38^floor(1-x)))*38)*(-sign(x)+1)/2 + (floor(a/(10^floor(1-x+floor(log(a)/log(10)))))-floor(a/(10^floor(2-x+floor(log(a)/log(10)))))*10+1)*(sign(x*(1+floor(log(a)/log(10))-x))+1)/2)*((x-floor(x))/(x-floor(x))) and a = 409934645150188735932989955096874814460093029410355089450528885836572906008986349510837855486226204224585330853698000814987765227338881457013469248176679760266855862222261845533227577301695333065165802645112204907337838012354358287398996802434568290050775053398567745295196070148585329180319877581974818650827435316056326321158592664393417695666458680003858273888764025885822628386720445948772545045226877516102864792082375917839588800310742460995793052122022018309525491205683672246292068019816578341961812265260427129224626475006061395668603707509394294124163878879190881953496116132821274612125108664736141290257369937097745189930870865959561184821167001199975124108963124932722383934086905577187771767503950349153732078733471992462038612427769149247962697044021865335997750507151669274915414658116906694817509285879072518103146660173661972932287208633157539936131863817142163889947164468994222429385941378833621664429104899555100327165008152093871309867200483921095435880522644065250418957405924246375573943306684456627911614694421146732714139606484205783358103615744670983032350405761100879178463325395189824548469872987770886115809593125345939392656861097467284624495611060844102322517180482906836194748488711956214334606183356766550006946712880307600915701014172324206554688736108040844591378236939920072137995118106512385001086149190051211483108001444019667353387050503941429923308013614672825603667181579770379507532592359968407609063150694836908086664512531976278496431455017754351054016068192613367124456039719583903834886757840641099762605131190342254636010368899422968155222964456357297014816131618961350885429484902653262506256400104854113180457118188235332101633263336100658592857287277673610293931294965716143218710135046800582904117344732984913676301473384148471315813015555969590263665520154791898165854906158516505081999677554451819485813833062349974477003625653000204268740575717398670288760886765541000573487669211135437792545390130549247910931804699471426015531155778793576530059194204227761887249755982758900524752675525787686108808015755118505922705594208423014235293796041606780429027148243535219109764879388486324845014568322158912912088983601336153551995435752164518265227644210372406223487031216434906096663983276332281269399983740181121416530821227057812759424546781020726073127456374141219932846909473678786862419402088814853159761615334230857754590340492983646100808158657433853392287991463575876066437486005252078215766661521406922786166082492756756465437004751939281815170574599274855896092332623313235429094382319443692459528901444846793491219213507345556952517949470534467272066802034004388793242363973415355242634194505382926790625409451217536655136193610316558684297599267310244946336528827740403264305116366328039167209953500263206767195095790718447103097702534745196057653007511332521203349429498203150395793864359497264085895989545500171514356155558898428623515333756116090971864334185358531345626754450763806261685419647007384153481237652025381505826186707648382596446373456059094292575398093589869134392221270774575069230099080220629101679603223667911381545015535481229247323295641303665039887829789411263636708335590326203532204502998058188045413310339466754538787037298261737547368192772385531515627311959377438179770393172121836680701003042628904486978451259722535417833938111333640235173498423458240602088945119901978909380169617610464784015956692469188760455808458297356650753782790174660542212403489285246677590272005999086489517028189475065867527887640356720155933485534751097875109275149000123626146255541216595551490790097780115280655734004053181946688837189008070747574116482645150474930882658483831204241143794221631765513125089009456168253959250848089223173104642003756095087361314481565882657210834112430273994981969732754506583921431735704578665848723934336162496530312199782952353386420943341043601349945800017298579821740696296193542653274370461268014102602697814489500862434470673053615240161052607918971825927435711006473388244363527379468998818019947873144671733612644758685153072369454287713271745360456092840454149835617760489577909928084544535233922337942210428742754326246932517571955995191732263713028742620912466475261288223461368755327002541883172724910108336138444170016795030323778143686411404269738234025574786203498342283404855699996707369114363450752627989516356033576879064927701028634713194700804396984592393557852492731126166485824727351491156017585517920309926689336457086042451219891597055739490831097471316432849904431552195516846149483943987002071801740063559196639501653705766393051102994247237078469528921421313854079330285847623638994752341383902458256556148833682879644341612019856401749270978117161759453811124432737469747120626424110610533462363783129291651772006827903927281470010483184081414001291663530813312829264095579012451348371700897816913863674648078248414584659920768136581013889127232673460330423283377257925436458188657018038287398346608856961820040719217149690450548461846042322836291306405118659446005372064410472199104866606442240304225593474027500834308090629252857409174930027101868749245940453167902213725313392238057838781747390933254061595055968372846384167206028482580510793718518362922031607888516401146534207426658287398009329104148858594314790786215883846866474574799477119262572850871176248997915968456709975931657815325677208428139820460293704803563169286395719774515154323522383708532908629652645824929818617009684538681577635075028343472616054775631777388205509445574706024655504565173005055786595936786430175453443204946540912736559758843662668369835471395531665970193709960823002591719882093230248617329346566571478076339855645478875254493528303546462384398882169453153612543652366479939223725621572673199316792635384376576476335089361633596713996124050677306839333548874211573349285033085831725251313503367307111684809404655183016566199878040636652586313294819363739414810658972230106832264747234391891527372840219885327864248194899192084895457789474914362424746071532050291649758559380263859746384008803814815006054878835945699807281174957887725357648577586105444772486312531655454365938828207812582327245497355781280964976294657048812668141783812110826318865427268697741167580315589051141140125227379599277743202506960789953054428752621492874059906418664654574881022244936186652388800966040804755263961862039183358779957752570671497462977321938318731114855186900481871121060189680775639424203524221670259994467083501401093617463392960728884401879575220408593634568636713269599183138612688710519571517898886950212557681859285952722313752152631125590224014994635159410034335640213513266491924466394319687991910533887936786652057513580044175155281467328781921138991566887526245235663377044010093515617133828674896153869638079791093595967517413515604454587779722369782193029715866907761287902999281872343473535763059821067097329874338152795883720014507116358163965343450552845765864895184055590473493395017602652207142135255284200341029036612617581287100933966770633005261049462384148834302702938792799464187884069013623945893253235932741532000446768654541398191926963464681562650838362187435886001117063177290901277395283193388984218790185790820878255457404519605492496266282404736361783943471671221998309220060253945238064856296668884669593539526052385777386135443348633019081560098276397679361883205756223470270458986217027478241206169712293179830261439012589634946426594637160216437022155626867238307110265963878226535085078561756819253510526385828578297114586332915991986437166871893518818047282397844874550465464111917739472267141768979772893796176870705531897285228215351857631697281722691854312617649088836175296774899484691001855750438044658793356626217678571640509183830375812055253270355099984974265955922249821102228485667398555594948422343119651755598220292059725006744771005071304267056460328720226732059233751250638681490889738556549882567459053433466946687952611940606703253108731870277270755548325517053985973784477128888105740016512614865115893928816385191095483601659997177273765872723041289012076719672355480156000034414628636593677397706580883799605518617876223922544411979078110716284857816616682637079412434625582306855361529207606381097159169297491741531918606898651060141740976301062379486349873012493555697793535250208902041009707348936150443855403363218236257391167884111273485812040408208103287498505231059095938930574269483869544307555199858352582017996007599801424652986607823309897064663524365945514313442101502401515513933487005131431085782757877875336551349141062883459997785092317930686687932463068201778465003552068075290887087666270100563239162209970364535621040469555092732616721210712212647428871175133796410615368099916711847368962153573406682377844327402686165157841368273857365058433816379645933082807505495994246459837920982072900046744985048159845758998320481675987955488536468171084948112775072873893055532741346864814948800040244621090938689972258676307604326081579885811089871727337157136310708976855724478570780363387577057133675023574085852485784802910397925328423294106242545051351736090113953145751799154116385947665568564697433516157323961679190215325198467499041280501902687038399596349312029593624351306403046031268193220565687860316208553354417986280323752221125831566985389855064753607994497302177589744276183904300505330289178308587643339874652226161553096897787544410440657862248948633788039523929792023546629259250102525762753005793472035026530050865684745773282617556081192656537605037469022530208650996112514020475627058085915719270876062996943080465517722336180628081623940998760841861718856703202882853635517312250221595351024925807411633342650880451954675549665091444936

Other equation experiments

I also experimented with implicit equations that create fractal-like structures:

sin(log(((4*x+sqrt(16*x^2-12*(x^2+y^2)))/4)*pi)/log(1.25))
* sin(log(((4*x-sqrt(16*x^2-12*(x^2+y^2)))/4)*pi)/log(1.25)) = 0
Fractal-like implicit equation plot

One final equation was made as a birthday present. It may not be mathematically elegant, but it was certainly original.

Equation drawn as a birthday present

Footnotes

  1. https://en.wikipedia.org/wiki/Tupper%27s_self-referential_formula