351 lines
22 KiB
HTML
351 lines
22 KiB
HTML
<html>
|
|
<head>
|
|
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
|
|
<link rel="stylesheet" href="../coverage.css"/> <title> walkmap/polygon.clj </title>
|
|
</head>
|
|
<body>
|
|
<span class="covered" title="1 out of 1 forms covered">
|
|
001 (ns walkmap.polygon
|
|
</span><br/>
|
|
<span class="not-tracked" title="0 out of 0 forms covered">
|
|
002 "Essentially the specification for things we shall consider to be polygons."
|
|
</span><br/>
|
|
<span class="not-tracked" title="0 out of 0 forms covered">
|
|
003 (:require [clojure.string :as s]
|
|
</span><br/>
|
|
<span class="not-tracked" title="0 out of 0 forms covered">
|
|
004 [walkmap.edge :as e]
|
|
</span><br/>
|
|
<span class="not-tracked" title="0 out of 0 forms covered">
|
|
005 [walkmap.tag :as t]
|
|
</span><br/>
|
|
<span class="not-tracked" title="0 out of 0 forms covered">
|
|
006 [walkmap.utils :refer [check-kind-type check-kind-type-seq kind-type]]
|
|
</span><br/>
|
|
<span class="not-tracked" title="0 out of 0 forms covered">
|
|
007 [walkmap.vertex :refer [check-vertex check-vertices vertex vertex?]]))
|
|
</span><br/>
|
|
<span class="blank" title="0 out of 0 forms covered">
|
|
008
|
|
</span><br/>
|
|
<span class="covered" title="1 out of 1 forms covered">
|
|
009 (defn polygon?
|
|
</span><br/>
|
|
<span class="not-tracked" title="0 out of 0 forms covered">
|
|
010 "True if `o` satisfies the conditions for a polygon. A polygon shall be a
|
|
</span><br/>
|
|
<span class="not-tracked" title="0 out of 0 forms covered">
|
|
011 map which has a value for the key `:vertices`, where that value is a sequence
|
|
</span><br/>
|
|
<span class="not-tracked" title="0 out of 0 forms covered">
|
|
012 of vertices."
|
|
</span><br/>
|
|
<span class="not-tracked" title="0 out of 0 forms covered">
|
|
013 [o]
|
|
</span><br/>
|
|
<span class="covered" title="1 out of 1 forms covered">
|
|
014 (let
|
|
</span><br/>
|
|
<span class="covered" title="3 out of 3 forms covered">
|
|
015 [v (:vertices o)]
|
|
</span><br/>
|
|
<span class="partial" title="18 out of 22 forms covered">
|
|
016 (and
|
|
</span><br/>
|
|
<span class="covered" title="3 out of 3 forms covered">
|
|
017 (coll? v)
|
|
</span><br/>
|
|
<span class="covered" title="6 out of 6 forms covered">
|
|
018 (> (count v) 2)
|
|
</span><br/>
|
|
<span class="covered" title="4 out of 4 forms covered">
|
|
019 (every? vertex? v)
|
|
</span><br/>
|
|
<span class="covered" title="3 out of 3 forms covered">
|
|
020 (:walkmap.id/id o)
|
|
</span><br/>
|
|
<span class="covered" title="9 out of 9 forms covered">
|
|
021 (or (nil? (:kind o)) (= (:kind o) :polygon)))))
|
|
</span><br/>
|
|
<span class="blank" title="0 out of 0 forms covered">
|
|
022
|
|
</span><br/>
|
|
<span class="covered" title="22 out of 22 forms covered">
|
|
023 (defmacro check-polygon
|
|
</span><br/>
|
|
<span class="not-tracked" title="0 out of 0 forms covered">
|
|
024 "If `o` is not a polygon, throw an `IllegalArgumentException` with an
|
|
</span><br/>
|
|
<span class="not-tracked" title="0 out of 0 forms covered">
|
|
025 appropriate message; otherwise, returns `o`. Macro, so exception is thrown
|
|
</span><br/>
|
|
<span class="not-tracked" title="0 out of 0 forms covered">
|
|
026 from the calling function."
|
|
</span><br/>
|
|
<span class="not-tracked" title="0 out of 0 forms covered">
|
|
027 [o]
|
|
</span><br/>
|
|
<span class="covered" title="1 out of 1 forms covered">
|
|
028 `(check-kind-type ~o polygon? :polygon))
|
|
</span><br/>
|
|
<span class="blank" title="0 out of 0 forms covered">
|
|
029
|
|
</span><br/>
|
|
<span class="covered" title="21 out of 21 forms covered">
|
|
030 (defmacro check-polygons
|
|
</span><br/>
|
|
<span class="not-tracked" title="0 out of 0 forms covered">
|
|
031 "If `o` is not a sequence of polygons, throw an `IllegalArgumentException` with an
|
|
</span><br/>
|
|
<span class="not-tracked" title="0 out of 0 forms covered">
|
|
032 appropriate message; otherwise, returns `o`. Macro, so exception is thrown
|
|
</span><br/>
|
|
<span class="not-tracked" title="0 out of 0 forms covered">
|
|
033 from the calling function."
|
|
</span><br/>
|
|
<span class="not-tracked" title="0 out of 0 forms covered">
|
|
034 [o]
|
|
</span><br/>
|
|
<span class="covered" title="1 out of 1 forms covered">
|
|
035 `(check-kind-type-seq ~o polygon? :polygon))
|
|
</span><br/>
|
|
<span class="blank" title="0 out of 0 forms covered">
|
|
036
|
|
</span><br/>
|
|
<span class="covered" title="1 out of 1 forms covered">
|
|
037 (defn triangle?
|
|
</span><br/>
|
|
<span class="not-tracked" title="0 out of 0 forms covered">
|
|
038 "True if `o` satisfies the conditions for a triangle. A triangle shall be a
|
|
</span><br/>
|
|
<span class="not-tracked" title="0 out of 0 forms covered">
|
|
039 polygon with exactly three vertices."
|
|
</span><br/>
|
|
<span class="not-tracked" title="0 out of 0 forms covered">
|
|
040 [o]
|
|
</span><br/>
|
|
<span class="partial" title="5 out of 6 forms covered">
|
|
041 (and
|
|
</span><br/>
|
|
<span class="covered" title="3 out of 3 forms covered">
|
|
042 (coll? o)
|
|
</span><br/>
|
|
<span class="covered" title="6 out of 6 forms covered">
|
|
043 (= (count (:vertices o)) 3)))
|
|
</span><br/>
|
|
<span class="blank" title="0 out of 0 forms covered">
|
|
044
|
|
</span><br/>
|
|
<span class="covered" title="23 out of 23 forms covered">
|
|
045 (defmacro check-triangle
|
|
</span><br/>
|
|
<span class="partial" title="2 out of 10 forms covered">
|
|
046 "If `o` is not a triangle, throw an `IllegalArgumentException` with an
|
|
</span><br/>
|
|
<span class="not-tracked" title="0 out of 0 forms covered">
|
|
047 appropriate message; otherwise, returns `o`. Macro, so exception is thrown
|
|
</span><br/>
|
|
<span class="not-tracked" title="0 out of 0 forms covered">
|
|
048 from the calling function."
|
|
</span><br/>
|
|
<span class="not-tracked" title="0 out of 0 forms covered">
|
|
049 [o]
|
|
</span><br/>
|
|
<span class="covered" title="1 out of 1 forms covered">
|
|
050 `(check-kind-type ~o triangle? :triangle))
|
|
</span><br/>
|
|
<span class="blank" title="0 out of 2 forms covered">
|
|
051
|
|
</span><br/>
|
|
<span class="covered" title="1 out of 1 forms covered">
|
|
052 (defn polygon
|
|
</span><br/>
|
|
<span class="not-tracked" title="0 out of 0 forms covered">
|
|
053 "Return a polygon constructed from these `vertices`."
|
|
</span><br/>
|
|
<span class="not-tracked" title="0 out of 0 forms covered">
|
|
054 [& vertices]
|
|
</span><br/>
|
|
<span class="covered" title="30 out of 30 forms covered">
|
|
055 {:vertices (check-vertices vertices)
|
|
</span><br/>
|
|
<span class="covered" title="5 out of 5 forms covered">
|
|
056 :walkmap.id/id (keyword (gensym "poly"))
|
|
</span><br/>
|
|
<span class="not-tracked" title="0 out of 0 forms covered">
|
|
057 :kind :polygon})
|
|
</span><br/>
|
|
<span class="blank" title="1 out of 1 forms covered">
|
|
058
|
|
</span><br/>
|
|
<span class="covered" title="1 out of 1 forms covered">
|
|
059 (defn rectangle
|
|
</span><br/>
|
|
<span class="not-tracked" title="0 out of 0 forms covered">
|
|
060 "Return a rectangle, with edges aligned east-west and north-south, whose
|
|
</span><br/>
|
|
<span class="not-tracked" title="0 out of 0 forms covered">
|
|
061 south-west corner is the vertex `vsw` and whose north-east corner is the
|
|
</span><br/>
|
|
<span class="not-tracked" title="0 out of 0 forms covered">
|
|
062 vertex `vne`."
|
|
</span><br/>
|
|
<span class="not-tracked" title="0 out of 0 forms covered">
|
|
063 [vsw vne]
|
|
</span><br/>
|
|
<span class="not-tracked" title="0 out of 0 forms covered">
|
|
064 ;; we can actually create any rectangle in the xy plane based on two opposite
|
|
</span><br/>
|
|
<span class="not-tracked" title="0 out of 0 forms covered">
|
|
065 ;; corners, but the maths are a bit to advanced for me today. TODO: do it!
|
|
</span><br/>
|
|
<span class="not-covered" title="0 out of 21 forms covered">
|
|
066 (let [vnw (vertex (:x (check-vertex vsw))
|
|
</span><br/>
|
|
<span class="not-covered" title="0 out of 18 forms covered">
|
|
067 (:y (check-vertex vne))
|
|
</span><br/>
|
|
<span class="not-covered" title="0 out of 20 forms covered">
|
|
068 (/ (reduce + (map #(or (:z %) 0) [vsw vne])) 2))
|
|
</span><br/>
|
|
<span class="not-covered" title="0 out of 5 forms covered">
|
|
069 vse (vertex (:x vne)
|
|
</span><br/>
|
|
<span class="partial" title="9 out of 12 forms covered">
|
|
070 (:y vsw)
|
|
</span><br/>
|
|
<span class="not-covered" title="0 out of 20 forms covered">
|
|
071 (/ (reduce + (map #(or (:z %) 0) [vsw vne])) 2))]
|
|
</span><br/>
|
|
<span class="not-covered" title="0 out of 9 forms covered">
|
|
072 (t/tag (polygon vsw vnw vne vse) :rectangle)))
|
|
</span><br/>
|
|
<span class="blank" title="0 out of 0 forms covered">
|
|
073
|
|
</span><br/>
|
|
<span class="not-tracked" title="0 out of 0 forms covered">
|
|
074 ;; (rectangle (vertex 1 2 3) (vertex 7 9 4))
|
|
</span><br/>
|
|
<span class="blank" title="0 out of 0 forms covered">
|
|
075
|
|
</span><br/>
|
|
<span class="covered" title="1 out of 1 forms covered">
|
|
076 (defn gradient
|
|
</span><br/>
|
|
<span class="not-tracked" title="0 out of 0 forms covered">
|
|
077 "Return a polygon like `triangle` but with a key `:gradient` whose value is a
|
|
</span><br/>
|
|
<span class="not-tracked" title="0 out of 0 forms covered">
|
|
078 unit vector representing the gradient across `triangle`."
|
|
</span><br/>
|
|
<span class="not-tracked" title="0 out of 0 forms covered">
|
|
079 [triangle]
|
|
</span><br/>
|
|
<span class="covered" title="12 out of 12 forms covered">
|
|
080 (let [order (sort #(max (:z %1) (:z %2))
|
|
</span><br/>
|
|
<span class="partial" title="8 out of 18 forms covered">
|
|
081 (:vertices (check-triangle triangle)))
|
|
</span><br/>
|
|
<span class="covered" title="3 out of 3 forms covered">
|
|
082 highest (first order)
|
|
</span><br/>
|
|
<span class="covered" title="3 out of 3 forms covered">
|
|
083 lowest (last order)]
|
|
</span><br/>
|
|
<span class="covered" title="10 out of 10 forms covered">
|
|
084 (assoc triangle :gradient (e/unit-vector (e/edge lowest highest)))))
|
|
</span><br/>
|
|
<span class="blank" title="0 out of 0 forms covered">
|
|
085
|
|
</span><br/>
|
|
<span class="covered" title="1 out of 1 forms covered">
|
|
086 (defn triangle-centre
|
|
</span><br/>
|
|
<span class="not-tracked" title="0 out of 0 forms covered">
|
|
087 "Return a canonicalised `facet` (i.e. a triangular polygon) with an added
|
|
</span><br/>
|
|
<span class="not-tracked" title="0 out of 0 forms covered">
|
|
088 key `:centre` whose value represents the centre of this facet in 3
|
|
</span><br/>
|
|
<span class="not-tracked" title="0 out of 0 forms covered">
|
|
089 dimensions. This only works for triangles, so is here not in
|
|
</span><br/>
|
|
<span class="not-tracked" title="0 out of 0 forms covered">
|
|
090 `walkmap.polygon`. It is an error (although no exception is currently
|
|
</span><br/>
|
|
<span class="not-tracked" title="0 out of 0 forms covered">
|
|
091 thrown) if the object past is not a triangular polygon."
|
|
</span><br/>
|
|
<span class="not-tracked" title="0 out of 0 forms covered">
|
|
092 [facet]
|
|
</span><br/>
|
|
<span class="partial" title="9 out of 19 forms covered">
|
|
093 (let [vs (:vertices (check-triangle facet))
|
|
</span><br/>
|
|
<span class="covered" title="3 out of 3 forms covered">
|
|
094 v1 (first vs)
|
|
</span><br/>
|
|
<span class="covered" title="10 out of 10 forms covered">
|
|
095 opposite (e/edge (nth vs 1) (nth vs 2))
|
|
</span><br/>
|
|
<span class="covered" title="3 out of 3 forms covered">
|
|
096 oc (e/centre opposite)]
|
|
</span><br/>
|
|
<span class="covered" title="3 out of 3 forms covered">
|
|
097 (assoc
|
|
</span><br/>
|
|
<span class="covered" title="1 out of 1 forms covered">
|
|
098 facet
|
|
</span><br/>
|
|
<span class="not-tracked" title="0 out of 0 forms covered">
|
|
099 :centre
|
|
</span><br/>
|
|
<span class="covered" title="2 out of 2 forms covered">
|
|
100 (vertex
|
|
</span><br/>
|
|
<span class="covered" title="16 out of 16 forms covered">
|
|
101 (+ (:x v1) (* (- (:x oc) (:x v1)) 2/3))
|
|
</span><br/>
|
|
<span class="covered" title="16 out of 16 forms covered">
|
|
102 (+ (:y v1) (* (- (:y oc) (:y v1)) 2/3))
|
|
</span><br/>
|
|
<span class="covered" title="16 out of 16 forms covered">
|
|
103 (+ (:z v1) (* (- (:z oc) (:z v1)) 2/3))))))
|
|
</span><br/>
|
|
<span class="blank" title="0 out of 0 forms covered">
|
|
104
|
|
</span><br/>
|
|
<span class="covered" title="1 out of 1 forms covered">
|
|
105 (defn centre
|
|
</span><br/>
|
|
<span class="not-tracked" title="0 out of 0 forms covered">
|
|
106 [poly]
|
|
</span><br/>
|
|
<span class="covered" title="22 out of 22 forms covered">
|
|
107 (case (count (:vertices (check-polygon poly)))
|
|
</span><br/>
|
|
<span class="covered" title="3 out of 3 forms covered">
|
|
108 3 (triangle-centre poly)
|
|
</span><br/>
|
|
<span class="not-tracked" title="0 out of 0 forms covered">
|
|
109 ;; else
|
|
</span><br/>
|
|
<span class="covered" title="1 out of 1 forms covered">
|
|
110 (throw
|
|
</span><br/>
|
|
<span class="covered" title="2 out of 2 forms covered">
|
|
111 (UnsupportedOperationException.
|
|
</span><br/>
|
|
<span class="not-tracked" title="0 out of 0 forms covered">
|
|
112 "The general case of centre for polygons is not yet implemented."))))
|
|
</span><br/>
|
|
<span class="blank" title="0 out of 0 forms covered">
|
|
113
|
|
</span><br/>
|
|
<span class="blank" title="0 out of 0 forms covered">
|
|
114
|
|
</span><br/>
|
|
</body>
|
|
</html>
|