diff --git a/build/ludus.mjs b/build/ludus.mjs
index 2296127..659dbe1 100644
--- a/build/ludus.mjs
+++ b/build/ludus.mjs
@@ -4,7 +4,10 @@ const mod = await init()
let result = null
+let code = null
+
export function run (source) {
+ code = source
const output = mod.ludus(source).value
result = JSON.parse(output)
return result
@@ -20,10 +23,6 @@ export function turtle_commands () {
return result.io.turtle.data
}
-export function svg () {
- // TODO
-}
-
const turtle_init = {
position: [0, 0],
heading: 0,
@@ -154,7 +153,7 @@ function command_to_state (prev_state, curr_command) {
let color = curr_command.slice(1)
if (color.lengh = 1) color = color[0]
background_color = color
- return
+ return prev_state
}
}
}
@@ -211,12 +210,106 @@ function turn_to_rad (heading) {
return heading * 2 * Math.PI
}
-function render_turtle (state, calls) {
+function turn_to_deg (heading) {
+ return (heading * 360) + 180
+}
+
+function svg_render_line (prev, curr) {
+ if (!prev.pendown) return ""
+ if (are_eq(prev.position, curr.position)) return ""
+ const {position: [x1, y1], pencolor, penwidth} = prev
+ const {position: [x2, y2]} = curr
+ const [r, g, b, a] = resolve_color(pencolor)
+ return `
+
+ `
+}
+
+function escape_svg (svg) {
+ return svg
+ .replace(/&/g, "&")
+ .replace(//g, ">")
+ .replace(/"/g, """)
+ .replace(/'/g, "'")
+}
+
+function svg_render_path (states) {
+ const path = []
+ for (let i = 1; i < states.length; ++i) {
+ const prev = states[i - 1]
+ const curr = states[i]
+ path.push(svg_render_line(prev, curr))
+ }
+ return path.join("")
+}
+
+function svg_render_turtle (state) {
+ if (!state.visible) return ""
+ const [fr, fg, fb, fa] = turtle_color
+ const fill_alpha = fa/255
+ const {heading, pencolor, position: [x, y], pendown, penwidth} = state
+ const origin = [0, turtle_radius]
+ const [x1, y1] = origin
+ const [x2, y2] = rotate(origin, turtle_angle)
+ const [x3, y3] = rotate(origin, -turtle_angle)
+ const [pr, pg, pb, pa] = resolve_color(pencolor)
+ const pen_alpha = pa/255
+ const ink = pendown ? `` : ""
+ return `
+
+
+ ${ink}
+
+ `
+}
+
+export function svg (commands) {
+ const states = [turtle_init]
+ commands.reduce((prev_state, command) => {
+ const new_state = command_to_state(prev_state, command)
+ states.push(new_state)
+ return new_state
+ }, turtle_init)
+ const {maxX, maxY, minX, minY} = states.reduce((accum, {position: [x, y]}) => {
+ accum.maxX = Math.max(accum.maxX, x)
+ accum.maxY = Math.max(accum.maxY, y)
+ accum.minX = Math.min(accum.minX, x)
+ accum.minY = Math.min(accum.minY, y)
+ return accum
+
+ }, {maxX: 0, maxY: 0, minX: 0, minY: 0})
+ const [r, g, b, a] = resolve_color(background_color)
+ const view_width = maxX - minX
+ const view_height = maxY - minY
+ const margin = Math.max(view_width, view_height) * 0.1
+ const x1 = minX - margin
+ const y1 = minY - margin
+ const x2 = maxX + margin
+ const y2 = maxY + margin
+ const path = svg_render_path(states)
+ const turtle = svg_render_turtle(states[states.length - 1])
+ return `
+
+ `
+}
+
+function p5_render_turtle (state, calls) {
if (!state.visible) return
calls.push(["push"])
const [r, g, b, a] = turtle_color
calls.push(["fill", r, g, b, a])
- const {heading, pencolor, position: [x, y], pendown} = state
+ const {heading, pencolor, position: [x, y], pendown, penwidth} = state
const origin = [0, turtle_radius]
const [x1, y1] = origin
const [x2, y2] = rotate(origin, turtle_angle)
@@ -229,6 +322,7 @@ function render_turtle (state, calls) {
calls.push(["vertex", x2, y2])
calls.push(["vertex", x3, y3])
calls.push(["endShape"])
+ calls.push(["strokeWeight", penwidth])
calls.push(["stroke", ...resolve_color(pencolor)])
if (pendown) calls.push(["line", 0, 0, x1, y1])
calls.push(["pop"])
@@ -252,6 +346,7 @@ export function p5_calls (commands) {
}
}
p5_calls[0] = ["background", ...resolve_color(background_color)]
- render_turtle(states[states.length - 1], p5_calls)
+ p5_render_turtle(states[states.length - 1], p5_calls)
return p5_calls
}
+
diff --git a/build/svg_test.mjs b/build/svg_test.mjs
new file mode 100644
index 0000000..cb9f4bb
--- /dev/null
+++ b/build/svg_test.mjs
@@ -0,0 +1,11 @@
+import {run, svg} from "./ludus.mjs"
+
+const code = `
+ forward! (100)
+ right! (0.25)
+ forward! (100)
+`
+
+const result = run(code)
+
+console.log(svg(result.io.turtle.data))
diff --git a/build/svg_test.svg b/build/svg_test.svg
new file mode 100644
index 0000000..23e55ab
--- /dev/null
+++ b/build/svg_test.svg
@@ -0,0 +1,26 @@
+
+
+
diff --git a/build/test.svg b/build/test.svg
new file mode 100644
index 0000000..af2ad10
--- /dev/null
+++ b/build/test.svg
@@ -0,0 +1,18 @@
+
+
+