Skip to content

Commit 6bfc863

Browse files
author
tom
committed
Cesium demo port.
A small demonstration of using clay, cesium, and scittle together to visualize wildfires over time.
1 parent eba9f80 commit 6bfc863

File tree

14 files changed

+1856
-0
lines changed

14 files changed

+1856
-0
lines changed
2.44 MB
Binary file not shown.

src/cesium/app.cljs

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
(ns cesium.cesium
2+
(:require [reagent.core :as r]
3+
[reagent.dom :as rdom]
4+
#_
5+
[cesiumdemo.widgets :as widget]))
6+
7+
(defonce appstate (atom {}))
8+
9+
(rdom/render
10+
[:div "Hello from a ClojureScript file (app.cljs)"]
11+
(js/document.getElementById "app4"))

src/cesium/cesium.cljs

Lines changed: 298 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,298 @@
1+
(ns cesiumdemo.cesium
2+
(:require [reagent.core :as r]
3+
[clojure.core]
4+
[clojure.protocols :as cljp]))
5+
6+
(def ^:const +wgs-84+
7+
js/Cesium.Ellipsoid.WGS84)
8+
9+
;;aux functions
10+
(defn radians [x] (js/Cesium.Math.toRadians x))
11+
12+
;;this doesn't work per the tutorial...
13+
(def +default-offset+
14+
(js/Cesium.HeadingPitchRange.
15+
(radians 90)
16+
(radians -45)))
17+
18+
;;basic cesium stuff
19+
(defprotocol ICartesian
20+
(-as-cartesian [c]))
21+
22+
#_(defn degree-heights->carts)
23+
24+
;;this lets us use vectors
25+
;;interchangably with cartesian
26+
;;types in cesium.
27+
(extend-protocol ICartesian
28+
js/Cesium.Cartesian3
29+
(-as-cartesian [c] c)
30+
js/Cesium.Cartesian2
31+
(-as-cartesian [c] c)
32+
js/Cesium.Cartesian4
33+
(-as-cartesian [c] c)
34+
clojure.core/PersistentVector
35+
(-as-cartesian [c]
36+
(case (count c)
37+
2 (let [[x y] c]
38+
(js/Cesium.Cartesian2. x y))
39+
3 (let [[x y z] c]
40+
(js/Cesium.Cartesian3. x y z))
41+
4 (let [[a b c d] c]
42+
(js/Cesium.Cartesian3. a b c d)))))
43+
44+
;;probably create a point protocol and
45+
;;extend it to vectors, like as-cartesian
46+
(defn ->cartesian
47+
([x y]
48+
(js/Cesium.Cartesian2. x y))
49+
([x y z]
50+
(js/Cesium.Cartesian3. x y z))
51+
([x y z w]
52+
(js/Cesium.Cartesian4. x y z w)))
53+
54+
(defn degrees->cartesian
55+
([lat long height ellipsoid]
56+
(js/Cesium.Cartesian3.fromDegrees lat long height ellipsoid))
57+
([lat long height]
58+
(degrees->cartesian lat long height +wgs-84+))
59+
([lat long]
60+
(degrees->cartesian lat long 0 +wgs-84+)))
61+
62+
(defn radians->cartesian
63+
([lat long height ellipsoid]
64+
(js/Cesium.Cartesian3.fromRadians lat long height ellipsoid))
65+
([lat long height]
66+
(degrees->cartesian lat long height +wgs-84+))
67+
([lat long]
68+
(degrees->cartesian lat long 0 +wgs-84+)))
69+
70+
;;Also want coercions for degree sequences
71+
;;to cart 3 coord....
72+
(defn degrees->cart3 [xs]
73+
(js/Cesium.Cartesian3.fromDegreesArray
74+
(clj->js (vec xs))))
75+
76+
;;more generic, data-driven version
77+
;;since the only version that supports
78+
;;this is cart3....we can get away.
79+
;;Most of the cesium examples show
80+
;;the Array methods (i.e. ingest and
81+
;;return js Arrays).
82+
(defn degrees->cartesians
83+
"Given a sequence of [lat1, long1, lat2, long2] pairs
84+
or [lat1, long1, height1, lat2, long2, height2] triples
85+
coerces to a Cartesian3 based on the specified encoding
86+
and optional ellipsoid. lat/long are encoded as degrees"
87+
([n xs]
88+
(degrees->cartesians n +wgs-84+ xs))
89+
([n ellipsoid xs]
90+
(let [f (case n
91+
2 (fn [lat long]
92+
(degrees->cartesian lat long 0 ellipsoid))
93+
3 (fn [lat long height]
94+
(degrees->cartesian lat long 0 ellipsoid)))]
95+
(->> xs
96+
(partition n)
97+
(map #(apply f %))))))
98+
99+
(defn radians->cartesians
100+
"Given a sequence of [lat1, long1, lat2, long2] pairs
101+
or [lat1, long1, height1, lat2, long2, height2] triples
102+
coerces to a Cartesian3 based on the specified encoding
103+
and optional ellipsoid. lat/long are encoded as radians"
104+
([n xs]
105+
(radians->cartesians n +wgs-84+ xs))
106+
([n ellipsoid xs]
107+
(let [f (case n
108+
2 (fn [lat long]
109+
(radians->cartesian lat long 0 ellipsoid))
110+
3 (fn [lat long height]
111+
(radians->cartesian lat long 0 ellipsoid)))]
112+
(->> xs
113+
(partition n)
114+
(map #(apply f %))))))
115+
116+
;;Generate a random lat/long
117+
;;along the respective domains
118+
;;[-90 89]
119+
;;[-180 179]
120+
(defn random-point []
121+
[(- (rand-int 90) 89)
122+
(- (rand-int 180) 179)])
123+
124+
;;n random coordinates.
125+
(defn random-coords [n]
126+
(repeatedly n (fn []
127+
(random-point))))
128+
129+
;;Generic color stuff
130+
;;probably useful to have an as-color....
131+
;;We can get a simple color bridge, going
132+
;;from
133+
(def red (js/Cesium.Color.RED.withAlpha 0.5))
134+
(def black js/Cesium.Color.BLACK)
135+
136+
;;we can define a protocol here...
137+
;;might be useful if we wrap the viewer object
138+
;;and delegate.
139+
140+
;;Entity Operations
141+
(defn entities [v]
142+
(-> v .-entities))
143+
144+
(defn select-entity! [v e]
145+
(-> v .-selectedEntity (set! e)))
146+
147+
(defn track-entity! [v e]
148+
(-> v .-trackedEntity (set! e)))
149+
150+
(defn add-entity! [v x]
151+
(let [es (.-entities v)]
152+
(.add es x)))
153+
154+
(defn add-entities! [v xs]
155+
(reduce (fn [acc e]
156+
(doto acc (.add e)))
157+
(.-entities v)
158+
xs))
159+
160+
;;note: this doesn't work with polygons, as the
161+
;;tutorial depicts! We either need a protocol or
162+
;;another function to help us out here...
163+
(defn set-position! [e pos]
164+
(-> e .-position (set! pos)))
165+
166+
(defn set-height! [e h]
167+
(-> e .-polygon .-height (set! h)))
168+
169+
(defn set-material! [e m]
170+
(-> e .-polygon .-material (set! m)))
171+
172+
(defn extrude-height! [e h]
173+
(-> e .-polygon .-extrudedHeight (set! h)))
174+
175+
(defn set-description! [e d]
176+
(-> e .-description (set! d)))
177+
178+
;; var heading = js/Cesium.Math.toRadians(90);
179+
;; var pitch = js/Cesium.Math.toRadians(-30);
180+
181+
;;Primitive Operations
182+
183+
184+
185+
;;View API (zooming, flying, selecting)
186+
(defn zoom-to!
187+
([v]
188+
(.zoomTo v (.-entities v)))
189+
([v e]
190+
(.zoomTo v e))
191+
([v e offset]
192+
(.zoomTo v e offset)))
193+
194+
;;look at decoupling the
195+
;;promise, or messing
196+
;;with the promise chain
197+
;;via a macro or something.
198+
199+
(defn fly-to!
200+
([v e]
201+
(-> v
202+
(.flyTo e)
203+
(.then (fn [result]
204+
(when result
205+
(select-entity! v e))))))
206+
([v e offset]
207+
(-> v
208+
(.flyTo e offset)
209+
(.then (fn [result]
210+
(when result
211+
(select-entity! v e)))))))
212+
213+
(defn ->point [lat long]
214+
{
215+
:position (js/Cesium.Cartesian3.fromDegrees lat long),
216+
:point {
217+
:pixelSize 5,
218+
:color js/Cesium.Color.RED,
219+
:outlineColor js/Cesium.Color.WHITE,
220+
:outlineWidth 2}})
221+
222+
(defn ->random-points [n]
223+
(for [[lat lng] (random-coords n)]
224+
(->point lat lng)))
225+
226+
227+
(defn obj-lookup [obj k]
228+
(if-not (keyword? k)
229+
(aget obj k)
230+
(aget obj (name k))))
231+
232+
(defprotocol IEntities
233+
(-entities [this]))
234+
235+
(defprotocol IProperty
236+
(-properties [e])
237+
(-property [e k]))
238+
239+
;;protocol helpers...
240+
(extend-protocol clojure.core/ILookup
241+
js/Cesium.EntityCollection
242+
(-lookup
243+
([e k] (.getById e k))
244+
([e k nf] (or (.getById e k) nf)))
245+
js/Cesium.Entity
246+
(-lookup
247+
([e k] (obj-lookup e k))
248+
([e k nf] (or (obj-lookup e k) nf)))
249+
js/Cesium.DataSourceCollection
250+
(-lookup
251+
([e k] (obj-lookup e k))
252+
([e k nf] (or (obj-lookup e k) nf)))
253+
)
254+
255+
(extend-protocol clojure.core/INamed
256+
js/Cesium.Entity
257+
(-name [e] (.-id e)))
258+
259+
(extend-protocol clojure.core/ISeqable
260+
js/Cesium.EntityCollection
261+
(-seq [e]
262+
(for [ent (.-values e)]
263+
[(name ent) ent nil])))
264+
265+
;;no deftype in sci
266+
(defrecord #_deftype lazy-props [ent]
267+
clojure.core/ILookup
268+
(-lookup [this k]
269+
(when-let [res (some-> (aget ent "properties") (obj-lookup k))]
270+
(.-_value res)))
271+
(-lookup [this k nf]
272+
(if-let [res (some-> (aget ent "properties") (obj-lookup k))]
273+
(.-_value res)
274+
nf))
275+
clojure.core/ISeqable
276+
(-seq [this]
277+
(let [props (aget ent "properties")]
278+
(for [k (some-> props (aget "propertyNames"))]
279+
[ k (aget props k) nil])))
280+
#_#_#_
281+
clojure.core/IFn
282+
(-invoke [this k] (-lookup this k))
283+
(-invoke [this k nf] (-lookup this k nf)))
284+
285+
(extend-protocol clojure.core/IMeta
286+
js/Cesium.Entity
287+
(-meta [this]
288+
(lazy-props. this)))
289+
290+
;;doesn't work like I'd want it too...
291+
#_
292+
(extend-protocol IEntities
293+
js/Cesium.Datasource
294+
(-entities [this] (.-_entityCollection this))
295+
js/Cesium.CzmlDataSource
296+
(-entities [this] (.-_entityCollection this)))
297+
298+

src/cesium/color.js

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
//replacements for goog.color since we're not in cljs...
2+
3+
//courtesy of https://stackoverflow.com/questions/5623838/rgb-to-hex-and-hex-to-rgb
4+
function rgbToHex(r, g, b) {
5+
return "#" + (1 << 24 | r << 16 | g << 8 | b).toString(16).slice(1);
6+
}
7+
8+
function hexToRgb(hex) {
9+
// Expand shorthand form (e.g. "03F") to full form (e.g. "0033FF")
10+
var shorthandRegex = /^#?([a-f\d])([a-f\d])([a-f\d])$/i;
11+
hex = hex.replace(shorthandRegex, function(m, r, g, b) {
12+
return r + r + g + g + b + b;
13+
});
14+
15+
var result = /^#?([a-f\d]{2})([a-f\d]{2})([a-f\d]{2})$/i.exec(hex);
16+
return result ? {
17+
r: parseInt(result[1], 16),
18+
g: parseInt(result[2], 16),
19+
b: parseInt(result[3], 16)
20+
} : null;
21+
}

0 commit comments

Comments
 (0)