Showing
15 changed files
with
66 additions
and
39 deletions
... | @@ -28,6 +28,7 @@ class TikZ (object) : | ... | @@ -28,6 +28,7 @@ class TikZ (object) : |
28 | "arrayscope": {}, | 28 | "arrayscope": {}, |
29 | "structscope": {}, | 29 | "structscope": {}, |
30 | "heapscope": {}, | 30 | "heapscope": {}, |
31 | + "boxscope": {}, | ||
31 | "valueread" : {"very thick": None, | 32 | "valueread" : {"very thick": None, |
32 | "draw": "blue!50!black", | 33 | "draw": "blue!50!black", |
33 | "fill": "blue!20"}, | 34 | "fill": "blue!20"}, |
... | @@ -44,6 +45,7 @@ class TikZ (object) : | ... | @@ -44,6 +45,7 @@ class TikZ (object) : |
44 | "heap": {"grow": "left", | 45 | "heap": {"grow": "left", |
45 | "distance": "15mm"}, | 46 | "distance": "15mm"}, |
46 | "group": {"opacity": 0, | 47 | "group": {"opacity": 0, |
48 | + "draw": "yellow", | ||
47 | "very thick": None, | 49 | "very thick": None, |
48 | "inner sep": "0pt", | 50 | "inner sep": "0pt", |
49 | "outer sep": "0pt"}, | 51 | "outer sep": "0pt"}, |
... | @@ -93,8 +95,8 @@ class CAniTikZ (CAni) : | ... | @@ -93,8 +95,8 @@ class CAniTikZ (CAni) : |
93 | {head}{code}{tail} | 95 | {head}{code}{tail} |
94 | \end{{tikzpicture}} | 96 | \end{{tikzpicture}} |
95 | """).format(opt=opt, | 97 | """).format(opt=opt, |
96 | - head=(head + "\n") if head else "", | 98 | + head=(head.strip("\n") + "\n") if head else "", |
97 | - tail=("\n" + tail) if tail else "", | 99 | + tail=("\n" + tail.strip("\n")) if tail else "", |
98 | code="\n ".join(self.tikz(**tikz).splitlines())) | 100 | code="\n ".join(self.tikz(**tikz).splitlines())) |
99 | 101 | ||
100 | class Pointer (CAniTikZ) : | 102 | class Pointer (CAniTikZ) : |
... | @@ -379,8 +381,7 @@ class Struct (Aggregate) : | ... | @@ -379,8 +381,7 @@ class Struct (Aggregate) : |
379 | self.__dict__[name] = value | 381 | self.__dict__[name] = value |
380 | 382 | ||
381 | class Heap (CAniTikZ) : | 383 | class Heap (CAniTikZ) : |
382 | - _defaults = {"group": {"opacity": 0, | 384 | + _defaults = {"group": {"inner sep": "5mm"}} |
383 | - "inner sep": "5mm"}} | ||
384 | def __init__ (self, **tikz) : | 385 | def __init__ (self, **tikz) : |
385 | super().__init__(tikz) | 386 | super().__init__(tikz) |
386 | self._alloc = {} | 387 | self._alloc = {} |
... | @@ -418,3 +419,51 @@ class Heap (CAniTikZ) : | ... | @@ -418,3 +419,51 @@ class Heap (CAniTikZ) : |
418 | children = " ".join(f"({nid})" for nid in fit) | 419 | children = " ".join(f"({nid})" for nid in fit) |
419 | yield fr" \node[{opt.group},fit={children}] ({self.nodeid}) {{}};" | 420 | yield fr" \node[{opt.group},fit={children}] ({self.nodeid}) {{}};" |
420 | yield r"\end{scope}" | 421 | yield r"\end{scope}" |
422 | + | ||
423 | +_flip = {"right": "below", | ||
424 | + "below": "right", | ||
425 | + "left": "above", | ||
426 | + "above": "left"} | ||
427 | + | ||
428 | +class Box (CAniTikZ) : | ||
429 | + def __init__ (self, *content, grow="right", distance="15mm", parent=None, **tikz) : | ||
430 | + super().__init__(tikz) | ||
431 | + self._grow = grow | ||
432 | + self._dist = distance | ||
433 | + self._parent = parent | ||
434 | + self._data = tuple(self._init(content)) | ||
435 | + def _init (self, content) : | ||
436 | + for obj in content : | ||
437 | + if isinstance(obj, CAniTikZ) : | ||
438 | + yield obj | ||
439 | + elif isinstance(obj, list) : | ||
440 | + yield self.__class__(*obj, | ||
441 | + grow=(_flip.get(self._grow) if self._parent is None | ||
442 | + else self._parent._grow), | ||
443 | + distance=self._dist, | ||
444 | + parent=self, | ||
445 | + **self._o.dict()) | ||
446 | + else : | ||
447 | + raise ValueError("invalid %s content: %r" | ||
448 | + % (self.__class__.__name__, obj)) | ||
449 | + def tikz (self, **tikz) : | ||
450 | + opt = TikZ(tikz) + self._o | ||
451 | + classname = self.__class__.__name__ | ||
452 | + nodeid = self.nodeid | ||
453 | + return (f"%% {classname} {nodeid} ({self._grow})\n" | ||
454 | + + "\n".join(self._tikz(opt)) | ||
455 | + + f"\n%% /{classname} {nodeid}") | ||
456 | + def _tikz (self, opt) : | ||
457 | + fit = [] | ||
458 | + yield fr"\begin{{scope}}[{opt.boxscope}]" | ||
459 | + for data in self._data : | ||
460 | + fit.append(data.nodeid) | ||
461 | + yield fr" %% box {self.nodeid} content" | ||
462 | + for line in data.tikz(**opt.dict()).splitlines() : | ||
463 | + yield " " + line | ||
464 | + opt = opt + {"pos": {self._grow: | ||
465 | + "{dist} of {prev}".format(dist=self._dist, | ||
466 | + prev=(data@None).nodeid)}} | ||
467 | + children = " ".join(f"({nid})" for nid in fit) | ||
468 | + yield fr" \node[{opt.group},fit={children}] ({self.nodeid}) {{}};" | ||
469 | + yield r"\end{scope}" | ... | ... |
... | @@ -6,11 +6,10 @@ mp4: qs-partition.mp4 qs-main.mp4 stack-push.mp4 | ... | @@ -6,11 +6,10 @@ mp4: qs-partition.mp4 qs-main.mp4 stack-push.mp4 |
6 | rm -f out.* | 6 | rm -f out.* |
7 | PYTHONPATH=..:$$PYTHONPATH python3 $< | 7 | PYTHONPATH=..:$$PYTHONPATH python3 $< |
8 | pdflatex tpl | 8 | pdflatex tpl |
9 | - pdflatex tpl | ||
10 | mv -f tpl.pdf $@ | 9 | mv -f tpl.pdf $@ |
11 | 10 | ||
12 | %.gif: %.pdf | 11 | %.gif: %.pdf |
13 | - rm -rf _gif | 12 | + rm -rf _gif $@ |
14 | mkdir _gif | 13 | mkdir _gif |
15 | gs -dSAFER -DBATCH -dNOPAUSE -sDEVICE=png16m -r400 -sOutputFile=_gif/%03d.png $< | 14 | gs -dSAFER -DBATCH -dNOPAUSE -sDEVICE=png16m -r400 -sOutputFile=_gif/%03d.png $< |
16 | mogrify -resize 800x600 -format gif _gif/*.png | 15 | mogrify -resize 800x600 -format gif _gif/*.png |
... | @@ -18,7 +17,7 @@ mp4: qs-partition.mp4 qs-main.mp4 stack-push.mp4 | ... | @@ -18,7 +17,7 @@ mp4: qs-partition.mp4 qs-main.mp4 stack-push.mp4 |
18 | rm -rf _gif | 17 | rm -rf _gif |
19 | 18 | ||
20 | %.mp4: %.pdf | 19 | %.mp4: %.pdf |
21 | - rm -rf _mp4 | 20 | + rm -rf _mp4 $@ |
22 | mkdir _mp4 | 21 | mkdir _mp4 |
23 | gs -dSAFER -DBATCH -dNOPAUSE -sDEVICE=png16m -r400 -sOutputFile=_mp4/%03d.png $< | 22 | gs -dSAFER -DBATCH -dNOPAUSE -sDEVICE=png16m -r400 -sOutputFile=_mp4/%03d.png $< |
24 | ffmpeg -r 1 -s 1024x768 -i _mp4/%03d.png -vcodec libx264 -crf 25 -pix_fmt yuv420p $@ | 23 | ffmpeg -r 1 -s 1024x768 -i _mp4/%03d.png -vcodec libx264 -crf 25 -pix_fmt yuv420p $@ | ... | ... |
No preview for this file type
No preview for this file type
No preview for this file type
1 | -from codanim.data import Array, Heap | 1 | +from codanim.data import Array, Box |
2 | from codanim.flow import FUNC, BLOCK, ENV, WS, XDECL, DECL, PY, EXPR, STMT, WHILE, IF | 2 | from codanim.flow import FUNC, BLOCK, ENV, WS, XDECL, DECL, PY, EXPR, STMT, WHILE, IF |
3 | 3 | ||
4 | ## | 4 | ## |
... | @@ -87,19 +87,6 @@ sort = FUNC(BLOCK(ENV("t", array), | ... | @@ -87,19 +87,6 @@ sort = FUNC(BLOCK(ENV("t", array), |
87 | src="while ({cond}) {{\n{body} }}\n")), | 87 | src="while ({cond}) {{\n{body} }}\n")), |
88 | src="void sort (Tab t) {{{body}}}") | 88 | src="void sort (Tab t) {{{body}}}") |
89 | 89 | ||
90 | -# let's play with Heap to layout the various data blocks | ||
91 | -# /!\ we must do this before simulating the code | ||
92 | -ha = Heap() | ||
93 | -ha.new(array) | ||
94 | -hs = Heap(heap={"grow": "right", | ||
95 | - "distance": "0pt"}) | ||
96 | -hs.new(first) | ||
97 | -hs.new(last) | ||
98 | -h = Heap(heap={"grow": "right", | ||
99 | - "distance": "5mm"}) | ||
100 | -h.new(ha) | ||
101 | -h.new(hs) | ||
102 | - | ||
103 | # run code and save its animation | 90 | # run code and save its animation |
104 | sort.IP += 1 | 91 | sort.IP += 1 |
105 | sort() | 92 | sort() |
... | @@ -107,5 +94,7 @@ with open("out.code", "w") as out : | ... | @@ -107,5 +94,7 @@ with open("out.code", "w") as out : |
107 | out.write(sort.tex()) | 94 | out.write(sort.tex()) |
108 | 95 | ||
109 | # save data animation | 96 | # save data animation |
97 | +b = Box(Box(array), Box(first, last, distance="0pt")) | ||
110 | with open("out.tikz", "w") as out : | 98 | with open("out.tikz", "w") as out : |
111 | - out.write(h.tex(tikzpicture={"scale": .55})) | 99 | + out.write(b.tex(tikzpicture={"scale": .55}, |
100 | + tail=r"\node at (-2,1) {};")) | ... | ... |
No preview for this file type
No preview for this file type
1 | -from codanim.data import Array, Struct, Value, Heap | 1 | +from codanim.data import Array, Struct, Value, Box |
2 | from codanim.flow import FUNC, BLOCK, ENV, WS, DECL, WHILE, EXPR, DO, STMT, RETURN, IF | 2 | from codanim.flow import FUNC, BLOCK, ENV, WS, DECL, WHILE, EXPR, DO, STMT, RETURN, IF |
3 | 3 | ||
4 | a = Array([3, 13, 5, 0, 7, 11, 4, 9, 14, 2, 10, 1, 12, 8, 6], | 4 | a = Array([3, 13, 5, 0, 7, 11, 4, 9, 14, 2, 10, 1, 12, 8, 6], |
5 | index=["a", "b"]) | 5 | index=["a", "b"]) |
6 | t = Struct({"len": Value(15), "val": a.ptr()}) | 6 | t = Struct({"len": Value(15), "val": a.ptr()}) |
7 | 7 | ||
8 | -h = Heap() | ||
9 | -h.new(a) | ||
10 | -h.new(t) | ||
11 | - | ||
12 | partition = FUNC(BLOCK(ENV("t", t), | 8 | partition = FUNC(BLOCK(ENV("t", t), |
13 | WS(" "), | 9 | WS(" "), |
14 | DECL("pivot", EXPR("t.val[(t.len-1)//2]", | 10 | DECL("pivot", EXPR("t.val[(t.len-1)//2]", |
... | @@ -55,5 +51,7 @@ with open("out.code", "w") as out : | ... | @@ -55,5 +51,7 @@ with open("out.code", "w") as out : |
55 | out.write(partition.tex()) | 51 | out.write(partition.tex()) |
56 | 52 | ||
57 | # save data animation | 53 | # save data animation |
54 | +b = Box(a, t, grow="left") | ||
58 | with open("out.tikz", "w") as out : | 55 | with open("out.tikz", "w") as out : |
59 | - out.write(h.tex(tikzpicture={"scale": .6})) | 56 | + out.write(b.tex(tikzpicture={"scale": .6}, |
57 | + tail=r"\node at (0,-2) {};")) | ... | ... |
No preview for this file type
No preview for this file type
1 | -from codanim.data import Heap, Struct, Value | 1 | +from codanim.data import Heap, Struct, Value, Box |
2 | from codanim.flow import FUNC, BLOCK, ENV, WS, DECL, EXPR, STMT | 2 | from codanim.flow import FUNC, BLOCK, ENV, WS, DECL, EXPR, STMT |
3 | 3 | ||
4 | heap = Heap() | 4 | heap = Heap() |
... | @@ -8,15 +8,6 @@ stack = heap.new(Struct({"val": Value(2), "next": stack})) | ... | @@ -8,15 +8,6 @@ stack = heap.new(Struct({"val": Value(2), "next": stack})) |
8 | s = Value(stack, nodeid="s") | 8 | s = Value(stack, nodeid="s") |
9 | t = Value(None, nodeid="t", value={"xshift": "-25mm"}) | 9 | t = Value(None, nodeid="t", value={"xshift": "-25mm"}) |
10 | 10 | ||
11 | -v = Heap(heap={"grow": "above", | ||
12 | - "separation": "0pt"}) | ||
13 | -h = Heap(heap={"grow": "right"}, | ||
14 | - ) | ||
15 | -h.new(t) | ||
16 | -h.new(s) | ||
17 | -v.new(heap) | ||
18 | -v.new(h) | ||
19 | - | ||
20 | push = FUNC(BLOCK(ENV("s", s), | 11 | push = FUNC(BLOCK(ENV("s", s), |
21 | ENV("u", Value(3)), | 12 | ENV("u", Value(3)), |
22 | ENV("top", t), | 13 | ENV("top", t), |
... | @@ -43,8 +34,9 @@ with open("out.code", "w") as out : | ... | @@ -43,8 +34,9 @@ with open("out.code", "w") as out : |
43 | out.write(push.tex()) | 34 | out.write(push.tex()) |
44 | 35 | ||
45 | # save data and animation | 36 | # save data and animation |
37 | +b = Box(heap, Box(t, s, grow="right"), grow="above") | ||
46 | with open("out.tikz", "w") as out : | 38 | with open("out.tikz", "w") as out : |
47 | - out.write(v.tex(tail=r""" | 39 | + out.write(b.tex(tail=r""" |
48 | \node[above] at (s.north) {\texttt{s}}; | 40 | \node[above] at (s.north) {\texttt{s}}; |
49 | \node[above] at (t.north) {\texttt{top}}; | 41 | \node[above] at (t.north) {\texttt{top}}; |
50 | """)) | 42 | """)) | ... | ... |
-
Please register or login to post a comment