From 4b76eb5e4f6c29dc21c3a6c217b20f0b511f0a42 Mon Sep 17 00:00:00 2001
From: Simon Brooke <simon@journeyman.cc>
Date: Wed, 3 Jun 2020 16:26:30 +0100
Subject: [PATCH] More tests, all pass.

---
 .gitignore                                    |   6 +
 docs/cloverage/index.html                     | 106 +++++++------
 docs/cloverage/walkmap/path.clj.html          |   2 +-
 docs/cloverage/walkmap/polygon.clj.html       | 142 ++++++++++--------
 docs/cloverage/walkmap/stl.clj.html           |   2 +-
 .../cloverage/walkmap/superstructure.clj.html |   2 +-
 docs/cloverage/walkmap/svg.clj.html           |   4 +-
 docs/cloverage/walkmap/tag.clj.html           |   2 +-
 docs/cloverage/walkmap/utils.clj.html         |  26 ++--
 docs/cloverage/walkmap/vertex.clj.html        |  29 ++--
 test/walkmap/utils_test.clj                   |  88 ++++++++++-
 11 files changed, 257 insertions(+), 152 deletions(-)

diff --git a/.gitignore b/.gitignore
index f747809..97b570a 100644
--- a/.gitignore
+++ b/.gitignore
@@ -20,3 +20,9 @@ resources/small_hill.svg
 s.edn
 
 .eastwood
+
+settlement_1.edn
+
+small_hill.edn
+
+small_hill.html
diff --git a/docs/cloverage/index.html b/docs/cloverage/index.html
index 93248aa..1c568a3 100644
--- a/docs/cloverage/index.html
+++ b/docs/cloverage/index.html
@@ -68,11 +68,11 @@
 </tr>
 <tr>
  <td><a href="walkmap/path.clj.html">walkmap.path</a></td><td class="with-bar"><div class="covered"
-                                style="width:93.60902255639098%;
-                                        float:left;"> 249 </div><div class="not-covered"
-                                style="width:6.390977443609023%;
-                                        float:left;"> 17 </div></td>
-<td class="with-number">93.61 %</td>
+                                style="width:93.98496240601504%;
+                                        float:left;"> 250 </div><div class="not-covered"
+                                style="width:6.015037593984962%;
+                                        float:left;"> 16 </div></td>
+<td class="with-number">93.98 %</td>
 <td class="with-bar"><div class="covered"
                                 style="width:89.74358974358974%;
                                         float:left;"> 35 </div><div class="partial"
@@ -85,20 +85,20 @@
 </tr>
 <tr>
  <td><a href="walkmap/polygon.clj.html">walkmap.polygon</a></td><td class="with-bar"><div class="covered"
-                                style="width:71.45969498910675%;
-                                        float:left;"> 328 </div><div class="not-covered"
-                                style="width:28.540305010893245%;
+                                style="width:72.0682302771855%;
+                                        float:left;"> 338 </div><div class="not-covered"
+                                style="width:27.931769722814497%;
                                         float:left;"> 131 </div></td>
-<td class="with-number">71.46 %</td>
+<td class="with-number">72.07 %</td>
 <td class="with-bar"><div class="covered"
-                                style="width:76.78571428571429%;
-                                        float:left;"> 43 </div><div class="partial"
-                                style="width:10.714285714285714%;
+                                style="width:77.58620689655173%;
+                                        float:left;"> 45 </div><div class="partial"
+                                style="width:10.344827586206897%;
                                         float:left;"> 6 </div><div class="not-covered"
-                                style="width:12.5%;
+                                style="width:12.068965517241379%;
                                         float:left;"> 7 </div></td>
-<td class="with-number">87.50 %</td>
-<td class="with-number">114</td><td class="with-number">13</td><td class="with-number">56</td>
+<td class="with-number">87.93 %</td>
+<td class="with-number">118</td><td class="with-number">13</td><td class="with-number">58</td>
 </tr>
 <tr>
  <td><a href="walkmap/read_svg.clj.html">walkmap.read-svg</a></td><td class="with-bar"><div class="covered"
@@ -128,11 +128,11 @@
 </tr>
 <tr>
  <td><a href="walkmap/stl.clj.html">walkmap.stl</a></td><td class="with-bar"><div class="covered"
-                                style="width:49.07216494845361%;
+                                style="width:50.638297872340424%;
                                         float:left;"> 238 </div><div class="not-covered"
-                                style="width:50.92783505154639%;
-                                        float:left;"> 247 </div></td>
-<td class="with-number">49.07 %</td>
+                                style="width:49.361702127659576%;
+                                        float:left;"> 232 </div></td>
+<td class="with-number">50.64 %</td>
 <td class="with-bar"><div class="covered"
                                 style="width:40.56603773584906%;
                                         float:left;"> 43 </div><div class="partial"
@@ -145,11 +145,11 @@
 </tr>
 <tr>
  <td><a href="walkmap/superstructure.clj.html">walkmap.superstructure</a></td><td class="with-bar"><div class="covered"
-                                style="width:71.76781002638522%;
-                                        float:left;"> 272 </div><div class="not-covered"
-                                style="width:28.232189973614776%;
+                                style="width:70.6043956043956%;
+                                        float:left;"> 257 </div><div class="not-covered"
+                                style="width:29.395604395604394%;
                                         float:left;"> 107 </div></td>
-<td class="with-number">71.77 %</td>
+<td class="with-number">70.60 %</td>
 <td class="with-bar"><div class="covered"
                                 style="width:71.26436781609195%;
                                         float:left;"> 62 </div><div class="partial"
@@ -162,11 +162,11 @@
 </tr>
 <tr>
  <td><a href="walkmap/svg.clj.html">walkmap.svg</a></td><td class="with-bar"><div class="covered"
-                                style="width:3.7542662116040955%;
+                                style="width:4.21455938697318%;
                                         float:left;"> 11 </div><div class="not-covered"
-                                style="width:96.24573378839591%;
-                                        float:left;"> 282 </div></td>
-<td class="with-number">3.75 %</td>
+                                style="width:95.78544061302682%;
+                                        float:left;"> 250 </div></td>
+<td class="with-number">4.21 %</td>
 <td class="with-bar"><div class="covered"
                                 style="width:12.121212121212121%;
                                         float:left;"> 8 </div><div class="not-covered"
@@ -178,7 +178,7 @@
 <tr>
  <td><a href="walkmap/tag.clj.html">walkmap.tag</a></td><td class="with-bar"><div class="covered"
                                 style="width:100.0%;
-                                        float:left;"> 178 </div></td>
+                                        float:left;"> 159 </div></td>
 <td class="with-number">100.00 %</td>
 <td class="with-bar"><div class="covered"
                                 style="width:100.0%;
@@ -188,43 +188,41 @@
 </tr>
 <tr>
  <td><a href="walkmap/utils.clj.html">walkmap.utils</a></td><td class="with-bar"><div class="covered"
