Mercurial > lasercutter
comparison src/laser/rasterize.clj @ 16:52f544d05414
I think I've made it worse....
author | Robert McIntyre <rlm@mit.edu> |
---|---|
date | Sun, 29 Aug 2010 23:40:39 -0400 |
parents | 8ad629298649 |
children | 962e223bab0d |
comparison
equal
deleted
inserted
replaced
15:8ad629298649 | 16:52f544d05414 |
---|---|
3 image-utils | 3 image-utils |
4 map-utils] | 4 map-utils] |
5 [clojure.contrib | 5 [clojure.contrib |
6 [str-utils :only [str-join re-gsub]] | 6 [str-utils :only [str-join re-gsub]] |
7 [seq :only [indexed]] | 7 [seq :only [indexed]] |
8 [math]]) | 8 [math] |
9 [def] | |
10 ]) | |
9 (:import [ij ImagePlus IJ])) | 11 (:import [ij ImagePlus IJ])) |
10 | 12 |
11 ;(import '(java.io File)) | 13 ;(import '(java.io File)) |
12 ;(import '(org.apache.commons.io FileUtils)) | 14 ;(import '(org.apache.commons.io FileUtils)) |
13 ;(import '(javax.imageio ImageIO) ) | 15 ;(import '(javax.imageio ImageIO) ) |
15 | 17 |
16 (set! *print-length* 20) | 18 (set! *print-length* 20) |
17 (def feed 120) | 19 (def feed 120) |
18 (def dpi [500, 500]) | 20 (def dpi [500, 500]) |
19 | 21 |
22 (def paramaters {:x-dpi 500 :y-dpi 500 :margin 0 :x-offset 0 :y-offset 0}) | |
20 | 23 |
21 ;;; this process is divided into two tasks, | 24 ;;; this process is divided into two tasks, |
22 ;;; creating the raster g-code, which sweeps back and forth | 25 ;;; creating the raster g-code, which sweeps back and forth |
23 ;;; and creating the gmask, which turns the laser on and off. | 26 ;;; and creating the gmask, which turns the laser on and off. |
24 | 27 |
25 | 28 |
26 ;;; we'll be using frame-hashes, which represent picutres as | 29 ;;; we'll be using frame-hashes, which represent picutres as |
27 ;;; a 3D vector field over 2D space, with the vectors representing | 30 ;;; a 3D vector field over 2D space, with the vectors representing |
28 ;;; the rgb values at that particulat point. | 31 ;;; the rgb values at that particular point. |
29 | 32 |
30 (defn select-row | 33 (defn select-row |
31 "returns a frame hash that is just a single line at the chosen y" | 34 "returns a frame hash that is just a single line at the chosen y" |
32 [y window] | 35 [y window] |
33 (filter-keys (comp (partial = y) last) window)) | 36 (reduce |
37 (fn [old-map number] | |
38 (let [pixel (get window [number y] nil)] | |
39 (if-not (nil? pixel) | |
40 (into old-map {[number y] pixel}) | |
41 old-map))) | |
42 {} | |
43 (range (width window)))) | |
34 | 44 |
35 (defn make-rows [pic] | 45 (defn make-rows [pic] |
36 (map (partial sort #(< (first %1) (first %2))) | 46 (map (partial sort #(< (first %1) (first %2))) |
37 (partition-by last | 47 (partition-by last |
38 (sort (fn [[x1 y1][x2 y2]] (> y2 y1)) | 48 (sort (fn [[x1 y1][x2 y2]] (> y2 y1)) |
39 (map first (filter-vals (partial = black) pic)))))) | 49 (map first (filter-vals (partial = black) pic)))))) |
40 | 50 |
41 | |
42 ;;; generate rastering g-code | 51 ;;; generate rastering g-code |
43 | 52 |
44 (defn raster-preamble [] | 53 (defn raster-preamble [] |
45 (str-join \newline | 54 (str-join \newline ["M63 P0\nG61" (str "F" feed) "M101" "M3 S1\n"])) |
46 ["M63 P0\nG61" | |
47 (str "F" feed) | |
48 "M101" | |
49 "M3 S1\n"])) | |
50 | 55 |
51 (defn raster-epilogue [] | 56 (defn raster-epilogue [] |
52 (str-join \newline | 57 (str-join \newline ["M63 P0" "M5" "M2\n"])) |
53 ["M63 P0" | 58 |
54 "M5" | 59 (defn raster-comment |
55 "M2\n"])) | 60 "wrap a statement in PARENTHENSIS to make it a comment in gcode. |
56 | 61 parenthesis themselves aren't allowed in comments. |
57 (defn raster-comment [string] | 62 Oh the humanity!!" |
63 [string] | |
58 (str "(" (re-gsub #"[()]" "" string) ")")) | 64 (str "(" (re-gsub #"[()]" "" string) ")")) |
59 | 65 |
60 | 66 (defn rows |
61 ;this is a sequence of rows | 67 "creates a sequence of one dimensional vector fields which |
62 | 68 represent the rows of a picture" |
63 ;(defn span [row] | 69 [pic] |
64 ; (let [sorted-row (sort #(< (first %1) (first %2)) row)] | 70 (let [non-empty-rows (apply sorted-set (map (comp last first) pic))] |
65 ; (vector (first sorted-row) (last sorted-row)))) | 71 (pmap (fn [n] (select-row n pic)) non-empty-rows))) |
66 | 72 |
67 | |
68 | |
69 (defn row->gcode [[x-dpi y-dpi] forward? row] | |
70 | 73 |
71 (let [[x1 y1] (if forward? (last row) (first row)) | 74 |
72 [x2 y2] (if forward? (first row) (last row))] | 75 |
76 | |
77 (defn row->gcode [{:keys [x-dpi y-dpi margin x-offset y-offset]} row] | |
78 (let [pixels (keys row) | |
79 x2 0 | |
80 [_ y2] (first pixels) | |
81 [_ y1] (first pixels) | |
82 x1 533] | |
83 | |
84 ;(let [ordered-row | |
85 ; (sort-map-by (fn [[x1 _] [x2 _]] (> x2 x1)) row)] | |
73 | 86 |
74 | 87 (let [;[x1 y1] (last (keys ordered-row)) |
75 ; (let [[x1 y1] (first row) | 88 ;[x2 y2] (first (keys ordered-row)) |
76 ; [x2 y2] (last row) | 89 [x1 y1 x2 y2] (if (odd? y1) [x2 y2 x1 y1] [x1 y1 x2 y2])] |
77 ; x2 (+ x2 (* x-dpi 0.318))] | 90 |
78 | 91 (str (format "G0 X%.3f Y%.3f\n" |
79 | 92 (float (* x1 (/ x-dpi))) |
80 ; (println x2) | 93 (float (* y1 (/ y-dpi)))) |
81 (str (format "G0 X%.3f Y%.3f\n" | 94 |
82 (float (* x1 (/ x-dpi))) | 95 (format "G1 X%.3f Y%.3f\n" |
83 (float (* y1 (/ y-dpi)))) | 96 (float (* x2 (/ x-dpi))) |
84 | 97 (float (* y2 (/ y-dpi)))))))) |
85 (format "G1 X%.3f Y%.3f\n" | 98 |
86 (float (* x2 (/ x-dpi))) | 99 |
87 (float (* y2 (/ y-dpi))))))) | 100 (defn pic->gcode [paramaters pic] |
88 | 101 (reduce (fn [gcode current-height] |
102 (let [current-row (select-row current-height pic)] | |
103 (if-not (empty? current-row) | |
104 (let [new-code (row->gcode paramaters current-row)] | |
105 (println new-code) | |
106 (str gcode new-code)) | |
107 gcode))) | |
108 "" | |
109 (range (height pic)))) | |
110 | |
111 | |
112 ;(defn pic->gcode [paramaters pic] | |
113 | |
89 | 114 |
90 (defn generate-gcode [pic] | 115 (defn generate-gcode [pic] |
91 (str (raster-preamble) | 116 (str (raster-preamble) |
92 (str-join "" | 117 (row->gcode paramaters pic) |
93 (map | 118 (raster-epilogue))) |
94 (fn [[index row]] | |
95 (row->gcode dpi (even? index) row)) | |
96 (indexed (make-rows pic)))) | |
97 (raster-epilogue))) | |
98 | 119 |
99 | 120 |
100 | 121 |
101 | 122 |
102 | 123 |
184 pic) | 205 pic) |
185 | 206 |
186 (defn update-state [] | 207 (defn update-state [] |
187 (def sing "/home/r/kevin/sing.png") | 208 (def sing "/home/r/kevin/sing.png") |
188 (def pic (frame-hash (ImagePlus. sing))) | 209 (def pic (frame-hash (ImagePlus. sing))) |
189 (def pic (b&w pic))) | 210 (def pic (b&w pic)) |
190 | 211 (def pic (filter-vals (partial = black) pic))) |
191 (defn compare-gen-fn [n f cmp] | 212 |
213 (defn compare-gen-fn | |
214 ([n f cmp] | |
192 (let [theirs (re-split #"\n" (slurp cmp)) | 215 (let [theirs (re-split #"\n" (slurp cmp)) |
193 ours (re-split #"\n" (f pic))] | 216 ours (re-split #"\n" (f pic))] |
194 (println (format "%1$-25s%2$s" "OURS" "THEIRS")) | 217 (println (format "%1$-25s%2$s" "OURS" "THEIRS")) |
195 (println "_______________________________________") | 218 (println "_______________________________________") |
196 (dorun (map (fn [[us them]] (println | 219 (dorun (map (fn [[us them]] (println |
197 (format "%1$-25s%2$s" us them))) | 220 (format "%1$-25s%2$s" us them))) |
198 (take n (partition 2 (interleave ours theirs))))))) | 221 (take n (partition 2 (interleave ours theirs)))))))) |
199 | 222 |
200 (defn compare-gcode [n] | 223 (defn compare-gcode |
201 (compare-gen-fn n generate-gcode "/home/r/kevin/reference.ngc")) | 224 ([] (compare-gcode 25)) |
202 (defn compare-gmask [n] | 225 ([n] (compare-gen-fn n generate-gcode "/home/r/kevin/reference.ngc"))) |
203 (compare-gen-fn n generate-gmask "/home/r/kevin/reference.gmask")) | 226 |
227 (defn compare-gmask | |
228 ([] compare-gmask 25) | |
229 ([n] (compare-gen-fn n generate-gmask "/home/r/kevin/reference.gmask"))) | |
204 | 230 |
205 | 231 |
206 | 232 |
207 | 233 |
208 | 234 |