C0.png C1.png C2.png C3.png C4.png C5.png C6.png C7.png C8.png C9.png C10.png C11.png C12.png C13.png

Kurvengenerator – Dokumentation


Grundlegendes

Der Kurven­generator ist eine Anwendung, die Kurven nach mathema­tischen Regeln generiert – ähnlich wie ein Spirograph. Die Kurve besteht aus einzelnen Kurven­segmenten, die anein­ander­hängen – ähnlich wie eine Kette – und eine bestimmte Länge haben. Die Kurven­segmente sind durchnummeriert: die Variable n bestimmt die Nummer eines Kurven­segments – für das erste Kurven­segment zum Beispiel gilt: n = 0; n wächst mit jedem Kurven­segment um einen bestimmten Wert.

1. Feld
2. Feld
3. Feld
4. Feld
5. Feld
Jedem Kurvensegment wird ein Wert von n zugewiesen

Das wichtigste ist der Winkel: jedes Kurven­segment hat einen bestimmten Winkel, der abhängig von n sein kann (auch die Länge der Segmente kann abhängig von n gemacht werden). Dadurch können die interessan­testen Muster, Formen, Fraktale und Kurven generiert werden.

So funktioniert es: Das erste Kurven­segment hat einen bestimmten Anfangs­winkel. Mit jedem weiteren Kurven­segment wird ein berechneter Winkel addiert und zu diesem Segment zugewiesen. Jedes Kurven­segment nimmt also den Winkel des jeweils vorigen Segments plus einen neuen berechneten Winkel an.

Die Anwendung besteht aus fünf Eingabe­feldern, mit denen man die Kurve kontrol­lieren kann. Im nächsten Abschnitt wird jedes Feld beschrieben.

Technische Details und wie man Kurven Teilt

Da diese Anwendung die HTML5-Canvas-API benutzt, kann man, falls der Browser es unterstützt, generierte Kurven wie eine Grafik mit Rechtsklick + „Grafik speichern unter…“ speichern.

Oben rechts im Generator steht der Link „SVG“; wenn man da drauf­klickt, oder mit Rechts­klick auf „Ziel speichern unter…“ geht, erhält man eine skalierbare Vektor­grafik-Version der Kurve. Hinweis: man kann die SVGs nur speichern aber die URIs nicht teilen. Abhängig vom Browser erhält man entweder eine „blob:“-URI die nur lokal und damit unzugänglich für andere ist oder eine „data:“-URI die viel zu lang ist um geteilt zu werden. Die gespeicherte Datei hingegen kann man teilen.

Es gibt auch eine Nur-SVG-Version, die viel schneller und etwas kompatibler ist, aber keine Bitmap-Bilder erzeugt.

Wenn eine Kurve generiert wurde, kann man auch die URL teilen, wenn sie etwas wie “#n*n@2160@1@4@0” am Ende enthält.

Die Fünf Felder

Erstes Feld: Die „Winkelfunktion“ (Änderung des Winkels jedes Kurven­segments)

Fangen wir simpel an: wir nehmen an, dass das zweite Feld 360, das dritte 1, das vierte 4 und das fünfte 0 enthält. Einer der simpelsten Werte für das erste Feld ist 0 – dies generiert nichts anderes als eine gerade Linie. Das erste Segment hat einen Winkel von (0° bedeutet rechts, 90° unten, 180° links und 270° oben), das zweite Segment hat einen Winkel von 0° plus den Wert des ersten Felds: 0°; 0° + 0° = 0°, also ist der nächste Winkel 0°, der nächste ebenfalls, und so weiter.

Gerade Linie

Ebenfalls simpel ist der Wert 1: dies generiert einen Kreis. Erstes Segment: 0°, zweites: 0° + 1° = 1°, drittes: 1° + 1° = 2°, dann 3°, 4°, 5°, etc. Das heißt, der Winkel jedes Kurven­segments wird um 1 erhöht. Der Wert 2 im ersten Feld generiert einen engeren Kreis; größere Werte generieren jedoch kantigere „Kreise“ – zum Beispiel generiert 72 ein Fünfeck und 144 einen fünfzackigen Stern (siehe den Abschnitt für das vierte Feld, um die Größe dieser Formen zu verändern).

Kreis

Weiterhin kann man mit der Variable n arbeiten (hierfür ist im zweiten Feld der Wert 719 empfehlens­wert): gibt man also n im ersten Feld ein, hat das erste Segment (n = 0) einen Winkel von ; das zweite (in diesem Fall n = 1) hat einen Winkel von 0° + n = 0° +  = 1°; das nächste Segment (n = 2) hat einen Winkel von 1° + n = 1° +  = 3°; dann 6°, 10°, 15°, 21°, etc.

Visualisierung für „Winkel­funktion“ „n“

Ähnliche Arithmetik erreicht man ebenfalls mit n*n, n*n*n, etc. Man kann genauso Multi­plikationen mit Zahlen eingeben: 2*n, 0.5*n, Additionen oder Subtraktionen: n*n+2, n*n*n-12, etc. Siehe den Abschnitt mit den möglichen Eingaben für mehr.

Zweites Feld: Die Kurvenlänge (Maximalwert der Zählung der Kurven­segmente)

