462 lines
29 KiB
HTML
462 lines
29 KiB
HTML
<html>
|
|
<head>
|
|
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
|
|
<link rel="stylesheet" href="../coverage.css"/> <title> walkmap/vertex.clj </title>
|
|
</head>
|
|
<body>
|
|
<span class="covered" title="1 out of 1 forms covered">
|
|
001 (ns walkmap.vertex
|
|
</span><br/>
|
|
<span class="not-tracked" title="0 out of 0 forms covered">
|
|
002 "Essentially the specification for things we shall consider to be vertices.
|
|
</span><br/>
|
|
<span class="blank" title="0 out of 0 forms covered">
|
|
003
|
|
</span><br/>
|
|
<span class="not-tracked" title="0 out of 0 forms covered">
|
|
004 Note that there's no `distance` function here; to find the distance between
|
|
</span><br/>
|
|
<span class="not-tracked" title="0 out of 0 forms covered">
|
|
005 two vertices, create an edge from them and use `walkmap.edge/length`."
|
|
</span><br/>
|
|
<span class="not-tracked" title="0 out of 0 forms covered">
|
|
006 (:require [clojure.math.numeric-tower :as m]
|
|
</span><br/>
|
|
<span class="not-tracked" title="0 out of 0 forms covered">
|
|
007 [clojure.string :as s]
|
|
</span><br/>
|
|
<span class="not-tracked" title="0 out of 0 forms covered">
|
|
008 [taoensso.timbre :as l]
|
|
</span><br/>
|
|
<span class="not-tracked" title="0 out of 0 forms covered">
|
|
009 [walkmap.utils :refer [=ish check-kind-type check-kind-type-seq kind-type truncate]]))
|
|
</span><br/>
|
|
<span class="blank" title="0 out of 0 forms covered">
|
|
010
|
|
</span><br/>
|
|
<span class="covered" title="1 out of 1 forms covered">
|
|
011 (defn vertex-key
|
|
</span><br/>
|
|
<span class="not-tracked" title="0 out of 0 forms covered">
|
|
012 "Making sure we get the same key everytime we key a vertex with the same
|
|
</span><br/>
|
|
<span class="not-tracked" title="0 out of 0 forms covered">
|
|
013 coordinates. `o` must have numeric values for `:x`, `:y`, and optionally
|
|
</span><br/>
|
|
<span class="not-tracked" title="0 out of 0 forms covered">
|
|
014 `:z`; it is an error and an exception will be thrown if `o` does not
|
|
</span><br/>
|
|
<span class="not-tracked" title="0 out of 0 forms covered">
|
|
015 conform to this specification.
|
|
</span><br/>
|
|
<span class="blank" title="0 out of 0 forms covered">
|
|
016
|
|
</span><br/>
|
|
<span class="not-tracked" title="0 out of 0 forms covered">
|
|
017 **Note:** these keys can be quite long. No apology is made: it is required
|
|
</span><br/>
|
|
<span class="not-tracked" title="0 out of 0 forms covered">
|
|
018 that the same key can *never* refer to two different locations in space."
|
|
</span><br/>
|
|
<span class="not-tracked" title="0 out of 0 forms covered">
|
|
019 [o]
|
|
</span><br/>
|
|
<span class="covered" title="2 out of 2 forms covered">
|
|
020 (keyword
|
|
</span><br/>
|
|
<span class="covered" title="4 out of 4 forms covered">
|
|
021 (s/replace
|
|
</span><br/>
|
|
<span class="partial" title="2 out of 3 forms covered">
|
|
022 (cond
|
|
</span><br/>
|
|
<span class="partial" title="15 out of 17 forms covered">
|
|
023 (and (:x o) (:y o) (:z o))
|
|
</span><br/>
|
|
<span class="covered" title="14 out of 14 forms covered">
|
|
024 (str "vert_" (:x o) "_" (:y o) "_" (:z o))
|
|
</span><br/>
|
|
<span class="partial" title="9 out of 10 forms covered">
|
|
025 (and (:x o) (:y o))
|
|
</span><br/>
|
|
<span class="covered" title="10 out of 10 forms covered">
|
|
026 (str "vert_" (:x o) "_" (:y o))
|
|
</span><br/>
|
|
<span class="not-tracked" title="0 out of 0 forms covered">
|
|
027 :else
|
|
</span><br/>
|
|
<span class="not-covered" title="0 out of 2 forms covered">
|
|
028 (throw (IllegalArgumentException.
|
|
</span><br/>
|
|
<span class="not-covered" title="0 out of 12 forms covered">
|
|
029 (truncate (str "Not a vertex: " (or o "nil")) 80))))
|
|
</span><br/>
|
|
<span class="not-tracked" title="0 out of 0 forms covered">
|
|
030 "."
|
|
</span><br/>
|
|
<span class="not-tracked" title="0 out of 0 forms covered">
|
|
031 "-")))
|
|
</span><br/>
|
|
<span class="blank" title="0 out of 0 forms covered">
|
|
032
|
|
</span><br/>
|
|
<span class="covered" title="1 out of 1 forms covered">
|
|
033 (defn vertex?
|
|
</span><br/>
|
|
<span class="not-tracked" title="0 out of 0 forms covered">
|
|
034 "True if `o` satisfies the conditions for a vertex. That is, essentially,
|
|
</span><br/>
|
|
<span class="not-tracked" title="0 out of 0 forms covered">
|
|
035 that it must rerpresent a two- or three- dimensional vector. A vertex is
|
|
</span><br/>
|
|
<span class="not-tracked" title="0 out of 0 forms covered">
|
|
036 shall be a map having at least the keys `:x` and `:y`, where the value of
|
|
</span><br/>
|
|
<span class="not-tracked" title="0 out of 0 forms covered">
|
|
037 those keys is a number. If the key `:z` is also present, its value must also
|
|
</span><br/>
|
|
<span class="not-tracked" title="0 out of 0 forms covered">
|
|
038 be a number.
|
|
</span><br/>
|
|
<span class="blank" title="0 out of 0 forms covered">
|
|
039
|
|
</span><br/>
|
|
<span class="not-tracked" title="0 out of 0 forms covered">
|
|
040 The name `vector?` was not used as that would clash with a function of that
|
|
</span><br/>
|
|
<span class="not-tracked" title="0 out of 0 forms covered">
|
|
041 name in `clojure.core` whose semantics are entirely different."
|
|
</span><br/>
|
|
<span class="not-tracked" title="0 out of 0 forms covered">
|
|
042 [o]
|
|
</span><br/>
|
|
<span class="partial" title="24 out of 26 forms covered">
|
|
043 (and
|
|
</span><br/>
|
|
<span class="covered" title="3 out of 3 forms covered">
|
|
044 (map? o)
|
|
</span><br/>
|
|
<span class="covered" title="3 out of 3 forms covered">
|
|
045 (:walkmap.id/id o)
|
|
</span><br/>
|
|
<span class="covered" title="5 out of 5 forms covered">
|
|
046 (number? (:x o))
|
|
</span><br/>
|
|
<span class="covered" title="5 out of 5 forms covered">
|
|
047 (number? (:y o))
|
|
</span><br/>
|
|
<span class="partial" title="20 out of 26 forms covered">
|
|
048 (or (nil? (:z o)) (number? (:z o)))
|
|
</span><br/>
|
|
<span class="covered" title="9 out of 9 forms covered">
|
|
049 (or (nil? (:kind o)) (= (:kind o) :vertex))))
|
|
</span><br/>
|
|
<span class="blank" title="0 out of 0 forms covered">
|
|
050
|
|
</span><br/>
|
|
<span class="covered" title="27 out of 27 forms covered">
|
|
051 (defmacro check-vertex
|
|
</span><br/>
|
|
<span class="not-tracked" title="0 out of 0 forms covered">
|
|
052 "If `o` is not a vertex, throw an `IllegalArgumentException` with an
|
|
</span><br/>
|
|
<span class="not-tracked" title="0 out of 0 forms covered">
|
|
053 appropriate message; otherwise, returns `o`. Macro, so exception is thrown
|
|
</span><br/>
|
|
<span class="not-tracked" title="0 out of 0 forms covered">
|
|
054 from the calling function."
|
|
</span><br/>
|
|
<span class="not-tracked" title="0 out of 0 forms covered">
|
|
055 [o]
|
|
</span><br/>
|
|
<span class="covered" title="1 out of 1 forms covered">
|
|
056 `(check-kind-type ~o vertex? :vertex))
|
|
</span><br/>
|
|
<span class="blank" title="0 out of 0 forms covered">
|
|
057
|
|
</span><br/>
|
|
<span class="covered" title="22 out of 22 forms covered">
|
|
058 (defmacro check-vertices
|
|
</span><br/>
|
|
<span class="not-tracked" title="0 out of 0 forms covered">
|
|
059 "If `o` is not a sequence of vertices, throw an `IllegalArgumentException` with an
|
|
</span><br/>
|
|
<span class="not-tracked" title="0 out of 0 forms covered">
|
|
060 appropriate message; otherwise, returns `o`. Macro, so exception is thrown
|
|
</span><br/>
|
|
<span class="not-tracked" title="0 out of 0 forms covered">
|
|
061 from the calling function."
|
|
</span><br/>
|
|
<span class="not-tracked" title="0 out of 0 forms covered">
|
|
062 [o]
|
|
</span><br/>
|
|
<span class="covered" title="1 out of 1 forms covered">
|
|
063 `(check-kind-type-seq ~o vertex? :vertex))
|
|
</span><br/>
|
|
<span class="blank" title="0 out of 0 forms covered">
|
|
064
|
|
</span><br/>
|
|
<span class="covered" title="1 out of 1 forms covered">
|
|
065 (defn vertex=
|
|
</span><br/>
|
|
<span class="not-tracked" title="0 out of 0 forms covered">
|
|
066 "True if vertices `v1`, `v2` represent the same vertex."
|
|
</span><br/>
|
|
<span class="not-tracked" title="0 out of 0 forms covered">
|
|
067 [v1 v2]
|
|
</span><br/>
|
|
<span class="partial" title="6 out of 16 forms covered">
|
|
068 (check-vertex v1)
|
|
</span><br/>
|
|
<span class="covered" title="16 out of 16 forms covered">
|
|
069 (check-vertex v2)
|
|
</span><br/>
|
|
<span class="covered" title="3 out of 3 forms covered">
|
|
070 (every?
|
|
</span><br/>
|
|
<span class="covered" title="8 out of 8 forms covered">
|
|
071 #(=ish (% v1) (% v2))
|
|
</span><br/>
|
|
<span class="covered" title="13 out of 13 forms covered">
|
|
072 [:x :y :z]))
|
|
</span><br/>
|
|
<span class="blank" title="0 out of 0 forms covered">
|
|
073
|
|
</span><br/>
|
|
<span class="covered" title="1 out of 1 forms covered">
|
|
074 (defn vertex*
|
|
</span><br/>
|
|
<span class="not-tracked" title="0 out of 0 forms covered">
|
|
075 "Return a vertex like `v1`, but with each of its coordinates multiplied
|
|
</span><br/>
|
|
<span class="not-tracked" title="0 out of 0 forms covered">
|
|
076 by the equivalent vertex in `v2`. It is an error, and an exception will
|
|
</span><br/>
|
|
<span class="not-tracked" title="0 out of 0 forms covered">
|
|
077 be thrown, if either `v1` or `v2` is not a vertex."
|
|
</span><br/>
|
|
<span class="not-tracked" title="0 out of 0 forms covered">
|
|
078 [v1 v2]
|
|
</span><br/>
|
|
<span class="covered" title="2 out of 2 forms covered">
|
|
079 (let [f (fn [v1 v2 coord]
|
|
</span><br/>
|
|
<span class="covered" title="10 out of 10 forms covered">
|
|
080 (* (or (coord v1) 0)
|
|
</span><br/>
|
|
<span class="not-tracked" title="0 out of 0 forms covered">
|
|
081 ;; one here is deliberate!
|
|
</span><br/>
|
|
<span class="covered" title="8 out of 8 forms covered">
|
|
082 (or (coord v2) 1)))]
|
|
</span><br/>
|
|
<span class="covered" title="41 out of 41 forms covered">
|
|
083 (assoc v1 :x (f (check-vertex v1) (check-vertex v2) :x)
|
|
</span><br/>
|
|
<span class="covered" title="5 out of 5 forms covered">
|
|
084 :y (f v1 v2 :y)
|
|
</span><br/>
|
|
<span class="covered" title="5 out of 5 forms covered">
|
|
085 :z (f v1 v2 :z))))
|
|
</span><br/>
|
|
<span class="blank" title="0 out of 0 forms covered">
|
|
086
|
|
</span><br/>
|
|
<span class="covered" title="1 out of 1 forms covered">
|
|
087 (defn vertex
|
|
</span><br/>
|
|
<span class="not-tracked" title="0 out of 0 forms covered">
|
|
088 "Make a vertex with this `x`, `y` and (if provided) `z` values. Returns a map
|
|
</span><br/>
|
|
<span class="not-tracked" title="0 out of 0 forms covered">
|
|
089 with those values, plus a unique `:walkmap.id/id` value, and `:kind` set to `:vertex`.
|
|
</span><br/>
|
|
<span class="not-tracked" title="0 out of 0 forms covered">
|
|
090 It's not necessary to use this function to create a vertex, but the `:walkmap.id/id`
|
|
</span><br/>
|
|
<span class="not-tracked" title="0 out of 0 forms covered">
|
|
091 must be present and must be unique."
|
|
</span><br/>
|
|
<span class="not-tracked" title="0 out of 0 forms covered">
|
|
092 ([x y]
|
|
</span><br/>
|
|
<span class="covered" title="8 out of 8 forms covered">
|
|
093 (let [v {:x x :y y :kind :vertex}]
|
|
</span><br/>
|
|
<span class="covered" title="7 out of 7 forms covered">
|
|
094 (assoc v :walkmap.id/id (vertex-key v))))
|
|
</span><br/>
|
|
<span class="not-tracked" title="0 out of 0 forms covered">
|
|
095 ([x y z]
|
|
</span><br/>
|
|
<span class="covered" title="10 out of 10 forms covered">
|
|
096 (let [v {:x x :y y :z z :kind :vertex}]
|
|
</span><br/>
|
|
<span class="covered" title="7 out of 7 forms covered">
|
|
097 (assoc v :walkmap.id/id (vertex-key v)))))
|
|
</span><br/>
|
|
<span class="blank" title="0 out of 0 forms covered">
|
|
098
|
|
</span><br/>
|
|
<span class="covered" title="1 out of 1 forms covered">
|
|
099 (defn canonicalise
|
|
</span><br/>
|
|
<span class="not-tracked" title="0 out of 0 forms covered">
|
|
100 "If `o` is a map with numeric values for `:x`, `:y` and optionally `:z`,
|
|
</span><br/>
|
|
<span class="not-tracked" title="0 out of 0 forms covered">
|
|
101 upgrade it to something we will recognise as a vertex."
|
|
</span><br/>
|
|
<span class="not-tracked" title="0 out of 0 forms covered">
|
|
102 [o]
|
|
</span><br/>
|
|
<span class="covered" title="1 out of 1 forms covered">
|
|
103 (if
|
|
</span><br/>
|
|
<span class="partial" title="16 out of 17 forms covered">
|
|
104 (and
|
|
</span><br/>
|
|
<span class="covered" title="3 out of 3 forms covered">
|
|
105 (map? o)
|
|
</span><br/>
|
|
<span class="covered" title="5 out of 5 forms covered">
|
|
106 (number? (:x o))
|
|
</span><br/>
|
|
<span class="covered" title="5 out of 5 forms covered">
|
|
107 (number? (:y o))
|
|
</span><br/>
|
|
<span class="covered" title="9 out of 9 forms covered">
|
|
108 (or (nil? (:z o)) (number? (:z o))))
|
|
</span><br/>
|
|
<span class="covered" title="9 out of 9 forms covered">
|
|
109 (assoc o :kind :vertex :walkmap.id/id (vertex-key o))
|
|
</span><br/>
|
|
<span class="covered" title="1 out of 1 forms covered">
|
|
110 (throw
|
|
</span><br/>
|
|
<span class="covered" title="1 out of 1 forms covered">
|
|
111 (IllegalArgumentException.
|
|
</span><br/>
|
|
<span class="covered" title="3 out of 3 forms covered">
|
|
112 (truncate
|
|
</span><br/>
|
|
<span class="covered" title="3 out of 3 forms covered">
|
|
113 (str "Not a proto-vertex: must have numeric `:x` and `:y`: "
|
|
</span><br/>
|
|
<span class="partial" title="5 out of 6 forms covered">
|
|
114 (or o "nil"))
|
|
</span><br/>
|
|
<span class="not-tracked" title="0 out of 0 forms covered">
|
|
115 80)))))
|
|
</span><br/>
|
|
<span class="blank" title="0 out of 0 forms covered">
|
|
116
|
|
</span><br/>
|
|
<span class="covered" title="1 out of 1 forms covered">
|
|
117 (def ensure3d
|
|
</span><br/>
|
|
<span class="not-tracked" title="0 out of 0 forms covered">
|
|
118 "Given a vertex `o`, if `o` has a `:z` value, just return `o`; otherwise
|
|
</span><br/>
|
|
<span class="not-tracked" title="0 out of 0 forms covered">
|
|
119 return a vertex like `o` but having this `dflt` value as the value of its
|
|
</span><br/>
|
|
<span class="not-tracked" title="0 out of 0 forms covered">
|
|
120 `:z` key, or zero as the value of its `:z` key if `dflt` is not specified.
|
|
</span><br/>
|
|
<span class="blank" title="0 out of 0 forms covered">
|
|
121
|
|
</span><br/>
|
|
<span class="not-tracked" title="0 out of 0 forms covered">
|
|
122 If `o` is not a vertex, throws an exception."
|
|
</span><br/>
|
|
<span class="covered" title="2 out of 2 forms covered">
|
|
123 (memoize
|
|
</span><br/>
|
|
<span class="covered" title="1 out of 1 forms covered">
|
|
124 (fn
|
|
</span><br/>
|
|
<span class="not-tracked" title="0 out of 0 forms covered">
|
|
125 ([o]
|
|
</span><br/>
|
|
<span class="covered" title="4 out of 4 forms covered">
|
|
126 (ensure3d o 0.0))
|
|
</span><br/>
|
|
<span class="not-tracked" title="0 out of 0 forms covered">
|
|
127 ([o dflt]
|
|
</span><br/>
|
|
<span class="partial" title="9 out of 19 forms covered">
|
|
128 (if (:z (check-vertex o))
|
|
</span><br/>
|
|
<span class="covered" title="1 out of 1 forms covered">
|
|
129 o
|
|
</span><br/>
|
|
<span class="covered" title="5 out of 5 forms covered">
|
|
130 (assoc o :z dflt))))))
|
|
</span><br/>
|
|
<span class="blank" title="0 out of 0 forms covered">
|
|
131
|
|
</span><br/>
|
|
<span class="covered" title="1 out of 1 forms covered">
|
|
132 (def ensure2d
|
|
</span><br/>
|
|
<span class="not-tracked" title="0 out of 0 forms covered">
|
|
133 "If `o` is a vertex, set its `:z` value to zero; else throw an exception."
|
|
</span><br/>
|
|
<span class="covered" title="2 out of 2 forms covered">
|
|
134 (memoize
|
|
</span><br/>
|
|
<span class="covered" title="1 out of 1 forms covered">
|
|
135 (fn [o]
|
|
</span><br/>
|
|
<span class="partial" title="10 out of 20 forms covered">
|
|
136 (assoc (check-vertex o) :z 0.0))))
|
|
</span><br/>
|
|
<span class="blank" title="0 out of 0 forms covered">
|
|
137
|
|
</span><br/>
|
|
<span class="covered" title="1 out of 1 forms covered">
|
|
138 (defn within-box?
|
|
</span><br/>
|
|
<span class="not-tracked" title="0 out of 0 forms covered">
|
|
139 "True if `target` is within the box defined by `minv` and `maxv`. All
|
|
</span><br/>
|
|
<span class="not-tracked" title="0 out of 0 forms covered">
|
|
140 arguments must be vertices; additionally, both `minv` and `maxv` must
|
|
</span><br/>
|
|
<span class="not-tracked" title="0 out of 0 forms covered">
|
|
141 have `:z` coordinates."
|
|
</span><br/>
|
|
<span class="not-tracked" title="0 out of 0 forms covered">
|
|
142 [target minv maxv]
|
|
</span><br/>
|
|
<span class="covered" title="1 out of 1 forms covered">
|
|
143 (do
|
|
</span><br/>
|
|
<span class="covered" title="34 out of 34 forms covered">
|
|
144 (check-vertices [target minv maxv])
|
|
</span><br/>
|
|
<span class="covered" title="2 out of 2 forms covered">
|
|
145 (every?
|
|
</span><br/>
|
|
<span class="covered" title="1 out of 1 forms covered">
|
|
146 true?
|
|
</span><br/>
|
|
<span class="covered" title="3 out of 3 forms covered">
|
|
147 (map
|
|
</span><br/>
|
|
<span class="covered" title="5 out of 5 forms covered">
|
|
148 #(if (% target)
|
|
</span><br/>
|
|
<span class="covered" title="11 out of 11 forms covered">
|
|
149 (<= (% minv) (% target) (% maxv))
|
|
</span><br/>
|
|
<span class="not-tracked" title="0 out of 0 forms covered">
|
|
150 true)
|
|
</span><br/>
|
|
<span class="covered" title="4 out of 4 forms covered">
|
|
151 [:x :y :z]))))
|
|
</span><br/>
|
|
</body>
|
|
</html>
|