git.haldean.org plotter / f9ea0c7
support for bezier curves via C pathspec Haldean Brown 4 years ago
4 changed file(s) with 57 addition(s) and 23 deletion(s). Raw diff Collapse all Expand all
0 (load "package.lisp")
1
2 (in-package :so3-cnc)
3
4 (defun vec+ (v1 v2) (cons (+ (car v1) (car v2)) (+ (cdr v1) (cdr v2))))
5 (defun vec* (s v) (cons (* s (car v)) (* s (cdr v))))
6
7 (defun eval-bezier (theta pts)
8 (if (= 1 (length pts))
9 (first pts)
10 (eval-bezier theta (loop for x in pts
11 for y in (rest pts)
12 collect (vec+ (vec* (- 1 theta) x) (vec* theta y))))))
13
14 (defun eval-bezier-cubic (theta p0 p1 p2 p3)
15 (eval-bezier theta (list p0 p1 p2 p3)))
0 (defpackage :so3-cnc
1 (:use :common-lisp)
2 (:export
3 :init
4 :disable-motors
5 :set-zero
6 :run-gcode-file))
7
0 (load "package.lisp")
81 (in-package :so3-cnc)
92
103 (ql:quickload :alexandria)
0 (defpackage :so3-cnc
1 (:use :common-lisp)
2 (:export
3 :init
4 :disable-motors
5 :set-zero
6 :run-gcode-file))
7
0 (load "cnc.lisp")
0 (load "package.lisp")
1 (load "bezier.lisp")
12 (in-package :so3-cnc)
23
34 (ql:quickload :alexandria)
5152 )))
5253
5354 (defstruct (svg-machine (:conc-name svgm-))
54 (current '(0 0)) ; current position
55 (current '(0 . 0)) ; current position
5556 (last-start nil) ; last path start position
5657 (gcode '())
5758 )
5859
5960 (defun to-abs-xy (svgm mode pairs)
6061 (let* ((cur-xy (svgm-current svgm))
61 (cur-x (first cur-xy))
62 (cur-y (second cur-xy)))
62 (cur-x (car cur-xy))
63 (cur-y (cdr cur-xy)))
6364 (cons mode (loop for i from 1 to (length pairs)
6465 for j in pairs
6566 collect (+ j (if (= (mod i 2) 1) cur-x cur-y))
9394 )))
9495
9596 (defun gcode-goto (xy &key (mode 1))
96 (list (cons :G mode) (cons :X (first xy)) (cons :Y (second xy))))
97 (list (cons :G mode) (cons :X (car xy)) (cons :Y (cdr xy))))
98
99 (defun push-polyline (svgm xform pts)
100 (reduce (lambda (svgm p) (push-stanza svgm (list #\L (car p) (cdr p)) xform)) pts :initial-value svgm))
101
102 (setf *theta-steps* '(0.00 0.05 0.10 0.15 0.20 0.25 0.30 0.35 0.40 0.45 0.50 0.55 0.60 0.65 0.70 0.75 0.80 0.85 0.90 0.95 1.00))
97103
98104 (defun push-stanza (svgm sraw xform)
99105 "Creates and returns a new svg machine that includes the result of interpreting the given stanza"
105111 (gcode (svgm-gcode svgm))
106112 )
107113 (alexandria:switch (mode)
108 (#\M (make-svg-machine
109 :current args :last-start args
110 :gcode (append gcode (list '((:G . 0) (:Z . 1))
111 (gcode-goto args :mode 0)
112 '((:G . 0) (:Z . -1))))
113 ))
114 (#\L (make-svg-machine
115 :current args :last-start ls
116 :gcode (append gcode (list (gcode-goto args)))
117 ))
114 (#\M (let ((p (cons (first args) (second args))))
115 (make-svg-machine
116 :current p :last-start p
117 :gcode (append gcode (list '((:G . 0) (:Z . 1))
118 (gcode-goto p :mode 0)
119 '((:G . 0) (:Z . -1))))
120 )))
121 (#\L (let ((p (cons (first args) (second args))))
122 (make-svg-machine
123 :current p :last-start (if (null ls) cur-xy ls)
124 :gcode (append gcode (list (gcode-goto p)))
125 )))
126 (#\C (push-polyline svgm xform
127 (loop for theta in *theta-steps*
128 collect (eval-bezier-cubic
129 theta
130 cur-xy
131 (cons (first args) (second args))
132 (cons (third args) (fourth args))
133 (cons (fifth args) (sixth args))
134 ))))
118135 (#\Z (progn
119136 (when (null ls)
120137 (error "got Z (close path) when there's no current path"))