Manche Kurven durchlaufen nach einigen Segmenten wieder den Anfang und verhalten sich „zirkulär“, manche durchlaufen nie den Anfang und verhalten sich „linear“, bei einigen Kurven ist es schwierig oder unmöglich vorauszusagen, wie sie sich verhalten. Für alle Zwecke gibt es also die Möglichkeit die Kurve nur bis zu einem bestimmten n laufen zu lassen. Zum Beispiel ein unvollständiger Kreis, wenn im zweiten Feld 269 steht.

Ein drei Viertel eines Kreises

Hier lassen sich auch arith­metische Ausdrücke wie z. B. 360*12-1 eingeben.

Drittes Feld: Die Schrittweite (Wie viele Schritte hinzugefügt werden)

Ändert man das dritte Feld, verändert dies, wie die einzelnen Kurven­segmente durch­numme­riert werden. Mit dem Standard­wert 1 sind die Werte von n für jedes Segment 0, 1, 2, 3, 4, etc. Mit dem Wert 0.5 ist n hingegen 0; 0,5; 1; 1,5; 2; etc.

Das beeinflusst stark das Aussehen der Kurve, da ganz andere n-Werte in der „Winkel­funktion“ verrechnet werden. Dies zum Beispiel ist n im ersten Feld; 360*7.5 im zweiten; .7 im dritten; 4 im vierten; 0 im fünften Feld:

Die Kurve sieht im Vergleich zur obigen „n“-Kurve anders aus

Viertes Feld: Die Segment­länge (Länge jedes Kurven­segments)

Dieses Feld gibt an, wie lang in Pixeln jedes der Kurven­segmente ist. 0 zeigt offen­sicht­lich keine Kurve an. 20 ist zum Beispiel gut für die oben genannten Fünfecks- und Stern­formen: jedes der Kanten ist in dem Fall 20 Pixel lang.

Fünfeck Fünfzackiger Stern

Auch hier kann man mathema­tische Ausdrücke mit n verwenden: z. B. 5 im ersten Feld und 0.01*n im vierten Feld generiert eine Spirale.

Spirale

Fünftes Feld: Anfangs­winkel (Start­winkel)

Ziemlich simpel: dieses Feld dreht letztendlich die Kurve, indem der Winkel des ersten Kurven­segments gesetzt wird.

Mögliche Eingaben

Allgemeines

Dies ist eine Web-basierte Anwendung. Die Programmier­sprache ist JavaScript und somit kann man in die Felder alles eingeben, was auch JavaScript versteht. Um einen großen Umfang an Funktionalität anzubieten, kann arbiträrer Code in diesen Feldern ausgeführt werden. Es gibt jedoch einige Ausnahmen: einige potentiell schädliche Schlüssel­wörter und Muster werden herausgefiltert und führen zu einer speziellen Fehlermeldung (insbesondere Sachen wie das this-Schlüsselwort, window, JSFuck-Code, eval, Function()-Syntax). Falls für deine beeindruckendsten kurvigen Kunstwerke dringend Cross-Site-Scripting benötigt wird, kannst du den Quellcode des Kurvengenerators ruhig „forken“ und modifizieren.

Für mathema­tische Eingaben können zunächst alle mathema­tischen Funktionen verwendet werden, die zum JavaScript-Math-Objekt gehören. Zur Verein­fachung muss Math. nicht eingegeben werden; das heißt, die Sinusfunktion gibt man mit sin() ein und nicht mit Math.sin(). Addition ist +, Subtraktion -, Multiplikation * und Division /.

Das Komma ist . („Dezimalpunkt“) – ein , bewirkt etwas völlig anderes. Beispiel: 0,2 + 5 = 7, weil 0,2 wie eine Art Liste von Ausdrücken ist, derer letzter Wert angenommen wird.

Bitte beachten, dass ^ nicht das Potenzieren bewirkt, sondern ein bitweises logisches XOR (siehe weiter unten); für Potenzen muss entweder bspw. pow(n,3) oder n*n*n geschrie­ben werden.

Beispiel mit der Sinusfunktion: 20*sin(0.2*n) im ersten, 203 im zweiten, 1 im dritten, 4 im vierten, 81 im fünften Feld.

Der Rest

% ist der Modulo-Operator. Dieser gibt den „Rest“ einer Division zurück (zum Beispiel: 8 % 3 = 2 bedeutet 8 mod 3 = 2). Ein Beispiel einer Kurve: n%180 im ersten, 720 im zweiten, 1 im dritten, 6 im vierten, 0 im fünften Feld.

Hier ist ein anderes Beispiel mit variabler Segment­länge: 60; 47; 1; 8*(n%12); 60

Kondition und Kontrolle – Disziplin!

Falls das zutrifft?Dann wird dieser Wert angenommen:Ansonsten dieser. Damit kann man die Kurve noch stärker kontrol­lieren. Beispiel: (n==40)?60:2; 100; 1; 6; 0. Hier gibt es einen Knick beim 41. Kurven­segment um 60°, ansonsten geht jedes Segment mit 2° weiter.

