#3 Inching forward, positively
This commit is contained in:
parent
9ee365b987
commit
79174af2c1
30 changed files with 766 additions and 410 deletions
|
|
@ -3,10 +3,17 @@
|
|||
An edge is a line segment having just a start and an end, with no intervening
|
||||
nodes."
|
||||
(:require [clojure.math.numeric-tower :as m]
|
||||
[walkmap.path :refer [path? polygon->path]]
|
||||
[walkmap.polygon :refer [polygon?]]
|
||||
[walkmap.vertex :refer [ensure3d vertex?]]))
|
||||
|
||||
(defn edge
|
||||
"Return an edge between vertices `v1` and `v2`."
|
||||
[v1 v2]
|
||||
(if
|
||||
(and (vertex? v1) (vertex? v2))
|
||||
{:kind :edge :id (keyword (gensym "edge")) :start v1 :end v2}
|
||||
(throw (IllegalArgumentException. "Must be vertices."))))
|
||||
|
||||
(defn edge?
|
||||
"True if `o` satisfies the conditions for a edge. An edge shall be a map
|
||||
having the keys `:start` and `:end`, such that the values of each of those
|
||||
|
|
@ -17,31 +24,6 @@
|
|||
(vertex? (:start o))
|
||||
(vertex? (:end o))))
|
||||
|
||||
(defn path->edges
|
||||
"if `o` is a path, a polygon, or a sequence of vertices, return a sequence of
|
||||
edges representing that path, polygon or sequence.
|
||||
|
||||
Throws `IllegalArgumentException` if `o` is not a path, a polygon, or
|
||||
sequence of vertices."
|
||||
[o]
|
||||
(cond
|
||||
(seq? o)
|
||||
(when
|
||||
(and
|
||||
(vertex? (first o))
|
||||
(vertex? (first (rest o))))
|
||||
(cons
|
||||
{:start (first o)
|
||||
:end (first (rest o))}
|
||||
(path->edges (rest o))))
|
||||
(path? o)
|
||||
(path->edges (:nodes o))
|
||||
(polygon? o)
|
||||
(path->edges (polygon->path o))
|
||||
:else
|
||||
(throw (IllegalArgumentException.
|
||||
"Not a path, polygon, or sequence of vertices!"))))
|
||||
|
||||
(defn length
|
||||
"Return the length of the edge `e`."
|
||||
[e]
|
||||
|
|
|
|||
|
|
@ -1,6 +1,9 @@
|
|||
(ns walkmap.path
|
||||
"Essentially the specification for things we shall consider to be path."
|
||||
(:require [walkmap.polygon :refer [polygon?]]
|
||||
"Essentially the specification for things we shall consider to be path.
|
||||
**Note that** for these purposes `path` means any continuous linear
|
||||
feature, where such features specifically include watercourses."
|
||||
(:require [walkmap.edge :as e]
|
||||
[walkmap.polygon :refer [polygon?]]
|
||||
[walkmap.vertex :refer [vertex?]]))
|
||||
|
||||
(defn path?
|
||||
|
|
@ -14,14 +17,16 @@
|
|||
(seq? v)
|
||||
(> (count v) 2)
|
||||
(every? vertex? v)
|
||||
(:id o)
|
||||
(or (nil? (:kind o)) (= (:kind o) :path)))))
|
||||
|
||||
(defn make-path
|
||||
[nodes]
|
||||
(defn path
|
||||
"Return a path constructed from these `vertices`."
|
||||
[& vertices]
|
||||
(if
|
||||
(every? vertex? nodes)
|
||||
{:nodes nodes :id (keyword (gensym "path")) :kind :path}
|
||||
(throw (Exception. "Each item on path must be a vertex."))))
|
||||
(every? vertex? vertices)
|
||||
{:nodes vertices :id (keyword (gensym "path")) :kind :path}
|
||||
(throw (IllegalArgumentException. "Each item on path must be a vertex."))))
|
||||
|
||||
(defn polygon->path
|
||||
"If `o` is a polygon, return an equivalent path. What's different about
|
||||
|
|
@ -34,5 +39,40 @@
|
|||
(if
|
||||
(polygon? o)
|
||||
(assoc (dissoc o :vertices) :kind :path :nodes (concat (:vertices o) (list (first (:vertices o)))))
|
||||
(throw (Exception. "Not a polygon!"))))
|
||||
(throw (IllegalArgumentException. "Not a polygon!"))))
|
||||
|
||||
(defn path->edges
|
||||
"if `o` is a path, a polygon, or a sequence of vertices, return a sequence of
|
||||
edges representing that path, polygon or sequence.
|
||||
|
||||
Throws `IllegalArgumentException` if `o` is not a path, a polygon, or
|
||||
sequence of vertices."
|
||||
[o]
|
||||
(cond
|
||||
(seq? o)
|
||||
(when
|
||||
(and
|
||||
(vertex? (first o))
|
||||
(vertex? (first (rest o))))
|
||||
(cons
|
||||
;; TODO: think about: when constructing an edge from a path, should the
|
||||
;; constructed edge be tagged with the tags of the path?
|
||||
(e/edge (first o) (rest o))
|
||||
(path->edges (rest o))))
|
||||
(path? o)
|
||||
(path->edges (:nodes o))
|
||||
:else
|
||||
(throw (IllegalArgumentException.
|
||||
"Not a path or sequence of vertices!"))))
|
||||
|
||||
(defn length
|
||||
"Return the length of this path, in metres. **Note that**
|
||||
1. This is not the same as the distance from the start to the end of the
|
||||
path, which, except for absolutely straight paths, will be shorter;
|
||||
2. It is not even quite the same as the length of the path *as rendered*,
|
||||
since paths will generally be rendered as spline curves."
|
||||
[path]
|
||||
(if
|
||||
(path? path)
|
||||
(reduce + (map e/length (path->edges path)))
|
||||
(throw (IllegalArgumentException. "Not a path!"))))
|
||||
|
|
|
|||
|
|
@ -6,7 +6,7 @@
|
|||
[org.clojars.smee.binary.core :as b]
|
||||
[taoensso.timbre :as l :refer [info error spy]]
|
||||
[walkmap.polygon :refer [polygon?]]
|
||||
[walkmap.vertex :refer [canonicalise-vertex]])
|
||||
[walkmap.vertex :as v])
|
||||
(:import org.clojars.smee.binary.core.BinaryIO
|
||||
java.io.DataInput))
|
||||
|
||||
|
|
@ -67,7 +67,7 @@
|
|||
:kind :polygon
|
||||
:vertices (canonicalise (:vertices o)))
|
||||
;; if it has a value for :x it's a vertex, but it doesn't yet conform to `vertex?`
|
||||
(:x o) (canonicalise-vertex o)
|
||||
(:x o) (v/canonicalise o)
|
||||
;; shouldn't happen
|
||||
:else o))
|
||||
|
||||
|
|
|
|||
|
|
@ -5,7 +5,11 @@
|
|||
(:require [clojure.set :refer [difference union]]))
|
||||
|
||||
(defn tagged?
|
||||
"True if this `object` is tagged with each of these `tags`."
|
||||
"True if this `object` is tagged with each of these `tags`. It is an error
|
||||
(and an exception will be thrown) if
|
||||
|
||||
1. `object` is not a map;
|
||||
2. any of `tags` is not a keyword."
|
||||
[object & tags]
|
||||
(if
|
||||
(map? object)
|
||||
|
|
@ -14,8 +18,7 @@
|
|||
(let [ot (::tags object)]
|
||||
(and
|
||||
(set? ot)
|
||||
(every? ot tags)
|
||||
true))
|
||||
(every? ot tags)))
|
||||
(throw (IllegalArgumentException.
|
||||
(str "Must be keyword(s): " (map type tags)))))
|
||||
(throw (IllegalArgumentException.
|
||||
|
|
@ -23,7 +26,11 @@
|
|||
|
||||
(defn tag
|
||||
"Return an object like this `object` but with these `tags` added to its tags,
|
||||
if they are not already present."
|
||||
if they are not already present.It is an error (and an exception will be
|
||||
thrown) if
|
||||
|
||||
1. `object` is not a map;
|
||||
2. any of `tags` is not a keyword."
|
||||
[object & tags]
|
||||
(if
|
||||
(map? object)
|
||||
|
|
@ -35,9 +42,17 @@
|
|||
(throw (IllegalArgumentException.
|
||||
(str "Must be a map: " (type object))))))
|
||||
|
||||
(defmacro tags
|
||||
"Return the tags of this object, if any."
|
||||
[object]
|
||||
`(::tags ~object))
|
||||
|
||||
(defn untag
|
||||
"Return an object like this `object` but with these `tags` removed from its
|
||||
tags, if present."
|
||||
tags, if present. It is an error (and an exception will be thrown) if
|
||||
|
||||
1. `object` is not a map;
|
||||
2. any of `tags` is not a keyword."
|
||||
[object & tags]
|
||||
(if
|
||||
(map? object)
|
||||
|
|
|
|||
|
|
@ -1,5 +1,8 @@
|
|||
(ns walkmap.vertex
|
||||
"Essentially the specification for things we shall consider to be vertices.")
|
||||
"Essentially the specification for things we shall consider to be vertices.
|
||||
|
||||
Note that there's no `distance` function here; to find the distance between
|
||||
two vertices, create an edge from them and use `walkmap.edge/length`.")
|
||||
|
||||
(defn vertex-key
|
||||
"Making sure we get the same key everytime we key a vertex with the same
|
||||
|
|
@ -29,7 +32,7 @@
|
|||
(or (nil? (:z o)) (number? (:z o)))
|
||||
(or (nil? (:kind o)) (= (:kind o) :vertex))))
|
||||
|
||||
(defn make-vertex
|
||||
(defn vertex
|
||||
"Make a vertex with this `x`, `y` and (if provided) `z` values. Returns a map
|
||||
with those values, plus a unique `:id` value, and `:kind` set to `:vertex`.
|
||||
It's not necessary to use this function to create a vertex, but the `:id`
|
||||
|
|
@ -38,9 +41,9 @@
|
|||
(let [v {:x x :y y :kind :vertex}]
|
||||
(assoc v :id (vertex-key v))))
|
||||
([x y z]
|
||||
(assoc (make-vertex x y) :z z)))
|
||||
(assoc (vertex x y) :z z)))
|
||||
|
||||
(defn canonicalise-vertex
|
||||
(defn canonicalise
|
||||
"If `o` is a map with numeric values for `:x`, `:y` and optionally `:z`,
|
||||
upgrade it to something we will recognise as a vertex."
|
||||
[o]
|
||||
|
|
@ -51,7 +54,7 @@
|
|||
(number? (:y o))
|
||||
(or (nil? (:z o)) (number? (:z o))))
|
||||
(assoc o :kind :vertex :id (vertex-key o))
|
||||
(throw (IllegalArgumentException. "Not a vertex."))))
|
||||
(throw (IllegalArgumentException. "Not a proto-vertex: must have numeric `:x` and `:y`."))))
|
||||
|
||||
(def ensure3d
|
||||
"Given a vertex `o`, if `o` has a `:z` value, just return `o`; otherwise
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue