7

I tried to draw a Z curve (Lebesgue curve) by using this example for Hilbert curves. But I don't see why it does not work.

\documentclass[12pt]{article}

\usepackage{tikz}
\usepackage{ifthen}

\usepackage[position=top,labelformat=empty]{subfig}
\usepackage{verbatim}

\newdimen\HilbertLastX
\newdimen\HilbertLastY
\newcounter{HilbertOrder}

\def\DrawToNext#1#2{%
   \advance \HilbertLastX by #1
   \advance \HilbertLastY by #2
   \pgfpathlineto{\pgfqpoint{\HilbertLastX}{\HilbertLastY}}
}

% \Hilbert[right_x,right_y,left_x,left_x,up_x,up_y,down_x,down_y]
\def\Hilbert[#1,#2,#3,#4,#5,#6,#7,#8] {
  \ifnum\value{HilbertOrder} > 0%
     \addtocounter{HilbertOrder}{-1}
     \Hilbert[#5,#6,#7,#8,#1,#2,#3,#4]
     \Hilbert[#1,#2,#3,#4,#5,#6,#7,#8]
     \DrawToNext {#1} {#5}
     \Hilbert[#1,#2,#3,#4,#5,#6,#7,#8]
     \DrawToNext {#3} {#3}
     \Hilbert[#7,#8,#5,#6,#3,#4,#1,#2]
     \DrawToNext {#1} {#5}
     \addtocounter{HilbertOrder}{1}
  \fi
}

\def\hilbert((#1,#2),#3){%
   \advance \HilbertLastX by #1
   \advance \HilbertLastY by #2
   \pgfpathmoveto{\pgfqpoint{\HilbertLastX}{\HilbertLastY}}
   \setcounter{HilbertOrder}{#3}
   \Hilbert[1mm,0mm,-1mm,0mm,0mm,1mm,0mm,-1mm]
   \pgfusepath{stroke}%
}

\begin{document}
\begin{figure}%
    \centering
    \subfloat[$n=1$]{\tikz[scale=18] \hilbert((0mm,0mm),1);}~~
    \subfloat[$n=2$]{\tikz[scale=6] \hilbert((0mm,0mm),2);}~~
    \subfloat[$n=3$]{\tikz[scale=2.6] \hilbert((0mm,0mm),3);}~~
    \subfloat[$n=4$]{\tikz[scale=1.2] \hilbert((0mm,0mm),4);}~~
    \subfloat[$n=5$]{\tikz[scale=0.58] \hilbert((0mm,0mm),5);}%
\end{figure}%

\end{document}

I get this result which is obviously wrong: enter image description here

Any suggestions how to make it work? Thank you!

10

Here's a way using the lindenmayersystems library. Orders above 8 will take ages:

\documentclass[tikz,border=5]{standalone}
\usetikzlibrary{lindenmayersystems}
\pgfdeclarelindenmayersystem{z-curve}{
\symbol{I}{\pgftransformscale{+0.25\pgflsystemstep}}
\symbol{p}{%
  \pgfpathmoveto{\pgfqpoint{1pt}{3pt}}\pgfpathlineto{\pgfqpoint{3pt}{3pt}}%
  \pgfpathlineto{\pgfqpoint{1pt}{1pt}}\pgfpathlineto{\pgfqpoint{3pt}{1pt}}%
}
\symbol{q}{%
  \pgfpathlineto{\pgfqpoint{1pt}{3pt}}\pgfpathlineto{\pgfqpoint{3pt}{3pt}}%
  \pgfpathlineto{\pgfqpoint{1pt}{1pt}}\pgfpathlineto{\pgfqpoint{3pt}{1pt}}%
}
\symbol{S}{\pgftransformscale{+0.5pt}}
\symbol{A}{\pgftransformshift{\pgfqpoint{0pt}{4pt}}}
\symbol{B}{\pgftransformshift{\pgfqpoint{4pt}{4pt}}}
\symbol{C}{\pgftransformshift{\pgfqpoint{4pt}{0pt}}}
\symbol{[}{\bgroup}
\symbol{]}{\egroup}
\rule{Z -> Ip}
\rule{p -> S[Ap][Bq][q][Cq]}
\rule{q -> S[Aq][Bq][q][Cq]}
}
\begin{document}
\foreach \i in {1,...,9}{
\begin{tikzpicture}[line join=round]
\draw [draw=red] (0,0) rectangle (5,5) (2.5, 5) node [above] {order: \i};
\draw [l-system={z-curve, step=5cm, axiom=Z, order=\i}] l-system;
\end{tikzpicture}}
\end{document}

enter image description here

| improve this answer | |
  • How can I place the first four orders horizontal side by side? In addition I get an error if I try it using \documentclass[a4paper,11pt]{article}. But why? – recipe_for_disaster Jan 8 '17 at 19:07
  • @Samuel the error is due to the fact that the tikz package was automatically included by the standalone class due to the tikz option. If the document class is changed then \usepackage{tikz} needs to be added to the preamble. To reposition the z-curve use the shift key as the first argument to the \draw command e.g., \draw [shift={(5,0)}, l-system={... – Mark Wibrow Jan 10 '17 at 8:43
  • I would like to use your approach also for Hilbert Curves. Since I do not really understand how your code works I would like to know how it works and how I can modify it in order to get Hilbert curves. That would be great! – recipe_for_disaster Jan 11 '17 at 11:29
  • This may be very impressive, but all I see is a solid black square with order: 9 above it. Is this supposed to illustrate something or is it a problem with my browser? Images sometimes disappear, but I've never known one turn into a black hole before! – cfr Jan 12 '17 at 0:18
  • 1
    @Manuel This time, I saw the animation. When I wrote that comment, I'd only seen the last frame. I didn't know that there were 8 before it. So, as far as I saw, there was just a black square which did not seem very useful as an illustration of anything. – cfr Jan 12 '17 at 0:55
1

No Lindenmayer system, only recursive.

Compile here: http://asymptote.ualberta.ca/

path Zordercurve(pair A, pair B, int ite=1){
path[] g;
if (ite == 1){ 
  g.push((xpart(A+(B-A)/4),ypart(A+3*(B-A)/4))--(A+3*(B-A)/4)--
         (A+(B-A)/4)--(xpart(A+3*(B-A)/4),ypart(A+(B-A)/4)));
  }
else {
  g.push(Zordercurve((A.x,ypart((A+B)/2)),(xpart((A+B)/2),B.y),ite-1));
  g.push(Zordercurve((A+B)/2,B,ite-1));
  g.push(Zordercurve(A,(A+B)/2,ite-1));
  g.push(Zordercurve((xpart((A+B)/2),A.y),(B.x,ypart((A+B)/2)),ite-1));
}
return operator --(... g);
}
unitsize(1cm);
size(300);
draw(box((0,0),(4,4)));
draw(Zordercurve((0,0),(4,4),4),linewidth(0.5bp));
label(Label("order: "+(string) 4,LeftSide),(0,4)--(4,4));
shipout(bbox(2mm,invisible));

enter image description here

Animation:

path Zordercurve(pair A, pair B, int ite=1){
path[] g;
if (ite == 1){ 
  g.push((xpart(A+(B-A)/4),ypart(A+3*(B-A)/4))--(A+3*(B-A)/4)--
         (A+(B-A)/4)--(xpart(A+3*(B-A)/4),ypart(A+(B-A)/4)));
  }
  else {
  g.push(Zordercurve((A.x,ypart((A+B)/2)),(xpart((A+B)/2),B.y), ite-1));
  g.push(Zordercurve((A+B)/2,B, ite-1));
  g.push(Zordercurve(A,(A+B)/2, ite-1));
  g.push(Zordercurve((xpart((A+B)/2),A.y),(B.x,ypart((A+B)/2)), ite-1));
}
return operator --(... g);
}
import animate;
settings.tex="pdflatex"; 
settings.outformat="pdf"; 
animation Ani;
unitsize(1cm);
size(300);
draw(box((0,0),(4,4)));
for (int i=1; i <= 9 ; ++i){
save();
draw(Zordercurve((0,0),(4,4),i),linewidth(0.3bp));
label(Label("order: "+(string) i,LeftSide),(0,4)--(4,4));
Ani.add();
restore();
}
erase();
Ani.movie(BBox(2mm,invisible));

enter image description here

Advanced animation.

path Zordercurve(pair A, pair B, int ite=1){
path[] g;
if (ite == 1){ 
  g.push((xpart(A+(B-A)/4),ypart(A+3*(B-A)/4))--(A+3*(B-A)/4)--
         (A+(B-A)/4)--(xpart(A+3*(B-A)/4),ypart(A+(B-A)/4)));
  }
  else {
  g.push(Zordercurve((A.x,ypart((A+B)/2)),(xpart((A+B)/2),B.y), ite-1));
  g.push(Zordercurve((A+B)/2,B, ite-1));
  g.push(Zordercurve(A,(A+B)/2, ite-1));
  g.push(Zordercurve((xpart((A+B)/2),A.y),(B.x,ypart((A+B)/2)), ite-1));
}
return operator --(... g);
}
pair[] Lebesguecurve(pair A, pair B, int ite=1){
path G=Zordercurve(A,B,ite);
pair C[];
for (int i=0; i <= length(G); ++i){ C.push(point(G,i)); }
return C;
}

import animate;
settings.tex="pdflatex"; 
settings.outformat="pdf"; 
animation Ani;
unitsize(1cm);
size(300);
pair[] M=Lebesguecurve((0,0),(4,4),4);
guide d;
for (int i=0; i < M.length ; ++i){
save();
d=d--M[i];
draw((i != 0) ? d : nullpath );
draw(box((0,0),(4,4)));
label(Label("order: "+(string) 4,LeftSide),(0,4)--(4,4));
Ani.add();
restore();
}
erase();
Ani.movie(BBox(2mm,invisible));

enter image description here

| improve this answer | |

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.