Ein anderes Beispiel zeigt eine Kombination aus Modulo- und Konditions-Operatoren: (n%12==0)?-144:12; 360; 1; 6; 0 – falls n durch 12 teilbar ist (also der Rest 0 ergibt), addiere den Winkel -144°, ansonsten addiere den Winkel 12°.

Zurück zur Vernunft und Logik

Oben wurde schon == als eines der logischen Operatoren zum Vergleichen von zwei Werten verwendet. < ist für „kleiner“; > für „größer“; <= für „kleiner oder gleich“; >= für „größer oder gleich“; != für „ungleich“. Außer­dem kann man diese Vergleiche verbinden mit && für „UND“; || für „ODER“; !(Ausdruck) für „NICHT“. Beispiel: (n%6==0||n%17==0)?0:360*(2/5); 800; 1; 30; 0.

Oder wenn man nur die „6“ im ersten Feld durch eine „7“ austauscht…

Bit-Operationen

Weiterhin kann man Bit-Operationen verwenden. Siehe interessante Kurven unten, für ein gutes Beispiel: die Drachen­kurve

Listen und Indizes

Mit Listen kann man ultimativ jede Möglichkeit einer Kurve erzeugen. Sie funktionieren wie JavaScript-Arrays und werden im Kurven­generator so verwendet: [20,40,80,140, 220,-20,-40,-80, -140,-220][n]. Der erste Teil in eckigen Klammern beschreibt eine Liste von einzelnen Winkeln. Der zweite Teil ist der sogenannte Index, der auswählt, welcher der Winkel angenommen und addiert wird.

Beim ersten Kurven­segment wird der Index „n“ als 0 ausgewertet – und der Index 0 wählt den ersten Winkel der Liste aus (20°); beim zweiten Kurven­segment ist n = 1, welches den zweiten Winkel auswählt (40°; insgesamt also 20° + 40° = 60°); beim dritten Kurven­segment ist n = 2, der dritte Winkel aus der Liste – 80° – wird ausgewählt und addiert: 60° + 80° = 140°; und so weiter.

Dieses Beispiel zeigt, wie es aussieht, wenn die oben genannte Liste im ersten Feld und 9 im zweiten Feld (1 im dritten, 12 im vierten, -71 im fünften) ist.

Eine unregelmäßige Figur, die den Regeln der Liste folgt

Wenn beim zehnten Segment n = 9 ist, wird der letzte Winkel dieser Liste ausgewählt und weitere Segmente würden zu Fehlern führen, weil diese Liste keinen Winkel für n = 10 mehr hat.

Dafür gibt es unter­schied­liche Lösungen: man könnte einfach mehr Winkel zur Liste hinzu­fügen, oder man könnte die Liste nach dem Ende von Anfang wieder­holen lassen, indem man den Modulo-Operator verwendet: [20,40,80,140, 220,-20,-40,-80, -140,-220][n%10] – im Index steht jetzt n mod 10, weil die Liste 10 lang ist; bei n = 10 wird dann einfach 10 mod 10 berechnet, was wieder 0 ist, womit der erste Winkel der Liste ausgewählt wird; bei n = 11 wird 11 mod 10 berechnet, was wiederum 1 ist, womit der zweite Winkel der Liste ausgewählt wird, und so weiter.

Diese Abbildung zeigt, wie die Kurve dann aussieht, wenn im ersten Feld die oben genannte „Winkel­funktion“ steht und im zweiten Feld 90.

Die kleine Kurve von oben wird wiederholt

Eine weitere Lösung bieten wiederum die Konditions-Opera­toren. Beispiel: n<10 ? [20,40,80,140, 220,-20,-40,-80, -140,-220][n] : -5.

Verschiedene Kniffe

Kennt man sich ein wenig mit JavaScript aus, kann man auch in den Quellcode des Kurven­generators hinein­schauen und ein paar weitere Möglich­keiten entdecken

Ein Beispiel dafür wäre die Verwendung der Variable w, in der der Winkel des aktuellen Kurven­segments gespeichert liegt. Man kann zum Beispiel das erste Feld mit -w+ beginnen, womit der letzte Winkel wieder abgezogen wird und ein neuer Wert addiert wird – somit würde sich der Kurven­generator so verhalten, als würde der Winkel aus der Funktion immer wieder neu gesetzt werden, statt zum vorigen Winkel hinzu­addiert zu werden.

Funktionen und curve

Noch mehr Möglichkeiten, den Kurven­generator zu bedienen, bieten JavaScript-Funktionen. Da der Kurven­generator momentan im „strict mode“ läuft und globale Objekte über window nicht erlaubt sind, kann ein Objekt namens curve benutzt werden, um persistente Werte in komplexeren Funktionen zu speichern (Beispiel: curve.x = 20; und dann später curve.x += 2;). Es gibt tatsächlich bereits zwei Werte in diesem Objekt:

  • curve.isPrime(Zahl): gibt true oder false zurück, abhängig davon, ob die angegebene Zahl in Klammern eine Primzahl ist oder nicht
  • curve.power(Zahl, Exponent): gibt den Rest der Division der Potenz der Zahl und des Exponenten durch 360 zurück (d. h. (ZahlExp.) mod 360), da nur dieser für den Winkel der Kurven­segmente relevant ist – nur der positive ganzzahlige Anteil des Exponenten wird benutzt

