Hilbert curve: The space filling curve drawn with JavaScript
jsxgraph.uni-bayreuth.de
jsxgraph.uni-bayreuth.de
Space-filling curves are ridiculously easy to implement with L-system rules, and I spent a few days developing a set of axioms to express it in a rewrite system. This was a fun puzzle [2].
A => BF-F-BFFFC-F-FC+F+BF-F-BFFFC-F-FC
B => BFFFC-F-FC+F+B
C => C+F+BF-F-BFFFC
[1] https://www.sciencedirect.com/science/article/pii/S0166218X0...Its locality properties provide a practical alternative to the Hilbert curve for this type of map. Also interesting that it is loopy.
maybe my translation is buggy?
hcurve {
Angle 4
Axiom A
A=BF-F-BFFFD-F-FD+F+BF-F-BFFFD-F-FD
B=BFFFD-F-FD+F+B
D=D+F+BF-F-BFFFD ; C is reserved in Fractint
}Can you try generating 1/8 or 1/4 curves to check the partial generation? Or these rules--should produce the triangular shape:
A=AFFFB-F-FB+F+A
B=B+F+AF-F-AFFFB A => BF-F-BFFFD-F-FD+F+BF-F-BFFFD-F-FD
B => BFFFD-F-FD+F+B
D => D+F+BF-F-BFFFD
maybe i'm hitting a fractint bug or unexpected behaviorthis recipe does work in fractint to produce the triangular shape:
debug {
Angle 4
Axiom A
A=AFFFB-F-FB+F+A
B=B+F+AF-F-AFFFB
}
and based on that, this produces the whole cycle: simplified {
Angle 4
Axiom AF-F-AF-F-
A=AFFFB-F-FB+F+A
B=B+F+AF-F-AFFFB
}
and accordingly this works on Kandalov's site with the same
axiom: A => AFFFB-F-FB+F+A
B => B+F+AF-F-AFFFB
oh, now i know what the problem is, D is a drawing command in fractint; i had too much D, the opposite of the usual problem. so this works: hcurve { ; by oneearedrabbit.net. See
; <https://news.ycombinator.com/item?id=38029945>. Based on "an obscure
; paper by Rolf Niedermeier, Klaus Reinhardt, and Peter Sanders that
; introduced a rather peculiar curve with an unfortunate name: H-curve
; [1]. The paper mentions that H-curve preserves better locality
; properties compared to Hilbert curve. It fills the space with H-like
; shapes, hence the name. Also, like the Moore curve, it generates a
; loop."
; <https://www.sciencedirect.com/science/article/pii/S0166218X00003267>
Angle 4
Axiom A
A=BF-F-BFFFX-F-FX+F+BF-F-BFFFX-F-FX
B=BFFFX-F-FX+F+B
X=X+F+BF-F-BFFFX ; C and D are reserved in Fractint
}
but i like `simplified` above betterincidentally the paper seems to call it 'h-indexing'
a where
a -> afffb-f-fb+f+a
b -> b+f+af-f-afffb
has the property that the axiom is a proper prefix of the axiom's expansion,
which turns out to be equivalent to the property
that every generation is a proper prefix of the following generation;
this means that in a sense each one is "approaching a limit"
of a single infinite string,
in the sense that it's a successively longer prefix of that string.
this infinite string,
called a 'morphic word',
is a fixed point of the mapping
the l-system does each generationthis is literally a numerical approximation if you treat the string as a fractional number in some base, e.g., base 10 with a=1, b=2, f=3, +=4, -=5
with that interpretation, the first approximation 'a' is 0.1, the second approximation 'afffb-f-fb+f+a' is 0.13332535324341, the third approximation 'afffb-f-fb+f+afffb+f+af-f-afffb-f-fb+f+af-f-afffb+f+afffb-f-fb+f+a' is 0.133325353243413332434135351333253532434135351333243413332535324341, and so on.
the thue-morse sequence can be generated in the same way with the l-system
0 where 0 -> 01 and 1 -> 10
although the so-called fibonacci word is slightly simpler a where a -> ab and b -> a
all of the above morphic words are aperiodic, though it's trivial to design a periodic morphic worda program to output the infinite morphic word of movement commands for the h-curve of a single triangle is
queue = ['a'], []
d = dict(a='afffb-f-fb+f+a', b='b+f+af-f-afffb')
while True:
for item in queue[0]:
for c in item:
n = d.get(c, c)
yield n
queue[1].append(n)
queue = queue[1][::-1], queue[0] # amortized constant time
queue[1].clear()
this is in http://canonical.org/~kragen/sw/dev3/hcurvestream.pywhich outputs about 5MB/s on this palmtop but will slow down as it runs into swap after generating less than the size of RAM in output
the output begins (via fold -w 70):
afffb-f-fb+f+aafffb-f-fb+f+afffb+f+af-f-afffb-f-fb+f+af-f-afffb+f+afff
b-f-fb+f+aafffb-f-fb+f+afffb+f+af-f-afffb-f-fb+f+af-f-afffb+f+afffb-f-
fb+f+a+f+b+f+af-f-afffb+f+afffb-f-fb+f+af-f-afffb-f-fb+f+afffb+f+af-f-
afffbf-f-b+f+af-f-afffb+f+afffb-f-fb+f+af-f-afffb-f-fb+f+afffb+f+af-f-
afffbfffafffb-f-fb+f+afffb+f+af-f-afffb-f-fb+f+af-f-afffb+f+afffb-f-fb
+f+aafffb-f-fb+f+afffb+f+af-f-afffb-f-fb+f+af-f-afffb+f+afffb-f-fb+f+a
+f+b+f+af-f-afffb+f+afffb-f-fb+f+af-f-afffb-f-fb+f+afffb+f+af-f-afffbf
-f-b+f+af-f-afffb+f+afffb-f-fb+f+af-f-afffb-f-fb+f+afffb+f+af-f-afffbf
ffafffb-f-fb+f+afffb+f+af-f-afffb-f-fb+f+af-f-afffb+f+afffb-f-fb+f+aff
fb+f+af-f-afffb+f+afffb-f-fb+f+af-f-afffb-f-fb+f+afffb+f+af-f-afffbfff
afffb-f-fb+f+afffb+f+af-f-afffb-f-fb+f+af-f-afffb+f+afffb-f-fb+f+a-f-f
afffb-f-fb+f+afffb+f+af-f-afffb-f-fb+f+af-f-afffb+f+afffb-f-fb+f+a+f+b
+f+af-f-afffb+f+afffb-f-fb+f+af-f-afffb-f-fb+f+afffb+f+af-f-afffb-f-fb
+f+af-f-afffb+f+afffb-f-fb+f+af-f-afffb-f-fb+f+afffb+f+af-f-afffbfffaf
ffb-f-fb+f+afffb+f+af-f-afffb-f-fb+f+af-f-afffb+f+afffb-f-fb+f+a-f-faf
ffb-f-fb+f+afffb+f+af-f-afffb-f-fb+f+af-f-afffb+f+afffb-f-fb+f+a+f+b+f
+af-f-afffb+f+afffb-f-fb+f+af-f-afffb-f-fb+f+afffb+f+af-f-afffb+f+afff
b-f-fb+f+afffb+f+af-f-afffb-f-fb+f+af-f-afffb+f+afffb-f-fb+f+a+f+b+f+a
f-f-afffb+f+afffb-f-fb+f+af-f-afffb-f-fb+f+afffb+f+af-f-afffbf-f-b+f+a
f-f-afffb+f+afffb-f-fb+f+af-f-afffb-f-fb+f+afffb+f+af-f-afffbfffafffb-(https://github.com/graypegg/hilbertcurveplayground)
Maps weather data, sorted by date onto the curve. Makes the seasons obvious since they get grouped together!
That means, his PhD advisor's advisor's advisor's advisor. There are a few thousand mathematicians who can claim that: https://www.mathgenealogy.org/id.php?id=7298
Shoutout to Prof. Wassermann for keeping up the good work.
One time I wrote some ruby and some lua to generate a hilbert curve in Factorio - I'm pretty happy with the result: https://github.com/kkuchta/factorio_hilbert
I threw together a hacky demo of the Hilbert curve and some other l-system curve for a middle school computer club I ran way back when. Not the best UI in the world, but it shows you either the string substitutions following each l-system ruleset, or with "show canvas" checked each click draws the next generation.
https://stackoverflow.com/questions/499166/mapping-n-dimensi...
#!/usr/bin/python3
T=['a'];[T.append(''.join(dict(a='lbffraffarffbl',b='rafflbffblffar').get(c,c)for c in T[-1]))for i in 'abcd'];D,V=[0],1
for c in T[-1]:M,T=dict(f=(1,1),r=(0,1j),l=(0,-1j)).get(c,(0,1));D.append(D[-1]+M*V);V*=T
X=range(31);print('\n'.join(''.join('⬜'[j-i*1j in D]for j in X)for i in X))
hn silently censors that in a way that breaks the code but the original is at http://canonical.org/~kragen/sw/dev3/hilbert.pythere is an almost perfectly correct explanation of the code by gpt-4 at https://bin.gy/altypsisca
the only problem was that gpt-4 guessed wrong about which particular fractal was being drawn
i think the turtle-graphics formulation of the hilbert curve that underlies this l-system is nicer than the manhattan formulation in the linked js. i'm undecided about whether the l-system formulation as string rewrite rules is better or worse than the explicit recursion with conditionals used in the js. fractint's l-system engine includes a `!` operator which swaps left and right, which i think could make the hilbert curve simpler, though the definition in fractint.l doesn't
sudo apt install xfractint and type tlsystem and hit enter to explore more l-systems`
arguably a formulation in terms of a shape grammar or iterated function system would be a better fit
also, if l-systems are the kind of thing you like, you'll probably enjoy http://canonical.org/~kragen/sw/dev3/skitch
Google’s S2, geometry on the sphere, cells and Hilbert curve
https://news.ycombinator.com/item?id=10066616
I've always thought S2 was a clever name for something built with the Hilbert curve. (Look at the shape of the glyphs.)
<rect x="0" y="0" width="1" height="1" />There is some infesting/weird aliasing at the 8 and 9 level (at least in my screen). I'm almost sure it's aliasing, not a real density difference.
Anyway, a real example has a line of non zero width, let's asume 1/2^n. Centered? How even is the average dendity distribution? Are the crosses real or an artifact of the pixels in my screen? I don't know and I'm curious?
https://medium.com/coffee-shop-math/coffee-shop-math-isometr...