diff --git a/docs/cloverage/index.html b/docs/cloverage/index.html index f5c20a4..046068e 100644 --- a/docs/cloverage/index.html +++ b/docs/cloverage/index.html @@ -14,17 +14,6 @@ Lines % TotalBlankInstrumented - - walkmap.core
1
-100.00 % -
1
-100.00 % -911 - walkmap.edge
5
100.00 % -18918104 +17517104 - walkmap.geometry
walkmap.id
62
+ float:left;"> 3
100.00 %
10
+ float:left;"> 2 100.00 % -17110 +822 walkmap.ocean
5
23
-17.86 % + style="width:64.28571428571429%; + float:left;"> 18
10
+64.29 %
4
4
-50.00 % + style="width:87.5%; + float:left;"> 7
1
+87.50 % 2448 walkmap.path
6
164
-3.53 % + style="width:12.041884816753926%; + float:left;"> 23
168
+12.04 %
6
32
-15.79 % -78738 + style="width:17.94871794871795%; + float:left;"> 7
1
31
+20.51 % +84739 walkmap.polygon
48
5
-90.57 % + style="width:72.42647058823529%; + float:left;"> 197
75
+72.43 %
9
32
5
13
+74.00 % +87850 + + + walkmap.read-svg
7
238
+2.86 % +
7
39
+15.22 % +97646 + + + walkmap.routing
1
100.00 % -19310 +
1
+100.00 % +1821 walkmap.stl
289
220
-56.78 % + style="width:49.07216494845361%; + float:left;"> 238
247
+49.07 %
44
43
10
46
-54.00 % -19114100 + style="width:50.0%; + float:left;"> 53 +50.00 % +20616106 walkmap.superstructure
4
150
-2.60 % + style="width:71.76781002638522%; + float:left;"> 272
107
+71.77 %
4
23
-14.81 % -85927 + style="width:71.26436781609195%; + float:left;"> 62
3
22
+74.71 % +1831887 walkmap.svg
58
12.12 % -108766 +110766 walkmap.tag
137
+ float:left;"> 181 100.00 %
36
+ float:left;"> 34 100.00 % -65736 +68834 walkmap.utils
3
35
-7.89 % + style="width:76.66666666666667%; + float:left;"> 92
28
+76.67 %
3
7
-30.00 % -23310 + style="width:80.0%; + float:left;"> 16
1
3
+85.00 % +43420 walkmap.vertex
253
71
-78.09 % + style="width:66.52078774617068%; + float:left;"> 304
153
+66.52 %
42
6
12
-80.00 % -1141160 + style="width:59.75609756097561%; + float:left;"> 49
9
24
+70.73 % +1481382 Totals: -61.24 % +60.81 % -61.28 % +62.17 % diff --git a/docs/cloverage/walkmap/edge.clj.html b/docs/cloverage/walkmap/edge.clj.html index 7f17b26..6d8db3e 100644 --- a/docs/cloverage/walkmap/edge.clj.html +++ b/docs/cloverage/walkmap/edge.clj.html @@ -20,556 +20,514 @@ 005    (:require [clojure.math.numeric-tower :as m]
- 006              [walkmap.polygon :refer [polygon?]] -
- - 007              [walkmap.vertex :refer [ensure2d ensure3d vertex vertex= vertex?]])) + 006              [walkmap.vertex :refer [ensure2d ensure3d vertex vertex= vertex?]]))
- 008   + 007  
- 009  (defn edge + 008  (defn edge
- 010    "Return an edge between vertices `v1` and `v2`." + 009    "Return an edge between vertices `v1` and `v2`."
- 011    [v1 v2] + 010    [v1 v2]
- 012    (if + 011    (if
- 013      (and (vertex? v1) (vertex? v2)) + 012      (and (vertex? v1) (vertex? v2))
- 014      {:kind :edge :id (keyword (gensym "edge")) :start v1 :end v2} + 013      {:kind :edge :walkmap.id/id (keyword (gensym "edge")) :start v1 :end v2}
- 015      (throw (IllegalArgumentException. "Must be vertices.")))) + 014      (throw (IllegalArgumentException. "Must be vertices."))))
- 016   + 015  
- 017  (defn edge? + 016  (defn edge?
- 018    "True if `o` satisfies the conditions for a edge. An edge shall be a map + 017    "True if `o` satisfies the conditions for a edge. An edge shall be a map
- 019    having the keys `:start` and `:end`, such that the values of each of those + 018    having the keys `:start` and `:end`, such that the values of each of those
- 020    keys shall be a vertex." + 019    keys shall be a vertex."
- 021    [o] + 020    [o]
- 022    (and + 021    (and
- 023      (map? o) + 022      (map? o)
- 024      (vertex? (:start o)) + 023      (vertex? (:start o))
- 025      (vertex? (:end o)))) + 024      (vertex? (:end o))))
- 026   + 025  
- 027  (defn length + 026  (defn length
- 028    "Return the length of the edge `e`." + 027    "Return the length of the edge `e`."
- 029    [e] + 028    [e]
- 030    (let [start (ensure3d (:start e)) + 029    (let [start (ensure3d (:start e))
- 031          end (ensure3d (:end e))] + 030          end (ensure3d (:end e))]
- 032      (m/sqrt + 031      (m/sqrt
- 033        (reduce + 032        (reduce
- 034          + + 033          +
- 035          (map + 034          (map
- 036            #(m/expt (- (% end) (% start)) 2) + 035            #(m/expt (- (% end) (% start)) 2)
- 037            [:x :y :z]))))) + 036            [:x :y :z])))))
- 038   + 037  
- 039  (defn centre + 038  (defn centre
- 040    "Return the vertex that represents the centre of this `edge`." + 039    "Return the vertex that represents the centre of this `edge`."
- 041    [edge] + 040    [edge]
- 042    (let [s (ensure3d (:start edge)) + 041    (let [s (ensure3d (:start edge))
- 043          e (ensure3d (:end edge))] + 042          e (ensure3d (:end edge))]
- 044      (vertex + 043      (vertex
- 045        (+ (:x s) (/ (- (:x e) (:x s)) 2)) + 044        (+ (:x s) (/ (- (:x e) (:x s)) 2))
- 046        (+ (:y s) (/ (- (:y e) (:y s)) 2)) + 045        (+ (:y s) (/ (- (:y e) (:y s)) 2))
- 047        (+ (:z s) (/ (- (:z e) (:z s)) 2))))) + 046        (+ (:z s) (/ (- (:z e) (:z s)) 2)))))
- 048   + 047  
- 049  (defn unit-vector + 048  (defn unit-vector
- 050    "Return an vertex parallel to `e` starting from the coordinate origin. Two + 049    "Return an vertex parallel to `e` starting from the coordinate origin. Two
- 051    edges which are parallel will have the same unit vector." + 050    edges which are parallel will have the same unit vector."
- 052    [e] + 051    [e]
- 053    (let [e' {:start (ensure3d (:start e)) :end (ensure3d (:end e))} + 052    (let [e' {:start (ensure3d (:start e)) :end (ensure3d (:end e))}
- 054          l (length e')] + 053          l (length e')]
- 055      (reduce + 054      (reduce
- 056        merge + 055        merge
- 057        {} + 056        {}
- 058        (map + 057        (map
- 059          (fn [k] + 058          (fn [k]
- 060            {k (/ (- (k (:end e')) (k (:start e'))) l)}) + 059            {k (/ (- (k (:end e')) (k (:start e'))) l)})
- 061          [:x :y :z])))) + 060          [:x :y :z]))))
- 062   + 061  
- 063  (defn parallel? + 062  (defn parallel?
- 064    "True if all `edges` passed are parallel with one another." + 063    "True if all `edges` passed are parallel with one another."
- 065    [& edges] + 064    [& edges]
- 066    (let [uvs (map unit-vector edges)] + 065    (let [uvs (map unit-vector edges)]
- 067      (every? + 066      (every?
- 068        #(vertex= % (first uvs)) + 067        #(vertex= % (first uvs))
- 069        (rest uvs)))) + 068        (rest uvs))))
- 070   + 069  
- 071  (defn collinear? + 070  (defn collinear?
- 072    "True if edges `e1` and `e2` are collinear with one another." + 071    "True if edges `e1` and `e2` are collinear with one another."
- 073    [e1 e2] + 072    [e1 e2]
- 074    (parallel? + 073    (parallel?
- 075      e1 + 074      e1
- 076      e2 + 075      e2
- 077      (if (vertex= (:start e1) (:start e2)) + 076      (if (vertex= (:start e1) (:start e2))
- 078        {:start (:start e1) :end (:end e2)} + 077        {:start (:start e1) :end (:end e2)}
- 079        {:start (:start e1) :end (:start e2)}))) + 078        {:start (:start e1) :end (:start e2)})))
- 080   + 079  
- 081  (defn collinear2d? + 080  (defn collinear2d?
- 082    "True if the projections of edges `e1`, `e2` onto the x, y plane are + 081    "True if the projections of edges `e1`, `e2` onto the x, y plane are
- 083    collinear." + 082    collinear."
- 084    [e1 e2] + 083    [e1 e2]
- 085    (collinear? {:start (ensure2d (:start e1)) :end (ensure2d (:end e1))} + 084    (collinear? {:start (ensure2d (:start e1)) :end (ensure2d (:end e1))}
- 086                {:start (ensure2d (:start e2)) :end (ensure2d (:end e2))})) + 085                {:start (ensure2d (:start e2)) :end (ensure2d (:end e2))}))
- 087   + 086  
- 088  (defn minimaxd + 087  (defn minimaxd
- 089    "Apply function `f` to `coord` of the vertices at start and end of `edge` + 088    "Apply function `f` to `coord` of the vertices at start and end of `edge`
- 090    and return the result. Intended use case is `f` = `min` or `max`, `coord` + 089    and return the result. Intended use case is `f` = `min` or `max`, `coord`
- 091    is `:x`, `:y` or `:z`. No checks are made for sane arguments." + 090    is `:x`, `:y` or `:z`. No checks are made for sane arguments."
- 092    [edge coord f] + 091    [edge coord f]
- 093    (apply f (list (coord (:start edge)) (coord (:end edge))))) + 092    (apply f (list (coord (:start edge)) (coord (:end edge)))))
- 094   + 093  
- 095  (defn on? + 094  (defn on?
- 096    "True if the vertex `v` is on the edge `e`." + 095    "True if the vertex `v` is on the edge `e`."
- 097    [e v] + 096    [e v]
- 098    (let [p (ensure3d (:start e)) + 097    (let [p (ensure3d (:start e))
- 099          q (ensure3d v) + 098          q (ensure3d v)
- 100          r (ensure3d (:end e))] + 099          r (ensure3d (:end e))]
- 101      (and + 100      (and
- 102        (collinear? (edge p q) (edge q r)) + 101        (collinear? (edge p q) (edge q r))
- 103        (<= (:x q) (max (:x p) (:x r))) + 102        (<= (:x q) (max (:x p) (:x r)))
- 104        (>= (:x q) (min (:x p) (:x r))) + 103        (>= (:x q) (min (:x p) (:x r)))
- 105        (<= (:y q) (max (:y p) (:y r))) + 104        (<= (:y q) (max (:y p) (:y r)))
- 106        (>= (:y q) (min (:y p) (:y r))) + 105        (>= (:y q) (min (:y p) (:y r)))
- 107        (<= (:z q) (max (:z p) (:z r))) + 106        (<= (:z q) (max (:z p) (:z r)))
- 108        (>= (:z q) (min (:z p) (:z r)))))) + 107        (>= (:z q) (min (:z p) (:z r))))))
- 109   + 108  
- 110  (defn on2d? + 109  (defn on2d?
- 111    "True if vertex `v` is on edge `e` when projected onto the x, y plane." + 110    "True if vertex `v` is on edge `e` when projected onto the x, y plane."
- 112    [e v] + 111    [e v]
- 113    (on? (edge (ensure2d (:start e)) (ensure2d (:end e))) v)) + 112    (on? (edge (ensure2d (:start e)) (ensure2d (:end e))) v))
- 114   + 113  
- 115  (defn overlaps2d? + 114  (defn overlaps2d?
- 116    "True if the recangle in the x,y plane bisected by edge `e1` overlaps that + 115    "True if the recangle in the x,y plane bisected by edge `e1` overlaps that
- 117    bisected by edge `e2`. It is an error if either `e1` or `e2` is not an edge." + 116    bisected by edge `e2`. It is an error if either `e1` or `e2` is not an edge."
- 118    [e1 e2] + 117    [e1 e2]
- 119    (when (and (edge? e1) (edge? e2)) + 118    (when (and (edge? e1) (edge? e2))
- 120      (and + 119      (and
- 121        (> (minimaxd e1 :x max) (minimaxd e2 :x min)) + 120        (> (minimaxd e1 :x max) (minimaxd e2 :x min))
- 122        (< (minimaxd e1 :x min) (minimaxd e2 :x max)) + 121        (< (minimaxd e1 :x min) (minimaxd e2 :x max))
- 123        (> (minimaxd e1 :y max) (minimaxd e2 :y min)) + 122        (> (minimaxd e1 :y max) (minimaxd e2 :y min))
- 124        (< (minimaxd e1 :y min) (minimaxd e2 :y max))))) + 123        (< (minimaxd e1 :y min) (minimaxd e2 :y max)))))
- 125   + 124   +
+ + 125  (defn intersection2d
- 126  ;; Don't think I need this. + 126    "The probability of two lines intersecting in 3d space is low, and actually
- 127  ;; (defn orientation + 127    that is mostly not something we're interested in. We're interested in
- 128  ;;   "Determine whether the ordered sequence of vertices `p`, `q` and `r` run + 128    intersection in the `x,y` plane. This function returns a vertex representing
- 129  ;;   clockwise, collinear or anticlockwise in the x,y plane." + 129    a point vertically over the intersection of edges `e1`, `e2` in the `x,y`
- 130  ;;   [p q r] + 130    plane, whose `z` coordinate is +
+ + 131  
- 131  ;;   (let [v (- (* (- (:y q) (:y p)) (- (:x r) (:x q))) + 132    * 0 if both edges are 2d (i.e. have missing or zero `z` coordinates);
- 132  ;;             (* (- (:x q) (:x p)) (- (:y r) (:y q))))] + 133    * if one edge is 2d, then the point on the other edge over the intersection;
- 133  ;;     (cond + 134    * otherwise, the average of the z coordinates of the points on the two
- 134  ;;       (zero? v) :collinear + 135    edges over the intersection. +
+ + 136  
- 135  ;;       (pos? v) :clockwise -
- - 136  ;;       :else -
- - 137  ;;       :anticlockwise))) + 137    If no such intersection exists, `nil` is returned.
138  
- - 139  (defn intersection2d + + 139    It is an error, and an exception will be thrown, if either `e1` or `e2` is
- 140    "The probability of two lines intersecting in 3d space is low, and actually + 140    not an edge."
- 141    that is mostly not something we're interested in. We're interested in -
- - 142    intersection in the `x,y` plane. This function returns a vertex representing -
- - 143    a point vertically over the intersection of edges `e1`, `e2` in the `x,y` -
- - 144    plane, whose `z` coordinate is -
- - 145   -
- - 146    * 0 if both edges are 2d (i.e. have missing or zero `z` coordinates); -
- - 147    * if one edge is 2d, then the point on the other edge over the intersection; -
- - 148    * otherwise, the average of the z coordinates of the points on the two -
- - 149    edges over the intersection. -
- - 150   -
- - 151    If no such intersection exists, `nil` is returned. -
- - 152   -
- - 153    It is an error, and an exception will be thrown, if either `e1` or `e2` is -
- - 154    not an edge." -
- - 155    [e1 e2] + 141    [e1 e2]
- 156    (if (and (edge? e1) (edge? e2)) + 142    (if (and (edge? e1) (edge? e2))
- 157      (when + 143      (when
- 158        (overlaps2d? e1 e2) ;; relatively cheap check + 144        (overlaps2d? e1 e2) ;; relatively cheap check
- 159        (if + 145        (if
- 160          (collinear2d? e1 e2) + 146          (collinear2d? e1 e2)
- 161          ;; any point within the overlap will do, but we'll pick the end of e1 + 147          ;; any point within the overlap will do, but we'll pick the end of e1
- 162          ;; which is on e2 + 148          ;; which is on e2
- 163          (if (on2d? e2 (:start e1)) (:start e1) (:end e1)) + 149          (if (on2d? e2 (:start e1)) (:start e1) (:end e1))
- 164          ;; blatantly stolen from + 150          ;; blatantly stolen from
- 165          ;; https://gist.github.com/cassiel/3e725b49670356a9b936 + 151          ;; https://gist.github.com/cassiel/3e725b49670356a9b936
- 166          (let [x1 (:x (:start e1)) + 152          (let [x1 (:x (:start e1))
- 167                x2 (:x (:end e1)) + 153                x2 (:x (:end e1))
- 168                x3 (:x (:start e2)) + 154                x3 (:x (:start e2))
- 169                x4 (:x (:end e2)) + 155                x4 (:x (:end e2))
- 170                y1 (:y (:start e1)) + 156                y1 (:y (:start e1))
- 171                y2 (:y (:end e1)) + 157                y2 (:y (:end e1))
- 172                y3 (:y (:start e2)) + 158                y3 (:y (:start e2))
- 173                y4 (:y (:end e2)) + 159                y4 (:y (:end e2))
- 174                denom (- (* (- x1 x2) (- y3 y4)) + 160                denom (- (* (- x1 x2) (- y3 y4))
- 175                         (* (- y1 y2) (- x3 x4))) + 161                         (* (- y1 y2) (- x3 x4)))
- 176                x1y2-y1x2 (- (* x1 y2) (* y1 x2)) + 162                x1y2-y1x2 (- (* x1 y2) (* y1 x2))
- 177                x3y4-y3x4 (- (* x3 y4) (* y3 x4)) + 163                x3y4-y3x4 (- (* x3 y4) (* y3 x4))
- 178                px-num (- (* x1y2-y1x2 (- x3 x4)) + 164                px-num (- (* x1y2-y1x2 (- x3 x4))
- 179                          (* (- x1 x2) x3y4-y3x4)) + 165                          (* (- x1 x2) x3y4-y3x4))
- 180                py-num (- (* x1y2-y1x2 (- y3 y4)) + 166                py-num (- (* x1y2-y1x2 (- y3 y4))
- 181                          (* (- y1 y2) x3y4-y3x4)) + 167                          (* (- y1 y2) x3y4-y3x4))
- 182                result (when-not (zero? denom) + 168                result (when-not (zero? denom)
- 183                         (vertex (/ px-num denom) (/ py-num denom)))] + 169                         (vertex (/ px-num denom) (/ py-num denom)))]
- 184            (when (and result (on2d? e1 result) (on2d? e2 result)) result)))) + 170            (when (and result (on2d? e1 result) (on2d? e2 result)) result))))
- 185      (throw (IllegalArgumentException. + 171      (throw (IllegalArgumentException.
- 186               (str + 172               (str
- 187                 "Both `e1` and `e2` must be edges." + 173                 "Both `e1` and `e2` must be edges."
- 188                 (map #(or (:kind %) (type %)) [e1 e2])))))) + 174                 (map #(or (:kind %) (type %)) [e1 e2]))))))
- 189   + 175  
diff --git a/docs/cloverage/walkmap/id.clj.html b/docs/cloverage/walkmap/id.clj.html new file mode 100644 index 0000000..1fc9abe --- /dev/null +++ b/docs/cloverage/walkmap/id.clj.html @@ -0,0 +1,32 @@ + + + + walkmap/id.clj + + + + 001  (ns walkmap.id +
+ + 002    "The namespace within which the privileged keyword `:walkmap.id/id` is defined.") +
+ + 003   +
+ + 004  (def ^:const id +
+ + 005    "The magic id key walkmap uses, to distinguish it from all other uses of +
+ + 006    the unprotected keyword." +
+ + 007    ::id) +
+ + 008   +
+ + diff --git a/docs/cloverage/walkmap/ocean.clj.html b/docs/cloverage/walkmap/ocean.clj.html index eb20c01..f729ad3 100644 --- a/docs/cloverage/walkmap/ocean.clj.html +++ b/docs/cloverage/walkmap/ocean.clj.html @@ -49,13 +49,13 @@ 015    [facet]
- + 016    (every?
- + 017      #(= % *sea-level*)
- + 018      (map :z (:vertices facet))))
diff --git a/docs/cloverage/walkmap/path.clj.html b/docs/cloverage/walkmap/path.clj.html index 025d1dc..ea999df 100644 --- a/docs/cloverage/walkmap/path.clj.html +++ b/docs/cloverage/walkmap/path.clj.html @@ -17,226 +17,244 @@ 004    feature, where such features specifically include watercourses."
- 005    (:require [walkmap.edge :as e] + 005    (:require [clojure.string :as s]
- 006              [walkmap.polygon :refer [polygon?]] + 006              [walkmap.edge :as e]
- 007              [walkmap.vertex :refer [vertex?]])) + 007              [walkmap.polygon :refer [polygon?]] +
+ + 008              [walkmap.utils :refer [kind-type]] +
+ + 009              [walkmap.vertex :refer [vertex?]]))
- 008   + 010  
- 009  (defn path? + 011  (defn path?
- 010    "True if `o` satisfies the conditions for a path. A path shall be a map + 012    "True if `o` satisfies the conditions for a path. A path shall be a map
- 011    having the key `:vertices`, whose value shall be a sequence of vertices as + 013    having the key `:vertices`, whose value shall be a sequence of vertices as
- 012    defined in `walkmap.vertex`." + 014    defined in `walkmap.vertex`."
- 013    [o] + 015    [o]
- 014    (let + 016    (let
- 015      [v (:vertices o)] + 017      [v (:vertices o)]
- 016      (and + 018      (and
- 017        (seq? v) + 019        (seq? v)
- 018        (> (count v) 2) + 020        (> (count v) 2)
- 019        (every? vertex? v) + 021        (every? vertex? v)
- 020        (:id o) + 022        (:walkmap.id/id o)
- 021        (or (nil? (:kind o)) (= (:kind o) :path))))) + 023        (or (nil? (:kind o)) (= (:kind o) :path)))))
- 022   + 024  
- 023  (defn path + 025  (defn path
- 024    "Return a path constructed from these `vertices`." + 026    "Return a path constructed from these `vertices`."
- 025    [& vertices] + 027    [& vertices]
- - 026    (if -
- - 027      (every? vertex? vertices) -
- - 028      {:vertices vertices :id (keyword (gensym "path")) :kind :path} -
- - 029      (throw (IllegalArgumentException. "Each item on path must be a vertex.")))) -
- - 030   -
- - 031  (defn polygon->path -
- - 032    "If `o` is a polygon, return an equivalent path. What's different about -
- - 033    a path is that in polygons there is an implicit edge between the first -
- - 034    vertex and the last. In paths, there isn't, so we need to add that -
- - 035    edge explicitly. -
- - 036   -
- - 037    If `o` is not a polygon, will throw an exception." -
- - 038    [o] -
- - 039    (if -
- - 040      (polygon? o) -
- - 041      (assoc (dissoc o :vertices) :kind :path :vertices (concat (:vertices o) (list (first (:vertices o))))) -
- - 042      (throw (IllegalArgumentException. "Not a polygon!")))) -
- - 043   -
- - 044  (defn path->edges -
- - 045    "if `o` is a path, a polygon, or a sequence of vertices, return a sequence of -
- - 046    edges representing that path, polygon or sequence. -
- - 047   -
- - 048    Throws `IllegalArgumentException` if `o` is not a path, a polygon, or -
- - 049    sequence of vertices." -
- - 050    [o] -
- - 051    (cond -
- - 052      (seq? o) + + 028    (when-not (every? vertex? vertices)
- 053      (when + 029      (throw (IllegalArgumentException.
- - 054        (and + + 030               (str
- - 055          (vertex? (first o)) + + 031                 "Each item on path must be a vertex: " +
+ + 032                 (s/join " " (map kind-type (remove vertex? vertices))))))) +
+ + 033    {:vertices vertices :walkmap.id/id (keyword (gensym "path")) :kind :path}) +
+ + 034   +
+ + 035  (defn polygon->path +
+ + 036    "If `o` is a polygon, return an equivalent path. What's different about +
+ + 037    a path is that in polygons there is an implicit edge between the first +
+ + 038    vertex and the last. In paths, there isn't, so we need to add that +
+ + 039    edge explicitly. +
+ + 040   +
+ + 041    If `o` is not a polygon, will throw an exception." +
+ + 042    [o]
- 056          (vertex? (first (rest o)))) -
- - 057        (cons -
- - 058          ;; TODO: think about: when constructing an edge from a path, should the -
- - 059          ;; constructed edge be tagged with the tags of the path? + 043    (when-not (polygon? o)
- 060          (e/edge (first o) (rest o)) -
- - 061          (path->edges (rest o)))) -
- - 062      (path? o) -
- - 063      (path->edges (:vertices o)) -
- - 064      :else -
- - 065      (throw (IllegalArgumentException. -
- - 066               "Not a path or sequence of vertices!")))) -
- - 067   -
- - 068  (defn length -
- - 069    "Return the length of this path, in metres. **Note that** -
- - 070    1. This is not the same as the distance from the start to the end of the -
- - 071    path, which, except for absolutely straight paths, will be shorter; -
- - 072    2. It is not even quite the same as the length of the path *as rendered*, -
- - 073    since paths will generally be rendered as spline curves." -
- - 074    [path] -
- - 075    (if -
- - 076      (path? path) + 044      (throw (IllegalArgumentException. (str "Not a polygon: " (kind-type o)))))
- 077      (reduce + (map e/length (path->edges path))) + 045    (assoc (dissoc o :vertices) +
+ + 046      :kind :path +
+ + 047      ;; `concat` rather than `conj` because order matters. +
+ + 048      :vertices (concat (:vertices o) (list (first (:vertices o)))))) +
+ + 049   +
+ + 050  (defn path->edges +
+ + 051    "if `o` is a path, a polygon, or a sequence of vertices, return a sequence of +
+ + 052    edges representing that path, polygon or sequence. +
+ + 053   +
+ + 054    Throws `IllegalArgumentException` if `o` is not a path, a polygon, or +
+ + 055    sequence of vertices." +
+ + 056    [o]
- 078      (throw (IllegalArgumentException. "Not a path!")))) + 057    (cond +
+ + 058      (seq? o) +
+ + 059      (when +
+ + 060        (and +
+ + 061          (vertex? (first o)) +
+ + 062          (vertex? (first (rest o)))) +
+ + 063        (cons +
+ + 064          ;; TODO: think about: when constructing an edge from a path, should the +
+ + 065          ;; constructed edge be tagged with the tags of the path? +
+ + 066          (e/edge (first o) (rest o)) +
+ + 067          (path->edges (rest o)))) +
+ + 068      (path? o) +
+ + 069      (path->edges (:vertices o)) +
+ + 070      :else +
+ + 071      (throw (IllegalArgumentException. +
+ + 072               "Not a path or sequence of vertices!")))) +
+ + 073   +
+ + 074  (defn length +
+ + 075    "Return the length of this path, in metres. **Note that** +
+ + 076    1. This is not the same as the distance from the start to the end of the +
+ + 077    path, which, except for absolutely straight paths, will be shorter; +
+ + 078    2. It is not even quite the same as the length of the path *as rendered*, +
+ + 079    since paths will generally be rendered as spline curves." +
+ + 080    [path] +
+ + 081    (if +
+ + 082      (path? path) +
+ + 083      (reduce + (map e/length (path->edges path))) +
+ + 084      (throw (IllegalArgumentException. "Not a path!"))))
diff --git a/docs/cloverage/walkmap/polygon.clj.html b/docs/cloverage/walkmap/polygon.clj.html index 2bb0272..9eae563 100644 --- a/docs/cloverage/walkmap/polygon.clj.html +++ b/docs/cloverage/walkmap/polygon.clj.html @@ -11,55 +11,259 @@ 002    "Essentially the specification for things we shall consider to be polygons."

- 003    (:require [walkmap.vertex :refer [vertex?]])) + 003    (:require [clojure.string :as s] +
+ + 004              [walkmap.edge :as e] +
+ + 005              [walkmap.tag :as t] +
+ + 006              [walkmap.utils :refer [kind-type]] +
+ + 007              [walkmap.vertex :refer [vertex vertex?]]))
- 004   + 008  
- 005  (defn polygon? + 009  (defn polygon?
- 006    "True if `o` satisfies the conditions for a polygon. A polygon shall be a + 010    "True if `o` satisfies the conditions for a polygon. A polygon shall be a
- 007    map which has a value for the key `:vertices`, where that value is a sequence + 011    map which has a value for the key `:vertices`, where that value is a sequence
- 008    of vertices." + 012    of vertices."
- 009    [o] + 013    [o]
- 010    (let + 014    (let
- 011      [v (:vertices o)] + 015      [v (:vertices o)]
- 012      (and + 016      (and
- 013        (coll? v) + 017        (coll? v)
- 014        (> (count v) 2) + 018        (> (count v) 2)
- 015        (every? vertex? v) + 019        (every? vertex? v)
- 016        (:id o) + 020        (:walkmap.id/id o)
- 017        (or (nil? (:kind o)) (= (:kind o) :polygon))))) + 021        (or (nil? (:kind o)) (= (:kind o) :polygon)))))
- 018   + 022   +
+ + 023  (defn triangle? +
+ + 024    "True if `o` satisfies the conditions for a triangle. A triangle shall be a +
+ + 025    polygon with exactly three vertices." +
+ + 026    [o] +
+ + 027    (and +
+ + 028      (coll? o) +
+ + 029      (= (count (:vertices o)) 3)))
- 019   + 030   +
+ + 031  (defn polygon +
+ + 032    "Return a polygon constructed from these `vertices`." +
+ + 033    [vertices] +
+ + 034    (when-not (every? vertex? vertices) +
+ + 035      (throw (IllegalArgumentException. +
+ + 036               (str +
+ + 037                 "Each item on vertices must be a vertex: " +
+ + 038                 (s/join " " (map kind-type (remove vertex? vertices))))))) +
+ + 039    {:vertices vertices :walkmap.id/id (keyword (gensym "poly")) :kind :polygon}) +
+ + 040   +
+ + 041  (defn gradient +
+ + 042    "Return a polygon like `triangle` but with a key `:gradient` whose value is a +
+ + 043    unit vector representing the gradient across `triangle`." +
+ + 044    [triangle] +
+ + 045    (when-not (triangle? triangle) +
+ + 046      (throw (IllegalArgumentException. +
+ + 047               (s/join " " ["Must be a triangle:" (kind-type triangle)])))) +
+ + 048    (let [order (sort #(max (:z %1) (:z %2)) (:vertices triangle)) +
+ + 049          highest (first order) +
+ + 050          lowest (last order)] +
+ + 051       (assoc triangle :gradient (e/unit-vector (e/edge lowest highest))))) +
+ + 052   +
+ + 053  (defn triangle-centre +
+ + 054    "Return a canonicalised `facet` (i.e. a triangular polygon) with an added +
+ + 055    key `:centre` whose value represents the centre of this facet in 3 +
+ + 056    dimensions. This only works for triangles, so is here not in +
+ + 057    `walkmap.polygon`. It is an error (although no exception is currently +
+ + 058    thrown) if the object past is not a triangular polygon." +
+ + 059    [facet] +
+ + 060    (when-not (triangle? facet) +
+ + 061      (throw (IllegalArgumentException. +
+ + 062               (s/join " " ["Must be a triangle:" (kind-type facet)])))) +
+ + 063    (let [vs (:vertices facet) +
+ + 064          v1 (first vs) +
+ + 065          opposite (e/edge (nth vs 1) (nth vs 2)) +
+ + 066          oc (e/centre opposite)] +
+ + 067        (assoc +
+ + 068        facet +
+ + 069        :centre +
+ + 070        (vertex +
+ + 071          (+ (:x v1) (* (- (:x oc) (:x v1)) 2/3)) +
+ + 072          (+ (:y v1) (* (- (:y oc) (:y v1)) 2/3)) +
+ + 073          (+ (:z v1) (* (- (:z oc) (:z v1)) 2/3)))))) +
+ + 074   +
+ + 075  (defn centre +
+ + 076    [poly] +
+ + 077    (when-not (polygon? poly) +
+ + 078          (throw (IllegalArgumentException. +
+ + 079               (s/join " " ["Must be a polygon:" (kind-type poly)])))) +
+ + 080    (case (count (:vertices poly)) +
+ + 081      3 (triangle-centre poly) +
+ + 082      ;; else +
+ + 083      (throw +
+ + 084        (UnsupportedOperationException. +
+ + 085          "The general case of centre for polygons is not yet implemented.")))) +
+ + 086   +
+ + 087  
diff --git a/docs/cloverage/walkmap/read_svg.clj.html b/docs/cloverage/walkmap/read_svg.clj.html new file mode 100644 index 0000000..0fd16df --- /dev/null +++ b/docs/cloverage/walkmap/read_svg.clj.html @@ -0,0 +1,299 @@ + + + + walkmap/read_svg.clj + + + + 001  (ns walkmap.read-svg +
+ + 002    "Utility functions for  scalable vector graphics (SVG) into walkmap +
+ + 003    structures." +
+ + 004    (:require [clojure.data.zip :as dz] +
+ + 005              [clojure.data.zip.xml :as zx] +
+ + 006              [clojure.java.io :as io] +
+ + 007              [clojure.string :as s] +
+ + 008              [clojure.xml :as x] +
+ + 009              [clojure.zip :as z] +
+ + 010              [taoensso.timbre :as l] +
+ + 011              [walkmap.path :refer [path]] +
+ + 012              [walkmap.tag :refer [tag]] +
+ + 013              [walkmap.utils :refer [kind-type truncate]] +
+ + 014              [walkmap.vertex :refer [vertex vertex?]])) +
+ + 015   +
+ + 016  (defn upper-case? +
+ + 017    [s] +
+ + 018    (every? #(Character/isUpperCase %) s)) +
+ + 019   +
+ + 020  (defn match->vertex +
+ + 021    [match-vector x y] +
+ + 022    (when-not (empty? match-vector) +
+ + 023      (let [command (nth match-vector 1) +
+ + 024            xcoord (read-string (nth match-vector 2)) +
+ + 025            ycoord (read-string (nth match-vector 3)) +
+ + 026            ;; upper case command letters mean the coordinates that follow are +
+ + 027            ;; absolute; lower case, relative. +
+ + 028            x' (if (upper-case? command) xcoord (+ x xcoord)) +
+ + 029            y' (if (upper-case? command) ycoord (+ y ycoord))] +
+ + 030        (case (s/lower-case command) +
+ + 031          ("m" "l") {:vertex (vertex x' y') :x x' :y y'} +
+ + 032          nil)))) +
+ + 033   +
+ + 034  (defn command-string->vertices +
+ + 035    "Return the destination of each successive line (`l`, `L`) and move (`m`, `M`) +
+ + 036    command in this string `s`, expected to be an SVG path command string." +
+ + 037    [s] +
+ + 038    (let [cmd-matcher ;; matches a 'command' in the string: a letter followed by +
+ + 039          ;;spaces and numbers +
+ + 040          (re-matcher #"[a-zA-Z][^a-zA-Z]*" s) +
+ + 041          seg-pattern ;; matches a command which initiates a move of the current +
+ + 042          ;; position. +
+ + 043          #"([a-zA-Z]) +([-+]?[0-9]*\.?[0-9]+) +([-+]?[0-9]*\.?[0-9]+) +"] +
+ + 044      (loop [match (re-find cmd-matcher) +
+ + 045             result [] +
+ + 046             x 0 +
+ + 047             y 0] +
+ + 048        (if-not match +
+ + 049          (filter vertex? result) +
+ + 050          (let [m (match->vertex (re-find seg-pattern match) x y)] +
+ + 051            (recur (re-find cmd-matcher)    ;loop with 2 new arguments +
+ + 052                   (conj result (:vertex m)) +
+ + 053                   (or (:x m) x) +
+ + 054                   (or (:y m) y))))))) +
+ + 055   +
+ + 056  (defn path-elt->path +
+ + 057    "Given the SVG path element `elt`, return a walkmap path structure +
+ + 058    representing the line (`l`, `L`) and move (`m`, `M`) commands in +
+ + 059    that path." +
+ + 060    [elt] +
+ + 061    (if (= (:tag elt) :path) +
+ + 062      (let [vs (command-string->vertices (-> elt :attrs :d)) +
+ + 063            p  (when-not (empty? vs) (apply path vs))] +
+ + 064        (if (and p (-> elt :attrs :class)) +
+ + 065          (tag p (map keyword (s/split (-> elt :attrs :class) #" "))) +
+ + 066          p)) +
+ + 067      (throw (IllegalArgumentException. +
+ + 068               (str "Must be an SVG `path` element: " elt))))) +
+ + 069   +
+ + 070  (defn progeny +
+ + 071    "Return all the nodes in the XML structure below this `elt` which match +
+ + 072    this `predicate`." +
+ + 073    ;; the name `descendants` is bound in `clojure.core` for something quite +
+ + 074    ;; different, and I chose not to rebind it. +
+ + 075    [elt predicate] +
+ + 076    (if +
+ + 077      (apply predicate (list elt)) +
+ + 078      (list elt) +
+ + 079      (reduce +
+ + 080        concat +
+ + 081        (remove +
+ + 082          empty? +
+ + 083          (map +
+ + 084            #(progeny % predicate) +
+ + 085            (:content elt)))))) +
+ + 086   +
+ + 087  (defn read-svg +
+ + 088    ;; I tried to get this working with all the clever zip stuff in +
+ + 089    ;; `clojure.zip`, `clojure.data.zip`, and so on. It would probably have +
+ + 090    ;; been more elegant, but it kept crashing out of heap space on even +
+ + 091    ;; quite small XML files. So I've implemented my own solution. +
+ + 092    ([file-name] +
+ + 093     (read-svg file-name nil)) +
+ + 094    ([file-name map-kind] +
+ + 095      (let [xml (x/parse (io/file file-name)) +
+ + 096            paths (progeny xml #(= (:tag %) :path))] +
+ + 097        (remove nil? (map path-elt->path paths))))) +
+ + diff --git a/docs/cloverage/walkmap/routing.clj.html b/docs/cloverage/walkmap/routing.clj.html new file mode 100644 index 0000000..ea31cf3 --- /dev/null +++ b/docs/cloverage/walkmap/routing.clj.html @@ -0,0 +1,62 @@ + + + + walkmap/routing.clj + + + + 001  (ns walkmap.routing +
+ + 002    "Finding optimal routes to traverse a map." +
+ + 003      (:require [walkmap.path :as p] +
+ + 004              [walkmap.polygon :as q] +
+ + 005              [walkmap.stl :as s] +
+ + 006              [walkmap.utils :as u] +
+ + 007              [walkmap.vertex :as v])) +
+ + 008   +
+ + 009  ;; Breadth first search is a good algorithm for terrain in which all steps have +
+ + 010  ;; equal, but in our world (like the real world), they don't. +
+ + 011   +
+ + 012  ;; Reading list: +
+ + 013  ;; +
+ + 014  ;; https://en.wikipedia.org/wiki/A*_search_algorithm +
+ + 015  ;; https://www.redblobgames.com/pathfinding/a-star/introduction.html +
+ + 016  ;; https://faculty.nps.edu/ncrowe/opmpaper2.htm +
+ + 017  ;; +
+ + 018  ;; See https://simon-brooke.github.io/the-great-game/codox/Pathmaking.html +
+ + diff --git a/docs/cloverage/walkmap/stl.clj.html b/docs/cloverage/walkmap/stl.clj.html index 0684c28..5240aa8 100644 --- a/docs/cloverage/walkmap/stl.clj.html +++ b/docs/cloverage/walkmap/stl.clj.html @@ -23,559 +23,604 @@ 006              [org.clojars.smee.binary.core :as b]

- 007              [taoensso.timbre :as l :refer [info error spy]] + 007              [taoensso.timbre :as l]
008              [walkmap.edge :as e]
- 009              [walkmap.polygon :refer [polygon?]] + 009              [walkmap.ocean :as o]
- 010              [walkmap.tag :refer [tag]] + 010              [walkmap.polygon :refer [centre gradient polygon?]]
- 011              [walkmap.vertex :as v]) + 011              [walkmap.superstructure :refer [store]]
- 012    (:import org.clojars.smee.binary.core.BinaryIO + 012              [walkmap.tag :refer [tag]]
- 013             java.io.DataInput)) + 013              [walkmap.utils :as u] +
+ + 014              [walkmap.vertex :as v]) +
+ + 015    (:import org.clojars.smee.binary.core.BinaryIO +
+ + 016             java.io.DataInput))
- 014   + 017  
- 015  (defn stl? + 018  (defn stl?
- 016    "True if `o` is recogniseable as an STL structure. An STL structure must + 019    "True if `o` is recogniseable as an STL structure. An STL structure must
- 017    have a key `:facets`, whose value must be a sequence of polygons; and + 020    have a key `:facets`, whose value must be a sequence of polygons; and
- 018    may have a key `:header` whose value should be a string, and/or a key + 021    may have a key `:header` whose value should be a string, and/or a key
- 019    `:count`, whose value should be a positive integer. + 022    `:count`, whose value should be a positive integer.
- 020   + 023  
- 021    If `verify-count?` is passed and is not `false`, verify that the value of + 024    If `verify-count?` is passed and is not `false`, verify that the value of
- 022    the `:count` header is equal to the number of facets." + 025    the `:count` header is equal to the number of facets."
- 023    ([o] + 026    ([o]
- 024     (stl? o false)) + 027     (stl? o false))
- 025    ([o verify-count?] + 028    ([o verify-count?]
- 026     (and + 029     (and
- 027       (map? o) + 030       (map? o)
- 028       (:facets o) + 031       (:facets o)
- 029       (every? polygon? (:facets o)) + 032       (every? polygon? (:facets o))
- 030       (if (:header o) (string? (:header o)) true) + 033       (if (:header o) (string? (:header o)) true)
- 031       (if (:count o) (integer? (:count o)) true) + 034       (if (:count o) (integer? (:count o)) true)
- 032       (or (nil? (:kind o)) (= (:kind o) :stl)) + 035       (or (nil? (:kind o)) (= (:kind o) :stl))
- 033       (if verify-count? (= (:count o) (count (:facets o))) true)))) + 036       (if verify-count? (= (:count o) (count (:facets o))) true))))
- 034   + 037  
- 035  (def vect + 038  (def vect
- 036    "A codec for vectors within a binary STL file." + 039    "A codec for vectors within a binary STL file."
- 037    (b/ordered-map + 040    (b/ordered-map
- 038      :x :float-le + 041      :x :float-le
- 039      :y :float-le + 042      :y :float-le
- 040      :z :float-le)) + 043      :z :float-le))
- 041   + 044  
- 042  (def facet + 045  (def facet
- 043    "A codec for a facet (triangle) within a binary STL file." + 046    "A codec for a facet (triangle) within a binary STL file."
- 044    (b/ordered-map + 047    (b/ordered-map
- 045      :normal vect + 048      :normal vect
- 046      :vertices [vect vect vect] + 049      :vertices [vect vect vect]
- 047      :abc :ushort-le)) + 050      :abc :ushort-le))
- 048   + 051  
- 049  (def binary-stl + 052  (def binary-stl
- 050    "A codec for binary STL files" + 053    "A codec for binary STL files"
- 051    (b/ordered-map + 054    (b/ordered-map
- 052     :header (b/string "ISO-8859-1" :length 80) ;; for the time being we neither know nor care what's in this. + 055     :header (b/string "ISO-8859-1" :length 80) ;; for the time being we neither know nor care what's in this.
- 053     :count :uint-le + 056     :count :uint-le
- 054     :facets (b/repeated facet))) + 057     :facets (b/repeated facet)))
- 055   + 058  
- 056  (defn centre + 059  (defn canonicalise
- 057    "Return a canonicalised `facet` (i.e. a triangular polygon) with an added + 060    "Objects read in from STL won't have all the keys/values we need them to have.
- 058    key `:centre` whose value represents the centre of this facet in 3 + 061    `o` may be a map (representing a facet or a vertex), or a sequence of such maps;
- 059    dimensions. This only works for triangles, so is here not in + 062    if it isn't recognised it is at present just returned unchanged. `map-kind`, if
- 060    `walkmap.polygon`. It is an error (although no exception is currently + 063    passed, must be a keyword indicating the value represented by the `z` axis
- 061    thrown) if the object past is not a triangular polygon." + 064    (defaults to `:height`). It is an error, and an exception will be thrown, if
- 062    [facet] + 065    `map-kind` is not a keyword."
- 063    (let [vs (:vertices facet) -
- - 064          v1 (first vs) -
- - 065          opposite (e/edge (nth vs 1) (nth vs 2)) -
- - 066          oc (e/centre opposite)] -
- - 067      (assoc -
- - 068        facet + 066    ([o] (canonicalise o :height))
- 069        :centre + 067    ([o map-kind]
- - 070        (v/vertex -
- - 071          (+ (:x v1) (* (- (:x oc) (:x v1)) 2/3)) -
- - 072          (+ (:y v1) (* (- (:y oc) (:y v1)) 2/3)) -
- - 073          (+ (:z v1) (* (- (:z oc) (:z v1)) 2/3)))))) -
- - 074   -
- - 075  (defn canonicalise + + 068     (canonicalise o map-kind (v/vertex 1 1 1)))
- 076    "Objects read in from STL won't have all the keys/values we need them to have. -
- - 077    `o` may be a map (representing a facet or a vertex), or a sequence of such maps; -
- - 078    if it isn't recognised it is at present just returned unchanged. `map-kind`, if -
- - 079    passed, must be a keyword indicating the value represented by the `z` axis -
- - 080    (defaults to `:height`). It is an error, and an exception will be thrown, if -
- - 081    `map-kind` is not a keyword." -
- - 082    ([o] (canonicalise o :height)) -
- - 083    ([o map-kind] + 069    ([o map-kind scale-vertex]
- 084     (when-not + 070     (when-not
- 085       (keyword? map-kind) + 071       (keyword? map-kind)
- 086       (throw (IllegalArgumentException. + 072       (throw (IllegalArgumentException.
- - 087                (subs (str "Must be a keyword: " (or map-kind "nil")) 0 80)))) + + 073                (u/truncate (str "Must be a keyword: " (or map-kind "nil")) 80))))
- 088     (cond + 074     (cond
- 089       (and (coll? o) (not (map? o))) (map #(canonicalise % map-kind) o) + 075       (and (coll? o) (not (map? o))) (map #(canonicalise % map-kind) o)
- 090       ;; if it has :facets it's an STL structure, but it doesn't yet conform to `stl?` + 076       ;; if it has :facets it's an STL structure, but it doesn't yet conform to `stl?`
- 091       (:facets o) (assoc o + 077       (:facets o) (assoc o
- 092                     :kind :stl + 078                     :kind :stl
- 093                     :id (or (:id o) (keyword (gensym "stl"))) + 079                     :walkmap.id/id (or (:walkmap.id/id o) (keyword (gensym "stl")))
- 094                     :facets (canonicalise (:facets o) map-kind)) + 080                     :facets (canonicalise (:facets o) map-kind))
- 095       ;; if it has :vertices it's a polygon, but it doesn't yet conform to `polygon?` + 081       ;; if it has :vertices it's a polygon, but it may not yet conform to
- - 096       (:vertices o) (centre + + 082       ;; `polygon?` +
+ + 083       (:vertices o) (let [f (gradient +
+ + 084                               (centre
- 097                       (tag + 085                                 (tag
- 098                         (assoc o + 086                                   (assoc o
- - 099                           :id (or (:id o) (keyword (gensym "poly"))) + + 087                                     :walkmap.id/id (or +
+ + 088                                                      (:walkmap.id/id o) +
+ + 089                                                      (keyword (gensym "poly")))
- 100                           :kind :polygon -
- - 101                           :vertices (canonicalise (:vertices o) map-kind)) -
- - 102                         :facet map-kind)) -
- - 103       ;; if it has a value for :x it's a vertex, but it doesn't yet conform to `vertex?` -
- - 104       (:x o) (v/canonicalise o) -
- - 105       ;; shouldn't happen -
- - 106       :else o))) -
- - 107   -
- - 108  (defn decode-binary-stl -
- - 109    "Parse a binary STL file from this `filename` and return an STL structure -
- - 110    representing its contents. `map-kind`, if passed, must be a keyword -
- - 111    indicating the value represented by the `z` axis (defaults to `:height`). -
- - 112    It is an error, and an exception will be thrown, if `map-kind` is not a -
- - 113    keyword. -
- - 114   -
- - 115    **NOTE** that we've no way of verifying that the input file is binary STL -
- - 116    data, if it is not this will run but will return garbage." -
- - 117    ([filename] -
- - 118     (decode-binary-stl filename :height)) -
- - 119    ([filename map-kind] -
- - 120     (when-not -
- - 121       (keyword? map-kind) -
- - 122       (throw (IllegalArgumentException. -
- - 123                (subs (str "Must be a keyword: " (or map-kind "nil")) 0 80)))) -
- - 124     (let [in (io/input-stream filename)] -
- - 125       (canonicalise (b/decode binary-stl in) map-kind)))) -
- - 126   + 090                                     :kind :polygon
- 127  (defn- vect->str [prefix v] + 091                                     :vertices (canonicalise +
+ + 092                                                 (:vertices o) +
+ + 093                                                 map-kind)) +
+ + 094                                   :facet map-kind)))] +
+ + 095                       (if (o/ocean? f) +
+ + 096                         (tag f :ocean :no-traversal) +
+ + 097                         f)) +
+ + 098       ;; if it has a value for :x it's a vertex, but it may not yet conform +
+ + 099       ;; to `vertex?`; it should also be scaled using the scale-vertex, if any. +
+ + 100       (:x o) (let [c (v/canonicalise o)] +
+ + 101                (if scale-vertex +
+ + 102                  (v/vertex* c scale-vertex) +
+ + 103                  c)) +
+ + 104       ;; shouldn't happen +
+ + 105       :else o))) +
+ + 106   +
+ + 107  (defn decode-binary-stl +
+ + 108    "Parse a binary STL file from this `filename` and return an STL structure +
+ + 109    representing its contents. `map-kind`, if passed, must be a keyword +
+ + 110    or sequence of keywords indicating the semantic value represented by the `z` +
+ + 111    axis (defaults to `:height`). +
+ + 112   +
+ + 113    If `superstructure` is supplied and is a map, the generated STL structure +
+ + 114    will be stored in that superstructure, which will be returned. +
+ + 115   +
+ + 116    If `scale-vertex` is supplied, it must be a three dimensional vertex (i.e. +
+ + 117    the `:z` key must have a numeric value) representing the amount by which +
+ + 118    each of the vertices read from the STL will be scaled. +
+ + 119   +
+ + 120    It is an error, and an exception will be thrown, if `map-kind` is not a +
+ + 121    keyword or sequence of keywords. +
+ + 122   +
+ + 123    **NOTE** that we've no way of verifying that the input file is binary STL +
+ + 124    data, if it is not this will run but will return garbage." +
+ + 125    ([filename] +
+ + 126     (decode-binary-stl filename :height)) +
+ + 127    ([filename map-kind] +
+ + 128     (when-not +
+ + 129       (keyword? map-kind) +
+ + 130       (throw (IllegalArgumentException. +
+ + 131                (u/truncate (str "Must be a keyword: " (or map-kind "nil")) 80)))) +
+ + 132     (decode-binary-stl filename map-kind nil)) +
+ + 133    ([filename mapkind superstucture] +
+ + 134     (decode-binary-stl filename mapkind superstucture (v/vertex 1 1 1))) +
+ + 135    ([filename map-kind superstructure scale-vertex] +
+ + 136     (let [in (io/input-stream filename) +
+ + 137           stl (canonicalise (b/decode binary-stl in) map-kind scale-vertex)] +
+ + 138       (if +
+ + 139         (map? superstructure) +
+ + 140         (store stl superstructure) +
+ + 141         stl)))) +
+ + 142   +
+ + 143  (defn- vect->str [prefix v]
- 128    (str prefix " " (:x v) " " (:y v) " " (:z v) "\n")) + 144    (str prefix " " (:x v) " " (:y v) " " (:z v) "\n"))
- 129   + 145  
- 130  (defn- facet2str [tri] + 146  (defn- facet2str [tri]
- 131    (str + 147    (str
- 132      (vect->str "facet normal" (:normal tri)) + 148      (vect->str "facet normal" (:normal tri))
- 133      "outer loop\n" + 149      "outer loop\n" +
+ + 150      (s/join
- 134      (apply str -
- - 135             (map + 151        (map
- 136               #(vect->str "vertex" %) + 152          #(vect->str "vertex" %)
- 137               (:vertices tri))) + 153          (:vertices tri)))
- 138      "endloop\nendfacet\n")) + 154      "endloop\nendfacet\n"))
- 139   + 155  
- 140  (defn stl->ascii + 156  (defn stl->ascii
- 141    "Return as a string an ASCII rendering of the `stl` structure." + 157    "Return as a string an ASCII rendering of the `stl` structure."
- 142    ([stl] + 158    ([stl]
- 143     (stl->ascii stl "unknown")) + 159     (stl->ascii stl "unknown"))
- 144    ([stl solidname] + 160    ([stl solidname]
- 145     (str + 161     (str
- 146       "solid " + 162       "solid "
- 147       solidname + 163       solidname
- 148       (s/trim (:header stl)) + 164       (s/trim (:header stl))
- 149       "\n" + 165       "\n"
- 150       (apply -
- - 151         str + 166       (s/join
- 152         (map + 167         (map
- 153           facet2str + 168           facet2str
- 154           (:facets stl))) + 169           (:facets stl)))
- 155       "endsolid " + 170       "endsolid "
- 156       solidname + 171       solidname
- 157       "\n"))) + 172       "\n")))
- 158   + 173  
- 159  (defn write-ascii-stl + 174  (defn write-ascii-stl
- 160    "Write an `stl` structure as read by `decode-binary-stl` to this + 175    "Write an `stl` structure as read by `decode-binary-stl` to this
- 161    `filename` as ASCII encoded STL." + 176    `filename` as ASCII encoded STL."
- 162    ([filename stl] + 177    ([filename stl]
- 163     (let [b (fs/base-name filename true)] + 178     (let [b (fs/base-name filename true)]
- 164       (write-ascii-stl + 179       (write-ascii-stl
- 165         filename stl + 180         filename stl
- 166         (subs b 0 (or (s/index-of b ".") (count b)))))) + 181         (subs b 0 (or (s/index-of b ".") (count b))))))
- 167    ([filename stl solidname] + 182    ([filename stl solidname]
- 168     (l/debug "Solid name is " solidname) + 183     (l/debug "Solid name is " solidname)
- 169     (spit + 184     (spit
- 170       filename + 185       filename
- 171       (stl->ascii stl solidname)))) + 186       (stl->ascii stl solidname))))
- 172   + 187  
- 173  (defn binary-stl-to-ascii + 188  (defn binary-stl-to-ascii
- 174    "Convert the binary STL file indicated by `in-filename`, and write it to + 189    "Convert the binary STL file indicated by `in-filename`, and write it to
- 175    `out-filename`, if specified; otherwise, to a file with the same basename + 190    `out-filename`, if specified; otherwise, to a file with the same basename
- 176    as `in-filename` but the extension `.ascii.stl`." + 191    as `in-filename` but the extension `.ascii.stl`."
- 177    ([in-filename] + 192    ([in-filename]
- 178     (let [[_ ext] (fs/split-ext in-filename)] + 193     (let [[_ ext] (fs/split-ext in-filename)]
- 179       (binary-stl-to-ascii + 194       (binary-stl-to-ascii
- 180         in-filename + 195         in-filename
- 181         (str + 196         (str
- 182           (subs + 197           (subs
- 183             in-filename + 198             in-filename
- 184             0 + 199             0
- 185             (or + 200             (or
- 186               (s/last-index-of in-filename ".") + 201               (s/last-index-of in-filename ".")
- 187               (count in-filename))) + 202               (count in-filename)))
- 188           ".ascii" + 203           ".ascii"
- 189           ext)))) + 204           ext))))
- 190    ([in-filename out-filename] + 205    ([in-filename out-filename]
- 191     (write-ascii-stl out-filename (decode-binary-stl in-filename)))) + 206     (write-ascii-stl out-filename (decode-binary-stl in-filename))))
diff --git a/docs/cloverage/walkmap/superstructure.clj.html b/docs/cloverage/walkmap/superstructure.clj.html index e2963e8..a83ad6d 100644 --- a/docs/cloverage/walkmap/superstructure.clj.html +++ b/docs/cloverage/walkmap/superstructure.clj.html @@ -11,253 +11,547 @@ 002    "single indexing structure for walkmap objects"

- 003    (:require [walkmap.path :as p] + 003    (:require [clojure.walk :refer [postwalk]]
- 004              [walkmap.polygon :as q] + 004              [taoensso.timbre :as l]
- 005              [walkmap.stl :as s] + 005              [walkmap.path :as p]
- 006              [walkmap.utils :as u] + 006              [walkmap.polygon :as q]
- 007              [walkmap.vertex :as v])) + 007              [walkmap.utils :as u] +
+ + 008              [walkmap.vertex :as v]))
- 008   + 009  
- 009  ;; TODO: Think about reification/dereification. How can we cull a polygon, if + 010  ;; TODO: Think about reification/dereification. How can we cull a polygon, if
- 010  ;; some vertices still index it? I *think* that what's needed is that when + 011  ;; some vertices still index it? I *think* that what's needed is that when
- 011  ;; we store something in the superstructure, we replace all its vertices (and + 012  ;; we store something in the superstructure, we replace all its vertices (and
- 012  ;; other dependent structures, if any with their ids - as well as, obviously, + 013  ;; other dependent structures, if any with their ids - as well as, obviously,
- 013  ;; adding/merging those vertices/dependent structures into the superstructure + 014  ;; adding/merging those vertices/dependent structures into the superstructure
- 014  ;; as first class objects in themselves. That means, for each identified thing, + 015  ;; as first class objects in themselves. That means, for each identified thing,
- 015  ;; the superstructure only contains one copy of it. + 016  ;; the superstructure only contains one copy of it.
- 016  ;; + 017  ;;
- 017  ;; The question then is, when we want to do things with those objects, do we + 018  ;; The question then is, when we want to do things with those objects, do we
- 018  ;; exteract a copy with its dependent structures fixed back up (reification), + 019  ;; exteract a copy with its dependent structures fixed back up (reification),
- 019  ;; or do we indirect through the superstructure every time we want to access + 020  ;; or do we indirect through the superstructure every time we want to access
- 020  ;; them? In a sense, the copy in the superstructure is the 'one true copy', + 021  ;; them? In a sense, the copy in the superstructure is the 'one true copy',
- 021  ;; but it may become very difficult then to have one true copy of the + 022  ;; but it may become very difficult then to have one true copy of the
- 022  ;; superstructure - unless we replace the superstructure altogether with a + 023  ;; superstructure - unless we replace the superstructure altogether with a
- 023  ;; database, which may be the Right Thing To Do. + 024  ;; database, which may be the Right Thing To Do.
- 024   + 025   +
+ + 026  (def vertex-index ::vertex-index) +
+ + 027  
- 025  (defn index-vertex + 028  (defn vertices
- 026    "Return a superstructure like `s` in which object `o` is indexed by vertex + 029    "If `o` is an object with vertices, return those vertices, else nil."
- 027    `v`. It is an error (and an exception may be thrown) if + 030    [o]
- - 028   -
- - 029    1. `s` is not a map; -
- - 030    2. `o` is not a map; -
- - 031    3. `o` does not have a value for the key `:id`; -
- - 032    4. `v` is not a vertex." -
- - 033    [s o v] + + 031    (cond
- 034    (if-not (v/vertex? o) + 032      (v/vertex? o) (list o) +
+ + 033      (q/polygon? o) (:vertices o) +
+ + 034      (p/path? o) (:vertices o))) +
+ + 035   +
+ + 036  (defn index-vertex +
+ + 037    "Return a superstructure like `s` in which object `o` is indexed by vertex +
+ + 038    `v`. It is an error (and an exception may be thrown) if +
+ + 039   +
+ + 040    1. `s` is not a map; +
+ + 041    2. `o` is not a map; +
+ + 042    3. `o` does not have a value for the key `:walkmap.id/id`; +
+ + 043    4. `v` is not a vertex." +
+ + 044    [s o v] +
+ + 045    (if-not (v/vertex? o) +
+ + 046      (if (:walkmap.id/id o) +
+ + 047        (if (v/vertex? v) +
+ + 048          (let [vi (or (::vertex-index s) {}) +
+ + 049                current (or (vi (:walkmap.id/id v)) {})] +
+ + 050            ;; deep-merge doesn't merge sets, only maps; so at this +
+ + 051            ;; stage we need to build a map. +
+ + 052            (assoc vi (:walkmap.id/id v) (assoc current (:walkmap.id/id o) (:walkmap.id/id v))))
- 035      (if (:id o) -
- - 036        (if (v/vertex? v) + 053          (throw (IllegalArgumentException. "Not a vertex: " v)))
- 037          (let [vi (or (:vertex-index s) {}) -
- - 038                current (or (vi (:id v)) {})] + 054        (throw (IllegalArgumentException. (u/truncate (str "No `:walkmap.id/id` value: " o) 80))))
- 039            ;; deep-merge doesn't merge sets, only maps; so at this + 055      ;; it shouldn't actually be an error to try to index a vertex, but it
- 040            ;; stage we need to build a map. -
- - 041            (assoc vi (:id v) (assoc current (:id o) (:id v)))) -
- - 042          (throw (IllegalArgumentException. "Not a vertex: " v))) -
- - 043        (throw (IllegalArgumentException. (subs (str "No `:id` value: " o) 0 80)))) -
- - 044      ;; it shouldn't actually be an error to try to index a vertex, but it -
- - 045      ;; also isn't useful to do so, so I'd be inclined to ignore it. + 056      ;; also isn't useful to do so, so I'd be inclined to ignore it.
- 046      (:vertex-index s))) + 057      (::vertex-index s)))
- 047   + 058  
- 048  (defn index-vertices + 059  (defn index-vertices
- 049    "Return a superstructure like `s` in which object `o` is indexed by its + 060    "Return a superstructure like `s` in which object `o` is indexed by its
- 050    vertices. It is an error (and an exception may be thrown) if + 061    vertices. It is an error (and an exception may be thrown) if
- 051   + 062  
- 052    1. `s` is not a map; + 063    1. `s` is not a map;
- 053    2. `o` is not a map; + 064    2. `o` is not a map;
- 054    3. `o` does not have a value for the key `:id`." + 065    3. `o` does not have a value for the key `:walkmap.id/id`."
- 055    [s o] + 066    [s o]
- - 056    (assoc + + 067    (u/deep-merge +
+ + 068      s +
+ + 069      {::vertex-index +
+ + 070       (reduce +
+ + 071         u/deep-merge +
+ + 072         {} +
+ + 073         (map +
+ + 074           #(index-vertex s o %) +
+ + 075           (:vertices o)))})) +
+ + 076   +
+ + 077  (defn in-retrieve +
+ + 078    "Internal guts of `retrieve`, q.v. `x` can be anything; `s` must be a +
+ + 079    walkmap superstructure. TODO: recursive, quite likely to blow the fragile +
+ + 080    Clojure stack. Probably better to do this with `walk`, but I don't yet +
+ + 081    understand that." +
+ + 082    [x s] +
+ + 083    (cond +
+ + 084      ;; if it's a keyword identifying something in s, retrieve that something. +
+ + 085      (keyword? x) (if (s x) +
+ + 086                     (in-retrieve (s x) s) +
+ + 087                     x) +
+ + 088      ;; if it's a map, for every key which is not `:walkmap.id/id`, recurse. +
+ + 089      (map? x) (let [v (reduce +
+ + 090                         (fn [m k] +
+ + 091                           (assoc m k (in-retrieve (x k) s))) +
+ + 092                         {} +
+ + 093                         (keys (dissoc x :walkmap.id/id))) +
+ + 094                     id (:walkmap.id/id x)] +
+ + 095                 ;; if it has an id, bind it to that id in the returned value. +
+ + 096                 (if id +
+ + 097                   (assoc +
+ + 098                     v +
+ + 099                     :walkmap.id/id +
+ + 100                     (:walkmap.id/id x))
- 057      s + 101                   v)) +
+ + 102      (set? x) x ;; TODO: should I search in sets for objects when storing? +
+ + 103      (coll? x) (map #(in-retrieve % s) x) +
+ + 104      :else x)) +
+ + 105   +
+ + 106  (defn retrieve
- 058      :vertex-index + 107    "Retrieve the canonical representation of the object with this `id` from the
- - 059      (reduce + + 108    superstructure `s`." +
+ + 109    [id s] +
+ + 110    (in-retrieve (id s) s)) +
+ + 111   +
+ + 112  (defn in-store-find-objects +
+ + 113    "Return an id -> object map of every object within `o`. Internal to +
+ + 114    `in-store`, q.v. Use at your own peril." +
+ + 115    ([o] +
+ + 116     (in-store-find-objects o {})) +
+ + 117    ([o s] +
+ + 118     (l/debug "Finding objects in:" o) +
+ + 119     (cond +
+ + 120       (set? o) s ;; TODO: should I search in sets for objects when storing? +
+ + 121       (map? o) (if (:walkmap.id/id o) +
+ + 122                  (assoc +
+ + 123                    (in-store-find-objects (vals o) s) +
+ + 124                    (:walkmap.id/id o) +
+ + 125                    o) +
+ + 126                  (in-store-find-objects (vals o) s)) +
+ + 127       (coll? o) (reduce merge s (map #(in-store-find-objects % s) o)) +
+ + 128       :else s))) +
+ + 129   +
+ + 130  (defn in-store-replace-with-keys +
+ + 131    "Return a copy of `o` in which each reified walkmap object within `o` has +
+ + 132    been replaced with the `:walkmap.id/id` of that object. Internal to +
+ + 133    `in-store`, q.v. Use at your own peril." +
+ + 134    [o] +
+ + 135    (assoc +
+ + 136      (postwalk #(or (:walkmap.id/id %) %) (dissoc o :walkmap.id/id)) +
+ + 137      :walkmap.id/id +
+ + 138      (:walkmap.id/id o))) +
+ + 139   +
+ + 140  ;; (in-store-replace-with-keys (p/path (v/vertex 0 0 0) (v/vertex 0 1 2) (v/vertex 3 3 3))) +
+ + 141  ;; (in-store-find-objects (p/path (v/vertex 0 0 0) (v/vertex 0 1 2) (v/vertex 3 3 3))) +
+ + 142   +
+ + 143  (defn store +
+ + 144    "Return a superstructure like `s` with object `o` added. If only one +
+ + 145    argument is supplied it will be assumed to represent `o` and a new +
+ + 146    superstructure will be returned. +
+ + 147   +
+ + 148    It is an error (and an exception may be thrown) if +
+ + 149   +
+ + 150    1. `s` is not a map; +
+ + 151    2. `o` is not a recognisable walkmap object" +
+ + 152    ([o] +
+ + 153     (store o {})) +
+ + 154    ([o s] +
+ + 155     (when-not (:walkmap.id/id o)
- 060        u/deep-merge + 156       (throw +
+ + 157         (IllegalArgumentException.
- 061        (map + 158           (str "Not a walkmap object: no value for `:walkmap.id/id`: " +
+ + 159                (u/kind-type o))))) +
+ + 160     (when-not (map? s) +
+ + 161       (throw +
+ + 162         (IllegalArgumentException. +
+ + 163           (str "Superstructure must be a map: " (u/kind-type s))))) +
+ + 164     (assoc +
+ + 165       (u/deep-merge s (in-store-find-objects o) (index-vertices s o)) +
+ + 166       (:walkmap.id/id o) +
+ + 167       (in-store-replace-with-keys o)))) +
+ + 168   +
+ + 169  (defn search-vertices +
+ + 170    "Search superstructure `s` for vertices within the box defined by vertices +
+ + 171    `minv` and `maxv`. Every coordinate in `minv` must have a lower value than +
+ + 172    the equivalent coordinate in `maxv`. If `d2?` is supplied and not false, +
+ + 173    search only in the x,y projection." +
+ + 174    ([s minv maxv] +
+ + 175     (search-vertices s minv maxv false)) +
+ + 176    ([s minv maxv d2?] +
+ + 177     (let [minv' (if d2? (assoc minv :z Double/NEGATIVE_INFINITY) minv) +
+ + 178           maxv' (if d2? (assoc maxv :z Double/POSITIVE_INFINITY) maxv)] +
+ + 179       (filter
- 062          #(index-vertex s o %) + 180         #(v/within-box? % minv maxv)
- - 063          (u/vertices o))))) + + 181         (filter #(= (:kind %) :vertex) (vals s))))))
- 064   -
- - 065  (defn add-to-superstructure -
- - 066    "Return a superstructure like `s` with object `o` added. If `o` is a collection, -
- - 067    return a superstructure like `s` with each element of `o` added. If only one -
- - 068    argument is supplied it will be assumed to represent `o` and a new -
- - 069    superstructure will be returned. + 182  
- 070   -
- - 071    It is an error (and an exception may be thrown) if -
- - 072   -
- - 073    1. `s` is not a map; -
- - 074    2. `o` is not a map, or a sequence of maps." -
- - 075    ([o] -
- - 076     (add-to-superstructure {} o)) -
- - 077    ([s o] -
- - 078    (cond -
- - 079      (map? o) (let [o' (if (:id o) o (assoc o :id (keyword (gensym "obj"))))] -
- - 080                 (index-vertices (assoc s (:id o') o') o')) -
- - 081      (coll? o) (reduce u/deep-merge (map #(add-to-superstructure s %) o)) -
- - 082      (nil? o) o -
- - 083      :else -
- - 084      (throw (IllegalArgumentException. (str "Don't know how to index " (or (type o) "nil"))))))) -
- - 085   + 183  
diff --git a/docs/cloverage/walkmap/svg.clj.html b/docs/cloverage/walkmap/svg.clj.html index 2d0b77e..c04a8b4 100644 --- a/docs/cloverage/walkmap/svg.clj.html +++ b/docs/cloverage/walkmap/svg.clj.html @@ -17,316 +17,322 @@ 004    (SVG)."

- 005    (:require [clojure.string :as s] + 005    (:require [clojure.java.io :as io]
- 006              [dali.io :as neatly-folded-clock] + 006              [clojure.string :as s]
- 007              [hiccup.core :refer [html]] + 007              [clojure.xml :as x]
- 008              [taoensso.timbre :as l :refer [info error spy]] + 008              [dali.io :as neatly-folded-clock]
- 009              [walkmap.ocean :refer [cull-ocean-facets]] + 009              [hiccup.core :refer [html]]
- 010              [walkmap.polygon :refer [polygon?]] + 010              [taoensso.timbre :as l :refer [info error spy]]
- 011              [walkmap.stl :refer [decode-binary-stl]] + 011              [walkmap.ocean :refer [cull-ocean-facets]]
- 012              [walkmap.vertex :refer [vertex?]])) + 012              [walkmap.polygon :refer [polygon?]] +
+ + 013              [walkmap.stl :refer [decode-binary-stl]] +
+ + 014              [walkmap.vertex :refer [vertex?]]))
- 013   + 015  
- 014  (def ^:dynamic *preferred-svg-render* + 016  (def ^:dynamic *preferred-svg-render*
- 015    "Mainly for debugging dali; switch SVG renderer to use. Expected values: + 017    "Mainly for debugging dali; switch SVG renderer to use. Expected values:
- 016    `:dali`, `:hiccup`." + 018    `:dali`, `:hiccup`."
- 017    :dali) + 019    :dali)
- 018   + 020  
- 019  (defn- facet->svg-poly + 021  (defn- facet->svg-poly
- 020    [facet] + 022    [facet]
- 021    [:polygon + 023    [:polygon
- 022     {:points (s/join " " (map #(str (:x %) "," (:y %)) (:vertices facet)))}]) + 024     {:points (s/join " " (map #(str (:x %) "," (:y %)) (:vertices facet)))}])
- 023   + 025  
- 024  (defn- dali-facet->svg-poly + 026  (defn- dali-facet->svg-poly
- 025    [facet] + 027    [facet]
- 026    (vec + 028    (vec
- 027      (cons + 029      (cons
- 028        :polygon + 030        :polygon
- 029        (map #(vec (list (:x %) (:y %))) (:vertices facet))))) + 031        (map #(vec (list (:x %) (:y %))) (:vertices facet)))))
- 030   + 032  
- 031  (defn dali-stl->svg + 033  (defn dali-stl->svg
- 032    "Format this `stl` as SVG for the `dali` renderer on a page with these + 034    "Format this `stl` as SVG for the `dali` renderer on a page with these
- 033    bounds." + 035    bounds."
- 034    [stl minx maxx miny maxy] + 036    [stl minx maxx miny maxy]
- 035    [:dali/page + 037    [:dali/page
- 036     {:xmlns "http://www.w3.org/2000/svg" + 038     {:xmlns "http://www.w3.org/2000/svg"
- 037      :version "1.2" + 039      :version "1.2"
- 038      :width (- maxx minx) + 040      :width (- maxx minx)
- 039      :height (- maxy miny) + 041      :height (- maxy miny)
- 040      :viewBox (s/join " " (map str [minx miny maxx maxy]))} + 042      :viewBox (s/join " " (map str [minx miny maxx maxy]))}
- 041     (vec + 043     (vec
- 042       (cons + 044       (cons
- 043         :g + 045         :g
- 044         (map + 046         (map
- 045           dali-facet->svg-poly + 047           dali-facet->svg-poly
- 046           (:facets stl))))]) + 048           (:facets stl))))])
- 047   + 049  
- 048  (defn hiccup-stl->svg + 050  (defn hiccup-stl->svg
- 049    "Format this `stl` as SVG for the `hiccup` renderer on a page with these + 051    "Format this `stl` as SVG for the `hiccup` renderer on a page with these
- 050    bounds." + 052    bounds."
- 051    [stl minx maxx miny maxy] + 053    [stl minx maxx miny maxy]
- 052    [:svg + 054    [:svg
- 053     {:xmlns "http://www.w3.org/2000/svg" + 055     {:xmlns "http://www.w3.org/2000/svg"
- 054      :version "1.2" + 056      :version "1.2"
- 055      :width (- maxx minx) + 057      :width (- maxx minx)
- 056      :height (- maxy miny) + 058      :height (- maxy miny)
- 057      :viewBox (s/join " " (map str [minx miny maxx maxy]))} + 059      :viewBox (s/join " " (map str [minx miny maxx maxy]))}
- 058     (vec + 060     (vec
- 059       (cons + 061       (cons
- 060         :g + 062         :g
- 061         (map + 063         (map
- 062           facet->svg-poly + 064           facet->svg-poly
- 063           (:facets stl))))]) + 065           (:facets stl))))])
- 064   + 066  
- 065  (defn stl->svg + 067  (defn stl->svg
- 066    "Convert this in-memory `stl` structure, as read by `decode-binary-stl`, into + 068    "Convert this in-memory `stl` structure, as read by `decode-binary-stl`, into
- 067    an in-memory hiccup representation of SVG structure, and return it." + 069    an in-memory hiccup representation of SVG structure, and return it."
- 068    [stl] + 070    [stl]
- 069    (let [minx (reduce + 071    (let [minx (reduce
- 070                 min + 072                 min
- 071                 (map + 073                 (map
- 072                   #(reduce min (map :x (:vertices %))) + 074                   #(reduce min (map :x (:vertices %)))
- 073                   (:facets stl))) + 075                   (:facets stl)))
- 074          maxx (reduce + 076          maxx (reduce
- 075                 max + 077                 max
- 076                 (map + 078                 (map
- 077                   #(reduce max (map :x (:vertices %))) + 079                   #(reduce max (map :x (:vertices %)))
- 078                   (:facets stl))) + 080                   (:facets stl)))
- 079          miny (reduce + 081          miny (reduce
- 080                 min + 082                 min
- 081                 (map + 083                 (map
- 082                   #(reduce min (map :y (:vertices %))) + 084                   #(reduce min (map :y (:vertices %)))
- 083                   (:facets stl))) + 085                   (:facets stl)))
- 084          maxy (reduce + 086          maxy (reduce
- 085                 max + 087                 max
- 086                 (map + 088                 (map
- 087                   #(reduce max (map :y (:vertices %))) + 089                   #(reduce max (map :y (:vertices %)))
- 088                   (:facets stl)))] + 090                   (:facets stl)))]
- 089      (l/info "Generating SVG for " *preferred-svg-render* " renderer") + 091      (l/info "Generating SVG for " *preferred-svg-render* " renderer")
- 090      (case *preferred-svg-render* + 092      (case *preferred-svg-render*
- 091        :hiccup (hiccup-stl->svg stl minx maxx miny maxy) + 093        :hiccup (hiccup-stl->svg stl minx maxx miny maxy)
- 092        :dali (dali-stl->svg stl minx maxx miny maxy) + 094        :dali (dali-stl->svg stl minx maxx miny maxy)
- 093        (throw (Exception. "Unexpected renderer value: " *preferred-svg-render*))))) + 095        (throw (Exception. "Unexpected renderer value: " *preferred-svg-render*)))))
- 094   + 096  
- 095  (defn binary-stl-file->svg + 097  (defn binary-stl-file->svg
- 096    "Given only an `in-filename`, parse the indicated file, expected to be + 098    "Given only an `in-filename`, parse the indicated file, expected to be
- 097    binary STL, and return an equivalent SVG structure. Given both `in-filename` + 099    binary STL, and return an equivalent SVG structure. Given both `in-filename`
- 098    and `out-filename`, as side-effect write the SVG to the indicated output file." + 100    and `out-filename`, as side-effect write the SVG to the indicated output file."
- 099    ([in-filename] + 101    ([in-filename]
- 100     (stl->svg (cull-ocean-facets (decode-binary-stl in-filename)))) + 102     (stl->svg (cull-ocean-facets (decode-binary-stl in-filename))))
- 101    ([in-filename out-filename] + 103    ([in-filename out-filename]
- 102     (let [s (binary-stl-file->svg in-filename)] + 104     (let [s (binary-stl-file->svg in-filename)]
- 103       (l/info "Emitting SVG with " *preferred-svg-render* " renderer") + 105       (l/info "Emitting SVG with " *preferred-svg-render* " renderer")
- 104       (case *preferred-svg-render* + 106       (case *preferred-svg-render*
- 105         :dali (neatly-folded-clock/render-svg s out-filename) + 107         :dali (neatly-folded-clock/render-svg s out-filename)
- 106         :hiccup (spit out-filename (html s)) + 108         :hiccup (spit out-filename (html s))
- 107         (throw (Exception. "Unexpected renderer value: " *preferred-svg-render*))) + 109         (throw (Exception. "Unexpected renderer value: " *preferred-svg-render*)))
- 108       s))) + 110       s)))
diff --git a/docs/cloverage/walkmap/tag.clj.html b/docs/cloverage/walkmap/tag.clj.html index a395271..32a0cd8 100644 --- a/docs/cloverage/walkmap/tag.clj.html +++ b/docs/cloverage/walkmap/tag.clj.html @@ -17,187 +17,196 @@ 004    This is in an attempt to avoid name clashes with other uses of this key."

- 005    (:require [clojure.set :refer [difference union]])) + 005    (:require [clojure.set :refer [difference union]] +
+ + 006              [taoensso.timbre :as l] +
+ + 007              [walkmap.utils :refer [kind-type]]))
- 006   + 008  
- 007  (defn tagged? + 009  (defn tagged?
- 008    "True if this `object` is tagged with each of these `tags`. It is an error + 010    "True if this `object` is tagged with each of these `tags`. It is an error
- 009    (and an exception will be thrown) if + 011    (and an exception will be thrown) if
- 010   + 012  
- 011    1. `object` is not a map; + 013    1. `object` is not a map;
- 012    2. any of `tags` is not a keyword." + 014    2. any of `tags` is not a keyword."
- 013    [object & tags] + 015    [object & tags]
- - 014    (if + + 016    (when-not (map? object)
- - 015      (map? object) + + 017      (throw (IllegalArgumentException.
- - 016      (if + + 018               (str "Must be a map: " (kind-type object)))))
- 017        (every? keyword? tags) + 019    (let [tags' (flatten tags)] +
+ + 020      (when-not (every? keyword? tags') +
+ + 021        (throw (IllegalArgumentException. +
+ + 022                 (str "Must be keywords: " (map kind-type tags')))))
- 018        (let [ot (::tags object)] + 023        (let [ot (::tags object)]
- 019          (and + 024          (and
- 020            (set? ot) + 025            (set? ot)
- 021            (every? ot tags))) + 026            (every? ot tags')))))
- - 022        (throw (IllegalArgumentException. + + 027  
- - 023                 (str "Must be keyword(s): " (map type tags))))) + + 028  (defn tag
- - 024      (throw (IllegalArgumentException. + + 029    "Return an object like this `object` but with these `tags` added to its tags, +
+ + 030    if they are not already present. It is an error (and an exception will be +
+ + 031    thrown) if +
+ + 032   +
+ + 033    1. `object` is not a map; +
+ + 034    2. any of `tags` is not a keyword or sequence of keywords. +
+ + 035   +
+ + 036    It's legal to include sequences of keywords in `tags`, so that users can do +
+ + 037    useful things like `(tag obj (map keyword some-strings))`." +
+ + 038    [object & tags] +
+ + 039    (l/debug "Tagging" (kind-type object) "with" tags)
- 025               (str "Must be a map: " (type object)))))) + 040    (when-not (map? object)
- - 026   + + 041      (throw (IllegalArgumentException.
- - 027  (defn tag -
- - 028    "Return an object like this `object` but with these `tags` added to its tags, -
- - 029    if they are not already present. It is an error (and an exception will be -
- - 030    thrown) if -
- - 031   -
- - 032    1. `object` is not a map; -
- - 033    2. any of `tags` is not a keyword." -
- - 034    [object & tags] -
- - 035    (if -
- - 036      (map? object) -
- - 037      (if + + 042               (str "Must be a map: " (kind-type object)))))
- 038        (every? keyword? tags) -
- - 039        (assoc object ::tags (union (set tags) (::tags object))) -
- - 040        (throw (IllegalArgumentException. + 043    (let [tags' (flatten tags)]
- 041                 (str "Must be keyword(s): " (map type tags))))) + 044      (when-not (every? keyword? tags')
- 042      (throw (IllegalArgumentException. + 045        (throw (IllegalArgumentException.
- - 043               (str "Must be a map: " (type object)))))) + + 046                 (str "Must be keywords: " (map kind-type tags'))))) +
+ + 047          (assoc object ::tags (union (set tags') (::tags object)))))
- 044   + 048  
- 045  (defmacro tags + 049  (defmacro tags
- 046    "Return the tags of this object, if any." + 050    "Return the tags of this object, if any."
- 047    [object] + 051    [object]
- 048    `(::tags ~object)) -
- - 049   -
- - 050  (defn untag -
- - 051    "Return an object like this `object` but with these `tags` removed from its -
- - 052    tags, if present. It is an error (and an exception will be thrown) if + 052    `(::tags ~object))
053  
- - 054    1. `object` is not a map; -
- - 055    2. any of `tags` is not a keyword." -
- - 056    [object & tags] -
- 057    (if + 054  (defn untag
- - 058      (map? object) + + 055    "Return an object like this `object` but with these `tags` removed from its
- - 059      (if + + 056    tags, if present. It is an error (and an exception will be thrown) if
- - 060        (every? keyword? tags) + + 057  
- - 061        (assoc object ::tags (difference (::tags object) (set tags))) + + 058    1. `object` is not a map;
- - 062        (throw (IllegalArgumentException. + + 059    2. any of `tags` is not a keyword or sequence of keywords."
- - 063                 (str "Must be keywords: " (map type tags))))) -
- - 064      (throw (IllegalArgumentException. + + 060    [object & tags]
- 065               (str "Must be a map: " (type object)))))) + 061    (when-not (map? object) +
+ + 062      (throw (IllegalArgumentException. +
+ + 063               (str "Must be a map: " (kind-type object))))) +
+ + 064    (let [tags' (flatten tags)] +
+ + 065      (when-not (every? keyword? tags') +
+ + 066        (throw (IllegalArgumentException. +
+ + 067                 (str "Must be keywords: " (map kind-type tags'))))) +
+ + 068      (assoc object ::tags (difference (::tags object) (set tags')))))
diff --git a/docs/cloverage/walkmap/utils.clj.html b/docs/cloverage/walkmap/utils.clj.html index 235c672..8a5a84d 100644 --- a/docs/cloverage/walkmap/utils.clj.html +++ b/docs/cloverage/walkmap/utils.clj.html @@ -11,67 +11,127 @@ 002    "Miscellaneous utility functions."

- 003    (:require [clojure.math.numeric-tower :as m] -
- - 004              [walkmap.path :as p] -
- - 005              [walkmap.polygon :as q] -
- - 006              [walkmap.vertex :as v])) + 003    (:require [clojure.math.numeric-tower :as m]))
- 007   + 004  
- 008  (defn deep-merge + 005  (defn deep-merge
- 009    "Recursively merges maps. If vals are not maps, the last value wins." + 006    "Recursively merges maps. If vals are not maps, the last value wins."
- 010    ;; TODO: not my implementation, not sure I entirely trust it. + 007    ;; TODO: not my implementation, not sure I entirely trust it.
- 011    [& vals] + 008    ;; TODO TODO: if we are to successfully merge walkmap objects, we must
- - 012    (if (every? map? vals) + + 009    ;; return, on each object, the union of its tags if any.
- - 013      (apply merge-with deep-merge vals) + + 010    [& vals]
- - 014      (last vals))) + + 011    (if (every? map? vals) +
+ + 012      (apply merge-with deep-merge vals) +
+ + 013      (last vals)))
- 015   + 014  
- 016  (defn vertices + 015  (defn truncate
- 017    "If `o` is an object with vertices, return those vertices, else nil." + 016    "If string `s` is more than `n` characters long, return the first `n`
- 018    [o] + 017    characters; otherwise, return `s`."
- - 019    (cond + + 018    [s n]
- - 020      (v/vertex? o) (list o) + + 019    (if (and (string? s) (number? n) (> (count s) n))
- - 021      (q/polygon? o) (:vertices o) + + 020      (subs s 0 n)
- - 022      (p/path? o) (:vertices o))) + + 021      s))
- 023   + 022   +
+ + 023  (defn kind-type +
+ + 024    "Identify the type of an `object`, e.g. for logging. If it has a `:kind` key, +
+ + 025    it's one of ours, and that's what we want. Otherwise, we want its type; but +
+ + 026    the type of `nil` is `nil`, which doesn't get printed when assembling error +
+ + 027    ,essages, so return \"nil\"." +
+ + 028    [object] +
+ + 029    (or (:kind object) (type object) "nil")) +
+ + 030   +
+ + 031  (defn =ish +
+ + 032    "True if numbers `n1`, `n2` are roughly equal; that is to say, equal to +
+ + 033    within `tolerance` (defaults to one part in a million)." +
+ + 034    ([n1 n2] +
+ + 035     (if (and (number? n1) (number? n2)) +
+ + 036       (let [m (m/abs (min n1 n2)) +
+ + 037             t (if (zero? m) 0.000001 (* 0.000001 m))] +
+ + 038         (=ish n1 n2 t)) +
+ + 039       (= n1 n2))) +
+ + 040    ([n1 n2 tolerance] +
+ + 041     (if (and (number? n1) (number? n2)) +
+ + 042       (< (m/abs (- n1 n2)) tolerance) +
+ + 043       (= n1 n2))))
diff --git a/docs/cloverage/walkmap/vertex.clj.html b/docs/cloverage/walkmap/vertex.clj.html index e9b80e8..2857af8 100644 --- a/docs/cloverage/walkmap/vertex.clj.html +++ b/docs/cloverage/walkmap/vertex.clj.html @@ -26,325 +26,427 @@ 007              [clojure.string :as s]

- 008              [walkmap.geometry :refer [=ish]])) + 008              [taoensso.timbre :as l] +
+ + 009              [walkmap.utils :refer [=ish kind-type truncate]]))
- 009   + 010  
- 010  (defn vertex-key + 011  (defn vertex-key
- 011    "Making sure we get the same key everytime we key a vertex with the same + 012    "Making sure we get the same key everytime we key a vertex with the same
- 012    coordinates. `o` must have numeric values for `:x`, `:y`, and optionally + 013    coordinates. `o` must have numeric values for `:x`, `:y`, and optionally
- 013    `:z`; it is an error and an exception will be thrown if `o` does not + 014    `:z`; it is an error and an exception will be thrown if `o` does not
- 014    conform to this specification. + 015    conform to this specification.
- 015   + 016  
- 016    **Note:** these keys can be quite long. No apology is made: it is required + 017    **Note:** these keys can be quite long. No apology is made: it is required
- 017    that the same key can *never* refer to two different locations in space." + 018    that the same key can *never* refer to two different locations in space."
- 018    [o] + 019    [o]
- 019    (keyword + 020    (keyword
- 020      (s/replace + 021      (s/replace
- 021        (cond + 022        (cond
- 022          (and (:x o) (:y o) (:z o)) + 023          (and (:x o) (:y o) (:z o))
- 023          (str "vert_" (:x o) "_" (:y o) "_" (:z o)) + 024          (str "vert_" (:x o) "_" (:y o) "_" (:z o))
- 024          (and (:x o) (:y o)) + 025          (and (:x o) (:y o))
- 025          (str "vert_" (:x o) "_" (:y o)) + 026          (str "vert_" (:x o) "_" (:y o))
- 026          :else + 027          :else
- 027          (throw (IllegalArgumentException. + 028          (throw (IllegalArgumentException.
- - 028                   (subs (str "Not a vertex: " (or o "nil")) 0 80)))) + + 029                   (truncate (str "Not a vertex: " (or o "nil")) 80))))
- 029        "." + 030        "."
- 030        "-"))) + 031        "-")))
- 031   + 032  
- 032  (defn vertex? + 033  (defn vertex?
- 033    "True if `o` satisfies the conditions for a vertex. That is, essentially, + 034    "True if `o` satisfies the conditions for a vertex. That is, essentially,
- 034    that it must rerpresent a two- or three- dimensional vector. A vertex is + 035    that it must rerpresent a two- or three- dimensional vector. A vertex is
- 035    shall be a map having at least the keys `:x` and `:y`, where the value of + 036    shall be a map having at least the keys `:x` and `:y`, where the value of
- 036    those keys is a number. If the key `:z` is also present, its value must also + 037    those keys is a number. If the key `:z` is also present, its value must also
- 037    be a number. + 038    be a number.
- 038   + 039  
- 039    The name  `vector?` was not used as that would clash with a function of that + 040    The name  `vector?` was not used as that would clash with a function of that
- 040    name in `clojure.core` whose semantics are entirely different." + 041    name in `clojure.core` whose semantics are entirely different."
- 041    [o] + 042    [o]
- 042    (and + 043    (and
- 043      (map? o) + 044      (map? o)
- 044      (:id o) + 045      (:walkmap.id/id o)
- 045      (number? (:x o)) + 046      (number? (:x o))
- 046      (number? (:y o)) + 047      (number? (:y o))
- 047      (or (nil? (:z o)) (number? (:z o))) + 048      (or (nil? (:z o)) (number? (:z o)))
- 048      (or (nil? (:kind o)) (= (:kind o) :vertex)))) + 049      (or (nil? (:kind o)) (= (:kind o) :vertex))))
- 049   + 050  
- 050  (defn vertex= + 051  (defn vertex=
- 051    "True if vertices `v1`, `v2` represent the same vertex." + 052    "True if vertices `v1`, `v2` represent the same vertex."
- 052    [v1 v2] + 053    [v1 v2]
- 053    (every? + 054    (every?
- 054      #(=ish (% v1) (% v2)) + 055      #(=ish (% v1) (% v2))
- 055      [:x :y :z])) + 056      [:x :y :z]))
- 056   + 057  
- 057  (defn vertex + 058  (defn vertex*
- 058    "Make a vertex with this `x`, `y` and (if provided) `z` values. Returns a map + 059    "Return a vertex like `v1`, but with each of its coordinates multiplied
- 059    with those values, plus a unique `:id` value, and `:kind` set to `:vertex`. + 060    by the equivalent vertex in `v2`."
- 060    It's not necessary to use this function to create a vertex, but the `:id` -
- - 061    must be present and must be unique." -
- - 062    ([x y] -
- - 063     (let [v {:x x :y y :kind :vertex}] -
- - 064       (assoc v :id (vertex-key v)))) -
- - 065    ([x y z] -
- - 066     (let [v (assoc (vertex x y) :z z)] -
- - 067       (assoc v :id (vertex-key v))))) -
- - 068   + 061    [v1 v2]
- 069  (defn canonicalise + 062    (if +
+ + 063      (and (vertex? v1) (vertex? v2)) +
+ + 064      (let [f (fn [v1 v2 coord] +
+ + 065                (* (or (coord v1) 0)
- 070    "If `o` is a map with numeric values for `:x`, `:y` and optionally `:z`, + 066                   ;; one here is deliberate!
- - 071    upgrade it to something we will recognise as a vertex." + + 067                   (or (coord v2) 1)))]
- - 072    [o] -
- - 073    (if -
- - 074      (and -
- - 075        (map? o) + + 068        (assoc v1 :x (f v1 v2 :x)
- 076        (number? (:x o)) + 069          :y (f v1 v2 :y)
- 077        (number? (:y o)) + 070          :z (f v1 v2 :z)))
- - 078        (or (nil? (:z o)) (number? (:z o)))) -
- - 079      (assoc o :kind :vertex :id (vertex-key o)) -
- - 080      (throw -
- - 081        (IllegalArgumentException. -
- - 082          (subs + + 071      (do (l/warn
- 083            (str "Not a proto-vertex: must have numeric `:x` and `:y`: " + 072            (s/join +
+ + 073              " " +
+ + 074              ["in `vertex-multiply`, both must be vectors. v1:" v1 "v2:" v2])) +
+ + 075        v1))) +
+ + 076   +
+ + 077  (defn vertex +
+ + 078    "Make a vertex with this `x`, `y` and (if provided) `z` values. Returns a map +
+ + 079    with those values, plus a unique `:walkmap.id/id` value, and `:kind` set to `:vertex`. +
+ + 080    It's not necessary to use this function to create a vertex, but the `:walkmap.id/id` +
+ + 081    must be present and must be unique." +
+ + 082    ([x y] +
+ + 083     (let [v {:x x :y y :kind :vertex}] +
+ + 084       (assoc v :walkmap.id/id (vertex-key v)))) +
+ + 085    ([x y z] +
+ + 086     (let [v (assoc (vertex x y) :z z)] +
+ + 087       (assoc v :walkmap.id/id (vertex-key v))))) +
+ + 088   +
+ + 089  (defn canonicalise +
+ + 090    "If `o` is a map with numeric values for `:x`, `:y` and optionally `:z`, +
+ + 091    upgrade it to something we will recognise as a vertex." +
+ + 092    [o] +
+ + 093    (if +
+ + 094      (and +
+ + 095        (map? o) +
+ + 096        (number? (:x o)) +
+ + 097        (number? (:y o)) +
+ + 098        (or (nil? (:z o)) (number? (:z o)))) +
+ + 099      (assoc o :kind :vertex :walkmap.id/id (vertex-key o)) +
+ + 100      (throw +
+ + 101        (IllegalArgumentException. +
+ + 102          (truncate +
+ + 103            (str "Not a proto-vertex: must have numeric `:x` and `:y`: "
- 084                 (or o "nil")) + 104                 (or o "nil"))
- 085            0 80))))) + 105            80)))))
- 086   + 106  
- 087  (def ensure3d + 107  (def ensure3d
- 088    "Given a vertex `o`, if `o` has a `:z` value, just return `o`; otherwise + 108    "Given a vertex `o`, if `o` has a `:z` value, just return `o`; otherwise
- 089    return a vertex like `o` but having thie `dflt` value as the value of its + 109    return a vertex like `o` but having thie `dflt` value as the value of its
- 090    `:z` key, or zero as the value of its `:z` key if `dflt` is not specified. + 110    `:z` key, or zero as the value of its `:z` key if `dflt` is not specified.
- 091   + 111  
- 092    If `o` is not a vertex, throws an exception." + 112    If `o` is not a vertex, throws an exception."
- 093    (memoize + 113    (memoize
- 094      (fn + 114      (fn
- 095        ([o] + 115        ([o]
- 096         (ensure3d o 0.0)) + 116         (ensure3d o 0.0))
- 097        ([o dflt] + 117        ([o dflt]
- 098         (cond + 118         (cond
- 099           (not (vertex? o)) (throw + 119           (not (vertex? o)) (throw
- 100                               (IllegalArgumentException. + 120                               (IllegalArgumentException.
- - 101                                 (subs (str "Not a vertex: " (or o "nil")) 0 80))) + + 121                                 (truncate (str "Not a vertex: " (or o "nil")) 80)))
- 102           (:z o) o + 122           (:z o) o
- 103           :else (assoc o :z dflt)))))) + 123           :else (assoc o :z dflt))))))
- 104   + 124  
- 105  (def ensure2d + 125  (def ensure2d
- 106    "If `o` is a vertex, set its `:z` value to zero; else throw an exception." + 126    "If `o` is a vertex, set its `:z` value to zero; else throw an exception."
- 107    (memoize + 127    (memoize
- 108      (fn [o] + 128      (fn [o]
- 109        (if + 129        (if
- 110          (vertex? o) + 130          (vertex? o)
- 111          (assoc o :z 0.0) + 131          (assoc o :z 0.0)
- 112          (throw + 132          (throw
- 113            (IllegalArgumentException. + 133            (IllegalArgumentException.
- - 114              (subs (str "Not a vertex: " (or o "nil")) 0 80))))))) + + 134              (truncate (str "Not a vertex: " (or o "nil")) 80))))))) +
+ + 135   +
+ + 136  (defn within-box? +
+ + 137    "True if `target` is within the box defined by `minv` and `maxv`. All +
+ + 138    arguments must be vertices; additionally, both `minv` and `maxv` must +
+ + 139    have `:z` coordinates." +
+ + 140    [target minv maxv] +
+ + 141    (when-not (and (vertex? target) (vertex? minv) (vertex? maxv)) +
+ + 142      (throw (IllegalArgumentException. +
+ + 143               (s/join " " ["Arguments to `within-box?` must be vertices:" +
+ + 144                            (map kind-type [target minv maxv])])))) +
+ + 145    (every? +
+ + 146      (map +
+ + 147        #(< (% minv) (or (% target) 0) (% maxv)) +
+ + 148        [:x :y :z])))
diff --git a/project.clj b/project.clj index 348e8ed..2636161 100644 --- a/project.clj +++ b/project.clj @@ -31,5 +31,5 @@ ["uberjar"] ["change" "version" "leiningen.release/bump-version"] ["vcs" "commit"]] - :repl-options {:init-ns walkmap.core} + :repl-options {:init-ns walkmap.superstructure} :url "https://simon-brooke.github.io/walkmap/") diff --git a/src/walkmap/routing.clj b/src/walkmap/routing.clj index b925341..fc35d54 100644 --- a/src/walkmap/routing.clj +++ b/src/walkmap/routing.clj @@ -1,4 +1,4 @@ -(ns walkmap.core +(ns walkmap.routing "Finding optimal routes to traverse a map." (:require [walkmap.path :as p] [walkmap.polygon :as q] diff --git a/src/walkmap/stl.clj b/src/walkmap/stl.clj index 864b4ca..892d17f 100644 --- a/src/walkmap/stl.clj +++ b/src/walkmap/stl.clj @@ -6,6 +6,7 @@ [org.clojars.smee.binary.core :as b] [taoensso.timbre :as l] [walkmap.edge :as e] + [walkmap.ocean :as o] [walkmap.polygon :refer [centre gradient polygon?]] [walkmap.superstructure :refer [store]] [walkmap.tag :refer [tag]] diff --git a/src/walkmap/svg.clj b/src/walkmap/svg.clj index bbb9d9f..5f14232 100644 --- a/src/walkmap/svg.clj +++ b/src/walkmap/svg.clj @@ -108,9 +108,3 @@ :hiccup (spit out-filename (html s)) (throw (Exception. "Unexpected renderer value: " *preferred-svg-render*))) s))) - - -(defn read-svg - ([file-name] - (read-svg file-name nil)) - ([file-name map-kind] diff --git a/src/walkmap/vertex.clj b/src/walkmap/vertex.clj index de7c81e..ca894c4 100644 --- a/src/walkmap/vertex.clj +++ b/src/walkmap/vertex.clj @@ -6,8 +6,7 @@ (:require [clojure.math.numeric-tower :as m] [clojure.string :as s] [taoensso.timbre :as l] - [walkmap.geometry :refer [=ish]] - [walkmap.utils :refer [kind-type truncate]])) + [walkmap.utils :refer [=ish kind-type truncate]])) (defn vertex-key "Making sure we get the same key everytime we key a vertex with the same diff --git a/test/walkmap/core_test.clj b/test/walkmap/core_test.clj deleted file mode 100644 index b84b538..0000000 --- a/test/walkmap/core_test.clj +++ /dev/null @@ -1,7 +0,0 @@ -(ns walkmap.core-test - (:require [clojure.test :refer :all] - [walkmap.core :refer :all])) - -;; (deftest a-test -;; (testing "FIXME, I fail." -;; (is (= 0 1)))) diff --git a/test/walkmap/geometry_test.clj b/test/walkmap/utils_test.clj similarity index 88% rename from test/walkmap/geometry_test.clj rename to test/walkmap/utils_test.clj index 9c7bc4d..3a09b01 100644 --- a/test/walkmap/geometry_test.clj +++ b/test/walkmap/utils_test.clj @@ -1,6 +1,6 @@ -(ns walkmap.geometry-test +(ns walkmap.utils-test (:require [clojure.test :refer :all] - [walkmap.geometry :refer :all])) + [walkmap.utils :refer :all])) (deftest =ish-tests (testing "Rough equality"