Funktionen müssen in IIFE-Form angegeben werden: (function(){Tue all das…; return …und das ist der zurückgegebene Wert;}()). Das ist für komplexere Berechnungen geeignet; ein überkompliziertes Beispiel wäre eine Kurve, bei der zunächst überprüft wird, ob n eine Primzahl ist, dann — falls sie eine Primzahl ist — wird die nächste Primzahl gefunden, dann geht die Kurve mit einem Winkel von 45° mal dem Abstand zur nächsten Primzahl weiter, oder mit 0° falls n keine Primzahl ist:

(function(){var prime=curve.isPrime(n); if(prime){var i=n; while(!curve.isPrime(++i));} return (prime?45*(i-n):0);}()) im ersten Feld; 11000 im zweiten Feld…

Fehlermeldungen, Probleme, Pläne

Fehlermeldungen und Optionen zum Ignorieren

Gibt man irgendetwas falsch in die Felder ein, kommt eine Fehler­meldung, die Auskunft darüber gibt, in welchem Feld der Fehler liegt, mit einer kleinen Übersicht über die möglichen Eingaben. Diese Fehler­meldungen sind „Feldfehler“. Man sollte darauf achten, dass JavaScript die Eingaben verstehen kann: Multi­plikationen können zum Beispiel nicht als 2n geschrieben werden, sondern müssen 2*n geschrieben werden.

Darüber hinaus gibt es auch „Kurvenfehler“. Soll in einem der mathe­matischen Ausdrücke zum Beispiel durch 0 geteilt werden, oder log(0) berechnet werden – mathema­tische Ausdrücke, die einfach nicht definiert sind – oder eine Zahl berechnet wird, die viel zu groß oder viel zu klein ist, dann wird ein mathema­tischer Fehler gemeldet. Dies passiert auch, wenn man eine Liste schreibt und der Index über die Listenpositionen hinausgeht.

Andere „Kurvenfehler“ tauchen auf, wenn die Kurve eine zu große Dichte hat, also wenn zu viele Kurven­segmente auf einem konzen­trierten Punkt gezeichnet werden oder wenn mehrere Linien übereinander gezeichnet werden. Dies hängt vermutlich damit zusammen, dass die Graustufen zwischen den weißen Linien und dem schwarzen Hinter­grund mehrfach neu berechnet werden müssen, was das Zeichnen der Kurve leider verlangsamt und in Extrem­fällen zu Browser­abstürzen führen kann. Leider wird die Dichte nur grob ermittelt. Es ist sicherer, die Kurve mit einer graduell ansteigenden Anzahl an Kurven­segmenten zu zeichnen, d. h. setze zuerst eine niedrige Zahl in das zweite Feld, dann füge jegliche Formeln in die anderen Felder ein und lasse erst dann die Anzahl im zweiten Feld ansteigen. Kurven wie diese (180.05 im ersten Feld) neigen dazu, schwerwiegende Browser­verlangsamungen zu verursachen:

Die Kurve sieht aus wie ein Querbinder (Fliege).

Genauso ist auch die Größe der Kurve limitiert; also wenn eine große Fläche in Anspruch genommen wird. Das liegt teilweise daran, dass auch dies den Browser beein­trächtigt, teilweise daran, dass die Kurve bei zu großen Dimensionen eventuell gar nicht angezeigt wird.

Eine weitere Einschränkung liegt bei der Anzahl der Kurven­segmente, da zu viele ebenfalls den Browser verlang­samen.

Es kann gut sein, dass es Fehlein­schätzungen bei diesen Vorsichts­maßnahmen gibt. Es gibt die Möglichkeit, Fehler­meldungen zu umgehen, indem man die Web-Konsole öffnet (abhängig vom Browser) und ignoreFieldErrors() und Enter eingibt, um alle „Feldfehler“ zu ignorieren oder ignoreCurveErrors() und Enter eingibt, um alle „Kurvenfehler“ zu ignorieren.

Alternativ kann man auch ignoreFieldErrors(),1 in das erste Feld eingeben (das zweite Feld sollte gering sein, weil die Entsperrung ansonsten unnötiger­weise mehrere tausend Mal erfolgt), bzw. den jeweils anderen Befehl. Dies unter­drückt die jeweiligen Fehler­meldungen bis die Seite mit dem Generator neugeladen wird.

Zuletzt gibt es noch eine Fehlermeldung, die sich nicht deaktivieren lässt: jegliche potentiell schädliche Schlüsselwörter und Muster werden blockiert und führen zu einer Fehlermeldung, die über die Anwendung unerlaubten Codes informiert.

Sehr Große Zahlen

Mathematik könnte so schön aussehen… wenn man n*n*n*n in das erste Feld eingibt und 2160*5 in das zweite (dann 1; 6; 0 in die anderen Felder), dann kommt fast eine schöne zirkuläre Kurve heraus. Rechts oben bildet sich ein offen­sicht­licher Fehler in der Kurve, der sehr unregel­mäßig und unerwartet im Vergleich zum Rest der Kurve erscheint.

Die Kurvenberechnung muss mit zu großen Zahlen kämpfen

