Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP
Newer
Older
100644 674 lines (589 sloc) 22.842 kB
03390a3 @camillol trying to make the applet work
authored
1 //import processing.opengl.*;
3675745 @camillol added MapView
authored
2 import com.modestmaps.*;
3 import com.modestmaps.core.*;
4 import com.modestmaps.geo.*;
5 import com.modestmaps.providers.*;
d727a20 @camillol background rendering of buffers
authored
6 import java.util.concurrent.*;
05f13de @camillol auto-position state glyphs
authored
7 import java.awt.geom.*;
8
9 /* Cohen-Sutherland algorithm */
6674d42 @jenikm Updated sightings
jenikm authored
10 Line2D clipLineToRect(Line2D l, Rectangle2D r){
05f13de @camillol auto-position state glyphs
authored
11 double x1 = l.getP1().getX();
12 double y1 = l.getP1().getY();
13 double x2 = l.getP2().getX();
14 double y2 = l.getP2().getY();
15 int out1 = r.outcode(x1, y1);
16 int out2 = r.outcode(x2, y2);
17
18 while (true) {
19 if ((out1 | out2) == 0) return new Line2D.Double(x1, y1, x2, y2); /* entirely inside */
20 if ((out1 & out2) != 0) return null; /* entirely outside */
21
22 int out = out1 != 0 ? out1 : out2;
23 double x, y;
24 if ((out & (Rectangle2D.OUT_LEFT | Rectangle2D.OUT_RIGHT)) != 0) {
25 x = r.getX();
26 if ((out & Rectangle2D.OUT_RIGHT) != 0) x += r.getWidth();
27 y = y1 + (x - x1) * (y2 - y1) / (x2 - x1);
28 } else {
29 y = r.getY();
30 if ((out & Rectangle2D.OUT_BOTTOM) != 0) y += r.getHeight();
31 x = x1 + (y - y1) * (x2 - x1) / (y2 - y1);
32 }
33 if (out == out1) {
34 x1 = x;
35 y1 = y;
36 out1 = r.outcode(x1, y1);
37 } else {
38 x2 = x;
39 y2 = y;
40 out2 = r.outcode(x2, y2);
41 }
42 }
43 }
3675745 @camillol added MapView
authored
44
45 class MapView extends View {
46 InteractiveMap mmap;
d46044f @pjimen5 UFOInfoBox+LimitMapZoom
pjimen5 authored
47 float zoomValue = 4;
48 float minZoom = 4;
95ab44d @pjimen5 SighingsDetailsViewUpdates
pjimen5 authored
49 float maxZoom = 15;
e952c0c @camillol can choose type of drawing
authored
50 int minPointSize= 5;
0882c8e @pjimen5 ColorsFixedOnApp
pjimen5 authored
51 int maxPointSize = 35;
44698ff @pjimen5 filterByUFOType+DrawingAirports
pjimen5 authored
52 int minIconSize= 10;
f051126 @pjimen5 DrawingSightings+SizeIconsAccordingZoom
pjimen5 authored
53 int maxIconSize = 25;
54 int minDistSize = 1;
44698ff @pjimen5 filterByUFOType+DrawingAirports
pjimen5 authored
55 int maxDistSize = 150;
e9fc876 @pjimen5 AddedDetailViewForSightings
pjimen5 authored
56 Sighting clickedSighting;
60a76c2 @pjimen5 InformationalBox
pjimen5 authored
57 Place clickedPlace;
3675745 @camillol added MapView
authored
58
d4325f8 @camillol tiled map overlay
authored
59 int MAX_BUFFERS_TO_KEEP = 64;
60
61
d727a20 @camillol background rendering of buffers
authored
62 Map<Coordinate, Future<PGraphics>> buffers;
63 ExecutorService bufferExec;
ac40bd5 @camillol optional tiled buffering
authored
64 boolean USE_BUFFERS = true;
afeb1eb @camillol experimental buffer for map overlay
authored
65
ad391e4 @camillol wider tile expansion for airport circles
authored
66 double TILE_EXPAND_FACTOR = 0.5; // as a fraction of the tile size
67 double AIRPORT_TILE_EXPAND_FACTOR = 0.15;
24fbd23 @camillol only draw places in area that needs to be drawn
authored
68
e952c0c @camillol can choose type of drawing
authored
69 boolean DRAW_ALL_TYPES = false;
d11196e @camillol use special buffers for state glyphs
authored
70
71 Map<State, StateGlyph> stateGlyphs;
05f13de @camillol auto-position state glyphs
authored
72 boolean movingGlyphs;
73 PMatrix2D glyphSavedMatrix;
b408f33 @camillol state mouseover
authored
74 PMatrix2D currentTileToMapMatrix;
d727a20 @camillol background rendering of buffers
authored
75
3675745 @camillol added MapView
authored
76 MapView(float x_, float y_, float w_, float h_)
77 {
78 super(x_, y_, w_, h_);
f9ff5e8 @camillol changed tileset
authored
79 // mmap = new InteractiveMap(papplet, new Microsoft.HybridProvider(), w, h);
80 // mmap = new InteractiveMap(papplet, new Microsoft.AerialProvider(), w, h);
733903f @camillol get map tiles through server (SOP)
authored
81 AbstractMapProvider provider;
82 if (sketchPath == null) {
83 provider = new TemplatedMapProvider("http://young-mountain-2805.heroku.com/map/tile/{X}/{Y}/{Z}", null);
84 } else {
85 String template = "http://{S}.mqcdn.com/tiles/1.0.0/osm/{Z}/{X}/{Y}.png";
86 String[] subdomains = new String[] { "otile1", "otile2", "otile3", "otile4"}; // optional
87 provider = new TemplatedMapProvider(template, subdomains);
88 }
89 mmap = new InteractiveMap(papplet, provider, w, h);
ad391e4 @camillol wider tile expansion for airport circles
authored
90 // mmap = new InteractiveMap(papplet, new Yahoo.RoadProvider(), w, h);
d46044f @pjimen5 UFOInfoBox+LimitMapZoom
pjimen5 authored
91
d4325f8 @camillol tiled map overlay
authored
92 mmap.MAX_IMAGES_TO_KEEP = 64;
afeb1eb @camillol experimental buffer for map overlay
authored
93 mmap.setCenterZoom(new Location(39,-98), int(zoomValue));
94
d727a20 @camillol background rendering of buffers
authored
95 buffers = new LinkedHashMap<Coordinate, Future<PGraphics>>(MAX_BUFFERS_TO_KEEP, 0.75, true) {
96 protected boolean removeEldestEntry(Entry<Coordinate, Future<PGraphics>> eldest) {
97 if (size() > MAX_BUFFERS_TO_KEEP) {
98 eldest.getValue().cancel(true);
99 this.remove(eldest.getKey());
100 }
101 return false;
d4325f8 @camillol tiled map overlay
authored
102 }
103 };
d727a20 @camillol background rendering of buffers
authored
104 bufferExec = Executors.newSingleThreadExecutor();
d11196e @camillol use special buffers for state glyphs
authored
105
106 stateGlyphs = new HashMap<State, StateGlyph>();
d4325f8 @camillol tiled map overlay
authored
107 }
108
56348f4 @camillol reload sighting counts only
authored
109 void rebuildOverlay()
110 {
d727a20 @camillol background rendering of buffers
authored
111 for (Future<PGraphics> future : buffers.values()) {
112 future.cancel(true);
113 }
56348f4 @camillol reload sighting counts only
authored
114 buffers.clear();
d11196e @camillol use special buffers for state glyphs
authored
115 stateGlyphs.clear();
56348f4 @camillol reload sighting counts only
authored
116 }
117
d4325f8 @camillol tiled map overlay
authored
118 void drawOverlay()
119 {
120 double sc = mmap.sc;
121 double tx = mmap.tx;
122 double ty = mmap.ty;
123
124 // translate and scale, from the middle
125 pushMatrix();
126 translate(width/2, height/2);
127 scale((float)sc);
128 translate((float)tx, (float)ty);
129
130 // find the bounds of the ur-tile in screen-space:
131 float minX = screenX(0,0);
132 float minY = screenY(0,0);
133 float maxX = screenX(mmap.TILE_WIDTH, mmap.TILE_HEIGHT);
134 float maxY = screenY(mmap.TILE_WIDTH, mmap.TILE_HEIGHT);
135
136 int zoom = mmap.getZoom();
137 int cols = (int)pow(2,zoom);
138 int rows = (int)pow(2,zoom);
139
140 // find start and end columns
141 // println("minX " + minX + " maxX " + maxX + " cols " + cols);
142 int minCol = (int)floor(cols * (0-minX) / (maxX-minX));
3dcf3e8 @camillol overlay with chicago location
authored
143 int maxCol = (int)ceil(cols * (w-minX) / (maxX-minX)) - 1;
d4325f8 @camillol tiled map overlay
authored
144 int minRow = (int)floor(rows * (0-minY) / (maxY-minY));
3dcf3e8 @camillol overlay with chicago location
authored
145 int maxRow = (int)ceil(rows * (h-minY) / (maxY-minY)) - 1;
d4325f8 @camillol tiled map overlay
authored
146
147 minCol = constrain(minCol, 0, cols);
148 maxCol = constrain(maxCol, 0, cols);
149 minRow = constrain(minRow, 0, rows);
150 maxRow = constrain(maxRow, 0, rows);
151
152 scale(1.0f/pow(2, zoom));
153 int count = 0;
154 for (int col = minCol; col <= maxCol; col++) {
155 for (int row = minRow; row <= maxRow; row++) {
156 // source coordinate wraps around the world:
157 Coordinate coord = mmap.provider.sourceCoordinate(new Coordinate(row,col,zoom));
158
159 // let's make sure we still have ints:
160 coord.row = round(coord.row);
161 coord.column = round(coord.column);
162 coord.zoom = round(coord.zoom);
163
164 if (!buffers.containsKey(coord))
d727a20 @camillol background rendering of buffers
authored
165 buffers.put(coord, bufferExec.submit(new BufferMaker(coord)));
d4325f8 @camillol tiled map overlay
authored
166
d727a20 @camillol background rendering of buffers
authored
167 if (buffers.get(coord).isDone()) {
168 try {
169 PGraphics img = buffers.get(coord).get();
170 image(img, coord.column*mmap.TILE_WIDTH, coord.row*mmap.TILE_HEIGHT, mmap.TILE_WIDTH, mmap.TILE_HEIGHT);
171 } catch (InterruptedException e) {
172 println(e);
173 } catch (ExecutionException e) {
174 println(e);
175 }
176 }
d4325f8 @camillol tiled map overlay
authored
177 count++;
178 }
179 }
180 popMatrix();
181 // println("images: " + count + " col " + minCol + " " + maxCol + " rows " + minRow + " " + maxRow);
182 }
183
05f13de @camillol auto-position state glyphs
authored
184 PMatrix2D makeMapToTileMatrix(Coordinate tileCoord) {
185 PMatrix2D m = new PMatrix2D();
186 m.translate(-tileCoord.column * mmap.TILE_WIDTH, -tileCoord.row * mmap.TILE_HEIGHT);
187 m.scale(pow(2, tileCoord.zoom));
188 m.translate(-(float)mmap.tx, -(float)mmap.ty);
189 m.scale(1.0/(float)mmap.sc);
190 m.translate(-mmap.width/2, -mmap.height/2);
191 return m;
192 }
193
194 PMatrix2D makeTileToMapMatrix(Coordinate tileCoord) {
195 PMatrix2D m = new PMatrix2D();
196 m.translate(mmap.width/2, mmap.height/2);
197 m.scale((float)mmap.sc);
198 m.translate((float)mmap.tx, (float)mmap.ty);
199 m.scale(pow(2, -tileCoord.zoom));
200 m.translate(tileCoord.column * mmap.TILE_WIDTH, tileCoord.row * mmap.TILE_HEIGHT);
201 return m;
202 }
203
ac40bd5 @camillol optional tiled buffering
authored
204 void applyMapToTileMatrix(PGraphics buffer, Coordinate tileCoord) {
205 buffer.translate(-tileCoord.column * mmap.TILE_WIDTH, -tileCoord.row * mmap.TILE_HEIGHT);
206 buffer.scale(pow(2, tileCoord.zoom));
207 buffer.translate(-(float)mmap.tx, -(float)mmap.ty);
208 buffer.scale(1.0/(float)mmap.sc);
209 buffer.translate(-mmap.width/2, -mmap.height/2);
210 }
211
05f13de @camillol auto-position state glyphs
authored
212
d4325f8 @camillol tiled map overlay
authored
213 PGraphics makeOverlayBuffer(Coordinate coord) {
ac40bd5 @camillol optional tiled buffering
authored
214 // println("makebuf: " + coord);
d4325f8 @camillol tiled map overlay
authored
215 PGraphics buf = createGraphics(mmap.TILE_WIDTH, mmap.TILE_HEIGHT, JAVA2D);
216 buf.beginDraw();
24fbd23 @camillol only draw places in area that needs to be drawn
authored
217 /* if ((coord.row + coord.column) % 2 == 0) {
d4325f8 @camillol tiled map overlay
authored
218 buf.background(255,0,0,128);
219 }
ac40bd5 @camillol optional tiled buffering
authored
220 buf.text(coord.toString(), 50, 50);*/
3dcf3e8 @camillol overlay with chicago location
authored
221
222 // we want to be compatible with drawing code that calls mmap.locationPoint
ac40bd5 @camillol optional tiled buffering
authored
223 applyMapToTileMatrix(buf, coord);
24fbd23 @camillol only draw places in area that needs to be drawn
authored
224
225 // only draw places inside this tile, but with a little margin to account for markers that cross tile boundaries
226 Location loc1 = mmap.provider.coordinateLocation(coord);
227 Coordinate coord2 = new Coordinate(coord.row + 1, coord.column + 1, coord.zoom);
228 Location loc2 = mmap.provider.coordinateLocation(coord2);
229
05d80ff @camillol initialize checkboxes with correct values
authored
230 if (showByStates) {
d11196e @camillol use special buffers for state glyphs
authored
231 // drawStates(buf, stateMap.values());
232 } else
e5384ed @camillol clustering by state
authored
233 drawPlaces(buf, placesInRect(cityTree, loc1, loc2, TILE_EXPAND_FACTOR));
2e33fd5 @pjimen5 animationWithTimer
pjimen5 authored
234 if (showAirports)
ad391e4 @camillol wider tile expansion for airport circles
authored
235 drawAirports(buf,placesInRect(airportTree,loc1,loc2,AIRPORT_TILE_EXPAND_FACTOR));
2e33fd5 @pjimen5 animationWithTimer
pjimen5 authored
236 if (showMilitaryBases)
706cecd @pjimen5 Map+Tree updates
pjimen5 authored
237 drawMilitaryBases(buf,placesInRect(militaryBaseTree,loc1,loc2,TILE_EXPAND_FACTOR));
2e33fd5 @pjimen5 animationWithTimer
pjimen5 authored
238 if (showWeatherStation)
706cecd @pjimen5 Map+Tree updates
pjimen5 authored
239 drawWeatherStations(buf,placesInRect(weatherStationTree,loc1,loc2,TILE_EXPAND_FACTOR));
3dcf3e8 @camillol overlay with chicago location
authored
240
d4325f8 @camillol tiled map overlay
authored
241 buf.endDraw();
242 return buf;
3675745 @camillol added MapView
authored
243 }
244
d727a20 @camillol background rendering of buffers
authored
245 class BufferMaker implements Callable<PGraphics> {
246 Coordinate coord;
247 BufferMaker(Coordinate coord)
248 {
249 this.coord = coord;
250 }
251
252 PGraphics call()
253 {
254 return makeOverlayBuffer(coord);
255 }
256 }
257
d11196e @camillol use special buffers for state glyphs
authored
258 class StateGlyph {
05f13de @camillol auto-position state glyphs
authored
259 final static float REPULSION = 0.85;
260 final static float RETURN = 0;
261 final static float FRICTION = 0.6;
262 final static int MARGIN = 2;
263 final static float STOP_THRESHOLD = 0.01;
264
d11196e @camillol use special buffers for state glyphs
authored
265 PGraphics buf;
05f13de @camillol auto-position state glyphs
authored
266 float x0, y0;
d11196e @camillol use special buffers for state glyphs
authored
267 float x;
268 float y;
05f13de @camillol auto-position state glyphs
authored
269 float vx;
270 float vy;
d11196e @camillol use special buffers for state glyphs
authored
271
272 StateGlyph(State state) {
273 int boxsz = ceil(sqrt(state.sightingCount));
274 buf = createGraphics(boxsz, boxsz, JAVA2D);
275 buf.beginDraw();
276 drawSightingDots(buf, state, new Point2f(boxsz/2, boxsz/2));
277 buf.endDraw();
05f13de @camillol auto-position state glyphs
authored
278
279 Point2f p = mmap.locationPoint(state.loc);
280 x = x0 = p.x;
281 y = y0 = p.y;
282 vx = vy = 0;
283 }
284
285 Rectangle2D rect()
286 {
287 return new Rectangle2D.Float(x - buf.width/2 - MARGIN, y - buf.height/2 - MARGIN, buf.width + MARGIN*2, buf.height + MARGIN*2);
288 }
289
b408f33 @camillol state mouseover
authored
290 Point2f posOnScreen()
291 {
292 float tilept[] = new float[2];
293 glyphSavedMatrix.mult(new float[] {x, y}, tilept);
294 float screenpt[] = new float[2];
295 currentTileToMapMatrix.mult(tilept, screenpt);
296 return new Point2f(screenpt[0], screenpt[1]);
297 }
298
05f13de @camillol auto-position state glyphs
authored
299 void collide(StateGlyph other)
300 {
301 Rectangle2D rect_this = this.rect();
302 Rectangle2D rect_other = other.rect();
303 Rectangle2D rect_intersect = rect_this.createIntersection(rect_other);
304
305 if (!rect_intersect.isEmpty()) {
306 double m_this = rect_this.getHeight() * rect_this.getWidth();
307 double m_other = rect_other.getHeight() * rect_other.getWidth();
308
309 Line2D l = new Line2D.Double(rect_this.getCenterX(), rect_this.getCenterY(), rect_other.getCenterX(), rect_other.getCenterY());
310 l = clipLineToRect(l, rect_intersect);
311
312 double dx = l.getX1() - l.getX2();
313 double dy = l.getY1() - l.getY2();
314
315 vx += dx * m_other / (m_this + m_other) * REPULSION;
316 vy += dy * m_other / (m_this + m_other) * REPULSION;
317
318 other.vx += - dx * m_this / (m_this + m_other) * REPULSION;
319 other.vy += - dy * m_this / (m_this + m_other) * REPULSION;
320 }
321 }
322
323 float move()
324 {
325 vx += (x0 - x) * RETURN;
326 vy += (y0 - y) * RETURN;
327
328 vx *= (1 - FRICTION);
329 vy *= (1 - FRICTION);
330
331 x += vx;
332 y += vy;
333
334 return sqrt(vx*vx + vy*vy);
d11196e @camillol use special buffers for state glyphs
authored
335 }
336 }
337
3675745 @camillol added MapView
authored
338 void drawContent()
339 {
ff69b0a @camillol added mouse wheel support to map
authored
340 imageMode(CORNER); // modestmaps needs this - I sent a patch, but who knows when it'll be committed
3675745 @camillol added MapView
authored
341 mmap.draw();
9874feb @camillol drag map, fix map positioning
authored
342
b408f33 @camillol state mouseover
authored
343 currentTileToMapMatrix = makeTileToMapMatrix(new Coordinate(0,0,0));
0c3a8e7 @camillol fast play
authored
344
345 if (playing) {
346 player.update();
347 noStroke();
348 for (SightingLite s : player.loaded) {
349 long age = player.ageInMillis(s);
350 if (age < 0) break;
aa943a7 @camillol cooler animation
authored
351
0c3a8e7 @camillol fast play
authored
352 Point2f p = mmap.locationPoint(s.location.loc);
aa943a7 @camillol cooler animation
authored
353 float c = map(age, 0, player.LINGER_MILLIS / 5, 0.0, 1.0);
354 if (c <= 1.0) {
355 noFill();
356 stroke(s.type.colr, 255 * (1.0-c*c));
357 strokeWeight(2);
358 ellipse(p.x, p.y, 40 * c, 40 * c);
359 noStroke();
360 }
361
362 float a = map(age, 0, player.LINGER_MILLIS, 255, 0);
0c3a8e7 @camillol fast play
authored
363 fill(s.type.colr, a);
364 ellipse(p.x, p.y, 10, 10);
365 }
366
367 return;
368 }
b408f33 @camillol state mouseover
authored
369
ac40bd5 @camillol optional tiled buffering
authored
370 if (USE_BUFFERS) drawOverlay();
44698ff @pjimen5 filterByUFOType+DrawingAirports
pjimen5 authored
371 else{
05d80ff @camillol initialize checkboxes with correct values
authored
372 if (!showByStates) drawPlaces(papplet.g, cityMap.values());
e5384ed @camillol clustering by state
authored
373 if (showAirports)
374 drawAirports(papplet.g, airportMap.values());
375 if (showMilitaryBases)
376 drawMilitaryBases(papplet.g,militaryBaseMap.values());
377 if (showWeatherStation)
378 drawWeatherStations(papplet.g,weatherStationMap.values());
44698ff @pjimen5 filterByUFOType+DrawingAirports
pjimen5 authored
379 }
05d80ff @camillol initialize checkboxes with correct values
authored
380 if (showByStates) {
d11196e @camillol use special buffers for state glyphs
authored
381 imageMode(CENTER);
05f13de @camillol auto-position state glyphs
authored
382
383 /* create all glyphs if missing */
384 if (stateGlyphs.size() == 0) {
385 for (State state : stateMap.values()) {
386 if (state.sightingCount <= 0) continue;
387 // if (state.abbr.equals("CA") || state.abbr.equals("NV"))
388 stateGlyphs.put(state, new StateGlyph(state));
389 }
34116fe @camillol don't draw place infobox when showing states
authored
390 if (stateGlyphs.size() > 0) {
391 movingGlyphs = true;
392 glyphSavedMatrix = makeMapToTileMatrix(new Coordinate(0,0,0));
393 /* this matrix maps from screen to megatile coordinates. hopefully. */
394 }
05f13de @camillol auto-position state glyphs
authored
395 }
396
397 if (movingGlyphs) {
398 float max_move = 0;
399 /* let's try to avoid overlaps */
400 int i = 0;
401 for (StateGlyph sg : stateGlyphs.values()) {
402 int j = 0;
403 for (StateGlyph sg2 : stateGlyphs.values()) {
404 if (j > i) sg.collide(sg2);
405 j++;
406 }
407 max_move = max(max_move, sg.move());
408 i++;
409 }
410 if (max_move < StateGlyph.STOP_THRESHOLD) {
411 movingGlyphs = false;
412 println("done moving");
413 }
414 }
415
d11196e @camillol use special buffers for state glyphs
authored
416 for (State state : stateMap.values()) {
417 if (state.sightingCount <= 0) continue;
05f13de @camillol auto-position state glyphs
authored
418 StateGlyph sg = stateGlyphs.get(state);
419
420 if (sg == null) continue;
d11196e @camillol use special buffers for state glyphs
authored
421
05f13de @camillol auto-position state glyphs
authored
422 // line(sg.x, sg.y, sg.x0, sg.y0);
b408f33 @camillol state mouseover
authored
423 Point2f p = sg.posOnScreen();
424 image(sg.buf, p.x, p.y);
d11196e @camillol use special buffers for state glyphs
authored
425 }
426 }
44698ff @pjimen5 filterByUFOType+DrawingAirports
pjimen5 authored
427
b408f33 @camillol state mouseover
authored
428 if (showByStates) drawStatesInformationBox();
429 else drawPlacesInformationBox();
9874feb @camillol drag map, fix map positioning
authored
430 }
431
ff69b0a @camillol added mouse wheel support to map
authored
432 boolean contentMouseWheel(float lx, float ly, int delta)
433 {
10e05a6 @pjimen5 lastupdates
pjimen5 authored
434 if ( ly > (settingsView.y+settingsView.h) && ly < (sightingDetailsView.y)){
435 float sc = 1.0;
436 if (delta < 0) {
437 sc = 1.05;
438 }
439 else if (delta > 0) {
440 sc = 1.0/1.05;
441 }
442 float mx = lx - w/2;
443 float my = ly - h/2;
444 mmap.tx -= mx/mmap.sc;
445 mmap.ty -= my/mmap.sc;
446 if (mmap.sc*sc > 16 && mmap.sc*sc < 900){
447 mmap.sc *= sc;
448 zoomValue = ceil(map((int)mmap.sc,16,900,minZoom,maxZoom));
449 }
450 mmap.tx += mx/mmap.sc;
451 mmap.ty += my/mmap.sc;
ff69b0a @camillol added mouse wheel support to map
authored
452 }
453 return true;
454 }
e9fc876 @pjimen5 AddedDetailViewForSightings
pjimen5 authored
455
b77cea0 @pjimen5 CallUpdateCitiesWhenSettingsChange
pjimen5 authored
456 boolean contentClicked(float px, float py)
e9fc876 @pjimen5 AddedDetailViewForSightings
pjimen5 authored
457 {
b77cea0 @pjimen5 CallUpdateCitiesWhenSettingsChange
pjimen5 authored
458 if (clickedPlace == null){
459 detailsAnimator.target(height);
460 }
461 else if (sightingDetailsView.place!=clickedPlace){
462 sightingDetailsView.place = clickedPlace;
2202254 @camillol isolated DB access layer
authored
463 sightingDetailsView.setSightings(data.sightingsForCity(mapv.clickedPlace));
b77cea0 @pjimen5 CallUpdateCitiesWhenSettingsChange
pjimen5 authored
464 detailsAnimator.target(height-200);
465 }
466
e9fc876 @pjimen5 AddedDetailViewForSightings
pjimen5 authored
467 return true;
468 }
469
9874feb @camillol drag map, fix map positioning
authored
470 boolean mouseDragged(float px, float py)
471 {
10e05a6 @pjimen5 lastupdates
pjimen5 authored
472 if ( py > (settingsView.y+settingsView.h) && py < (sightingDetailsView.y)){
473 mmap.mouseDragged();
474 }
475 return true;
3675745 @camillol added MapView
authored
476 }
f051126 @pjimen5 DrawingSightings+SizeIconsAccordingZoom
pjimen5 authored
477
44698ff @pjimen5 filterByUFOType+DrawingAirports
pjimen5 authored
478 void drawAirports(PGraphics buffer, Iterable<Place> airports){
479 buffer.imageMode(CENTER);
480 buffer.noStroke();
481 buffer.fill(airportAreaColor,40);
482 for (Place airport : airports) {
483 float pointSize = map(zoomValue, minZoom, maxZoom, minDistSize, maxDistSize);
484 float iconSize = map(zoomValue,minZoom,maxZoom,minIconSize,maxIconSize);
485 Point2f p = mmap.locationPoint(airport.loc);
486 buffer.ellipse(p.x,p.y,pointSize,pointSize);
487 buffer.image(airplaneImage,p.x,p.y,iconSize,iconSize);
488 }
f051126 @pjimen5 DrawingSightings+SizeIconsAccordingZoom
pjimen5 authored
489 }
490
d8ca394 @pjimen5 DrawingMilitaryBases
pjimen5 authored
491 void drawMilitaryBases(PGraphics buffer, Iterable<Place> militaryBases){
492 buffer.imageMode(CENTER);
493 buffer.noStroke();
1b99571 @pjimen5 DrawingWeatherStations
pjimen5 authored
494 buffer.fill(militaryBaseColor,40);
d8ca394 @pjimen5 DrawingMilitaryBases
pjimen5 authored
495 for (Place militaryBase : militaryBases) {
496 float pointSize = map(zoomValue, minZoom, maxZoom, minDistSize, maxDistSize);
497 float iconSize = map(zoomValue,minZoom,maxZoom,minIconSize,maxIconSize);
498 Point2f p = mmap.locationPoint(militaryBase.loc);
499 buffer.ellipse(p.x,p.y,pointSize,pointSize);
500 buffer.image(militaryBaseImage,p.x,p.y,iconSize,iconSize);
501 }
502 }
503
1b99571 @pjimen5 DrawingWeatherStations
pjimen5 authored
504 void drawWeatherStations(PGraphics buffer, Iterable<Place> weatherStations){
505 buffer.imageMode(CENTER);
506 buffer.noStroke();
507 buffer.fill(weatherStationColor,40);
508 for (Place weatherStation : weatherStations) {
509 float pointSize = map(zoomValue, minZoom, maxZoom, minDistSize, maxDistSize);
510 float iconSize = map(zoomValue,minZoom,maxZoom,minIconSize,maxIconSize);
511 Point2f p = mmap.locationPoint(weatherStation.loc);
512 buffer.ellipse(p.x,p.y,pointSize,pointSize);
513 buffer.image(weatherStationImage,p.x,p.y,iconSize,iconSize);
514 }
515 }
516
d11196e @camillol use special buffers for state glyphs
authored
517 void drawSightingDots(PGraphics buffer, Place place, Point2f p)
e5384ed @camillol clustering by state
authored
518 {
519 int boxsz = ceil(sqrt(place.sightingCount));
520 int boxx = 0;
521 int boxy = 0;
522 buffer.pushMatrix();
523 buffer.translate(p.x - boxsz/2, p.y - boxsz/2);
524 int idx = 0;
525
526 buffer.noStroke();
527 for (SightingType st : sightingTypeMap.values()) {
d3b94ed @camillol fix state active types
authored
528 if (st.active) {
529 buffer.fill(st.colr);
530 int count = place.counts[idx];
531 while (count > 0) {
532 if (boxx == boxsz){
533 boxx = 0;
534 boxy++;
535 }
536 int len = min(boxsz - boxx, count);
537 buffer.rect(boxx, boxy, len, 1);
538 boxx += len;
539 count -= len;
e5384ed @camillol clustering by state
authored
540 }
541 }
542 idx++;
543 }
544 buffer.popMatrix();
545 }
546
547 void drawPlaces(PGraphics buffer, Iterable<? extends Place> places) {
afeb1eb @camillol experimental buffer for map overlay
authored
548 buffer.imageMode(CENTER);
c36fe9b @camillol try drawing all types
authored
549
550 buffer.noStroke();
24fbd23 @camillol only draw places in area that needs to be drawn
authored
551 for (Place place : places) {
430e863 @pjimen5 yearQuery
pjimen5 authored
552 if (place.sightingCount > 0){
d11196e @camillol use special buffers for state glyphs
authored
553 Point2f p = mmap.locationPoint(place.loc);
e952c0c @camillol can choose type of drawing
authored
554 if (DRAW_ALL_TYPES) {
d11196e @camillol use special buffers for state glyphs
authored
555 drawSightingDots(buffer, place, p);
e952c0c @camillol can choose type of drawing
authored
556 } else {
4bc6668 @camillol fix use of sightingtype color
authored
557 SightingType st = mainSightingTypeForPlace(place);
e952c0c @camillol can choose type of drawing
authored
558 float maxPointValue = map(zoomValue, minZoom, maxZoom, minPointSize, maxPointSize);
559 float dotSize = map(place.sightingCount, minCountSightings, maxCountSightings, minPointSize, maxPointValue);
8cb1727 @pjimen5 HighlightedPlaces-NearAirport-MilitaryBase-WeatherStation
pjimen5 authored
560
561 if ((showAirports && place.airportDist < 10) || (showMilitaryBases && place.militaryDist < 10) || (showWeatherStation && place.weatherDist < 10)){
562 buffer.stroke(0);
563 buffer.strokeWeight(2);
564 if (st == null)
565 buffer.fill(255);
566 else
567 buffer.fill(st.colr,255);
568 }
569 else{
570 if (st == null) {
571 buffer.strokeWeight(0.5);
572 buffer.stroke(0);
573 buffer.fill(255);
574 }
575 else{
576 buffer.noStroke();
577 buffer.fill(st.colr,180);
578 }
e952c0c @camillol can choose type of drawing
authored
579 }
8cb1727 @pjimen5 HighlightedPlaces-NearAirport-MilitaryBase-WeatherStation
pjimen5 authored
580 buffer.ellipse(p.x, p.y, dotSize, dotSize);
581 //buffer.image((sightingTypeMap.get(place.sightingType)).icon, p.x, p.y, dotSize, dotSize)
adeea9f @pjimen5 ChangeIconForEllipses
pjimen5 authored
582 }
430e863 @pjimen5 yearQuery
pjimen5 authored
583 }
a675529 @camillol simplified data loading
authored
584 }
585 }
586
4bc6668 @camillol fix use of sightingtype color
authored
587 SightingType mainSightingTypeForPlace(Place place)
588 {
589 /* I now load sighting counts for all types, but this calculates the values we had before */
590 int typeOfSightingCount = 0;
591 SightingType sightingType = null;
592 int idx = 0;
593 for (SightingType st : sightingTypeMap.values()) {
f062acc @camillol fixed filtering by type
authored
594 if (st.active && place.counts[idx] > 0) {
4bc6668 @camillol fix use of sightingtype color
authored
595 typeOfSightingCount++;
596 sightingType = st;
597 }
598 idx++;
599 }
600 if (typeOfSightingCount == 1) return sightingType;
601 else return null;
602 }
603
b408f33 @camillol state mouseover
authored
604 void drawStatesInformationBox() {
605 textAlign(LEFT, TOP);
606 fill(0);
607 for (Entry<State,StateGlyph> entry : stateGlyphs.entrySet()) {
608 State state = entry.getKey();
609 StateGlyph sg = entry.getValue();
339171a @pjimen5 InformationBoxByState
pjimen5 authored
610
b408f33 @camillol state mouseover
authored
611 Point2f p = sg.posOnScreen();
612 float x = p.x - sg.buf.width/2;
613 float y = p.y - sg.buf.height/2;
614 Rectangle2D r = new Rectangle2D.Float(x, y, sg.buf.width, sg.buf.height);
615 if (r.contains(mouseX, mouseY)) {
339171a @pjimen5 InformationBoxByState
pjimen5 authored
616 fill(infoBoxBackground);
617 stroke(textColor);
618 float w_ = textWidth("Total # of sightings = "+nfc(state.sightingCount))+20;
619 float x_ = (x+w_ > w)?w-w_-5:x;
620 float h_ = (textAscent() + textDescent()) * 2 + 15;
621 float y_ = (y + sg.buf.height+h_ > sightingDetailsView.y)?sightingDetailsView.y-h_-5:y + sg.buf.height;
622 rect(x_,y_,w_,h_);
623 fill(textColor);
624 text(state.name, x_ + (w_ - textWidth(state.name))/2 ,y_+5);
625 text("Total # of sightings = "+nfc(state.sightingCount),x_ + (w_ - textWidth("Total # of sightings = "+state.sightingCount))/2, (y_+ h_/2)+5);
b408f33 @camillol state mouseover
authored
626 }
627 }
628 }
629
60a76c2 @pjimen5 InformationalBox
pjimen5 authored
630 void drawPlacesInformationBox() {
631 imageMode(CENTER);
d3b94ed @camillol fix state active types
authored
632 textAlign(LEFT, TOP);
b748dec @camillol only scan points around cursor for overlay
authored
633
634 float maxPointValue = map(zoomValue, minZoom, maxZoom, minPointSize, maxPointSize);
635 Location loc1 = mmap.pointLocation(mouseX - maxPointValue, mouseY - maxPointValue); // TODO: use local coordinates (although they're identical in this app)
636 Location loc2 = mmap.pointLocation(mouseX + maxPointValue, mouseY + maxPointValue);
637
706cecd @pjimen5 Map+Tree updates
pjimen5 authored
638 for (Place place : placesInRect(cityTree,loc1, loc2, 0.0)) {
c90ff16 @pjimen5 RetrievedPlaces&SightingsByDateTime
pjimen5 authored
639 if (place.sightingCount > 0){
640 float dotSize = map(place.sightingCount, minCountSightings, maxCountSightings, minPointSize, maxPointValue);
641 Point2f p = mmap.locationPoint(place.loc);
642 if (dist(mouseX,mouseY,p.x,p.y) < dotSize/2 && p.y > (settingsView.y+settingsView.h) && p.y < (sightingDetailsView.y)){
643 textSize(normalFontSize);
644 strokeWeight(1);
645 String textToPrint = "Click on it to see details";
339171a @pjimen5 InformationBoxByState
pjimen5 authored
646 String numOfSightings = "Total # of sightings = " + nfc(place.sightingCount);
c90ff16 @pjimen5 RetrievedPlaces&SightingsByDateTime
pjimen5 authored
647 if (textToPrint.length() < place.name.length())
648 textToPrint = place.name;
649 if (textToPrint.length() < numOfSightings.length())
650 textToPrint = numOfSightings;
651 fill(infoBoxBackground);
4bc6668 @camillol fix use of sightingtype color
authored
652 SightingType st = mainSightingTypeForPlace(place);
653 if (st == null) stroke(255);
654 else stroke(st.colr);
c90ff16 @pjimen5 RetrievedPlaces&SightingsByDateTime
pjimen5 authored
655 float w_ = textWidth(textToPrint)+10;
656 float x_ = (p.x+w_ > w)?w-w_-5:p.x;
a4a5056 @pjimen5 ChangeFont
pjimen5 authored
657 float h_ = (textAscent() + textDescent()) * 3 + 15;
c90ff16 @pjimen5 RetrievedPlaces&SightingsByDateTime
pjimen5 authored
658 float y_ = (p.y+h_ > sightingDetailsView.y)?sightingDetailsView.y-h_-5:p.y;
659 rect(x_,y_,w_,h_);
660 fill(textColor);
061667c @pjimen5 UpdateSomeColors
pjimen5 authored
661 text(place.name, x_ + (w_ - textWidth(place.name))/2 ,y_+5);
c90ff16 @pjimen5 RetrievedPlaces&SightingsByDateTime
pjimen5 authored
662 text(numOfSightings,x_ + (w_ - textWidth(numOfSightings))/2, (y_+ h_/3)+5);
663 textSize(smallFontSize);
a4a5056 @pjimen5 ChangeFont
pjimen5 authored
664 text("Click on it to see details",x_+5,y_+h_-12);
c90ff16 @pjimen5 RetrievedPlaces&SightingsByDateTime
pjimen5 authored
665 if (mousePressed){
666 clickedPlace = place;
667 }
668 }
669 }
670 }
d46044f @pjimen5 UFOInfoBox+LimitMapZoom
pjimen5 authored
671 }
3675745 @camillol added MapView
authored
672 }
673
Something went wrong with that request. Please try again.