import {eq_vect, eq_color, resolve_color, turtle_color, turtle_radius, turtle_angle, turn_to_rad, turtle_init, command_to_state, background_color, rotate, last} from "./turtle_geometry.js" function states_to_call (prev, curr) { const calls = [] // whose state should we use? // pen states will only differ on more than one property // if we use `loadstate` // my sense is `prev`, but that may change if (prev.pendown && !eq_vect(prev.position, curr.position)) { calls.push(["line", prev.position[0], prev.position[1], curr.position[0], curr.position[1]]) } if (!eq_color(curr.pencolor, prev.pencolor)) { calls.push(["stroke", ...resolve_color(curr.pencolor)]) } if (curr.penwidth !== prev.penwidth) { calls.push(["strokeWeight", curr.penwidth]) } return calls } function p5_call_root () { return [ ["background", ...resolve_color(background_color)], ["push"], ["rotate", Math.PI], ["scale", -1, 1], ["stroke", ...resolve_color(turtle_init.pencolor)], ] } 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, 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) calls.push(["translate", x, y]) // need negative turtle rotation with the other p5 translations calls.push(["rotate", -turn_to_rad(heading)]) calls.push(["noStroke"]) calls.push(["beginShape"]) calls.push(["vertex", x1, y1]) 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"]) return calls } export function p5 (commands) { const all_states = {} for (const command of commands) { const [turtle_id, _, this_command] = command let stack = all_states[turtle_id] if (!stack) { const new_stack = [turtle_init] all_states[turtle_id] = new_stack stack = new_stack } let prev_state = last(all_states[turtle_id]) const new_state = command_to_state(prev_state, this_command) all_states[turtle_id].push(new_state) } const [r, g, b, _] = resolve_color(background_color) if ((r + g + b)/3 > 128) turtle_color = [0, 0, 0, 150] const p5_calls = [...p5_call_root()] for (const states of Object.values(all_states)) { console.log(states) for (let i = 1; i < states.length; ++i) { const prev = states[i - 1] const curr = states[i] const calls = states_to_call(prev, curr) for (const call of calls) { p5_calls.push(call) } } p5_calls[0] = ["background", ...resolve_color(background_color)] p5_render_turtle(states[states.length - 1], p5_calls) } p5_calls.push(["pop"]) return p5_calls }