63 lines
3 KiB
Text
63 lines
3 KiB
Text
|
|
(ns arthur.domain.outline-test
|
||
|
|
(:require [cljs.test :refer [deftest is]]
|
||
|
|
[arthur.domain.outline :as outline]
|
||
|
|
[arthur.domain.raster :as r]))
|
||
|
|
|
||
|
|
(defn- covered [{:keys [buf]}] (count (filter #(= 1 %) (array-seq buf))))
|
||
|
|
|
||
|
|
(deftest a-traced-ring-fills-back-to-exactly-the-mask
|
||
|
|
(let [m (outline/stamp! (outline/mask 40 30) [8 8] [30 20] 6)
|
||
|
|
[ring & more] (outline/rings m)
|
||
|
|
back (r/fill-poly-buf! (r/make 40 30) ring (quot (count ring) 2) 1)]
|
||
|
|
(is (empty? more) "one stroke is one piece")
|
||
|
|
(is (= (vec (array-seq (:buf m))) (vec (array-seq (:buf back)))))))
|
||
|
|
|
||
|
|
(deftest a-single-pixel-is-a-square
|
||
|
|
(let [m (outline/mask 5 5)]
|
||
|
|
(aset (:buf m) 12 1)
|
||
|
|
(is (= [[2 2 3 2 3 3 2 3]] (outline/rings m 0)))))
|
||
|
|
|
||
|
|
(deftest pieces-are-traced-apart-biggest-first
|
||
|
|
(let [m (-> (outline/mask 40 20)
|
||
|
|
(outline/stamp! [5 10] [5 10] 4)
|
||
|
|
(outline/stamp! [20 10] [34 10] 6))]
|
||
|
|
(is (= 2 (count (outline/rings m))))
|
||
|
|
(is (< 8 (covered m)))
|
||
|
|
(is (< 15 (apply min (take-nth 2 (first (outline/rings m))))) "the long one first")))
|
||
|
|
|
||
|
|
(deftest simplify-keeps-exactly-the-count-asked-for
|
||
|
|
(let [ring (first (outline/rings (outline/stamp! (outline/mask 60 60) [30 30] [30 30] 40)))]
|
||
|
|
(is (= 24 (count (outline/simplify ring 12))))
|
||
|
|
(is (= 6 (count (outline/simplify ring 1))) "never fewer than three points")
|
||
|
|
(is (= ring (outline/simplify ring 10000)))))
|
||
|
|
|
||
|
|
(deftest a-loop-keeps-its-hole-in-one-ring
|
||
|
|
;; A ring of brush round a gap: one piece, one hole, and the one polygon it
|
||
|
|
;; makes fills back to the ring and leaves the gap empty.
|
||
|
|
(let [m (reduce (fn [m a]
|
||
|
|
(let [p #(vector (+ 30 (* 15 (js/Math.cos %))) (+ 30 (* 15 (js/Math.sin %))))]
|
||
|
|
(outline/stamp! m (p a) (p (+ a 0.3)) 5)))
|
||
|
|
(outline/mask 60 60) (range 0 6.6 0.3))
|
||
|
|
[piece & more] (outline/pieces m)
|
||
|
|
fill (fn [ring] (:buf (r/fill-poly-buf! (r/make 60 60) ring (quot (count ring) 2) 1)))
|
||
|
|
middle (+ 30 (* 30 60))]
|
||
|
|
(is (empty? more))
|
||
|
|
(is (= 1 (count (:holes piece))))
|
||
|
|
(is (= (vec (array-seq (:buf m))) (vec (array-seq (fill (outline/polygon piece 0.01)))))
|
||
|
|
"unsimplified, the bridged ring is the stroke exactly")
|
||
|
|
(is (zero? (aget (fill (outline/polygon piece 0.01)) middle)) "the middle is a hole")
|
||
|
|
(is (zero? (aget (fill (outline/polygon piece 8)) middle)) "and simplified, still a hole")))
|
||
|
|
|
||
|
|
(deftest points-go-by-length
|
||
|
|
(let [dab (first (outline/pieces (outline/stamp! (outline/mask 80 40) [10 20] [10 20] 8)))
|
||
|
|
long (first (outline/pieces (outline/stamp! (outline/mask 80 40) [10 20] [70 20] 8)))]
|
||
|
|
(is (< (count (outline/polygon dab 6)) (count (outline/polygon long 6))))
|
||
|
|
(is (= 6 (count (outline/polygon dab 1000))) "never fewer than three")))
|
||
|
|
|
||
|
|
(deftest a-gap-open-to-the-outside-is-not-a-hole
|
||
|
|
(let [m (-> (outline/mask 40 40)
|
||
|
|
(outline/stamp! [5 5] [30 5] 4)
|
||
|
|
(outline/stamp! [30 5] [30 30] 4)
|
||
|
|
(outline/stamp! [30 30] [5 30] 4))]
|
||
|
|
(is (= [] (:holes (first (outline/pieces m)))))))
|