view org/sense-util.org @ 156:e8df6e76c3e5

refactored touch
author Robert McIntyre <rlm@mit.edu>
date Fri, 03 Feb 2012 06:15:34 -0700
parents aaacf087504c
children c33a8e5fe7bc
line wrap: on
line source
1 #+title: General sense/effector utilities
2 #+author: Robert McIntyre
3 #+email: rlm@mit.edu
4 #+description: sensory utilities
5 #+keywords: simulation, jMonkeyEngine3, clojure, simulated senses
6 #+SETUPFILE: ../../aurellem/org/setup.org
7 #+INCLUDE: ../../aurellem/org/level-0.org
10 #+name: sense-util
11 #+begin_src clojure
12 (ns cortex.sense)
13 (cortex.import/mega-import-jme3)
14 (import ij.process.ImageProcessor)
15 (import java.awt.image.BufferedImage)
18 (defn meta-data [blender-node key]
19 (if-let [data (.getUserData blender-node "properties")]
20 (.findValue data key)
21 nil))
23 (defn closest-node
24 "Return the object in creature which is closest to the given node."
25 ;;dylan"The closest object in creature to the given node."
26 [#^Node creature #^Node eye]
27 (loop [radius (float 0.01)]
28 (let [results (CollisionResults.)]
29 (.collideWith
30 creature
31 (BoundingBox. (.getWorldTranslation eye)
32 radius radius radius)
33 results)
34 (if-let [target (first results)]
35 (.getGeometry target)
36 (recur (float (* 2 radius)))))))
38 (defn bind-sense
39 "Bind the sense to the Spatial such that it will maintain its
40 current position relative to the Spatial no matter how the spatial
41 moves. 'sense can be either a Camera or Listener object."
42 [#^Spatial obj sense]
43 (let [sense-offset (.subtract (.getLocation sense)
44 (.getWorldTranslation obj))
45 initial-sense-rotation (Quaternion. (.getRotation sense))
46 base-anti-rotation (.inverse (.getWorldRotation obj))]
47 (.addControl
48 obj
49 (proxy [AbstractControl] []
50 (controlUpdate [tpf]
51 (let [total-rotation
52 (.mult base-anti-rotation (.getWorldRotation obj))]
53 (.setLocation sense
54 (.add
55 (.mult total-rotation sense-offset)
56 (.getWorldTranslation obj)))
57 (.setRotation sense
58 (.mult total-rotation initial-sense-rotation))))
59 (controlRender [_ _])))))
61 (def white -1)
63 (defn filter-pixels
64 "List the coordinates of all pixels matching pred, within the bounds
65 provided. Bounds -> [x0 y0 width height]"
66 {:author "Dylan Holmes"}
67 ([pred #^BufferedImage image]
68 (filter-pixels pred image [0 0 (.getWidth image) (.getHeight image)]))
69 ([pred #^BufferedImage image [x0 y0 width height]]
70 ((fn accumulate [x y matches]
71 (cond
72 (>= y (+ height y0)) matches
73 (>= x (+ width x0)) (recur 0 (inc y) matches)
74 (pred (.getRGB image x y))
75 (recur (inc x) y (conj matches [x y]))
76 :else (recur (inc x) y matches)))
77 x0 y0 [])))
79 (defn white-coordinates
80 "Coordinates of all the white pixels in a subset of the image."
81 ([#^BufferedImage image bounds]
82 (filter-pixels #(= % white) image bounds))
83 ([#^BufferedImage image]
84 (filter-pixels #(= % white) image)))
86 (defn points->image
87 "Take a sparse collection of points and visuliaze it as a
88 BufferedImage."
90 ;; TODO maybe parallelize this since it's easy
92 [points]
93 (if (empty? points)
94 (BufferedImage. 1 1 BufferedImage/TYPE_BYTE_BINARY)
95 (let [xs (vec (map first points))
96 ys (vec (map second points))
97 x0 (apply min xs)
98 y0 (apply min ys)
99 width (- (apply max xs) x0)
100 height (- (apply max ys) y0)
101 image (BufferedImage. (inc width) (inc height)
102 BufferedImage/TYPE_INT_RGB)]
103 (dorun
104 (for [x (range (.getWidth image))
105 y (range (.getHeight image))]
106 (.setRGB image x y 0xFF0000)))
107 (dorun
108 (for [index (range (count points))]
109 (.setRGB image (- (xs index) x0) (- (ys index) y0) -1)))
111 image)))
113 (defn average [coll]
114 (/ (reduce + coll) (count coll)))
116 (defn collapse-1d
117 "One dimensional analogue of collapse"
118 [center line]
119 (let [length (count line)
120 num-above (count (filter (partial < center) line))
121 num-below (- length num-above)]
122 (range (- center num-below)
123 (+ center num-above))))
125 (defn collapse
126 "Take a set of pairs of integers and collapse them into a
127 contigous bitmap."
128 [points]
129 (if (empty? points) []
130 (let
131 [num-points (count points)
132 center (vector
133 (int (average (map first points)))
134 (int (average (map first points))))
135 flattened
136 (reduce
137 concat
138 (map
139 (fn [column]
140 (map vector
141 (map first column)
142 (collapse-1d (second center)
143 (map second column))))
144 (partition-by first (sort-by first points))))
145 squeezed
146 (reduce
147 concat
148 (map
149 (fn [row]
150 (map vector
151 (collapse-1d (first center)
152 (map first row))
153 (map second row)))
154 (partition-by second (sort-by second flattened))))
155 relocate
156 (let [min-x (apply min (map first squeezed))
157 min-y (apply min (map second squeezed))]
158 (map (fn [[x y]]
159 [(- x min-x)
160 (- y min-y)])
161 squeezed))]
162 relocate)))
164 (defn world-to-local
165 "Convert the world coordinates into coordinates relative to the
166 object (i.e. local coordinates), taking into account the rotation
167 of object."
168 [#^Spatial object world-coordinate]
169 (.worldToLocal object world-coordinate nil))
171 (defn local-to-world
172 "Convert the local coordinates into coordinates into world relative
173 coordinates"
174 [#^Spatial object local-coordinate]
175 (.localToWorld object local-coordinate nil))
177 #+end_src
179 #+results: sense-util
180 : #'cortex.sense/meta-data
184 * COMMENT generate source
185 #+begin_src clojure :tangle ../src/cortex/sense.clj
186 <<sense-util>>
187 #+end_src