-                                style="width:56.216931216931215%;
-                                        float:left;"> 425 </div><div class="not-covered"
-                                style="width:43.783068783068785%;
-                                        float:left;"> 331 </div></td>
-<td class="with-number">56.22 %</td>
+                                style="width:99.86772486772487%;
+                                        float:left;"> 755 </div><div class="not-covered"
+                                style="width:0.13227513227513227%;
+                                        float:left;"> 1 </div></td>
+<td class="with-number">99.87 %</td>
 <td class="with-bar"><div class="covered"
-                                style="width:69.44444444444444%;
-                                        float:left;"> 25 </div><div class="partial"
-                                style="width:11.11111111111111%;
-                                        float:left;"> 4 </div><div class="not-covered"
-                                style="width:19.444444444444443%;
-                                        float:left;"> 7 </div></td>
-<td class="with-number">80.56 %</td>
+                                style="width:97.22222222222223%;
+                                        float:left;"> 35 </div><div class="partial"
+                                style="width:2.7777777777777777%;
+                                        float:left;"> 1 </div></td>
+<td class="with-number">100.00 %</td>
 <td class="with-number">101</td><td class="with-number">9</td><td class="with-number">36</td>
 </tr>
 <tr>
  <td><a href="walkmap/vertex.clj.html">walkmap.vertex</a></td><td class="with-bar"><div class="covered"
-                                style="width:86.52094717668488%;
-                                        float:left;"> 475 </div><div class="not-covered"
-                                style="width:13.479052823315119%;
-                                        float:left;"> 74 </div></td>
-<td class="with-number">86.52 %</td>
+                                style="width:89.45454545454545%;
+                                        float:left;"> 492 </div><div class="not-covered"
+                                style="width:10.545454545454545%;
+                                        float:left;"> 58 </div></td>
+<td class="with-number">89.45 %</td>
 <td class="with-bar"><div class="covered"
-                                style="width:82.1917808219178%;
-                                        float:left;"> 60 </div><div class="partial"
-                                style="width:15.068493150684931%;
-                                        float:left;"> 11 </div><div class="not-covered"
-                                style="width:2.73972602739726%;
+                                style="width:83.78378378378379%;
+                                        float:left;"> 62 </div><div class="partial"
+                                style="width:13.513513513513514%;
+                                        float:left;"> 10 </div><div class="not-covered"
+                                style="width:2.7027027027027026%;
                                         float:left;"> 2 </div></td>
-<td class="with-number">97.26 %</td>
-<td class="with-number">150</td><td class="with-number">15</td><td class="with-number">73</td>
+<td class="with-number">97.30 %</td>
+<td class="with-number">151</td><td class="with-number">15</td><td class="with-number">74</td>
 </tr>
 <tr><td>Totals:</td>
 <td class="with-bar"></td>
-<td class="with-number">64.52 %</td>
+<td class="with-number">72.81 %</td>
 <td class="with-bar"></td>
-<td class="with-number">67.67 %</td>
+<td class="with-number">68.80 %</td>
    </tr>
   </table>
  </body>
diff --git a/docs/cloverage/walkmap/path.clj.html b/docs/cloverage/walkmap/path.clj.html
index 907a2e7..4df3664 100644
--- a/docs/cloverage/walkmap/path.clj.html
+++ b/docs/cloverage/walkmap/path.clj.html
@@ -58,7 +58,7 @@
 <span class="covered" title="3 out of 3 forms covered">
                 018&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;[v&nbsp;(:vertices&nbsp;o)]
                 </span><br/>
-<span class="partial" title="18 out of 22 forms covered">
+<span class="partial" title="19 out of 22 forms covered">
                 019&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(and
                 </span><br/>
 <span class="covered" title="3 out of 3 forms covered">
diff --git a/docs/cloverage/walkmap/polygon.clj.html b/docs/cloverage/walkmap/polygon.clj.html
index c3b5f51..a7c5f47 100644
--- a/docs/cloverage/walkmap/polygon.clj.html
+++ b/docs/cloverage/walkmap/polygon.clj.html
@@ -166,185 +166,197 @@
 <span class="not-tracked" title="0 out of 0 forms covered">
                 054&nbsp;&nbsp;&nbsp;&nbsp;[&amp;&nbsp;vertices]
                 </span><br/>
-<span class="covered" title="30 out of 30 forms covered">
-                055&nbsp;&nbsp;&nbsp;&nbsp;{:vertices&nbsp;(check-vertices&nbsp;vertices)
+<span class="covered" title="1 out of 1 forms covered">
+                055&nbsp;&nbsp;&nbsp;&nbsp;(if
                 </span><br/>
-<span class="covered" title="5 out of 5 forms covered">
-                056&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;:walkmap.id&#x2F;id&nbsp;(keyword&nbsp;(gensym&nbsp;&quot;poly&quot;))
+<span class="covered" title="6 out of 6 forms covered">
+                056&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(&gt;&nbsp;(count&nbsp;vertices)&nbsp;2)
+                </span><br/>
+<span class="covered" title="30 out of 30 forms covered">
+                057&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;{:vertices&nbsp;(check-vertices&nbsp;vertices)
+                </span><br/>
+<span class="covered" title="6 out of 6 forms covered">
+                058&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;:walkmap.id&#x2F;id&nbsp;(keyword&nbsp;(gensym&nbsp;&quot;poly&quot;))
                 </span><br/>
 <span class="not-tracked" title="0 out of 0 forms covered">
-                057&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;:kind&nbsp;:polygon})
+                059&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;:kind&nbsp;:polygon}
                 </span><br/>
-<span class="blank" title="1 out of 1 forms covered">
-                058&nbsp;&nbsp;
+<span class="covered" title="3 out of 3 forms covered">
+                060&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(throw&nbsp;(IllegalArgumentException.
+                </span><br/>
+<span class="not-tracked" title="0 out of 0 forms covered">
+                061&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&quot;A&nbsp;polygon&nbsp;must&nbsp;have&nbsp;at&nbsp;least&nbsp;3&nbsp;vertices.&quot;))))
+                </span><br/>
+<span class="blank" title="0 out of 0 forms covered">
+                062&nbsp;&nbsp;
                 </span><br/>
 <span class="covered" title="1 out of 1 forms covered">