Der Grund dafür liegt an der Berechnung von zu großen Zahlen an dieser Stelle. Diese großen Zahlen können im Computer nicht mehr korrekt dargestellt werden.

Dafür gibt es eine Lösung: zunächst muss heraus­gefunden werden, wann die Kurve sich wieder­holt (im Falle von n*n*n*n wieder­holt sich die Kurve bei n = 90), dann kann man statt­dessen eintippen (n%90)*(n%90)*(n%90)*(n%90), womit die ganze Kurve angezeigt wird.

Alternativ kann man auch nach jeder Multiplikation mit n den Rest der Division mit 360 nehmen, da nur dieser für den Winkel relevant ist. Dies kann man mithilfe der oben erwähnten curve.power-Funktion erreichen, die im Prinzip eine Verschachtelung erzeugt: curve.power(n,4) ist äquivalent zu ((((n%360)*n%360)*n%360)*n%360). Somit lassen sich auch Kurven mit weitaus größeren Exponenten generieren.

Trotzdem kann man gespannt sein, falls Wieder­holungen in der Kurve jemals automatisch erkannt werden. Oder womöglich werden irgend­wann Wege eingebracht, die arithmetische Fehler generell vermeiden…

Dreckige Kurven und dreckiges Verhalten

Ein sehr bedauerliches Problem ist das eventuelle Auftreten von fehlerhaften horizontalen Linien oder Blöcken, wenn die Kurve zu dicht ist. Meistens hilft eine einfache Vergrößerung der Kurve mit Hilfe des vierten Felds oder eine leichte Drehung mithilfe des fünften Felds. Ob dieses Problem in einer zukünftigen Version umgangen werden kann?

Man sieht störende Linien

Ein weiteres Problem könnte das Auftreten eines Flackerns der Kurve sein (wahrscheinlich eher in einer mobilen Version). Ob auch da etwas getan werden kann?

Eine Auswahl an interssanten Kurven

Zu guter Letzt, eine Auswahl an interessanten Kurven: die einzelnen Eingaben für die jeweil­igen Felder sind mit Semikolon getrennt.

  • .7*(n*n)*pow(-1,-n); 7199; 1; 5; 0 Ansehen – generiert ein kreuzartiges Objekt. Komischerweise, wenn man die „.7“ durch „.1“, „.2“, …, „.6“, „.8“, „.9“ oder „1“ ersetzt, erhält man nur eine Art Kasten.
  • .55*(n*n)*pow(-1,-n); 14399; 1; 6; 0 Ansehen – generiert eine flockenartigere Version des kreuzartigen Objekts.
  • .85*(n*n)*pow(-1,-n); 14399; 1; 5; 0 Ansehen – generiert ein Objekt, das etwas an Bismuth erinnert.
  • sin(n)+4; 333; .1; 16; 0 Ansehen – generiert etwas, das wie ein perfekter Torus aussieht.
  • n*sin(n); 1600; .1; 4; 80 Ansehen – generiert ein Schwert.
  • (n*n)*1.2-(n*2); 899; 1; 12; 0 Ansehen – generiert eine Kurve, die geschlossen ist – also ihren Anfang wiederholt durchläuft – jedoch völlig asymmetrisch ist.
  • (n*n)%180; 2159; 1; 80; 0 Ansehen – wenn man bei dieser Kurve genau in die Mitte guckt, sieht man, wie fein die Kurve dort ist, wie grob sie jedoch wird, je weiter es nach außen geht.
  • (((n&-n)<<1)&n)==0?90:-90; 16383; 1; 3; 0 Ansehen – generiert die Drachenkurve. Angenommen man gibt im zweiten Feld einen Wert nach der Formel 2k-1 (2*2**2*2-1) ein, wobei k jede beliebige natürliche Zahl ist, wird die Kurve detaillierter und größer, wenn k größer ist (hier lohnt es sich „Kurvenfehler“ zu entsperren).
  • [n,-n][n%2]+1.5; 719; 1; 5; 90 Ansehen – generiert eine Art der Kardioide (man kann statt der 1.5 auch andere Zahlen eingeben, wodurch die Kurve ebenfalls interessant aussieht).
  • (n%7==0)?45:-90; 52; 1; 200; 0 Ansehen — generiert ein 2D-Modell eines Tesserakts.

Curve Generator — Documentation


Basics

The curve generator is an application that generates curves according to mathema­tical rules — similar to a spirograph. The curve consists of individual curve segments that are connected — much like a chain — and have a certain length. The curve segments are consecu­tively numbered: the variable n determines the number of a curve segment — the first curve segment’s value for n for example is: n = 0; n increases for each curve segment by a certain value.

1. field
2. field
3. field
4. field
5. field
Each curve segment is assigned to a value of n

The most important part is the angle: each curve segment has a certain angle that can be dependent of n (the length of the segments can be made dependent of n, too). This way the most interesting shapes, forms, fractals and curves can be generated.

This is how it works: The first curve segment has a certain starting angle. With each additional curve segment a calculated angle is added and assigned to that segment. That means, each curve segment assumes the angle of the preceding segment plus a new calculated angle.

The application consists of five input fields used to control the curve. In the next section, each field is described.

