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