-                059&nbsp;&nbsp;(defn&nbsp;rectangle
+                063&nbsp;&nbsp;(defn&nbsp;rectangle
                 </span><br/>
 <span class="not-tracked" title="0 out of 0 forms covered">
-                060&nbsp;&nbsp;&nbsp;&nbsp;&quot;Return&nbsp;a&nbsp;rectangle,&nbsp;with&nbsp;edges&nbsp;aligned&nbsp;east-west&nbsp;and&nbsp;north-south,&nbsp;whose
+                064&nbsp;&nbsp;&nbsp;&nbsp;&quot;Return&nbsp;a&nbsp;rectangle,&nbsp;with&nbsp;edges&nbsp;aligned&nbsp;east-west&nbsp;and&nbsp;north-south,&nbsp;whose
                 </span><br/>
 <span class="not-tracked" title="0 out of 0 forms covered">
-                061&nbsp;&nbsp;&nbsp;&nbsp;south-west&nbsp;corner&nbsp;is&nbsp;the&nbsp;vertex&nbsp;`vsw`&nbsp;and&nbsp;whose&nbsp;north-east&nbsp;corner&nbsp;is&nbsp;the
+                065&nbsp;&nbsp;&nbsp;&nbsp;south-west&nbsp;corner&nbsp;is&nbsp;the&nbsp;vertex&nbsp;`vsw`&nbsp;and&nbsp;whose&nbsp;north-east&nbsp;corner&nbsp;is&nbsp;the
                 </span><br/>
 <span class="not-tracked" title="0 out of 0 forms covered">
-                062&nbsp;&nbsp;&nbsp;&nbsp;vertex&nbsp;`vne`.&quot;
+                066&nbsp;&nbsp;&nbsp;&nbsp;vertex&nbsp;`vne`.&quot;
                 </span><br/>
 <span class="not-tracked" title="0 out of 0 forms covered">
-                063&nbsp;&nbsp;&nbsp;&nbsp;[vsw&nbsp;vne]
+                067&nbsp;&nbsp;&nbsp;&nbsp;[vsw&nbsp;vne]
                 </span><br/>
 <span class="not-tracked" title="0 out of 0 forms covered">
-                064&nbsp;&nbsp;&nbsp;&nbsp;;;&nbsp;we&nbsp;can&nbsp;actually&nbsp;create&nbsp;any&nbsp;rectangle&nbsp;in&nbsp;the&nbsp;xy&nbsp;plane&nbsp;based&nbsp;on&nbsp;two&nbsp;opposite
+                068&nbsp;&nbsp;&nbsp;&nbsp;;;&nbsp;we&nbsp;can&nbsp;actually&nbsp;create&nbsp;any&nbsp;rectangle&nbsp;in&nbsp;the&nbsp;xy&nbsp;plane&nbsp;based&nbsp;on&nbsp;two&nbsp;opposite
                 </span><br/>
 <span class="not-tracked" title="0 out of 0 forms covered">
-                065&nbsp;&nbsp;&nbsp;&nbsp;;;&nbsp;corners,&nbsp;but&nbsp;the&nbsp;maths&nbsp;are&nbsp;a&nbsp;bit&nbsp;to&nbsp;advanced&nbsp;for&nbsp;me&nbsp;today.&nbsp;TODO:&nbsp;do&nbsp;it!
+                069&nbsp;&nbsp;&nbsp;&nbsp;;;&nbsp;corners,&nbsp;but&nbsp;the&nbsp;maths&nbsp;are&nbsp;a&nbsp;bit&nbsp;to&nbsp;advanced&nbsp;for&nbsp;me&nbsp;today.&nbsp;TODO:&nbsp;do&nbsp;it!
                 </span><br/>
-<span class="not-covered" title="0 out of 21 forms covered">
-                066&nbsp;&nbsp;&nbsp;&nbsp;(let&nbsp;[vnw&nbsp;(vertex&nbsp;(:x&nbsp;(check-vertex&nbsp;vsw))
+<span class="partial" title="9 out of 30 forms covered">
+                070&nbsp;&nbsp;&nbsp;&nbsp;(let&nbsp;[vnw&nbsp;(vertex&nbsp;(:x&nbsp;(check-vertex&nbsp;vsw))
                 </span><br/>
 <span class="not-covered" title="0 out of 18 forms covered">
-                067&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(:y&nbsp;(check-vertex&nbsp;vne))
+                071&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(:y&nbsp;(check-vertex&nbsp;vne))
                 </span><br/>
 <span class="not-covered" title="0 out of 20 forms covered">
-                068&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(&#x2F;&nbsp;(reduce&nbsp;+&nbsp;(map&nbsp;#(or&nbsp;(:z&nbsp;%)&nbsp;0)&nbsp;[vsw&nbsp;vne]))&nbsp;2))
+                072&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(&#x2F;&nbsp;(reduce&nbsp;+&nbsp;(map&nbsp;#(or&nbsp;(:z&nbsp;%)&nbsp;0)&nbsp;[vsw&nbsp;vne]))&nbsp;2))
                 </span><br/>
 <span class="not-covered" title="0 out of 5 forms covered">
-                069&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;vse&nbsp;(vertex&nbsp;(:x&nbsp;vne)
+                073&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;vse&nbsp;(vertex&nbsp;(:x&nbsp;vne)
                 </span><br/>
-<span class="partial" title="9 out of 12 forms covered">
-                070&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(:y&nbsp;vsw)
+<span class="not-covered" title="0 out of 3 forms covered">
+                074&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(:y&nbsp;vsw)
                 </span><br/>
 <span class="not-covered" title="0 out of 20 forms covered">
-                071&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(&#x2F;&nbsp;(reduce&nbsp;+&nbsp;(map&nbsp;#(or&nbsp;(:z&nbsp;%)&nbsp;0)&nbsp;[vsw&nbsp;vne]))&nbsp;2))]
+                075&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(&#x2F;&nbsp;(reduce&nbsp;+&nbsp;(map&nbsp;#(or&nbsp;(:z&nbsp;%)&nbsp;0)&nbsp;[vsw&nbsp;vne]))&nbsp;2))]
                 </span><br/>
 <span class="not-covered" title="0 out of 9 forms covered">
-                072&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(t&#x2F;tag&nbsp;(polygon&nbsp;vsw&nbsp;vnw&nbsp;vne&nbsp;vse)&nbsp;:rectangle)))
+                076&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(t&#x2F;tag&nbsp;(polygon&nbsp;vsw&nbsp;vnw&nbsp;vne&nbsp;vse)&nbsp;:rectangle)))
                 </span><br/>
 <span class="blank" title="0 out of 0 forms covered">
-                073&nbsp;&nbsp;
+                077&nbsp;&nbsp;
                 </span><br/>
 <span class="not-tracked" title="0 out of 0 forms covered">
-                074&nbsp;&nbsp;;;&nbsp;(rectangle&nbsp;(vertex&nbsp;1&nbsp;2&nbsp;3)&nbsp;(vertex&nbsp;7&nbsp;9&nbsp;4))
+                078&nbsp;&nbsp;;;&nbsp;(rectangle&nbsp;(vertex&nbsp;1&nbsp;2&nbsp;3)&nbsp;(vertex&nbsp;7&nbsp;9&nbsp;4))
                 </span><br/>
 <span class="blank" title="0 out of 0 forms covered">
-                075&nbsp;&nbsp;
+                079&nbsp;&nbsp;
                 </span><br/>
 <span class="covered" title="1 out of 1 forms covered">
-                076&nbsp;&nbsp;(defn&nbsp;gradient
+                080&nbsp;&nbsp;(defn&nbsp;gradient
                 </span><br/>
 <span class="not-tracked" title="0 out of 0 forms covered">
-                077&nbsp;&nbsp;&nbsp;&nbsp;&quot;Return&nbsp;a&nbsp;polygon&nbsp;like&nbsp;`triangle`&nbsp;but&nbsp;with&nbsp;a&nbsp;key&nbsp;`:gradient`&nbsp;whose&nbsp;value&nbsp;is&nbsp;a
+                081&nbsp;&nbsp;&nbsp;&nbsp;&quot;Return&nbsp;a&nbsp;polygon&nbsp;like&nbsp;`triangle`&nbsp;but&nbsp;with&nbsp;a&nbsp;key&nbsp;`:gradient`&nbsp;whose&nbsp;value&nbsp;is&nbsp;a
                 </span><br/>
 <span class="not-tracked" title="0 out of 0 forms covered">
-                078&nbsp;&nbsp;&nbsp;&nbsp;unit&nbsp;vector&nbsp;representing&nbsp;the&nbsp;gradient&nbsp;across&nbsp;`triangle`.&quot;
+                082&nbsp;&nbsp;&nbsp;&nbsp;unit&nbsp;vector&nbsp;representing&nbsp;the&nbsp;gradient&nbsp;across&nbsp;`triangle`.&quot;
                 </span><br/>
 <span class="not-tracked" title="0 out of 0 forms covered">
-                079&nbsp;&nbsp;&nbsp;&nbsp;[triangle]
+                083&nbsp;&nbsp;&nbsp;&nbsp;[triangle]
                 </span><br/>
 <span class="covered" title="12 out of 12 forms covered">
-                080&nbsp;&nbsp;&nbsp;&nbsp;(let&nbsp;[order&nbsp;(sort&nbsp;#(max&nbsp;(:z&nbsp;%1)&nbsp;(:z&nbsp;%2))
+                084&nbsp;&nbsp;&nbsp;&nbsp;(let&nbsp;[order&nbsp;(sort&nbsp;#(max&nbsp;(:z&nbsp;%1)&nbsp;(:z&nbsp;%2))
                 </span><br/>
 <span class="partial" title="8 out of 18 forms covered">
-                081&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(:vertices&nbsp;(check-triangle&nbsp;triangle)))
+                085&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(:vertices&nbsp;(check-triangle&nbsp;triangle)))
                 </span><br/>
 <span class="covered" title="3 out of 3 forms covered">
-                082&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;highest&nbsp;(first&nbsp;order)
+                086&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;highest&nbsp;(first&nbsp;order)
                 </span><br/>
 <span class="covered" title="3 out of 3 forms covered">
-                083&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;lowest&nbsp;(last&nbsp;order)]
+                087&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;lowest&nbsp;(last&nbsp;order)]
                 </span><br/>
 <span class="covered" title="10 out of 10 forms covered">
-                084&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(assoc&nbsp;triangle&nbsp;:gradient&nbsp;(e&#x2F;unit-vector&nbsp;(e&#x2F;edge&nbsp;lowest&nbsp;highest)))))
+                088&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(assoc&nbsp;triangle&nbsp;:gradient&nbsp;(e&#x2F;unit-vector&nbsp;(e&#x2F;edge&nbsp;lowest&nbsp;highest)))))
                 </span><br/>
 <span class="blank" title="0 out of 0 forms covered">
-                085&nbsp;&nbsp;
+                089&nbsp;&nbsp;
                 </span><br/>
 <span class="covered" title="1 out of 1 forms covered">
-                086&nbsp;&nbsp;(defn&nbsp;triangle-centre
+                090&nbsp;&nbsp;(defn&nbsp;triangle-centre
                 </span><br/>
 <span class="not-tracked" title="0 out of 0 forms covered">
-                087&nbsp;&nbsp;&nbsp;&nbsp;&quot;Return&nbsp;a&nbsp;canonicalised&nbsp;`facet`&nbsp;(i.e.&nbsp;a&nbsp;triangular&nbsp;polygon)&nbsp;with&nbsp;an&nbsp;added
+                091&nbsp;&nbsp;&nbsp;&nbsp;&quot;Return&nbsp;a&nbsp;canonicalised&nbsp;`facet`&nbsp;(i.e.&nbsp;a&nbsp;triangular&nbsp;polygon)&nbsp;with&nbsp;an&nbsp;added
                 </span><br/>
 <span class="not-tracked" title="0 out of 0 forms covered">
-                088&nbsp;&nbsp;&nbsp;&nbsp;key&nbsp;`:centre`&nbsp;whose&nbsp;value&nbsp;represents&nbsp;the&nbsp;centre&nbsp;of&nbsp;this&nbsp;facet&nbsp;in&nbsp;3
+                092&nbsp;&nbsp;&nbsp;&nbsp;key&nbsp;`:centre`&nbsp;whose&nbsp;value&nbsp;represents&nbsp;the&nbsp;centre&nbsp;of&nbsp;this&nbsp;facet&nbsp;in&nbsp;3
                 </span><br/>
 <span class="not-tracked" title="0 out of 0 forms covered">
-                089&nbsp;&nbsp;&nbsp;&nbsp;dimensions.&nbsp;This&nbsp;only&nbsp;works&nbsp;for&nbsp;triangles,&nbsp;so&nbsp;is&nbsp;here&nbsp;not&nbsp;in
+                093&nbsp;&nbsp;&nbsp;&nbsp;dimensions.&nbsp;This&nbsp;only&nbsp;works&nbsp;for&nbsp;triangles,&nbsp;so&nbsp;is&nbsp;here&nbsp;not&nbsp;in
                 </span><br/>
 <span class="not-tracked" title="0 out of 0 forms covered">
-                090&nbsp;&nbsp;&nbsp;&nbsp;`walkmap.polygon`.&nbsp;It&nbsp;is&nbsp;an&nbsp;error&nbsp;(although&nbsp;no&nbsp;exception&nbsp;is&nbsp;currently
+                094&nbsp;&nbsp;&nbsp;&nbsp;`walkmap.polygon`.&nbsp;It&nbsp;is&nbsp;an&nbsp;error&nbsp;(although&nbsp;no&nbsp;exception&nbsp;is&nbsp;currently
                 </span><br/>
 <span class="not-tracked" title="0 out of 0 forms covered">
-                091&nbsp;&nbsp;&nbsp;&nbsp;thrown)&nbsp;if&nbsp;the&nbsp;object&nbsp;past&nbsp;is&nbsp;not&nbsp;a&nbsp;triangular&nbsp;polygon.&quot;
+                095&nbsp;&nbsp;&nbsp;&nbsp;thrown)&nbsp;if&nbsp;the&nbsp;object&nbsp;past&nbsp;is&nbsp;not&nbsp;a&nbsp;triangular&nbsp;polygon.&quot;
                 </span><br/>
 <span class="not-tracked" title="0 out of 0 forms covered">
-                092&nbsp;&nbsp;&nbsp;&nbsp;[facet]
+                096&nbsp;&nbsp;&nbsp;&nbsp;[facet]
                 </span><br/>
 <span class="partial" title="9 out of 19 forms covered">
-                093&nbsp;&nbsp;&nbsp;&nbsp;(let&nbsp;[vs&nbsp;(:vertices&nbsp;(check-triangle&nbsp;facet))
+                097&nbsp;&nbsp;&nbsp;&nbsp;(let&nbsp;[vs&nbsp;(:vertices&nbsp;(check-triangle&nbsp;facet))
                 </span><br/>
 <span class="covered" title="3 out of 3 forms covered">
-                094&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;v1&nbsp;(first&nbsp;vs)
+                098&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;v1&nbsp;(first&nbsp;vs)
                 </span><br/>
 <span class="covered" title="10 out of 10 forms covered">
-                095&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;opposite&nbsp;(e&#x2F;edge&nbsp;(nth&nbsp;vs&nbsp;1)&nbsp;(nth&nbsp;vs&nbsp;2))
+                099&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;opposite&nbsp;(e&#x2F;edge&nbsp;(nth&nbsp;vs&nbsp;1)&nbsp;(nth&nbsp;vs&nbsp;2))
                 </span><br/>
 <span class="covered" title="3 out of 3 forms covered">
-                096&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;oc&nbsp;(e&#x2F;centre&nbsp;opposite)]
+                100&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;oc&nbsp;(e&#x2F;centre&nbsp;opposite)]
                 </span><br/>
 <span class="covered" title="3 out of 3 forms covered">
-                097&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(assoc
+                101&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(assoc
                 </span><br/>
 <span class="covered" title="1 out of 1 forms covered">
-                098&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;facet
+                102&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;facet
                 </span><br/>
 <span class="not-tracked" title="0 out of 0 forms covered">
-                099&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;:centre
+                103&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;:centre
                 </span><br/>
 <span class="covered" title="2 out of 2 forms covered">
-                100&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(vertex
+                104&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(vertex
                 </span><br/>
 <span class="covered" title="16 out of 16 forms covered">
-                101&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(+&nbsp;(:x&nbsp;v1)&nbsp;(*&nbsp;(-&nbsp;(:x&nbsp;oc)&nbsp;(:x&nbsp;v1))&nbsp;2&#x2F;3))
+                105&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(+&nbsp;(:x&nbsp;v1)&nbsp;(*&nbsp;(-&nbsp;(:x&nbsp;oc)&nbsp;(:x&nbsp;v1))&nbsp;2&#x2F;3))
                 </span><br/>
 <span class="covered" title="16 out of 16 forms covered">
-                102&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(+&nbsp;(:y&nbsp;v1)&nbsp;(*&nbsp;(-&nbsp;(:y&nbsp;oc)&nbsp;(:y&nbsp;v1))&nbsp;2&#x2F;3))
+                106&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(+&nbsp;(:y&nbsp;v1)&nbsp;(*&nbsp;(-&nbsp;(:y&nbsp;oc)&nbsp;(:y&nbsp;v1))&nbsp;2&#x2F;3))
                 </span><br/>
 <span class="covered" title="16 out of 16 forms covered">
-                103&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(+&nbsp;(:z&nbsp;v1)&nbsp;(*&nbsp;(-&nbsp;(:z&nbsp;oc)&nbsp;(:z&nbsp;v1))&nbsp;2&#x2F;3))))))
+                107&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(+&nbsp;(:z&nbsp;v1)&nbsp;(*&nbsp;(-&nbsp;(:z&nbsp;oc)&nbsp;(:z&nbsp;v1))&nbsp;2&#x2F;3))))))
                 </span><br/>
 <span class="blank" title="0 out of 0 forms covered">
-                104&nbsp;&nbsp;
+                108&nbsp;&nbsp;
                 </span><br/>
 <span class="covered" title="1 out of 1 forms covered">
-                105&nbsp;&nbsp;(defn&nbsp;centre
+                109&nbsp;&nbsp;(defn&nbsp;centre
                 </span><br/>
 <span class="not-tracked" title="0 out of 0 forms covered">
-                106&nbsp;&nbsp;&nbsp;&nbsp;[poly]
+                110&nbsp;&nbsp;&nbsp;&nbsp;[poly]
                 </span><br/>
 <span class="covered" title="22 out of 22 forms covered">
-                107&nbsp;&nbsp;&nbsp;&nbsp;(case&nbsp;(count&nbsp;(:vertices&nbsp;(check-polygon&nbsp;poly)))
+                111&nbsp;&nbsp;&nbsp;&nbsp;(case&nbsp;(count&nbsp;(:vertices&nbsp;(check-polygon&nbsp;poly)))
                 </span><br/>
 <span class="covered" title="3 out of 3 forms covered">
-                108&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;3&nbsp;(triangle-centre&nbsp;poly)
+                112&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;3&nbsp;(triangle-centre&nbsp;poly)
                 </span><br/>
 <span class="not-tracked" title="0 out of 0 forms covered">
-                109&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;;;&nbsp;else
+                113&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;;;&nbsp;else
                 </span><br/>
 <span class="covered" title="1 out of 1 forms covered">
-                110&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(throw
+                114&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(throw
                 </span><br/>
 <span class="covered" title="2 out of 2 forms covered">
-                111&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(UnsupportedOperationException.
+                115&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(UnsupportedOperationException.
                 </span><br/>
 <span class="not-tracked" title="0 out of 0 forms covered">
-                112&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&quot;The&nbsp;general&nbsp;case&nbsp;of&nbsp;centre&nbsp;for&nbsp;polygons&nbsp;is&nbsp;not&nbsp;yet&nbsp;implemented.&quot;))))
+                116&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&quot;The&nbsp;general&nbsp;case&nbsp;of&nbsp;centre&nbsp;for&nbsp;polygons&nbsp;is&nbsp;not&nbsp;yet&nbsp;implemented.&quot;))))
                 </span><br/>
 <span class="blank" title="0 out of 0 forms covered">
-                113&nbsp;&nbsp;
+                117&nbsp;&nbsp;
                 </span><br/>
 <span class="blank" title="0 out of 0 forms covered">
-                114&nbsp;&nbsp;
+                118&nbsp;&nbsp;
                 </span><br/>
  </body>
 </html>
diff --git a/docs/cloverage/walkmap/stl.clj.html b/docs/cloverage/walkmap/stl.clj.html
index 5240aa8..ff71dd2 100644
--- a/docs/cloverage/walkmap/stl.clj.html
+++ b/docs/cloverage/walkmap/stl.clj.html
@@ -550,7 +550,7 @@
 <span class="not-tracked" title="0 out of 0 forms covered">
                 182&nbsp;&nbsp;&nbsp;&nbsp;([filename&nbsp;stl&nbsp;solidname]
                 </span><br/>
-<span class="not-covered" title="0 out of 16 forms covered">
+<span class="not-covered" title="0 out of 1 forms covered">
                 183&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(l&#x2F;debug&nbsp;&quot;Solid&nbsp;name&nbsp;is&nbsp;&quot;&nbsp;solidname)
                 </span><br/>
 <span class="not-covered" title="0 out of 2 forms covered">
diff --git a/docs/cloverage/walkmap/superstructure.clj.html b/docs/cloverage/walkmap/superstructure.clj.html
index a83ad6d..229b2b9 100644
--- a/docs/cloverage/walkmap/superstructure.clj.html
+++ b/docs/cloverage/walkmap/superstructure.clj.html
@@ -355,7 +355,7 @@
 <span class="not-tracked" title="0 out of 0 forms covered">
                 117&nbsp;&nbsp;&nbsp;&nbsp;([o&nbsp;s]
                 </span><br/>
-<span class="covered" title="16 out of 16 forms covered">
+<span class="covered" title="1 out of 1 forms covered">
                 118&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(l&#x2F;debug&nbsp;&quot;Finding&nbsp;objects&nbsp;in:&quot;&nbsp;o)
                 </span><br/>
 <span class="covered" title="4 out of 4 forms covered">
diff --git a/docs/cloverage/walkmap/svg.clj.html b/docs/cloverage/walkmap/svg.clj.html
index c04a8b4..29fe91d 100644
--- a/docs/cloverage/walkmap/svg.clj.html
+++ b/docs/cloverage/walkmap/svg.clj.html
@@ -274,7 +274,7 @@
 <span class="not-covered" title="0 out of 3 forms covered">
                 090&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(:facets&nbsp;stl)))]
                 </span><br/>
-<span class="not-covered" title="0 out of 17 forms covered">
+<span class="not-covered" title="0 out of 1 forms covered">
                 091&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(l&#x2F;info&nbsp;&quot;Generating&nbsp;SVG&nbsp;for&nbsp;&quot;&nbsp;*preferred-svg-render*&nbsp;&quot;&nbsp;renderer&quot;)
                 </span><br/>
 <span class="not-covered" title="0 out of 3 forms covered">
@@ -316,7 +316,7 @@
 <span class="not-covered" title="0 out of 4 forms covered">
                 104&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(let&nbsp;[s&nbsp;(binary-stl-file-&gt;svg&nbsp;in-filename)]
                 </span><br/>
-<span class="not-covered" title="0 out of 17 forms covered">
+<span class="not-covered" title="0 out of 1 forms covered">
                 105&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(l&#x2F;info&nbsp;&quot;Emitting&nbsp;SVG&nbsp;with&nbsp;&quot;&nbsp;*preferred-svg-render*&nbsp;&quot;&nbsp;renderer&quot;)
                 </span><br/>
 <span class="not-covered" title="0 out of 3 forms covered">
diff --git a/docs/cloverage/walkmap/tag.clj.html b/docs/cloverage/walkmap/tag.clj.html
index d26ce5f..1a20e0b 100644
--- a/docs/cloverage/walkmap/tag.clj.html
+++ b/docs/cloverage/walkmap/tag.clj.html
@@ -118,7 +118,7 @@
 <span class="not-tracked" title="0 out of 0 forms covered">
                 038&nbsp;&nbsp;&nbsp;&nbsp;[object&nbsp;&amp;&nbsp;tags]
                 </span><br/>
-<span class="covered" title="20 out of 20 forms covered">
+<span class="covered" title="1 out of 1 forms covered">
                 039&nbsp;&nbsp;&nbsp;&nbsp;(l&#x2F;debug&nbsp;&quot;Tagging&quot;&nbsp;(kind-type&nbsp;object)&nbsp;&quot;with&quot;&nbsp;tags)
                 </span><br/>
 <span class="covered" title="6 out of 6 forms covered">
diff --git a/docs/cloverage/walkmap/utils.clj.html b/docs/cloverage/walkmap/utils.clj.html
index 84e02ec..1ed6104 100644
--- a/docs/cloverage/walkmap/utils.clj.html
+++ b/docs/cloverage/walkmap/utils.clj.html
@@ -61,7 +61,7 @@
 <span class="not-tracked" title="0 out of 0 forms covered">
                 019&nbsp;&nbsp;&nbsp;&nbsp;[s&nbsp;n]
                 </span><br/>
-<span class="partial" title="19 out of 21 forms covered">
+<span class="partial" title="20 out of 21 forms covered">
                 020&nbsp;&nbsp;&nbsp;&nbsp;(if&nbsp;(and&nbsp;(string?&nbsp;s)&nbsp;(number?&nbsp;n)&nbsp;(&gt;&nbsp;(count&nbsp;s)&nbsp;n))
                 </span><br/>
 <span class="covered" title="5 out of 5 forms covered">
@@ -91,7 +91,7 @@
 <span class="not-tracked" title="0 out of 0 forms covered">
                 029&nbsp;&nbsp;&nbsp;&nbsp;[object]
                 </span><br/>
-<span class="partial" title="14 out of 15 forms covered">
+<span class="covered" title="15 out of 15 forms covered">
                 030&nbsp;&nbsp;&nbsp;&nbsp;(or&nbsp;(:kind&nbsp;object)&nbsp;(type&nbsp;object)&nbsp;&quot;nil&quot;))
                 </span><br/>
 <span class="blank" title="0 out of 0 forms covered">
@@ -104,7 +104,7 @@
                 033&nbsp;&nbsp;&nbsp;&nbsp;&quot;True&nbsp;if&nbsp;numbers&nbsp;`n1`,&nbsp;`n2`&nbsp;are&nbsp;roughly&nbsp;equal;&nbsp;that&nbsp;is&nbsp;to&nbsp;say,&nbsp;equal&nbsp;to
                 </span><br/>
 <span class="not-tracked" title="0 out of 0 forms covered">
-                034&nbsp;&nbsp;&nbsp;&nbsp;within&nbsp;`tolerance`&nbsp;(defaults&nbsp;to&nbsp;one&nbsp;part&nbsp;in&nbsp;a&nbsp;million).&quot;
+                034&nbsp;&nbsp;&nbsp;&nbsp;within&nbsp;`tolerance`&nbsp;(defaults&nbsp;to&nbsp;one&nbsp;part&nbsp;in&nbsp;one&nbsp;hundred&nbsp;thousand).&quot;
                 </span><br/>
 <span class="not-tracked" title="0 out of 0 forms covered">
                 035&nbsp;&nbsp;&nbsp;&nbsp;([n1&nbsp;n2]
@@ -116,7 +116,7 @@
                 037&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(let&nbsp;[m&nbsp;(m&#x2F;abs&nbsp;(min&nbsp;n1&nbsp;n2))
                 </span><br/>
 <span class="covered" title="9 out of 9 forms covered">
-                038&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;t&nbsp;(if&nbsp;(zero?&nbsp;m)&nbsp;0.000001&nbsp;(*&nbsp;0.000001&nbsp;m))]
+                038&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;t&nbsp;(if&nbsp;(zero?&nbsp;m)&nbsp;0.00001&nbsp;(*&nbsp;0.00001&nbsp;m))]
                 </span><br/>
 <span class="covered" title="5 out of 5 forms covered">
                 039&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(=ish&nbsp;n1&nbsp;n2&nbsp;t))
@@ -139,7 +139,7 @@
 <span class="blank" title="0 out of 0 forms covered">
                 045&nbsp;&nbsp;
                 </span><br/>
-<span class="partial" title="94 out of 198 forms covered">
+<span class="covered" title="198 out of 198 forms covered">
                 046&nbsp;&nbsp;(defmacro&nbsp;check-kind-type
                 </span><br/>
 <span class="not-tracked" title="0 out of 0 forms covered">
@@ -163,7 +163,7 @@
 <span class="not-tracked" title="0 out of 0 forms covered">
                 053&nbsp;&nbsp;&nbsp;&nbsp;([object&nbsp;expected]
                 </span><br/>
-<span class="not-covered" title="0 out of 2 forms covered">
+<span class="covered" title="2 out of 2 forms covered">
                 054&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;`(if-not&nbsp;(=&nbsp;(kind-type&nbsp;~object)&nbsp;~expected)
                 </span><br/>
 <span class="not-tracked" title="0 out of 0 forms covered">
@@ -178,10 +178,10 @@
 <span class="not-tracked" title="0 out of 0 forms covered">
                 058&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&quot;&nbsp;&quot;
                 </span><br/>
-<span class="not-covered" title="0 out of 2 forms covered">
+<span class="covered" title="2 out of 2 forms covered">
                 059&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;[&quot;Expected&quot;&nbsp;~expected&nbsp;&quot;but&nbsp;found&quot;&nbsp;(kind-type&nbsp;~object)])))
                 </span><br/>
-<span class="not-covered" title="0 out of 1 forms covered">
+<span class="covered" title="1 out of 1 forms covered">
                 060&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;~object))
                 </span><br/>
 <span class="not-tracked" title="0 out of 0 forms covered">
@@ -211,7 +211,7 @@
 <span class="blank" title="0 out of 0 forms covered">
                 069&nbsp;&nbsp;
                 </span><br/>
-<span class="partial" title="203 out of 416 forms covered">
+<span class="covered" title="416 out of 416 forms covered">
                 070&nbsp;&nbsp;(defmacro&nbsp;check-kind-type-seq
                 </span><br/>
 <span class="not-tracked" title="0 out of 0 forms covered">
@@ -235,7 +235,7 @@
 <span class="not-tracked" title="0 out of 0 forms covered">
                 077&nbsp;&nbsp;&nbsp;&nbsp;([s&nbsp;expected]
                 </span><br/>
-<span class="not-covered" title="0 out of 2 forms covered">
+<span class="covered" title="2 out of 2 forms covered">
                 078&nbsp;&nbsp;&nbsp;&nbsp;`(if-not&nbsp;(every?&nbsp;#(=&nbsp;(kind-type&nbsp;%)&nbsp;~expected)&nbsp;~s)
                 </span><br/>
 <span class="not-tracked" title="0 out of 0 forms covered">
@@ -253,19 +253,19 @@
 <span class="not-tracked" title="0 out of 0 forms covered">
                 083&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;[&quot;Expected&nbsp;sequence&nbsp;of&quot;
                 </span><br/>
-<span class="not-covered" title="0 out of 1 forms covered">
+<span class="covered" title="1 out of 1 forms covered">
                 084&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;~expected
                 </span><br/>
 <span class="not-tracked" title="0 out of 0 forms covered">
                 085&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&quot;but&nbsp;found&nbsp;(&quot;
                 </span><br/>
-<span class="not-covered" title="0 out of 2 forms covered">
+<span class="covered" title="2 out of 2 forms covered">
                 086&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(s&#x2F;join&nbsp;&quot;,&nbsp;&quot;&nbsp;(remove&nbsp;#(=&nbsp;~expected&nbsp;%)&nbsp;(map&nbsp;kind-type&nbsp;~s)))
                 </span><br/>
 <span class="not-tracked" title="0 out of 0 forms covered">
                 087&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&quot;)&quot;])))
                 </span><br/>
-<span class="not-covered" title="0 out of 1 forms covered">
+<span class="covered" title="1 out of 1 forms covered">
                 088&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;~s))
                 </span><br/>
 <span class="not-tracked" title="0 out of 0 forms covered">
diff --git a/docs/cloverage/walkmap/vertex.clj.html b/docs/cloverage/walkmap/vertex.clj.html
index b1ca90f..6495272 100644
--- a/docs/cloverage/walkmap/vertex.clj.html
+++ b/docs/cloverage/walkmap/vertex.clj.html
@@ -130,7 +130,7 @@
 <span class="not-tracked" title="0 out of 0 forms covered">
                 042&nbsp;&nbsp;&nbsp;&nbsp;[o]
                 </span><br/>
-<span class="partial" title="23 out of 26 forms covered">
+<span class="partial" title="24 out of 26 forms covered">
                 043&nbsp;&nbsp;&nbsp;&nbsp;(and
                 </span><br/>
 <span class="covered" title="3 out of 3 forms covered">
@@ -139,7 +139,7 @@
 <span class="covered" title="3 out of 3 forms covered">
                 045&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(:walkmap.id&#x2F;id&nbsp;o)
                 </span><br/>
-<span class="partial" title="13 out of 17 forms covered">
+<span class="partial" title="11 out of 17 forms covered">
                 046&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(number?&nbsp;(:x&nbsp;o))
                 </span><br/>
 <span class="covered" title="5 out of 5 forms covered">
@@ -205,13 +205,13 @@
 <span class="not-tracked" title="0 out of 0 forms covered">
                 067&nbsp;&nbsp;&nbsp;&nbsp;[v1&nbsp;v2]
                 </span><br/>
-<span class="covered" title="16 out of 16 forms covered">
+<span class="partial" title="6 out of 16 forms covered">
                 068&nbsp;&nbsp;&nbsp;&nbsp;(check-vertex&nbsp;v1)
                 </span><br/>
 <span class="covered" title="16 out of 16 forms covered">
                 069&nbsp;&nbsp;&nbsp;&nbsp;(check-vertex&nbsp;v2)
                 </span><br/>
-<span class="partial" title="5 out of 12 forms covered">
+<span class="covered" title="12 out of 12 forms covered">
                 070&nbsp;&nbsp;&nbsp;&nbsp;(every?
                 </span><br/>
 <span class="covered" title="8 out of 8 forms covered">
@@ -430,29 +430,32 @@
 <span class="not-tracked" title="0 out of 0 forms covered">
                 142&nbsp;&nbsp;&nbsp;&nbsp;[target&nbsp;minv&nbsp;maxv]
                 </span><br/>
-<span class="partial" title="14 out of 34 forms covered">
-                143&nbsp;&nbsp;&nbsp;&nbsp;(check-vertices&nbsp;[target&nbsp;minv&nbsp;maxv])
+<span class="covered" title="1 out of 1 forms covered">
+                143&nbsp;&nbsp;&nbsp;&nbsp;(do
+                </span><br/>
+<span class="covered" title="34 out of 34 forms covered">
+                144&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(check-vertices&nbsp;[target&nbsp;minv&nbsp;maxv])
                 </span><br/>
 <span class="covered" title="2 out of 2 forms covered">
-                144&nbsp;&nbsp;&nbsp;&nbsp;(every?
+                145&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(every?
                 </span><br/>
 <span class="covered" title="1 out of 1 forms covered">
-                145&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;true?
+                146&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;true?
                 </span><br/>
 <span class="covered" title="3 out of 3 forms covered">
-                146&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(map
+                147&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(map
                 </span><br/>
 <span class="covered" title="5 out of 5 forms covered">
-                147&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;#(if&nbsp;(%&nbsp;target)
+                148&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;#(if&nbsp;(%&nbsp;target)
                 </span><br/>
 <span class="covered" title="11 out of 11 forms covered">
-                148&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(&lt;=&nbsp;(%&nbsp;minv)&nbsp;(%&nbsp;target)&nbsp;(%&nbsp;maxv))
+                149&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(&lt;=&nbsp;(%&nbsp;minv)&nbsp;(%&nbsp;target)&nbsp;(%&nbsp;maxv))
                 </span><br/>
 <span class="not-tracked" title="0 out of 0 forms covered">
-                149&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;true)
+                150&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;true)
                 </span><br/>
 <span class="covered" title="4 out of 4 forms covered">
-                150&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;[:x&nbsp;:y&nbsp;:z])))
+                151&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;[:x&nbsp;:y&nbsp;:z]))))
                 </span><br/>
  </body>
 </html>
diff --git a/test/walkmap/utils_test.clj b/test/walkmap/utils_test.clj
index 3a09b01..d2ce375 100644
--- a/test/walkmap/utils_test.clj
+++ b/test/walkmap/utils_test.clj
@@ -1,6 +1,7 @@
 (ns walkmap.utils-test
   (:require [clojure.test :refer :all]
-            [walkmap.utils :refer :all]))
+            [walkmap.utils :refer :all]
+            [walkmap.vertex :refer [vertex vertex?]]))
 
 (deftest =ish-tests
   (testing "Rough equality"
@@ -12,3 +13,88 @@
     (is (=ish :foo :foo) "Fails over to plain old equals for non-numbers.")
     (is (=ish 6 5 10000) "If tolerance is wide enough, anything can be equal.")
     (is (not (=ish "hello" "goodbye" 10000)) "Well, except non-numbers, of course.")))
+
+(deftest truncate-tests
+  (testing "String truncation"
+    (is (= (truncate "The quick brown fox jumped over the lazy dog" 19)
+           "The quick brown fox")
+        "If it's a sting, and longer than the desired length, it should be
+        truncated.")
+    (is (= (truncate "The quick brown fox jumped over the lazy dog" 100)
+           "The quick brown fox jumped over the lazy dog")
+        "If it's a sting, and shorter than the desired length, it should not be
+        truncated.")
+    (is (= (truncate :the-quick-brown-fox 10) :the-quick-brown-fox)
+        "If it's not a string, it should not be truncated, regardless.")))
+
+
+(deftest kind-type-tests
+  (testing "Type identification."
+    (is (= (kind-type {:kind :test}) :test)
+        "Maps with a value for `:kind` return that as their kind.")
+    (is (= (kind-type {:dnik :test}) clojure.lang.PersistentArrayMap)
+        "Maps with no value for `:kind` are just maps.")
+    (is (= (kind-type nil) "nil")
+        "As a special case, the kind of `nil` is the string \"nil\".")
+    (is (= (kind-type "Fred") java.lang.String)
+        "The kind-type of anything else is just its Java class.")))
+
+(deftest check-kind-type-tests
+  (testing "Exception thrown if kind not as expected."
+    (let [v {:kind :test}]
+      (is (= (check-kind-type v :test) v)
+          "If the check passes, the object is returned."))
+    (let [v "test"]
+      (is (= (check-kind-type v java.lang.String) v)
+          "If the check passes, the object is returned."))
+    (let [v "test"]
+      (is (= (check-kind-type v string? java.lang.String) v)
+          "If the check passes, the object is returned."))
+    (let [v (vertex 1 1 1)]
+      (is (= (check-kind-type v :vertex) v)
+          "If the check passes, the object is returned."))
+    (let [v (vertex 1 1 1)]
+      (is (= (check-kind-type v vertex? :vertex) v)
+          "If the check passes, the object is returned."))
+    (let [v "test"]
+      (is (thrown? IllegalArgumentException
+                   (check-kind-type v :test))
+          "If the check doesn't pass, an exception is thrown."))
+    (let [v {:kind :test}]
+      (is (thrown? IllegalArgumentException
+                   (check-kind-type v vertex? :vertex))
+          "If the check doesn't pass, an exception is thrown."))))
+
+(deftest check-kind-type-seq-tests
+  (testing "Exception thrown if kind not as expected: sequence variant."
+    (let [v [{:kind :test} {:kind :test}]]
+      (is (= (check-kind-type-seq v :test) v)
+          "If the check passes, the object is returned."))
+    (let [v (list "another" "test")]
+      (is (= (check-kind-type-seq v java.lang.String) v)
+          "If the check passes, the object is returned."))
+    (let [v ["more" "test" "strings"]]
+      (is (= (check-kind-type-seq v string? java.lang.String) v)
+          "If the check passes, the object is returned."))
+    (let [v (list (vertex 1 1 1) (vertex 2 2 2) (vertex 3 3 3))]
+      (is (= (check-kind-type-seq v :vertex) v)
+          "If the check passes, the object is returned."))
+    (let [v (list (vertex 1 1 1))]
+      (is (= (check-kind-type-seq v vertex? :vertex) v)
+          "If the check passes, the object is returned."))
+    (let [v :test]
+      (is (thrown? IllegalArgumentException
+                   (check-kind-type-seq v :test))
+          "If the arg isn't a sequence, an exception is thrown."))
+    (let [v (list (vertex 1 1 1) "test" (vertex 3 3 3))]
+      (is (thrown? IllegalArgumentException
+                   (check-kind-type-seq v :test))
+          "If the check doesn't pass for any item, an exception is thrown."))
+    (let [v (list (vertex 1 1 1) (vertex 2 2 2) "test")]
+      (is (thrown? IllegalArgumentException
+                   (check-kind-type-seq v vertex? :vertex))
+          "If the check doesn't pass, an exception is thrown."))))
+
+
+
+