Skip to content

Commit 1f5ceeb

Browse files
jkseppantarleb
authored andcommitted
diagram-generator: Asymptote graphics
1 parent 1892136 commit 1f5ceeb

File tree

2 files changed

+122
-9
lines changed

2 files changed

+122
-9
lines changed

diagram-generator/diagram-generator.lua

+57-6
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,10 @@ local dot_path = os.getenv("DOT") or "dot"
5656
-- document, use the meta data to define the key "pdflatex_path".
5757
local pdflatex_path = os.getenv("PDFLATEX") or "pdflatex"
5858

59+
-- The asymptote path. There is also the metadata variable
60+
-- "asymptote_path".
61+
local asymptote_path = os.getenv ("ASYMPTOTE") or "asy"
62+
5963
-- The default format is SVG i.e. vector graphics:
6064
local filetype = "svg"
6165
local mimetype = "image/svg+xml"
@@ -100,6 +104,9 @@ function Meta(meta)
100104
pdflatex_path = stringify(
101105
meta.pdflatex_path or meta.pdflatexPath or pdflatex_path
102106
)
107+
asymptote_path = stringify(
108+
meta.asymptote_path or meta.asymptotePath or asymptote_path
109+
)
103110
end
104111

105112
-- Call plantuml.jar with some parameters (cf. PlantUML help):
@@ -135,11 +142,10 @@ local tikz_template = [[
135142
\end{document}
136143
]]
137144

138-
--- Returns a function which takes the filename of a PDF and a
139-
-- target filename, and writes the input as the given format.
140-
-- Returns `nil` if conversion into the target format is not
141-
-- possible.
142-
local function convert_from_pdf(filetype)
145+
-- Returns a function which takes the filename of a PDF or SVG file
146+
-- and a target filename, and writes the input as the given format.
147+
-- Returns `nil` if conversion into the target format is not possible.
148+
local function convert_with_inkscape(filetype)
143149
-- Build the basic Inkscape command for the conversion
144150
local inkscape_output_args
145151
if filetype == 'png' then
@@ -165,7 +171,7 @@ end
165171

166172
--- Compile LaTeX with Tikz code to an image
167173
local function tikz2image(src, filetype, additional_packages)
168-
local convert = convert_from_pdf(filetype)
174+
local convert = convert_with_inkscape(filetype)
169175
-- Bail if there is now known way from PDF to the target format.
170176
if not convert then
171177
error(string.format("Don't know how to convert pdf to %s.", filetype))
@@ -248,6 +254,50 @@ local function py2image(code, filetype)
248254
return imgData
249255
end
250256

257+
--
258+
-- Asymptote
259+
--
260+
261+
local function asymptote(code, filetype)
262+
local convert
263+
if filetype ~= 'svg' and filetype ~= 'png' then
264+
error(string.format("Conversion to %s not implemented", filetype))
265+
end
266+
return with_temporary_directory(
267+
"asymptote",
268+
function(tmpdir)
269+
return with_working_directory(
270+
tmpdir,
271+
function ()
272+
local asy_file = "pandoc_diagram.asy"
273+
local svg_file = "pandoc_diagram.svg"
274+
local f = io.open(asy_file, 'w')
275+
f:write(code)
276+
f:close()
277+
278+
pandoc.pipe(asymptote_path, {"-f", "svg", "-o", "pandoc_diagram", asy_file}, "")
279+
280+
local r
281+
if filetype == 'svg' then
282+
r = io.open(svg_file, 'rb')
283+
else
284+
local png_file = "pandoc_diagram.png"
285+
convert_with_inkscape("png")(svg_file, png_file)
286+
r = io.open(png_file, 'rb')
287+
end
288+
289+
local img_data
290+
if r then
291+
img_data = r:read("*all")
292+
r:close()
293+
else
294+
error("could not read asymptote result file")
295+
end
296+
return img_data
297+
end)
298+
end)
299+
end
300+
251301
-- Executes each document's code block to find matching code blocks:
252302
function CodeBlock(block)
253303

@@ -260,6 +310,7 @@ function CodeBlock(block)
260310
graphviz = graphviz,
261311
tikz = tikz2image,
262312
py2image = py2image,
313+
asymptote = asymptote,
263314
}
264315

265316
-- Check if a converter exists for this block. If not, return the block

diagram-generator/sample.md

+65-3
Original file line numberDiff line numberDiff line change
@@ -2,9 +2,9 @@
22

