Fix plotting closed shapes

This commit is contained in:
arne 2022-12-09 16:01:08 +01:00
commit 9b18bc507f

View file

@ -18,39 +18,55 @@
(map (fn [[x y z]] (map (fn [[x y z]]
(str "G01 X" x " Y" y " Z" z)) gcode-verts)) (str "G01 X" x " Y" y " Z" z)) gcode-verts))
(defn- vertices*
"Wrapper around geom.core/vertices that makes sure calls for geometries
which don't support the resolution parameter don't fail."
[geom {:keys [res]}]
(try
(if res (g/vertices geom res) (g/vertices geom))
(catch clojure.lang.ArityException _
(g/vertices geom))))
(defn- vertices
"Return the vertices of the outline of a shape; if a geometry is closed, the
first and last vertex will be the same."
([geom] (vertices geom {}))
([geom opts]
(let [last-p (last (g/sample-uniform geom Double/MAX_VALUE true))
vertices (vertices* geom opts)]
(cond-> vertices
(not= last-p (last vertices)) (conj last-p)))))
(defn- ->gcode-verts (defn- ->gcode-verts
([geom] ([geom]
(->gcode-verts geom {})) (->gcode-verts geom {}))
([geom {:keys [r]}] ([geom {:keys [res]}]
(vertices->gcode-verts (try (vertices->gcode-verts (vertices geom res))))
(if r (g/vertices geom r) (g/vertices geom))
(catch IllegalArgumentException _
(g/vertices geom))))))
(def gcode-seq (def gcode-seq
"Convert thi.ng.geom types into a sequence of G-Code to plot them. "Convert thi.ng.geom types into a sequence of G-Code to plot them.
An optional parameter `{:r 10}` can be used to adjust the sampling resolution An optional parameter `{:res 10}` can be used to adjust the sampling resolution
for the shape." for the shape, if the shape supports it."
(comp gcode-verts->gcode-seq ->gcode-verts)) (comp gcode-verts->gcode-seq ->gcode-verts))
(defn- geom? [x] (defn- geom? [x]
(str/starts-with? (pr-str x) "#thi.ng.geom.")) (str/starts-with? (pr-str x) "#thi.ng.geom."))
;; (pr-str (c/circle 20)) ;; => "#thi.ng.geom.types.Circle2{:p [0.0 0.0], :r 20.0}" ;; (pr-str (c/circle 20)) ;; => "#thi.ng.geom.types.Circle2{:p [0.0 0.0], :res 20.0}"
(defn scene->gcode-seq (defn scene->gcode-seq
"Converts a scene into a sequence of G-Code instructions. A scene is an "Converts a scene into a sequence of G-Code instructions. A scene is an
arbitrarily nested vector of geom instances and hiccup-like in that each arbitrarily nested vector of geom instances and hiccup-like in that each
object can be followed by a map of attributes. The map is currently ignored." object can be followed by a map of attributes. The map is currently ignored."
([scene] (scene->gcode-seq scene {})) ([scene] (scene->gcode-seq scene {}))
([scene {:keys [r] :as opts}] ([scene {:keys [res] :as opts}]
(loop [[el & rs] scene (loop [[el & rs] scene
result []] result []]
(cond (cond
(nil? el) result (nil? el) result
(sequential? el) (recur rs (vec (concat result (scene->gcode-seq el opts)))) ;; recursively convert sequences (sequential? el) (recur rs (vec (concat result (scene->gcode-seq el opts)))) ;; recursively convert sequences
(geom? el) (recur rs (conj result (if r (gcode-seq el r) (gcode-seq el)))) ;; convert geoms (geom? el) (recur rs (conj result (if res (gcode-seq el res) (gcode-seq el)))) ;; convert geoms
(map? el) (recur rs result))))) ;; ignore attribute maps (map? el) (recur rs result))))) ;; ignore attribute maps
(comment (comment
@ -67,22 +83,32 @@
;; "G01 X200.0 Y200.0 Z1000") ;; "G01 X200.0 Y200.0 Z1000")
;; you can pass a second argument to increase or decrease resolution ;; you can pass a second argument to increase or decrease resolution
(gcode-seq (c/circle) {:r 10}) (gcode-seq (c/circle) {:res 10})
;; => ("G01 X1.0 Y0.0 Z1000" ;; => ("G01 X1.0 Y0.0 Z1000"
;; "G01 X1.0 Y0.0 Z0" ;; "G01 X1.0 Y0.0 Z0"
;; "G01 X0.9510565162951535 Y0.3090169943749474 Z0"
;; "G01 X0.8090169943749475 Y0.5877852522924731 Z0" ;; "G01 X0.8090169943749475 Y0.5877852522924731 Z0"
;; "G01 X0.5877852522924731 Y0.8090169943749475 Z0"
;; "G01 X0.30901699437494745 Y0.9510565162951535 Z0" ;; "G01 X0.30901699437494745 Y0.9510565162951535 Z0"
;; "G01 X6.123233995736766E-17 Y1.0 Z0"
;; "G01 X-0.30901699437494734 Y0.9510565162951536 Z0" ;; "G01 X-0.30901699437494734 Y0.9510565162951536 Z0"
;; "G01 X-0.587785252292473 Y0.8090169943749475 Z0"
;; "G01 X-0.8090169943749473 Y0.5877852522924732 Z0" ;; "G01 X-0.8090169943749473 Y0.5877852522924732 Z0"
;; "G01 X-0.9510565162951535 Y0.3090169943749475 Z0"
;; "G01 X-1.0 Y1.2246467991473532E-16 Z0" ;; "G01 X-1.0 Y1.2246467991473532E-16 Z0"
;; "G01 X-0.9510565162951535 Y-0.30901699437494773 Z0"
;; "G01 X-0.8090169943749476 Y-0.587785252292473 Z0" ;; "G01 X-0.8090169943749476 Y-0.587785252292473 Z0"
;; "G01 X-0.5877852522924732 Y-0.8090169943749473 Z0"
;; "G01 X-0.30901699437494756 Y-0.9510565162951535 Z0" ;; "G01 X-0.30901699437494756 Y-0.9510565162951535 Z0"
;; "G01 X-1.8369701987210297E-16 Y-1.0 Z0"
;; "G01 X0.30901699437494723 Y-0.9510565162951536 Z0" ;; "G01 X0.30901699437494723 Y-0.9510565162951536 Z0"
;; "G01 X0.5877852522924729 Y-0.8090169943749476 Z0"
;; "G01 X0.8090169943749473 Y-0.5877852522924734 Z0" ;; "G01 X0.8090169943749473 Y-0.5877852522924734 Z0"
;; "G01 X0.8090169943749473 Y-0.5877852522924734 Z1000") ;; "G01 X0.9510565162951535 Y-0.3090169943749476 Z0"
;; "G01 X0.9510565162951535 Y-0.3090169943749476 Z1000")
;; `scene->gcode-seq` converts a tree of arbitrarily nested elements into a ;; `scene->gcode-seq` converts a tree of arbitrarily nested elements into a
;; sequence of gcode drawing instructions ;; sequence of gcode drawing instructions
(scene->gcode-seq (scene->gcode-seq
[[(r/rect [0 0] [10 10]) {:attributes/ignored? true}] [[(r/rect [0 0] [10 10]) {:attributes/ignored? true}]
(r/rect [0 0] [10 10]) (r/rect [0 0] [10 10])
@ -90,47 +116,64 @@
(r/rect [20 20] [40 40]) (r/rect [20 20] [40 40])
[(c/circle [5 5] 10)] [(c/circle [5 5] 10)]
(r/rect [20 20] [40 40])]] (r/rect [20 20] [40 40])]]
{:r 10}) {:res 10})
;; => [("G01 X0.0 Y0.0 Z1000" ;; => [("G01 X0.0 Y0.0 Z1000"
;; "G01 X0.0 Y0.0 Z0" ;; "G01 X0.0 Y0.0 Z0"
;; "G01 X10.0 Y0.0 Z0" ;; "G01 X10.0 Y0.0 Z0"
;; "G01 X10.0 Y10.0 Z0" ;; "G01 X10.0 Y10.0 Z0"
;; "G01 X0.0 Y10.0 Z0" ;; "G01 X0.0 Y10.0 Z0"
;; "G01 X0.0 Y10.0 Z1000") ;; "G01 X0.0 Y0.0 Z0"
;; "G01 X0.0 Y0.0 Z1000")
;; ("G01 X0.0 Y0.0 Z1000" ;; ("G01 X0.0 Y0.0 Z1000"
;; "G01 X0.0 Y0.0 Z0" ;; "G01 X0.0 Y0.0 Z0"
;; "G01 X10.0 Y0.0 Z0" ;; "G01 X10.0 Y0.0 Z0"
;; "G01 X10.0 Y10.0 Z0" ;; "G01 X10.0 Y10.0 Z0"
;; "G01 X0.0 Y10.0 Z0" ;; "G01 X0.0 Y10.0 Z0"
;; "G01 X0.0 Y10.0 Z1000") ;; "G01 X0.0 Y0.0 Z0"
;; "G01 X0.0 Y0.0 Z1000")
;; ("G01 X5.0 Y5.0 Z1000" ;; ("G01 X5.0 Y5.0 Z1000"
;; "G01 X5.0 Y5.0 Z0" ;; "G01 X5.0 Y5.0 Z0"
;; "G01 X15.0 Y5.0 Z0" ;; "G01 X15.0 Y5.0 Z0"
;; "G01 X15.0 Y15.0 Z0" ;; "G01 X15.0 Y15.0 Z0"
;; "G01 X5.0 Y15.0 Z0" ;; "G01 X5.0 Y15.0 Z0"
;; "G01 X5.0 Y15.0 Z1000") ;; "G01 X5.0 Y5.0 Z0"
;; "G01 X5.0 Y5.0 Z1000")
;; ("G01 X20.0 Y20.0 Z1000" ;; ("G01 X20.0 Y20.0 Z1000"
;; "G01 X20.0 Y20.0 Z0" ;; "G01 X20.0 Y20.0 Z0"
;; "G01 X40.0 Y20.0 Z0" ;; "G01 X40.0 Y20.0 Z0"
;; "G01 X40.0 Y40.0 Z0" ;; "G01 X40.0 Y40.0 Z0"
;; "G01 X20.0 Y40.0 Z0" ;; "G01 X20.0 Y40.0 Z0"
;; "G01 X20.0 Y40.0 Z1000") ;; "G01 X20.0 Y20.0 Z0"
;; "G01 X20.0 Y20.0 Z1000")
;; ("G01 X15.0 Y5.0 Z1000" ;; ("G01 X15.0 Y5.0 Z1000"
;; "G01 X15.0 Y5.0 Z0" ;; "G01 X15.0 Y5.0 Z0"
;; "G01 X14.510565162951535 Y8.090169943749475 Z0"
;; "G01 X13.090169943749475 Y10.877852522924732 Z0" ;; "G01 X13.090169943749475 Y10.877852522924732 Z0"
;; "G01 X10.877852522924732 Y13.090169943749475 Z0"
;; "G01 X8.090169943749475 Y14.510565162951535 Z0" ;; "G01 X8.090169943749475 Y14.510565162951535 Z0"
;; "G01 X5.000000000000001 Y15.0 Z0"
;; "G01 X1.9098300562505264 Y14.510565162951536 Z0" ;; "G01 X1.9098300562505264 Y14.510565162951536 Z0"
;; "G01 X-0.87785252292473 Y13.090169943749475 Z0"
;; "G01 X-3.0901699437494727 Y10.877852522924734 Z0" ;; "G01 X-3.0901699437494727 Y10.877852522924734 Z0"
;; "G01 X-4.510565162951535 Y8.090169943749475 Z0"
;; "G01 X-5.0 Y5.000000000000001 Z0" ;; "G01 X-5.0 Y5.000000000000001 Z0"
;; "G01 X-4.510565162951535 Y1.9098300562505228 Z0"
;; "G01 X-3.0901699437494763 Y-0.87785252292473 Z0" ;; "G01 X-3.0901699437494763 Y-0.87785252292473 Z0"
;; "G01 X-0.8778525229247327 Y-3.0901699437494727 Z0"
;; "G01 X1.9098300562505246 Y-4.510565162951535 Z0" ;; "G01 X1.9098300562505246 Y-4.510565162951535 Z0"
;; "G01 X4.999999999999998 Y-5.0 Z0"
;; "G01 X8.090169943749473 Y-4.510565162951536 Z0" ;; "G01 X8.090169943749473 Y-4.510565162951536 Z0"
;; "G01 X10.87785252292473 Y-3.0901699437494763 Z0"
;; "G01 X13.090169943749473 Y-0.8778525229247336 Z0" ;; "G01 X13.090169943749473 Y-0.8778525229247336 Z0"
;; "G01 X13.090169943749473 Y-0.8778525229247336 Z1000") ;; "G01 X14.510565162951535 Y1.9098300562505237 Z0"
;; "G01 X15.0 Y5.0 Z0"
;; "G01 X15.0 Y5.0 Z1000")
;; ("G01 X20.0 Y20.0 Z1000" ;; ("G01 X20.0 Y20.0 Z1000"
;; "G01 X20.0 Y20.0 Z0" ;; "G01 X20.0 Y20.0 Z0"
;; "G01 X40.0 Y20.0 Z0" ;; "G01 X40.0 Y20.0 Z0"
;; "G01 X40.0 Y40.0 Z0" ;; "G01 X40.0 Y40.0 Z0"
;; "G01 X20.0 Y40.0 Z0" ;; "G01 X20.0 Y40.0 Z0"
;; "G01 X20.0 Y40.0 Z1000")] ;; "G01 X20.0 Y20.0 Z0"
;; "G01 X20.0 Y20.0 Z1000")]
) )