Skip to content

Instantly share code, notes, and snippets.

@lgiorda
Created April 8, 2010 14:52
Show Gist options
  • Save lgiorda/360147 to your computer and use it in GitHub Desktop.
Save lgiorda/360147 to your computer and use it in GitHub Desktop.
(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))))
@cemerick
Copy link

cemerick commented Apr 8, 2010

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))

@lgiorda
Copy link
Author

lgiorda commented Apr 22, 2010

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...

@cemerick
Copy link

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