Technical Details and how to Share Curves

Because this application utilizesutilises the HTML5 Canvas API you can, if your browser supports this, save generated curves like you would save a graphic with right mouse button + “Save Graphic As…”.

In the upper right corner of the generator there’s a link labeled “SVG”; when you click on it or when you right-click it and select „Save Link As…“, you’ll get a scalable vector graphic version of that curve. Note: you can only save the SVGs and not share the URIs. Depending on your browser you either receive a “blob:” URI which is local and inaccessible to others or a “data:” URI which is way too long to be shared. You can share the saved file, however.

Also, there’s an SVG-only version which is way faster and slightly more compatible but doesn’t generate bitmap pictures.

Whenever a curve is generated you can also share the URL when it contains something like “#n*n@2160@1@4@0” at the end.

The Five Fields

First Field: The “Angle Function” (Change of the Angle of each Curve Segment)

Let’s start with simple examples: we assume that the second field contains 360, the third one 1, the fourth one 4 and the fifth one 0. One of the simplest values for the first field is 0 — this generates nothing else than a straight line. The first segment has an angle of (0° means right, 90° down, 180° left and 270° up), the second segment has an angle of 0° plus the value of the first field: 0°; 0° + 0° = 0°, so the next angle is 0°, as is the next one, and so forth.

Straight line

Equally simple is the value 1: this generates a circle. First segment: 0°, second one: 0° + 1° = 1°, third one: 1° + 1° = 2°, then 3°, 4°, 5°, etc. That means, the angle of each curve segment is incremented by 1. The value 2 in the first field generates a smaller circle; even larger values however generate rather edged “circles” — for instance 72 generates a pentagon and 144 generates a pentagram (see the section for the fourth field to resize these shapes).

Circle

Furthermore you can work with the variable n (for this the value 719 in the second field is recommended): so if you input n in the first field, the first segment (n = 0) has an angle of ; the second one (in this case n = 1) has an angle of 0° + n = 0° +  = 1°; the next segment (n = 2) has an angle of 1° + n = 1° +  = 3°; then 6°, 10°, 15°, 21°, etc.

Visualization for the “angle function” “n” Visualisation for the “angle function” “n”

Similar arithmetics are also achieved with n*n, n*n*n, etc. Multipli­cations with numbers are also possible: 2*n, 0.5*n, additions or subtrac­tions: n*n+2, n*n*n-12, etc. See the section with possible inputs for more.

Second Field: The Curve Length (Maximum Value of Curve Segment Count)

Some curves go through their beginning after some number of segments and behave “circularly”, some never go through their beginning and behave “linearly”, the behaviorbehaviour of some curves however is difficult or impossible to predict. Therefore, for all purposes there is the possibility of letting the curve go only to a certain n. E.g. an incomplete circle if the second field contains 269.

Three quarters of a circle

Arithmetic expressions like 360*12-1 are also possible.

Third Field: The n Count Increment (how many Steps are Added)

Changing the third field alters the way the individual curve segments are numbered. With the standard value 1 the values of n for each segment are 0, 1, 2, 3, 4, etc. With a value of 0.5 the values for n are 0, 0.5, 1, 1.5, 2, etc.

This strongly influences the appearance of the curve, because completely different values for n are applied in the “angle function”. This for example is n in the first field; 360*7.5 in the second one; .7 in the third one; 4 in the fourth one; 0 in the fifth one:

The curve looks differently in comparison to the above “n”-curve

Fourth Field: The Segment Length (Length of each Curve Segment)

This field represents how long each of the curve segments is in pixels. 0 obviously doesn’t show a curve. 20 for example is a good value for the pentagon and pentagram shapes mentioned above: each of their edges in this case is 20 pixels long.

Pentagon Pentagram

Mathema­tical expressions with n are possible here as well: e.g. 5 in the first field and 0.01*n in the fourth field generates a spiral.

Spiral

Fifth Field: Starting Angle (Initial Angle)

This field quite simply rotates the curve by setting the angle of the first curve segment.

Possible Inputs

General Remarks

This is a Web based application. The programming language is JavaScript and that means in these five fields you can input anything that JavaScript under­stands as well. In order to allow enhanced functionality arbitrary code may be executed. There are a few exceptions though: some potentially harmful keywords and patterns are filtered out and result in a “field error” (most notably, stuff like the this keyword, window, JSFuck code, eval, Function() syntax). If you desperately need cross-site scripting for your most powerful curvy creation, feel free to “fork” and modify the source code of the curve generator.

To begin with, for mathema­tical inputs all mathema­tical functions can be used that belong to the JavaScript Math Object. For simplifi­cation Math. doesn’t need to be typed; that is, the sine function is to be typed as sin() and not as Math.sin(). Addition is +, subtraction is -, multipli­cation is * and division is /.

Please note that ^ does not cause exponen­tiation but a bitwise logical XOR (see below); for mathema­tical powers you have to write either e.g. pow(n,3) or n*n*n.

An example using the sine function: 20*sin(0.2*n) in the first, 203 in the second, 1 in the third, 4 in the fourth, 81 in the fifth field.

The Rest

