Skip to content

Commit c696501

Browse files
Jg/refactortikz (#20)
* Create tikz.jl * add canvas * Update canvas.jl * Update generate_graph.jl * Tikz graph plot (#18) * simplify weighted (#17) * simplify weighted * automatically general rotated and reflected gadgets * fix simplifier gadgets * new tikz * fix merge * fix bounding box args * clean up Co-authored-by: minhthin1028 <84551256+minhthin1028@users.noreply.github.com> Co-authored-by: Minh-Thi Nguyen <mtnguyen@quera-computing.com>
1 parent a3f182b commit c696501

File tree

9 files changed

+220
-59
lines changed

9 files changed

+220
-59
lines changed

.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
11
/.vscode/
22
/Manifest.toml
33
.DS_Store
4+
_local/

project/vizgadget.jl

Lines changed: 19 additions & 47 deletions
Original file line numberDiff line numberDiff line change
@@ -1,38 +1,16 @@
1-
using UnitDiskMapping, Graphs
1+
using UnitDiskMapping.TikzGraph, Graphs
2+
using UnitDiskMapping: crossing_ruleset, Pattern, source_graph, mapped_graph
23

3-
function command_graph(locs, graph, pins, dx, dy, r, name)
4-
cmd = ""
4+
function command_graph!(canvas, locs, graph, pins, dx, dy, r, name)
55
for (i,loc) in enumerate(locs)
66
if count(==(loc), locs) == 2
7-
type = 2
8-
else
9-
type = 1
7+
Node(loc[1]+dx, loc[2]+dy, fill="none", id="ext-$name$i", minimum_size="$(1.5*r)cm") >> canvas
108
end
11-
cmd *= command_node(loc[1]+dx, loc[2]+dy, type, i pins, "$name$i", r) * "\n"
9+
Node(loc[1]+dx, loc[2]+dy, fill=ipins ? "red" : "black", draw="none", id="$name$i", minimum_size="$(r)cm") >> canvas
1210
end
1311
for e in edges(graph)
14-
cmd *= command_edge("$name$(e.src)", "$name$(e.dst)") * "\n"
12+
Line("$name$(e.src)", "$name$(e.dst)"; line_width=1.0) >> canvas
1513
end
16-
return cmd
17-
end
18-
19-
function command_node(x, y, type::Int, ispin::Bool, id, r)
20-
if type == 2
21-
return "\\node[fill=black,circle,radius=$(r)cm,inner sep=0cm, minimum size=$(r)cm] at ($x, $y) () {};\n\\node[draw=black,fill=none,circle,radius=$(1.5*r)cm,minimum size=$(1.5*r)cm,inner sep=0cm] at ($x, $y) ($id) {};"
22-
elseif abs(type) == 1
23-
if ispin
24-
color = "red"
25-
else
26-
color = "black"
27-
end
28-
return "\\node[fill=$color,circle,radius=$(r)cm,inner sep=0cm, minimum size=$(r)cm] at ($x, $y) ($id) {};"
29-
else
30-
error("")
31-
end
32-
end
33-
34-
function command_edge(i, j)
35-
return "\\draw[thick] ($i) -- ($j);"
3614
end
3715

3816
function viz_gadget(p::Pattern)
@@ -45,28 +23,22 @@ function viz_gadget(p::Pattern)
4523
xmid, ymid = Wx/2-0.5, Wy/2-0.5
4624
dx1, dy1 = xmid-Gx, 0
4725
dx2, dy2 = xmid+1, 0
48-
source_nodes = command_graph(locs1, g1, pin1, dx1, dy1, 0.3, "s")
49-
mapped_nodes = command_graph(locs2, g2, pin2, dx2, dy2, 0.3, "d")
50-
return """
51-
\\documentclass[crop,tikz]{standalone}% 'crop' is the default for v1.0, before it was 'preview'
52-
\\begin{document}
53-
\\begin{tikzpicture}[scale=0.8]
54-
\\useasboundingbox (-1,-1) rectangle ($Wx,$Wy);
55-
\\draw[step=1cm,gray,very thin] ($dx1,$(dy1)) grid ($(Gx+dx1-1),$(Gy+dy1-1));
56-
$source_nodes
57-
\\draw[step=1cm,gray,very thin] ($dx2,$(dy2)) grid ($(Gx+dx2-1),$(Gy+dy2-1));
58-
$mapped_nodes
59-
\\node at ($xmid, $ymid) {\$\\mathbf{\\rightarrow}\$};
60-
\\end{tikzpicture}
61-
62-
\\end{document}
63-
"""
26+
return canvas(; props=Dict("scale"=>"0.8")) do c
27+
BoundingBox(-1,Wx-1,-1,Wy-1) >> c
28+
Mesh(dx1, Gx+dx1-1, dy1, Gy+dy1-1; step="1cm", draw=rgbcolor!(c, 100,200,200), line_width=0.5) >> c
29+
command_graph!(c, locs1, g1, pin1, dx1, dy1, 0.3, "s")
30+
Mesh(dx2, Gx+dx2-1, dy2, Gy+dy2-1; step="1cm", draw=rgbcolor!(c, 200,100,100), line_width=0.03) >> c
31+
command_graph!(c, locs2, g2, pin2, dx2, dy2, 0.3, "d")
32+
PlainText(xmid, ymid, "\$\\mathbf{\\rightarrow}\$") >> c
33+
end
6434
end
6535

6636
function pattern2tikz(folder::String)
67-
for (p, sub) in UnitDiskMapping.crossing_ruleset
68-
open(joinpath(folder, sub*"-udg.tex"), "w") do f
37+
for p in crossing_ruleset
38+
open(joinpath(folder, string(typeof(p).name.name)*"-udg.tex"), "w") do f
6939
write(f, viz_gadget(p))
7040
end
7141
end
72-
end
42+
end
43+
44+
pattern2tikz(joinpath("_local"))

src/UnitDiskMapping.jl

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,6 @@ include("weighted.jl")
1717
include("simplifiers.jl")
1818
include("extracting_results.jl")
1919
include("pathdecomposition/pathdecomposition.jl")
20-
#include("shrinking/compressUDG.jl")
20+
include("tikz/tikz.jl")
2121

2222
end

src/gadgets.jl

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -19,20 +19,20 @@ abstract type Pattern end
1919
"""
2020
abstract type CrossPattern <: Pattern end
2121

22-
abstract type Node end
23-
struct SimpleNode{T} <: Node
22+
abstract type AbstractNode end
23+
struct SimpleNode{T} <: AbstractNode
2424
x::T
2525
y::T
2626
end
2727
SimpleNode(xy::Tuple{Int,Int}) = SimpleNode(xy...)
2828
SimpleNode(xy::Vector{Int}) = SimpleNode(xy...)
2929
getxy(p::SimpleNode) = (p.x, p.y)
3030
chxy(p::SimpleNode, loc) = SimpleNode(loc...)
31-
Base.iterate(p::Node, i) = Base.iterate((p.x, p.y), i)
32-
Base.iterate(p::Node) = Base.iterate((p.x, p.y))
33-
Base.length(p::Node) = 2
34-
Base.getindex(p::Node, i::Int) = i==1 ? p.x : (@assert i==2; p.y)
35-
offset(p::Node, xy) = chxy(p, getxy(p) .+ xy)
31+
Base.iterate(p::AbstractNode, i) = Base.iterate((p.x, p.y), i)
32+
Base.iterate(p::AbstractNode) = Base.iterate((p.x, p.y))
33+
Base.length(p::AbstractNode) = 2
34+
Base.getindex(p::AbstractNode, i::Int) = i==1 ? p.x : (@assert i==2; p.y)
35+
offset(p::AbstractNode, xy) = chxy(p, getxy(p) .+ xy)
3636

3737
export source_matrix, mapped_matrix
3838
function source_matrix(p::Pattern)
@@ -53,7 +53,7 @@ function mapped_matrix(p::Pattern)
5353
locs2matrix(m, n, locs)
5454
end
5555

56-
function locs2matrix(m, n, locs::AbstractVector{NT}) where NT <: Node
56+
function locs2matrix(m, n, locs::AbstractVector{NT}) where NT <: AbstractNode
5757
a = fill(empty(_cell_type(NT)), m, n)
5858
for loc in locs
5959
add_cell!(a, loc)
@@ -387,7 +387,7 @@ for T in [:RotatedGadget, :ReflectedGadget]
387387
end
388388

389389
for T in [:RotatedGadget, :ReflectedGadget]
390-
@eval _apply_transform(r::$T, node::Node, center) = chxy(node, _apply_transform(r, getxy(node), center))
390+
@eval _apply_transform(r::$T, node::AbstractNode, center) = chxy(node, _apply_transform(r, getxy(node), center))
391391
end
392392
function _apply_transform(r::RotatedGadget, loc::Tuple{Int,Int}, center)
393393
for _=1:r.n

src/simplifiers.jl

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@ function vertices_on_boundary(locs, m, n)
2626
findall(loc->loc[1]==1 || loc[1]==m || loc[2]==1 || loc[2]==n, locs)
2727
end
2828

29-
struct GridGraph{NT<:Node}
29+
struct GridGraph{NT<:AbstractNode}
3030
size::Tuple{Int,Int}
3131
nodes::Vector{NT}
3232
end

src/tikz/tikz.jl

Lines changed: 154 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,154 @@
1+
module TikzGraph
2+
export rgbcolor!, Node, Line, BoundingBox, Mesh, Canvas, >>, command, canvas, generate_standalone, StringElement, PlainText
3+
4+
const instance_counter = Ref(0)
5+
abstract type AbstractTikzElement end
6+
7+
struct Canvas
8+
header::String
9+
colors::Dict{String, Tuple{Int,Int,Int}}
10+
contents::Vector{AbstractTikzElement}
11+
props::Dict{String,String}
12+
end
13+
14+
function canvas(f; header="", colors=Dict{String,Tuple{Int,Int,Int}}(), props=Dict{String,String}())
15+
canvas = Canvas(header, colors, AbstractTikzElement[], props)
16+
f(canvas)
17+
return canvas
18+
end
19+
20+
Base.:(>>)(element::AbstractTikzElement, canvas::Canvas) = push!(canvas.contents, element)
21+
Base.:(>>)(element::String, canvas::Canvas) = push!(canvas.contents, StringElement(element))
22+
23+
function rgbcolor!(canvas::Canvas, red::Int, green::Int, blue::Int)
24+
instance_counter[] += 1
25+
colorname = "color$(instance_counter[])"
26+
canvas.colors[colorname] = (red,green,blue)
27+
return colorname
28+
end
29+
function generate_rgbcolor(name, red, green, blue)
30+
return "\\definecolor{$name}{RGB}{$red,$green,$blue}"
31+
end
32+
33+
struct StringElement <: AbstractTikzElement
34+
str::String
35+
end
36+
command(s::StringElement) = s.str
37+
38+
struct BoundingBox <: AbstractTikzElement
39+
xmin::Float64
40+
xmax::Float64
41+
ymin::Float64
42+
ymax::Float64
43+
end
44+
function command(box::BoundingBox)
45+
return "\\useasboundingbox ($(box.xmin),$(box.ymin)) rectangle ($(box.xmax-box.xmin),$(box.ymax-box.ymin));"
46+
end
47+
48+
struct Node <: AbstractTikzElement
49+
x::Float64
50+
y::Float64
51+
shape::String
52+
id::String
53+
text::String
54+
props::Dict{String,String}
55+
end
56+
57+
function Node(x, y;
58+
shape::String = "circle",
59+
id = string((instance_counter[] += 1; instance_counter[])),
60+
text::String = "",
61+
fill = "none",
62+
draw = "black",
63+
inner_sep = "0cm",
64+
minimum_size = "0.2cm",
65+
line_width = 0.03,
66+
kwargs...)
67+
props = build_props(;
68+
fill = fill,
69+
draw = draw,
70+
inner_sep = inner_sep,
71+
minimum_size = minimum_size,
72+
line_width = line_width,
73+
kwargs...)
74+
return Node(x, y, shape, id, text, props)
75+
end
76+
function build_props(; kwargs...)
77+
Dict([replace(string(k), "_"=>" ")=>string(v) for (k,v) in kwargs])
78+
end
79+
80+
function command(node::Node)
81+
return "\\node[$(node.shape), $(command(node.props))] at ($(node.x), $(node.y)) ($(node.id)) {$(node.text)};"
82+
end
83+
84+
struct Mesh <: AbstractTikzElement
85+
xmin::Float64
86+
xmax::Float64
87+
ymin::Float64
88+
ymax::Float64
89+
props::Dict{String,String}
90+
end
91+
92+
function Mesh(xmin, xmax, ymin, ymax; step="1.0cm", draw="gray", line_width=0.03, kwargs...)
93+
Mesh(xmin, xmax, ymin, ymax, build_props(; step=step, draw=draw, line_width=line_width, kwargs...))
94+
end
95+
function command(grid::Mesh)
96+
return "\\draw[$(command(grid.props))] ($(grid.xmin),$(grid.ymin)) grid ($(grid.xmax),$(grid.ymax));"
97+
end
98+
99+
struct Line <: AbstractTikzElement
100+
src::String
101+
dst::String
102+
controls::Vector{Int}
103+
props::Dict{String,String}
104+
end
105+
106+
function Line(src, dst; controls=Int[], line_width = "0.03", kwargs...)
107+
Line(string(src), string(dst), controls, build_props(; line_width=line_width, kwargs...))
108+
end
109+
Line(src::Node, dst::Node; kwargs...) = Line(src.id, dst.id)
110+
111+
function command(edge::Line)
112+
head = "\\draw[$(command(edge.props))]"
113+
if isempty(edge.controls)
114+
return "$head ($(edge.src)) -- ($(edge.dst));"
115+
else
116+
return "$head ($(edge.src)) .. controls $(join(["($c)" for c in edge.controls], " and ")) .. ($(edge.dst));"
117+
end
118+
end
119+
120+
struct PlainText <: AbstractTikzElement
121+
x::Float64
122+
y::Float64
123+
text::String
124+
props::Dict{String,String}
125+
end
126+
function PlainText(x, y, text; kwargs...)
127+
PlainText(x, y, text, build_props(; kwargs...))
128+
end
129+
function command(text::PlainText)
130+
"\\node[$(command(text.props))] at ($(text.x), $(text.y)) {$(text.text)};"
131+
end
132+
133+
function command(node::Dict) # properties
134+
return join(["$k=$v" for (k,v) in node], ", ")
135+
end
136+
137+
function generate_standalone(header::String, props::Dict, content::String)
138+
return """
139+
\\documentclass[crop,tikz]{standalone}
140+
$(header)
141+
\\begin{document}
142+
\\begin{tikzpicture}[$(command(props))]
143+
$content
144+
\\end{tikzpicture}
145+
\\end{document}
146+
"""
147+
end
148+
generate_standalone(canvas::Canvas) = generate_standalone(canvas.header, canvas.props, join([[generate_rgbcolor(k,v...) for (k,v) in canvas.colors]..., command.(canvas.contents)...], "\n"))
149+
150+
function Base.write(io::IO, canvas::Canvas)
151+
write(io, generate_standalone(canvas))
152+
end
153+
154+
end

src/weighted.jl

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,7 @@ function Base.show(io::IO, x::WeightedCell)
3232
end
3333
Base.show(io::IO, ::MIME"text/plain", cl::WeightedCell) = Base.show(io, cl)
3434

35-
struct WeightedNode{T,WT} <: Node
35+
struct WeightedNode{T,WT} <: AbstractNode
3636
x::T
3737
y::T
3838
weight::WT

test/runtests.jl

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,3 +28,7 @@ end
2828
@testset "weighted" begin
2929
include("weighted.jl")
3030
end
31+
32+
@testset "tikz" begin
33+
include("tikz/tikz.jl")
34+
end

test/tikz/tikz.jl

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
using UnitDiskMapping.TikzGraph, Test
2+
3+
@testset "commands" begin
4+
n = Node(0.2, 0.5)
5+
@test command(n) isa String
6+
m = Node(0.6, 0.5)
7+
@test command(n) isa String
8+
l = Line(m, n)
9+
@test command(n) isa String
10+
b = BoundingBox(0, 10, 0, 10)
11+
@test command(b) isa String
12+
g = Mesh(0, 10, 0, 10)
13+
@test command(g) isa String
14+
s = StringElement("jajaja")
15+
@test command(s) == "jajaja"
16+
s = PlainText(20.0, 3.0, "jajaja")
17+
@test command(s) isa String
18+
end
19+
20+
@testset "canvas" begin
21+
res = canvas() do c
22+
Node(0.2, 0.5; draw=rgbcolor!(c, 21, 42, 36)) >> c
23+
"jajaja" >> c
24+
end
25+
@test res isa Canvas
26+
@test generate_standalone(res) isa String
27+
write("test.tex", res)
28+
@test isfile("test.tex")
29+
rm("test.tex")
30+
end

0 commit comments

Comments
 (0)