module Popup using LinearAlgebra function read_model(filename) read_numbers(str, numtype) = map(s -> parse(numtype, s), split(str)) vertices = [] faces = [] for line in eachline(filename) if line[1] == 'v' push!(vertices, read_numbers(line[2:end], Float64)) elseif line[1] == 'f' push!(faces, read_numbers(line[2:end], Int)) end end (vertices, faces) end """ write_popup(model, filename, scaling, translation) Writes an EPS file to the given `filename` based on `model`, which is a pair of `(vertices, faces)`. Scaling and translation are optional. The model is assumed to have one face at `Z=0`; the paper is folded at `Y=0`. only faces looking in the positive `Y` and `Z` directions are drawn. Except for the scaling/translation, coordinates are transformed to `[x, y - z]`. """ function write_popup(model, filename, scaling = 1, translation = [0, 0]) transform(p) = [p[1], p[2] - p[3]] * scaling + translation vertices, faces = model open(filename, "w") do f println(f, "%!PS-Adobe EPSF-3.0") println(f, "%%BoundingBox: 0 0 595 842") println(f, "newpath") p1 = transform([-1000, 0, 0]) p2 = transform([1000, 0, 0]) println(f, "$(p1[1]) $(p1[2]) moveto") println(f, "$(p2[1]) $(p2[2]) lineto") println(f, "stroke") for face in faces u = vertices[face[2]] - vertices[face[1]] v = vertices[face[3]] - vertices[face[2]] d = normalize!(cross(u, v)) if norm(d - [0, 1, 0]) < 1e-5 || norm(d - [0, 0, 1]) < 1e-5 n = length(face) println(f, "newpath") for i in 1:n p1 = transform(vertices[face[i]]) p2 = transform(vertices[face[mod1(i+1,n)]]) println(f, "$(p1[1]) $(p1[2]) moveto") println(f, "$(p2[1]) $(p2[2]) lineto") end println(f, "stroke") end end println(f, "showpage") end end end # module