% is the modulo operator. This one returns the “remainder” of a division (for example: 8 % 3 = 2 meaning 8 mod 3 = 2). One example of a curve: n%180 in the first, 720 in the second, 1 in the third, 6 in the fourth, 0 in the fifth field.

Here is another example with a variable segment length: 60; 47; 1; 8*(n%12); 60

Conditioning and Controlling — Strict Discipline!

If this is true?Then this value is assumed:Otherwise this one. This can be used to gain more control of the curve. Example: (n==40)?60:2; 100; 1; 6; 0. Here the curve bends at the 41st curve segment by 60°, otherwise all segments continue with an angle of 2°.

Another example shows a combination of modulo and conditional operators: (n%12==0)?-144:12; 360; 1; 6; 0 — if n is divisible by 12 (which means there’s a remainder of 0), add the angle -144°, otherwise add 12°.

Back to Reason and Logic

As a logical operator == has already been used above for confirming equality between two values. < is for “less than”; > for “greater than”; <= for “less than or equal to”; >= for “greater than or equal to”; != for “unequal”. Also it is possible to connect these comparisons with && for “AND”; || for “OR”; !(Expression) for “NOT”. E.g.: (n%6==0||n%17==0)?0:360*(2/5); 800; 1; 30; 0.

Or if you just replaced that “6” in the first field by a “7”…

Bit Operations

Furthermore bitwise opera­tions can be used. See the section with interesting curves below for a good example: the dragon curve

Lists and Indexes

With lists ultimately every possibility of a curve can be generated. They work like JavaScript Arrays and can be used like this in the curve generator: [20,40,80,140, 220,-20,-40,-80, -140,-220][n]. The first part in the square brackets describes a list of individual angles. The second part is the so-called index that selects which of these angles is to be added.

For the first curve segment the index “n” evaluates to 0 — and an index of 0 selects the first angle in the list (20°); for the second curve segment n equals 1, which selects the second angle (40°; in total: 20° + 40° = 60°); for the third curve segment n equals 2, the third angle in the list — 80° — is selected and added: 60° + 80° = 140°; and so on.

This example demon­strates how it looks like if the list mentioned above is put in the first field and 9 in the second field (1 in the third, 12 in the fourth, -71 in the fifth).

An irregular shape following the rules of the list

When for the tenth segment n equals 9, the last angle in the list is selected and any additional segment would lead to an error, because this list doesn’t offer an angle for n = 10 anymore.

There are various solutions for this: one could simply add more angles to the list, or one could repeat the values in the list from the beginning by utilizing the modulo operator: [20,40,80,140, 220,-20,-40,-80, -140,-220][n%10] — the index now reads n mod 10, because the list has a length of 10; for n = 10 the generator simply computes 10 mod 10 which is 0 again, selecting the first angle from the list; for n = 11 it computes 11 mod 10 which in turn is 1, selecting the second angle from the list and so forth.

This picture illustrates how the curve looks like when the first field contains the “angle function” from above and the second field contains 90.

The little curve from above is repeated

Conditional operators offer yet another solution. E.g.: n<10 ? [20,40,80,140, 220,-20,-40,-80, -140,-220][n] : -5.

Various Tricks

If you’re familiar with JavaScript, you can actually look inside the source code of the curve generator and discover a few possibili­ties to manipulate the curve even more.

One example of this is the use of the variable w (originally for “Winkel”, the German word for “angle”) that refers to the angle of the current curve segment. For example you could start the first field with -w+ which would subtract the previous angle and add the recently calculated one — in this case the curve generator would behave as if the angles weren’t added to their preceding angles but as if the angles were set anew for each segment.

Functions and curve

Even more possibili­ties to operate the curve generator are offered by JavaScript functions. Because the curve generator currently runs in strict mode and global objects via window are forbidden you can use an object called curve to store persistent values in more complex functions (example: curve.x = 20; and then later curve.x += 2;). In fact, there are two values already stored in this object:

  • curve.isPrime(number): returns true or false depending on whether the given number in brackets is a prime number
  • curve.power(number, exponent): returns the exponentiation of the number and the exponent modulo 360 (i.e. (num.exp.) mod 360), because only that is relevant for the curve segments’ angle — only the positive integer part of the exponent will be used

Functions are specified in the IIFE form like this: (function(){Do all this…; return …and this is the returned value;}()). This is for more complex computations; one over-complicated example would be a curve where first it is checked whether n is a prime number, then — if it is a prime number — the next prime number is found, then the curve turns by 45° times the distance to the next prime number, or 0° if n is not a prime:

(function(){var prime=curve.isPrime(n); if(prime){var i=n; while(!curve.isPrime(++i));} return (prime?45*(i-n):0);}()) in the first field; 11000 in the second field…

Error Messages, Problems, Plans

Error Messages and Options to Ignore them

If you input something erroneous in the fields, an error message will appear that tells you which field the error is in, followed by an overview of possible inputs. These errors are “field errors”. Make sure that JavaScript under­stands the inputs: Multipli­cations for example cannot be written like 2n but have to be written like 2*n.

Moreover there are “curve errors”. If one of the mathema­tical expressions for instance includes division by 0 or if log(0) is to be computed — mathema­tical expressions that are simply not defined — or if a number is to be computed which is way too big or way too small, then a mathema­tical error is reported. This also happens whenever you write a list in the first field and the index exceeds the list positions.

