Created
April 8, 2010 14:52
-
-
Save lgiorda/360147 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
(ns com.snowtide.util.test-coord-search | |
(:import (com.snowtide.dom Direction RectStruct Bounded)) | |
(:require [com.snowtide.dom.regionutils :as reg] | |
[clojure.set :as sets]) | |
(:use com.snowtide.util | |
(com.snowtide.dom regionutils) | |
(clojure.contrib def test-is | |
[map-utils :only (deep-merge-with)] | |
[seq-utils :only (shuffle)]))) | |
(defn- reg | |
[lx by rx ty text] | |
(assoc (RectStruct. lx by rx ty nil nil) :chars text)) | |
; lx by rx ty | |
(def first-zero (reg 147.44 309.9139 152.94057 320.9052 "0")) | |
(def seven (reg 152.94057 309.9139 158.44113 320.9052 "7")) | |
(def slash (reg 158.44113 309.9139 161.1865 320.9052 "/")) | |
(def sec-zero (reg 161.1865 309.9139 166.68706 320.9052 "0")) | |
(def thr-zero (reg 166.68706 309.9139 172.18762 320.9052 "0")) | |
(def tst (reg 169.68706 312.9139 175.18762 323.9052 "t")) | |
(def reg-coll [[147.44 309.9139 152.94057 320.9052 "0"] | |
[152.94057 309.9139 158.44113 320.9052 "7"] | |
[158.44113 309.9139 161.1865 320.9052 "/"] | |
[161.1865 309.9139 166.68706 320.9052 "0"] | |
[166.68706 309.9139 172.18762 320.9052 "0"] | |
[147.44 291.1939 157.25049 302.1852 "W"] | |
[157.25049 291.1939 162.75105 302.1852 "a"] | |
[162.75105 291.1939 165.10281 302.1852 "i"] | |
[165.10281 291.1939 167.84818 302.1852 "t"] | |
[167.84818 291.1939 171.18393 302.1852 "r"] | |
[171.18393 291.1939 176.6845 302.1852 "o"] | |
[176.6845 291.1939 181.59465 302.1852 "s"] | |
[181.59465 291.1939 187.09521 302.1852 "e"]]) | |
; given a vector of vectors of Rects, create the RectStructs | |
(def boundeds (map (fn [[lx by rx ty text]] | |
(assoc (RectStruct. lx by rx ty nil nil) | |
:chars text)) reg-coll)) | |
(defn create-y-coords [boundeds] | |
"takes a collection of RectStructs and returns | |
a lazy seq of :by and :ty coords mapped to their | |
adjacent RectStructs" | |
(concat | |
(for [b boundeds] | |
[(:by b) b]) | |
(for [b boundeds] | |
[(:ty b) b]))) | |
(defn create-x-coords [boundeds] | |
"takes a collection of RectStructs and returns | |
a lazy seq of :lx and :rx coords mapped to their | |
adjacent RectStructs" | |
(concat | |
(for [b boundeds] | |
[(:lx b) b]) | |
(for [b boundeds] | |
[(:rx b) b]))) | |
(defn conjoin-set | |
[s v] | |
(if s | |
(conj s v) | |
#{v})) | |
(defn to-coord-set [xy-coords] | |
"input x-coords or y-coords, returns a sorted-map | |
of {coord, #{set of Rects adjacent to coord}}" | |
(reduce (fn [map [num rect]] | |
(update-in map [num] conjoin-set rect)) | |
(sorted-map) xy-coords)) | |
(defn left [rect coll] | |
(subseq coll < (:rx rect))) | |
(defn right [rect coll] | |
(subseq coll > (:lx rect))) | |
(defn up [rect coll] | |
(subseq coll > (:by rect))) | |
(defn down [rect coll] | |
(subseq coll < (:ty rect))) | |
(defn horiz-sweep [dir rect boundeds] | |
"left/right [rect] (boundeds)" | |
(let [coll (to-coord-set (create-x-coords boundeds))] | |
(reduce (fn [set [num rectset]] | |
(sets/union set rectset)) | |
#{} (dir rect coll)))) | |
(defn vert-sweep [dir rect boundeds] | |
"up/down [rect] (boundeds)" | |
(let [coll (to-coord-set (create-y-coords boundeds))] | |
(reduce (fn [set [num rectset]] | |
(sets/union set rectset)) | |
#{} (dir rect coll)))) |
Comments:
- There's no need for into or the empty lazy-seq there. Just (for ...) will do.
- Of course, you don't want to have the coordinate-rect seqs defined at the top level; those should be bindings local to whatever calls to-coord-set
- the merge-with usage is fine, but is slower than necessary. You're creating a map and a set when you don't need to. This would be preferable (totally untested, but I hope the idea is clear):
(defn conj-set [s v](if s %28conj s v%29 #{v}))
(fn [map [num rect]](update-in map [num] conj-set rect))
Hey Chas, I wanted to come up with some funcs to find the set of all rects either up/down/left/right of a given rect. I'm figuring we're always going to have two sorted-maps (x-coords and y-coords), therefore I'll need one function to operate on each. I suppose the hope was to be able to union/intersection the results of these function into some sort of (semi) interesting result. Let me know what you think...
This is good. Next steps would be:
- make the sweep fns composable so that arbitrary predicates can be provided to filter the result of the (dir) calls.
- use an internal set to ensure that you're not gathering duplicates, rather than reducing and returning a set. Remember that key to a consumer of this API would be having no duplicates in the result of a query but also retaining the order of regions encountered in a particular traversal.
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
test