33
## Introduction
44
This Lua filter is used to create images with or without captions from code
5-
blocks. Currently PlantUML, Graphviz, Ti*k*Z and Python can be processed.
6-
This document also serves as a test document, which is why the subsequent
7-
test diagrams are integrated in every supported language.
5+
blocks. Currently PlantUML, Graphviz, Ti*k*Z, Asymptote, and Python can be
6+
processed. This document also serves as a test document, which is why the
7+
subsequent test diagrams are integrated in every supported language.
88

99
## Prerequisites
1010
To be able to use this Lua filter, the respective external tools must be
@@ -211,6 +211,66 @@ key `activate_python_path` to `c:\ProgramData\Anaconda3\Scripts\activate.bat`.
211211

212212
Pandoc will activate this Python environment and starts Python with your code.
213213

214+
## Asymptote
215+
[Asymptote](https://asymptote.sourceforge.io/) is a graphics
216+
language inspired by Metapost. To use Asymptote, you will need to
217+
install the software itself, a TeX distribution such as
218+
[TeX Live](https://www.tug.org/texlive/), and
219+
[dvisvgm](https://dvisvgm.de/), which may be included in the TeX
220+
distribution.
221+
222+
If png output is required (such as for the `docx`, `pptx` and `rtf`
223+
output formats) Inkscape must be installed. See the Ti*k*Z section
224+
for details.
225+
226+
Ensure that the Asymptote `asy` binary is in the path, or point
227+
the environment variable `ASYMPTOTE` or the metadata variable
228+
`asymptotePath` to the full path name. Asymptote calls the various
229+
TeX utilities and dvipdfm, so you will need to configure Asymptote
230+
so that it finds them.
231+
232+
```{.asymptote caption="This is an image, created by **Asymptote**."}
233+
size(5cm);
234+
include graph;
235+
236+
pair circumcenter(pair A, pair B, pair C)
237+
{
238+
pair P, Q, R, S;
239+
P = (A+B)/2;
240+
Q = (B+C)/2;
241+
R = rotate(90, P) * A;
242+
S = rotate(90, Q) * B;
243+
return extension(P, R, Q, S);
244+
}
245+
246+
pair incenter(pair A, pair B, pair C)
247+
{
248+
real a = abs(angle(C-A)-angle(B-A)),
249+
b = abs(angle(C-B)-angle(A-B)),
250+
c = abs(angle(A-C)-angle(B-C));
251+
return (sin(a)*A + sin(b)*B + sin(c)*C) / (sin(a)+sin(b)+sin(c));
252+
}
253+
254+
real dist_A_BC(pair A, pair B, pair C)
255+
{
256+
real det = cross(B-A, C-A);
257+
return abs(det/abs(B-C));
258+
}
259+
260+
pair A = (0, 0), B = (5, 0), C = (3.5, 4),
261+
O = circumcenter(A, B, C),
262+
I = incenter(A, B, C);
263+
dot(A); dot(B); dot(C); dot(O, blue); dot(I, magenta);
264+
draw(A--B--C--cycle, linewidth(2));
265+
draw(Circle(O, abs(A-O)), blue+linewidth(1.5));
266+
draw(Circle(I, dist_A_BC(I, A, B)), magenta+linewidth(1.5));
267+
label("$A$", A, SW);
268+
label("$B$", B, SE);
269+
label("$C$", C, NE);
270+
label("$O$", O, W);
271+
label("$I$", I, E);
272+
```
273+
214274
## How to run pandoc
215275
This section will show, how to call Pandoc in order to use this filter with
216276
meta keys. The following command assume, that the filters are stored in the
@@ -232,6 +292,7 @@ All available environment variables:
232292
- `JAVA_HOME` e.g. `c:\Program Files\Java\jre1.8.0_201`; Default: n/a
233293
- `DOT` e.g. `c:\ProgramData\chocolatey\bin\dot.exe`; Default: `dot`
234294
- `PDFLATEX` e.g. `c:\Program Files\MiKTeX 2.9\miktex\bin\x64\pdflatex.exe`; Default: `pdflatex`
295+
- `ASYMPTOTE` e.g. `c:\Program Files\Asymptote\asy`; Default: `asy`
235296

236297
All available meta keys:
237298

@@ -242,3 +303,4 @@ All available meta keys:
242303
- `java_path`
243304
- `dot_path`
244305
- `pdflatex_path`
306+
- `asymptote_path`

0 commit comments

Comments
 (0)