Other “curve errors” appear when the curve’s density is too high, that is when too many curve segments are drawn in one concen­trated point or multiple lines are redrawn over each other. This is probably because the grayscalegreyscale between the white line and the black background has to be recalcu­lated multiple times which unfortu­nately slows down the drawing of the curve and in extreme cases leads to browser crashes. Unfortunately, the density is detected only very roughly. It’s safer to draw the curve with a gradually rising number of segments, i.e. first set the second field to a low number, then input your formulas for any other field and only then increase the number of segments. Curves like the one below (180.05 in the first field) tend to cause severe browser lags:

The curve looks like a bow-tie.

Equally, the size of the curve is limited; that is if the curve uses too much space. This is partly because it impairs the browser as well and partly because the curve possibly won’t even be displayed with too large dimensions.

Another limitation is for the number of curve segments because, once again, too many of them slow down the browser.

It may well be that there is a misjudgment in these precautions. It is possible to circumvent these error messages by opening the Web Console (depending on your browser) and inputing ignoreFieldErrors() and Enter to ignore all “field errors” or ignoreCurveErrors() and Enter to ignore all “curve errors”.

Alterna­tively, you can input ignoreFieldErrors(),1 in the first field (the second field should be a small number because otherwise the unlocking would unneces­sarily take place thousands of times) or the other command, respec­tively. This keeps the respective error messages suppressed until the page with the generator is reloaded.

Lastly, there’s another error message that you cannot disable: any potentially harmful keywords and patterns are blocked and result in an error message which informs about the use of forbidden code.

Very Big Numbers

Mathematics could be so beautiful… consider the input n*n*n*n in the first field and 2160*5 in the second one (then 1; 6; 0 in the other fields): you almost get a good circular curve. At the top on the right an obvious imper­fection forms in the curve which appears very irregularly and unexpec­tedly in comparison to the rest of the curve.

Curve computation encounters numbers that are too big

The reason for this is the computation of too large numbers at this point. These large numbers cannot be correctly represented in the computer anymore.

There is a solution for this: first, find out when a repetition occurs (in the case of n*n*n*n the curve repeats at n = 90), then you can instead type (n%90)*(n%90)*(n%90)*(n%90), which shows the whole curve.

Alternatively, you can return the remainder of a division by 360 of every single multiplication with n, since only the remainder is relevant for the angle. This can be achieved with the above mentioned curve.power function which in principle nests the muliplications: curve.power(n,4) is equivalent to ((((n%360)*n%360)*n%360)*n%360). This way it’s possible to generate curves with much higher exponents.

Still, one may only wonder if repetitions in the curve will ever be automati­cally recognizedrecognised. Or perhaps a way to circumvent arithmetic errors in general will be introduced at some time…

Dirty Curves and Dirty BehaviorBehaviour

One very unfortunate problem is the possible occurence of buggy horizontal lines or blocks when the curve is too dense. Oftentimes, a simple resize of the curve via the fourth field or a slight rotation via the fifth one helps. Whether this problem will be fixed in a future version?

You can see annoying lines

Another problem could be the occurence of a flickering of the curve (maybe more likely to happen in a mobile version). Whether something can be done about this as well?

A Selection of Interesting Curves

Finally, here’s a selection of interesting curves: the individual inputs for the corres­ponding fields are separated by semicolons, followed by a link to the curve.

  • .7*(n*n)*pow(-1,-n); 7199; 1; 5; 0 ViewView — generates a cross-like object. Strangely, if the “.7” is replaced by a “.1”, “.2”, …, “.6”, “.8”, “.9” or a “1”, you only get some sort of box.
  • .55*(n*n)*pow(-1,-n); 14399; 1; 6; 0 ViewView — generates a more flake-like version of the cross-like object.
  • .85*(n*n)*pow(-1,-n); 14399; 1; 5; 0 ViewView — generates an object that kind of reminds of bismuth.
  • sin(n)+4; 333; .1; 16; 0 ViewView — generates something that looks like a perfect torus.
  • n*sin(n); 1600; .1; 4; 80 ViewView — generates a sword.
  • (n*n)*1.2-(n*2); 899; 1; 12; 0 ViewView — generates a closed curve that loops through its beginning but is completely asymmet­rical.
  • (n*n)%180; 2159; 1; 80; 0 ViewView — if you regard the centercentre of this curve, you will notice how detailed it is in the centercentre but how rough it gets the further you look outwards.
  • (((n&-n)<<1)&n)==0?90:-90; 16383; 1; 3; 0 ViewView — generates the dragon curve. Assuming the second field contains a value according to the formula 2k-1 (2*2**2*2-1), where k is any natural number, the curve gets bigger and more detailed if k is bigger (in this case you may want to unlock “curve errors”).
  • [n,-n][n%2]+1.5; 719; 1; 5; 90 ViewView — generates some sort of cardioid (instead of the 1.5 you can also input other numbers which will generate other interesting curves).
  • (n%7==0)?45:-90; 52; 1; 200; 0 ViewView — generates a 2D model of a tesseract.