From 77933f39499bd74c7013913e2414ad90b812c9a5 Mon Sep 17 00:00:00 2001 From: Andrey Antukh <niwi@niwi.nz> Date: Wed, 22 Jun 2016 19:59:52 +0300 Subject: [PATCH] Move kdtree, lru and heap into uxbox.util submodule. --- .../heap.js => src/uxbox/util/heap_impl.js | 12 +-- src/uxbox/util/kdtree.cljs | 30 +++++++ .../core.js => src/uxbox/util/kdtree_impl.js | 89 ++++++++++--------- vendor/lru.js => src/uxbox/util/lru_impl.js | 11 +-- src/uxbox/view.cljs | 1 + src/uxbox/worker/align.cljs | 9 +- 6 files changed, 94 insertions(+), 58 deletions(-) rename vendor/kdtree/heap.js => src/uxbox/util/heap_impl.js (91%) create mode 100644 src/uxbox/util/kdtree.cljs rename vendor/kdtree/core.js => src/uxbox/util/kdtree_impl.js (86%) rename vendor/lru.js => src/uxbox/util/lru_impl.js (91%) diff --git a/vendor/kdtree/heap.js b/src/uxbox/util/heap_impl.js similarity index 91% rename from vendor/kdtree/heap.js rename to src/uxbox/util/heap_impl.js index 60d2fc987..3956202f6 100644 --- a/vendor/kdtree/heap.js +++ b/src/uxbox/util/heap_impl.js @@ -8,13 +8,15 @@ * @license MIT License <https://opensource.org/licenses/MIT> */ -goog.provide("kdtree.heap"); -goog.provide("kdtree.heap.MinHeap"); +"use strict"; + +goog.provide("uxbox.util.heap_impl"); +goog.provide("uxbox.util.heap_impl.MinHeap"); goog.scope(function() { - "use strict"; + const self = uxbox.util.heap_impl; - const compare = (x,y) => x-y; + const compare = (x, y) => x - y; class MinHeap { constructor(cmp) { @@ -108,5 +110,5 @@ goog.scope(function() { } } - kdtree.heap.MinHeap = MinHeap; + self.MinHeap = MinHeap; }); diff --git a/src/uxbox/util/kdtree.cljs b/src/uxbox/util/kdtree.cljs new file mode 100644 index 000000000..e03e2360a --- /dev/null +++ b/src/uxbox/util/kdtree.cljs @@ -0,0 +1,30 @@ +;; This Source Code Form is subject to the terms of the Mozilla Public +;; License, v. 2.0. If a copy of the MPL was not distributed with this +;; file, You can obtain one at http://mozilla.org/MPL/2.0/. +;; +;; Copyright (c) 2016 Andrey Antukh <niwi@niwi.nz> + +(ns uxbox.util.kdtree + "A cljs layer on top of js impl of kdtree located in `kdtree_impl.js`." + (:require [uxbox.util.kdtree-impl :as impl])) + +(defn create + "Create an empty or initialized kd-tree instance." + ([] (impl/create)) + ([points] (impl/create (clj->js points)))) + +(defn setup! + "Generate new kd-tree instance with provided generation parameter + or just return a prevuously created from internal LRU cache." + [t w h ws hs] + (impl/setup t w h ws hs)) + +(defn nearest + "Search nearest points to the provided point + and return the `n` maximum results." + ([t p] + (nearest t p 10)) + ([t p n] + {:pre [(vector? p)]} + (let [p (into-array p)] + (map clj->js (impl/nearest t p n))))) diff --git a/vendor/kdtree/core.js b/src/uxbox/util/kdtree_impl.js similarity index 86% rename from vendor/kdtree/core.js rename to src/uxbox/util/kdtree_impl.js index 92c2e0724..dcc20f198 100644 --- a/vendor/kdtree/core.js +++ b/src/uxbox/util/kdtree_impl.js @@ -13,12 +13,16 @@ "use strict"; -goog.provide("kdtree.core"); -goog.require("kdtree.heap"); -goog.require("lru"); +goog.provide("uxbox.util.kdtree_impl"); +goog.require("uxbox.util.heap_impl"); +goog.require("uxbox.util.lru_impl"); goog.require("goog.asserts"); goog.scope(function() { + const self = uxbox.util.kdtree_impl; + + const heap = uxbox.util.heap_impl; + const lru = uxbox.util.lru_impl; const assert = goog.asserts.assert; // Hardcoded dimensions value; @@ -76,7 +80,7 @@ goog.scope(function() { function searchNearest(root, point, maxNodes) { const search = (best, node) => { if (best === null) { - best = new kdtree.heap.MinHeap((x, y) => x[1] - y[1]); + best = new heap.MinHeap((x, y) => x[1] - y[1]); } let distance = precision(calculateDistance(point, node.obj)); @@ -147,38 +151,7 @@ goog.scope(function() { // --- Public Api const cache = new lru.create(); - function create(points) { - const tree = new KDTree(); - if (goog.isArray(points)) { - return initialize(tree, points); - } else { - return tree; - } - }; - function generate(width, height, widthStep, heightStep) { - const key = `${width}.${height}.${widthStep}.${heightStep}`; - - let tree = lru.get(cache, key); - if (tree instanceof KDTree) { - return tree; - } else { - tree = new KDTree(); - setup(tree, width, height, widthStep, heightStep); - lru.set(cache, key, tree); - return tree; - } - } - - function initialize(tree, points) { - assert(goog.isArray(points)); - assert(tree instanceof KDTree); - - tree.root = buildTree(null, points, 0); - return tree; - } - - function setup(tree, width, height, widthStep, heightStep) { const totalSize = Math.floor((width/widthStep) * (height/heightStep)); const points = new Array(totalSize); let pos = 0; @@ -189,7 +162,21 @@ goog.scope(function() { } } - initialize(tree, points); + return points; + } + + function setup(tree, width, height, widthStep, heightStep) { + const key = `${width}.${height}.${widthStep}.${heightStep}`; + const root = lru.get(cache, key); + + if (root instanceof Node) { + tree.root = root; + } else { + const points = generate(width, height, widthStep, heightStep); + tree.root = buildTree(null, points, 0); + lru.set(cache, key, tree.root); + } + return tree; } @@ -198,6 +185,23 @@ goog.scope(function() { return tree.root !== null; } + function initialize(tree, points) { + assert(goog.isArray(points)); + assert(tree instanceof KDTree); + + tree.root = buildTree(null, points, 0); + return tree; + } + + function create(points) { + const tree = new KDTree(); + if (goog.isArray(points)) { + return initialize(tree, points); + } else { + return tree; + } + }; + function clear(tree) { assert(tree instanceof KDTree); tree.root = null; @@ -212,11 +216,10 @@ goog.scope(function() { } // Factory functions - kdtree.core.create = create; - kdtree.core.generate = generate; - kdtree.core.initialize = initialize; - kdtree.core.setup = setup; - kdtree.core.isInitialized = isInitialized; - kdtree.core.clear = clear; - kdtree.core.nearest = nearest; + self.create = create; + self.initialize = initialize; + self.setup = setup; + self.isInitialized = isInitialized; + self.clear = clear; + self.nearest = nearest; }); diff --git a/vendor/lru.js b/src/uxbox/util/lru_impl.js similarity index 91% rename from vendor/lru.js rename to src/uxbox/util/lru_impl.js index 16c7a6d4a..d3b0ed25e 100644 --- a/vendor/lru.js +++ b/src/uxbox/util/lru_impl.js @@ -10,10 +10,11 @@ "use strict"; -goog.provide("lru"); +goog.provide("uxbox.util.lru_impl"); goog.require("goog.asserts"); goog.scope(function() { + const self = uxbox.util.lru_impl; const assert = goog.asserts.assert; class Node { @@ -118,8 +119,8 @@ goog.scope(function() { return new Cache(limit); } - lru.create = create; - lru.get = (c, key) => c.getItem(key); - lru.set = (c, key, val) => c.setItem(key, val); - lru.remove = (c, key) => c.removeItem(key); + self.create = create; + self.get = (c, key) => c.getItem(key); + self.set = (c, key, val) => c.setItem(key, val); + self.remove = (c, key) => c.removeItem(key); }); diff --git a/src/uxbox/view.cljs b/src/uxbox/view.cljs index 4315201ef..44d98060c 100644 --- a/src/uxbox/view.cljs +++ b/src/uxbox/view.cljs @@ -6,6 +6,7 @@ (ns uxbox.view (:require [uxbox.view.state :as st] + [uxbox.common.constants] #_[uxbox.view.locales :as lc] [uxbox.view.ui :as ui])) diff --git a/src/uxbox/worker/align.cljs b/src/uxbox/worker/align.cljs index 9dad2f704..3c221f88a 100644 --- a/src/uxbox/worker/align.cljs +++ b/src/uxbox/worker/align.cljs @@ -7,7 +7,7 @@ (ns uxbox.worker.align "Workspace aligment indexes worker." (:require [beicon.core :as rx] - [kdtree.core :as kd] + [uxbox.util.kdtree :as kd] [uxbox.worker.impl :as impl] [uxbox.common.geom.point :as gpt])) @@ -16,14 +16,13 @@ (defmethod impl/handler :grid/init [{:keys [sender width height x-axis y-axis] :as opts}] (time - (let [value (kd/generate width height (or x-axis 10) (or y-axis 10))] - (set! tree value))) + (kd/setup! tree width height (or x-axis 10) (or y-axis 10))) (impl/reply! sender nil)) (defmethod impl/handler :grid/align [{:keys [sender point] :as message}] - (let [point #js [(:x point) (:y point)] - results (js->clj (kd/nearest tree point 1)) + (let [point [(:x point) (:y point)] + results (kd/nearest tree point 1) [[x y] d] (first results) result (gpt/point x y)] (impl/reply! sender {:point (gpt/point x y)})))