propane 2.7.2-java → 2.8.0.pre-java

Sign up to get free protection for your applications and to get access to all the features.
Files changed (124) hide show
  1. checksums.yaml +4 -4
  2. data/.travis.yml +10 -0
  3. data/CHANGELOG.md +1 -1
  4. data/README.md +10 -8
  5. data/Rakefile +1 -1
  6. data/lib/propane/app.rb +3 -3
  7. data/lib/propane/version.rb +1 -1
  8. data/lib/{processing-core.jar → propane-2.8.0.jar} +0 -0
  9. data/library/control_panel/control_panel.rb +3 -2
  10. data/pom.rb +89 -88
  11. data/pom.xml +75 -46
  12. data/propane.gemspec +1 -2
  13. data/src/main/java/japplemenubar/JAppleMenuBar.java +88 -0
  14. data/src/main/java/japplemenubar/libjAppleMenuBar.jnilib +0 -0
  15. data/src/{monkstone → main/java/monkstone}/ColorUtil.java +0 -0
  16. data/src/{monkstone → main/java/monkstone}/MathToolModule.java +0 -0
  17. data/src/{monkstone → main/java/monkstone}/PropaneLibrary.java +0 -0
  18. data/src/{monkstone → main/java/monkstone}/core/LibraryProxy.java +0 -0
  19. data/src/{monkstone → main/java/monkstone}/fastmath/Deglut.java +0 -0
  20. data/src/{monkstone → main/java/monkstone}/fastmath/package-info.java +0 -0
  21. data/src/{monkstone → main/java/monkstone}/filechooser/Chooser.java +0 -0
  22. data/src/{monkstone → main/java/monkstone}/noise/SimplexNoise.java +0 -0
  23. data/src/{monkstone → main/java/monkstone}/slider/CustomHorizontalSlider.java +0 -0
  24. data/src/{monkstone → main/java/monkstone}/slider/CustomVerticalSlider.java +0 -0
  25. data/src/{monkstone → main/java/monkstone}/slider/SimpleHorizontalSlider.java +0 -0
  26. data/src/{monkstone → main/java/monkstone}/slider/SimpleSlider.java +0 -0
  27. data/src/{monkstone → main/java/monkstone}/slider/SimpleVerticalSlider.java +0 -0
  28. data/src/{monkstone → main/java/monkstone}/slider/Slider.java +0 -0
  29. data/src/{monkstone → main/java/monkstone}/slider/SliderBar.java +0 -0
  30. data/src/{monkstone → main/java/monkstone}/slider/SliderGroup.java +0 -0
  31. data/src/{monkstone → main/java/monkstone}/slider/WheelHandler.java +0 -0
  32. data/src/{monkstone → main/java/monkstone}/vecmath/AppRender.java +0 -0
  33. data/src/{monkstone → main/java/monkstone}/vecmath/JRender.java +0 -0
  34. data/src/{monkstone → main/java/monkstone}/vecmath/ShapeRender.java +0 -0
  35. data/src/{monkstone → main/java/monkstone}/vecmath/package-info.java +0 -0
  36. data/src/{monkstone → main/java/monkstone}/vecmath/vec2/Vec2.java +0 -0
  37. data/src/{monkstone → main/java/monkstone}/vecmath/vec2/package-info.java +0 -0
  38. data/src/{monkstone → main/java/monkstone}/vecmath/vec3/Vec3.java +0 -0
  39. data/src/{monkstone → main/java/monkstone}/vecmath/vec3/package-info.java +0 -0
  40. data/src/{monkstone → main/java/monkstone}/videoevent/VideoInterface.java +0 -0
  41. data/src/{monkstone → main/java/monkstone}/videoevent/package-info.java +0 -0
  42. data/src/main/java/processing/awt/PGraphicsJava2D.java +3029 -0
  43. data/src/main/java/processing/awt/PShapeJava2D.java +377 -0
  44. data/src/main/java/processing/awt/PSurfaceAWT.java +1567 -0
  45. data/src/main/java/processing/core/PApplet.java +15709 -0
  46. data/src/main/java/processing/core/PConstants.java +527 -0
  47. data/src/main/java/processing/core/PFont.java +1098 -0
  48. data/src/main/java/processing/core/PGraphics.java +8467 -0
  49. data/src/main/java/processing/core/PImage.java +3438 -0
  50. data/src/main/java/processing/core/PMatrix.java +208 -0
  51. data/src/main/java/processing/core/PMatrix2D.java +534 -0
  52. data/src/main/java/processing/core/PMatrix3D.java +877 -0
  53. data/src/main/java/processing/core/PShape.java +3445 -0
  54. data/src/main/java/processing/core/PShapeOBJ.java +469 -0
  55. data/src/main/java/processing/core/PShapeSVG.java +1787 -0
  56. data/src/main/java/processing/core/PStyle.java +63 -0
  57. data/src/main/java/processing/core/PSurface.java +161 -0
  58. data/src/main/java/processing/core/PSurfaceNone.java +374 -0
  59. data/src/main/java/processing/core/PVector.java +1063 -0
  60. data/src/main/java/processing/data/FloatDict.java +829 -0
  61. data/src/main/java/processing/data/FloatList.java +912 -0
  62. data/src/main/java/processing/data/IntDict.java +796 -0
  63. data/src/main/java/processing/data/IntList.java +913 -0
  64. data/src/main/java/processing/data/JSONArray.java +1260 -0
  65. data/src/main/java/processing/data/JSONObject.java +2282 -0
  66. data/src/main/java/processing/data/JSONTokener.java +435 -0
  67. data/src/main/java/processing/data/Sort.java +46 -0
  68. data/src/main/java/processing/data/StringDict.java +601 -0
  69. data/src/main/java/processing/data/StringList.java +775 -0
  70. data/src/main/java/processing/data/Table.java +4923 -0
  71. data/src/main/java/processing/data/TableRow.java +198 -0
  72. data/src/main/java/processing/data/XML.java +1149 -0
  73. data/src/main/java/processing/event/Event.java +125 -0
  74. data/src/main/java/processing/event/KeyEvent.java +70 -0
  75. data/src/main/java/processing/event/MouseEvent.java +149 -0
  76. data/src/main/java/processing/event/TouchEvent.java +57 -0
  77. data/src/main/java/processing/opengl/FontTexture.java +379 -0
  78. data/src/main/java/processing/opengl/FrameBuffer.java +503 -0
  79. data/src/main/java/processing/opengl/LinePath.java +623 -0
  80. data/src/main/java/processing/opengl/LineStroker.java +685 -0
  81. data/src/main/java/processing/opengl/PGL.java +3366 -0
  82. data/src/main/java/processing/opengl/PGraphics2D.java +615 -0
  83. data/src/main/java/processing/opengl/PGraphics3D.java +281 -0
  84. data/src/main/java/processing/opengl/PGraphicsOpenGL.java +13634 -0
  85. data/src/main/java/processing/opengl/PJOGL.java +1966 -0
  86. data/src/main/java/processing/opengl/PShader.java +1478 -0
  87. data/src/main/java/processing/opengl/PShapeOpenGL.java +5234 -0
  88. data/src/main/java/processing/opengl/PSurfaceJOGL.java +1315 -0
  89. data/src/main/java/processing/opengl/Texture.java +1670 -0
  90. data/src/main/java/processing/opengl/VertexBuffer.java +88 -0
  91. data/src/main/java/processing/opengl/cursors/arrow.png +0 -0
  92. data/src/main/java/processing/opengl/cursors/cross.png +0 -0
  93. data/src/main/java/processing/opengl/cursors/hand.png +0 -0
  94. data/src/main/java/processing/opengl/cursors/license.txt +27 -0
  95. data/src/main/java/processing/opengl/cursors/move.png +0 -0
  96. data/src/main/java/processing/opengl/cursors/text.png +0 -0
  97. data/src/main/java/processing/opengl/cursors/wait.png +0 -0
  98. data/src/main/java/processing/opengl/shaders/ColorFrag.glsl +32 -0
  99. data/src/main/java/processing/opengl/shaders/ColorVert.glsl +34 -0
  100. data/src/main/java/processing/opengl/shaders/LightFrag.glsl +33 -0
  101. data/src/main/java/processing/opengl/shaders/LightVert-vc4.glsl +154 -0
  102. data/src/main/java/processing/opengl/shaders/LightVert.glsl +151 -0
  103. data/src/main/java/processing/opengl/shaders/LineFrag.glsl +32 -0
  104. data/src/main/java/processing/opengl/shaders/LineVert.glsl +100 -0
  105. data/src/main/java/processing/opengl/shaders/MaskFrag.glsl +40 -0
  106. data/src/main/java/processing/opengl/shaders/PointFrag.glsl +32 -0
  107. data/src/main/java/processing/opengl/shaders/PointVert.glsl +56 -0
  108. data/src/main/java/processing/opengl/shaders/TexFrag.glsl +37 -0
  109. data/src/main/java/processing/opengl/shaders/TexLightFrag.glsl +37 -0
  110. data/src/main/java/processing/opengl/shaders/TexLightVert-vc4.glsl +160 -0
  111. data/src/main/java/processing/opengl/shaders/TexLightVert.glsl +157 -0
  112. data/src/main/java/processing/opengl/shaders/TexVert.glsl +38 -0
  113. data/src/main/resources/icon/icon-1024.png +0 -0
  114. data/src/main/resources/icon/icon-128.png +0 -0
  115. data/src/main/resources/icon/icon-16.png +0 -0
  116. data/src/main/resources/icon/icon-256.png +0 -0
  117. data/src/main/resources/icon/icon-32.png +0 -0
  118. data/src/main/resources/icon/icon-48.png +0 -0
  119. data/src/main/resources/icon/icon-512.png +0 -0
  120. data/src/main/resources/icon/icon-64.png +0 -0
  121. data/src/main/resources/license.txt +508 -0
  122. data/vendors/Rakefile +5 -20
  123. metadata +115 -33
  124. data/lib/propane.jar +0 -0
@@ -0,0 +1,829 @@
1
+ package processing.data;
2
+
3
+ import java.io.*;
4
+ import java.util.HashMap;
5
+ import java.util.Iterator;
6
+
7
+ import processing.core.PApplet;
8
+
9
+
10
+ /**
11
+ * A simple table class to use a String as a lookup for an float value.
12
+ *
13
+ * @webref data:composite
14
+ * @see IntDict
15
+ * @see StringDict
16
+ */
17
+ public class FloatDict {
18
+
19
+ /** Number of elements in the table */
20
+ protected int count;
21
+
22
+ protected String[] keys;
23
+ protected float[] values;
24
+
25
+ /** Internal implementation for faster lookups */
26
+ private HashMap<String, Integer> indices = new HashMap<>();
27
+
28
+
29
+ public FloatDict() {
30
+ count = 0;
31
+ keys = new String[10];
32
+ values = new float[10];
33
+ }
34
+
35
+
36
+ /**
37
+ * Create a new lookup with a specific size. This is more efficient than not
38
+ * specifying a size. Use it when you know the rough size of the thing you're creating.
39
+ *
40
+ * @nowebref
41
+ */
42
+ public FloatDict(int length) {
43
+ count = 0;
44
+ keys = new String[length];
45
+ values = new float[length];
46
+ }
47
+
48
+
49
+ /**
50
+ * Read a set of entries from a Reader that has each key/value pair on
51
+ * a single line, separated by a tab.
52
+ *
53
+ * @nowebref
54
+ */
55
+ public FloatDict(BufferedReader reader) {
56
+ String[] lines = PApplet.loadStrings(reader);
57
+ keys = new String[lines.length];
58
+ values = new float[lines.length];
59
+
60
+ for (int i = 0; i < lines.length; i++) {
61
+ String[] pieces = PApplet.split(lines[i], '\t');
62
+ if (pieces.length == 2) {
63
+ keys[count] = pieces[0];
64
+ values[count] = PApplet.parseFloat(pieces[1]);
65
+ indices.put(pieces[0], count);
66
+ count++;
67
+ }
68
+ }
69
+ }
70
+
71
+
72
+ /**
73
+ * @nowebref
74
+ */
75
+ public FloatDict(String[] keys, float[] values) {
76
+ if (keys.length != values.length) {
77
+ throw new IllegalArgumentException("key and value arrays must be the same length");
78
+ }
79
+ this.keys = keys;
80
+ this.values = values;
81
+ count = keys.length;
82
+ for (int i = 0; i < count; i++) {
83
+ indices.put(keys[i], i);
84
+ }
85
+ }
86
+
87
+
88
+ /**
89
+ * Constructor to allow (more intuitive) inline initialization, e.g.:
90
+ * <pre>
91
+ * new FloatDict(new Object[][] {
92
+ * { "key1", 1 },
93
+ * { "key2", 2 }
94
+ * });
95
+ * </pre>
96
+ */
97
+ public FloatDict(Object[][] pairs) {
98
+ count = pairs.length;
99
+ this.keys = new String[count];
100
+ this.values = new float[count];
101
+ for (int i = 0; i < count; i++) {
102
+ keys[i] = (String) pairs[i][0];
103
+ values[i] = (Float) pairs[i][1];
104
+ indices.put(keys[i], i);
105
+ }
106
+ }
107
+
108
+
109
+ /**
110
+ * @webref floatdict:method
111
+ * @brief Returns the number of key/value pairs
112
+ */
113
+ public int size() {
114
+ return count;
115
+ }
116
+
117
+
118
+ /**
119
+ * Resize the internal data, this can only be used to shrink the list.
120
+ * Helpful for situations like sorting and then grabbing the top 50 entries.
121
+ */
122
+ public void resize(int length) {
123
+ if (length == count) return;
124
+
125
+ if (length > count) {
126
+ throw new IllegalArgumentException("resize() can only be used to shrink the dictionary");
127
+ }
128
+ if (length < 1) {
129
+ throw new IllegalArgumentException("resize(" + length + ") is too small, use 1 or higher");
130
+ }
131
+
132
+ String[] newKeys = new String[length];
133
+ float[] newValues = new float[length];
134
+ PApplet.arrayCopy(keys, newKeys, length);
135
+ PApplet.arrayCopy(values, newValues, length);
136
+ keys = newKeys;
137
+ values = newValues;
138
+ count = length;
139
+ resetIndices();
140
+ }
141
+
142
+
143
+ /**
144
+ * Remove all entries.
145
+ *
146
+ * @webref floatdict:method
147
+ * @brief Remove all entries
148
+ */
149
+ public void clear() {
150
+ count = 0;
151
+ indices = new HashMap<>();
152
+ }
153
+
154
+
155
+ private void resetIndices() {
156
+ indices = new HashMap<>(count);
157
+ for (int i = 0; i < count; i++) {
158
+ indices.put(keys[i], i);
159
+ }
160
+ }
161
+
162
+
163
+ // . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
164
+
165
+
166
+ public class Entry {
167
+ public String key;
168
+ public float value;
169
+
170
+ Entry(String key, float value) {
171
+ this.key = key;
172
+ this.value = value;
173
+ }
174
+ }
175
+
176
+
177
+ public Iterable<Entry> entries() {
178
+ return new Iterable<Entry>() {
179
+
180
+ public Iterator<Entry> iterator() {
181
+ return entryIterator();
182
+ }
183
+ };
184
+ }
185
+
186
+
187
+ public Iterator<Entry> entryIterator() {
188
+ return new Iterator<Entry>() {
189
+ int index = -1;
190
+
191
+ public void remove() {
192
+ removeIndex(index);
193
+ index--;
194
+ }
195
+
196
+ public Entry next() {
197
+ ++index;
198
+ Entry e = new Entry(keys[index], values[index]);
199
+ return e;
200
+ }
201
+
202
+ public boolean hasNext() {
203
+ return index+1 < size();
204
+ }
205
+ };
206
+ }
207
+
208
+
209
+ // . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
210
+
211
+
212
+ public String key(int index) {
213
+ return keys[index];
214
+ }
215
+
216
+
217
+ protected void crop() {
218
+ if (count != keys.length) {
219
+ keys = PApplet.subset(keys, 0, count);
220
+ values = PApplet.subset(values, 0, count);
221
+ }
222
+ }
223
+
224
+
225
+ public Iterable<String> keys() {
226
+ return new Iterable<String>() {
227
+
228
+ @Override
229
+ public Iterator<String> iterator() {
230
+ return keyIterator();
231
+ }
232
+ };
233
+ }
234
+
235
+
236
+ // Use this to iterate when you want to be able to remove elements along the way
237
+ public Iterator<String> keyIterator() {
238
+ return new Iterator<String>() {
239
+ int index = -1;
240
+
241
+ public void remove() {
242
+ removeIndex(index);
243
+ index--;
244
+ }
245
+
246
+ public String next() {
247
+ return key(++index);
248
+ }
249
+
250
+ public boolean hasNext() {
251
+ return index+1 < size();
252
+ }
253
+ };
254
+ }
255
+
256
+
257
+ /**
258
+ * Return a copy of the internal keys array. This array can be modified.
259
+ *
260
+ * @webref floatdict:method
261
+ * @brief Return a copy of the internal keys array
262
+ */
263
+ public String[] keyArray() {
264
+ crop();
265
+ return keyArray(null);
266
+ }
267
+
268
+
269
+ public String[] keyArray(String[] outgoing) {
270
+ if (outgoing == null || outgoing.length != count) {
271
+ outgoing = new String[count];
272
+ }
273
+ System.arraycopy(keys, 0, outgoing, 0, count);
274
+ return outgoing;
275
+ }
276
+
277
+
278
+ public float value(int index) {
279
+ return values[index];
280
+ }
281
+
282
+
283
+ /**
284
+ * @webref floatdict:method
285
+ * @brief Return the internal array being used to store the values
286
+ */
287
+ public Iterable<Float> values() {
288
+ return new Iterable<Float>() {
289
+
290
+ @Override
291
+ public Iterator<Float> iterator() {
292
+ return valueIterator();
293
+ }
294
+ };
295
+ }
296
+
297
+
298
+ public Iterator<Float> valueIterator() {
299
+ return new Iterator<Float>() {
300
+ int index = -1;
301
+
302
+ public void remove() {
303
+ removeIndex(index);
304
+ index--;
305
+ }
306
+
307
+ public Float next() {
308
+ return value(++index);
309
+ }
310
+
311
+ public boolean hasNext() {
312
+ return index+1 < size();
313
+ }
314
+ };
315
+ }
316
+
317
+
318
+ /**
319
+ * Create a new array and copy each of the values into it.
320
+ *
321
+ * @webref floatdict:method
322
+ * @brief Create a new array and copy each of the values into it
323
+ */
324
+ public float[] valueArray() {
325
+ crop();
326
+ return valueArray(null);
327
+ }
328
+
329
+
330
+ /**
331
+ * Fill an already-allocated array with the values (more efficient than
332
+ * creating a new array each time). If 'array' is null, or not the same
333
+ * size as the number of values, a new array will be allocated and returned.
334
+ */
335
+ public float[] valueArray(float[] array) {
336
+ if (array == null || array.length != size()) {
337
+ array = new float[count];
338
+ }
339
+ System.arraycopy(values, 0, array, 0, count);
340
+ return array;
341
+ }
342
+
343
+
344
+ /**
345
+ * Return a value for the specified key.
346
+ *
347
+ * @webref floatdict:method
348
+ * @brief Return a value for the specified key
349
+ */
350
+ public float get(String key) {
351
+ int index = index(key);
352
+ if (index == -1) {
353
+ throw new IllegalArgumentException("No key named '" + key + "'");
354
+ }
355
+ return values[index];
356
+ }
357
+
358
+
359
+ public float get(String key, float alternate) {
360
+ int index = index(key);
361
+ if (index == -1) {
362
+ return alternate;
363
+ }
364
+ return values[index];
365
+ }
366
+
367
+
368
+ /**
369
+ * @webref floatdict:method
370
+ * @brief Create a new key/value pair or change the value of one
371
+ */
372
+ public void set(String key, float amount) {
373
+ int index = index(key);
374
+ if (index == -1) {
375
+ create(key, amount);
376
+ } else {
377
+ values[index] = amount;
378
+ }
379
+ }
380
+
381
+
382
+ public void setIndex(int index, String key, float value) {
383
+ if (index < 0 || index >= count) {
384
+ throw new ArrayIndexOutOfBoundsException(index);
385
+ }
386
+ keys[index] = key;
387
+ values[index] = value;
388
+ }
389
+
390
+
391
+ /**
392
+ * @webref floatdict:method
393
+ * @brief Check if a key is a part of the data structure
394
+ */
395
+ public boolean hasKey(String key) {
396
+ return index(key) != -1;
397
+ }
398
+
399
+
400
+ /**
401
+ * @webref floatdict:method
402
+ * @brief Add to a value
403
+ */
404
+ public void add(String key, float amount) {
405
+ int index = index(key);
406
+ if (index == -1) {
407
+ create(key, amount);
408
+ } else {
409
+ values[index] += amount;
410
+ }
411
+ }
412
+
413
+
414
+ /**
415
+ * @webref floatdict:method
416
+ * @brief Subtract from a value
417
+ */
418
+ public void sub(String key, float amount) {
419
+ add(key, -amount);
420
+ }
421
+
422
+
423
+ /**
424
+ * @webref floatdict:method
425
+ * @brief Multiply a value
426
+ */
427
+ public void mult(String key, float amount) {
428
+ int index = index(key);
429
+ if (index != -1) {
430
+ values[index] *= amount;
431
+ }
432
+ }
433
+
434
+
435
+ /**
436
+ * @webref floatdict:method
437
+ * @brief Divide a value
438
+ */
439
+ public void div(String key, float amount) {
440
+ int index = index(key);
441
+ if (index != -1) {
442
+ values[index] /= amount;
443
+ }
444
+ }
445
+
446
+
447
+ private void checkMinMax(String functionName) {
448
+ if (count == 0) {
449
+ String msg =
450
+ String.format("Cannot use %s() on an empty %s.",
451
+ functionName, getClass().getSimpleName());
452
+ throw new RuntimeException(msg);
453
+ }
454
+ }
455
+
456
+
457
+ /**
458
+ * @webref floatlist:method
459
+ * @brief Return the smallest value
460
+ */
461
+ public int minIndex() {
462
+ //checkMinMax("minIndex");
463
+ if (count == 0) return -1;
464
+
465
+ // Will still return NaN if there are 1 or more entries, and they're all NaN
466
+ float m = Float.NaN;
467
+ int mi = -1;
468
+ for (int i = 0; i < count; i++) {
469
+ // find one good value to start
470
+ if (values[i] == values[i]) {
471
+ m = values[i];
472
+ mi = i;
473
+
474
+ // calculate the rest
475
+ for (int j = i+1; j < count; j++) {
476
+ float d = values[j];
477
+ if ((d == d) && (d < m)) {
478
+ m = values[j];
479
+ mi = j;
480
+ }
481
+ }
482
+ break;
483
+ }
484
+ }
485
+ return mi;
486
+ }
487
+
488
+
489
+ // return the key for the minimum value
490
+ public String minKey() {
491
+ checkMinMax("minKey");
492
+ int index = minIndex();
493
+ if (index == -1) {
494
+ return null;
495
+ }
496
+ return keys[index];
497
+ }
498
+
499
+
500
+ // return the minimum value, or throw an error if there are no values
501
+ public float minValue() {
502
+ checkMinMax("minValue");
503
+ int index = minIndex();
504
+ if (index == -1) {
505
+ return Float.NaN;
506
+ }
507
+ return values[index];
508
+ }
509
+
510
+
511
+ /**
512
+ * @webref floatlist:method
513
+ * @brief Return the largest value
514
+ */
515
+ // The index of the entry that has the max value. Reference above is incorrect.
516
+ public int maxIndex() {
517
+ //checkMinMax("maxIndex");
518
+ if (count == 0) {
519
+ return -1;
520
+ }
521
+ // Will still return NaN if there is 1 or more entries, and they're all NaN
522
+ float m = Float.NaN;
523
+ int mi = -1;
524
+ for (int i = 0; i < count; i++) {
525
+ // find one good value to start
526
+ if (values[i] == values[i]) {
527
+ m = values[i];
528
+ mi = i;
529
+
530
+ // calculate the rest
531
+ for (int j = i+1; j < count; j++) {
532
+ float d = values[j];
533
+ if (!Float.isNaN(d) && (d > m)) {
534
+ m = values[j];
535
+ mi = j;
536
+ }
537
+ }
538
+ break;
539
+ }
540
+ }
541
+ return mi;
542
+ }
543
+
544
+
545
+ /** The key for a max value; null if empty or everything is NaN (no max). */
546
+ public String maxKey() {
547
+ //checkMinMax("maxKey");
548
+ int index = maxIndex();
549
+ if (index == -1) {
550
+ return null;
551
+ }
552
+ return keys[index];
553
+ }
554
+
555
+
556
+ /** The max value. (Or NaN if no entries or they're all NaN.) */
557
+ public float maxValue() {
558
+ //checkMinMax("maxValue");
559
+ int index = maxIndex();
560
+ if (index == -1) {
561
+ return Float.NaN;
562
+ }
563
+ return values[index];
564
+ }
565
+
566
+
567
+ public float sum() {
568
+ double amount = sumDouble();
569
+ if (amount > Float.MAX_VALUE) {
570
+ throw new RuntimeException("sum() exceeds " + Float.MAX_VALUE + ", use sumDouble()");
571
+ }
572
+ if (amount < -Float.MAX_VALUE) {
573
+ throw new RuntimeException("sum() lower than " + -Float.MAX_VALUE + ", use sumDouble()");
574
+ }
575
+ return (float) amount;
576
+ }
577
+
578
+
579
+ public double sumDouble() {
580
+ double sum = 0;
581
+ for (int i = 0; i < count; i++) {
582
+ sum += values[i];
583
+ }
584
+ return sum;
585
+ }
586
+
587
+
588
+ public int index(String what) {
589
+ Integer found = indices.get(what);
590
+ return (found == null) ? -1 : found.intValue();
591
+ }
592
+
593
+
594
+ protected void create(String what, float much) {
595
+ if (count == keys.length) {
596
+ keys = PApplet.expand(keys);
597
+ values = PApplet.expand(values);
598
+ }
599
+ indices.put(what, Integer.valueOf(count));
600
+ keys[count] = what;
601
+ values[count] = much;
602
+ count++;
603
+ }
604
+
605
+
606
+ /**
607
+ * @webref floatdict:method
608
+ * @brief Remove a key/value pair
609
+ */
610
+ public int remove(String key) {
611
+ int index = index(key);
612
+ if (index != -1) {
613
+ removeIndex(index);
614
+ }
615
+ return index;
616
+ }
617
+
618
+
619
+ public String removeIndex(int index) {
620
+ if (index < 0 || index >= count) {
621
+ throw new ArrayIndexOutOfBoundsException(index);
622
+ }
623
+ String key = keys[index];
624
+ //System.out.println("index is " + which + " and " + keys[which]);
625
+ indices.remove(keys[index]);
626
+ for (int i = index; i < count-1; i++) {
627
+ keys[i] = keys[i+1];
628
+ values[i] = values[i+1];
629
+ indices.put(keys[i], i);
630
+ }
631
+ count--;
632
+ keys[count] = null;
633
+ values[count] = 0;
634
+ return key;
635
+ }
636
+
637
+
638
+ public void swap(int a, int b) {
639
+ String tkey = keys[a];
640
+ float tvalue = values[a];
641
+ keys[a] = keys[b];
642
+ values[a] = values[b];
643
+ keys[b] = tkey;
644
+ values[b] = tvalue;
645
+
646
+ // indices.put(keys[a], Integer.valueOf(a));
647
+ // indices.put(keys[b], Integer.valueOf(b));
648
+ }
649
+
650
+
651
+ /**
652
+ * Sort the keys alphabetically (ignoring case). Uses the value as a
653
+ * tie-breaker (only really possible with a key that has a case change).
654
+ *
655
+ * @webref floatdict:method
656
+ * @brief Sort the keys alphabetically
657
+ */
658
+ public void sortKeys() {
659
+ sortImpl(true, false, true);
660
+ }
661
+
662
+
663
+ /**
664
+ * @webref floatdict:method
665
+ * @brief Sort the keys alphabetically in reverse
666
+ */
667
+ public void sortKeysReverse() {
668
+ sortImpl(true, true, true);
669
+ }
670
+
671
+
672
+ /**
673
+ * Sort by values in descending order (largest value will be at [0]).
674
+ *
675
+ * @webref floatdict:method
676
+ * @brief Sort by values in ascending order
677
+ */
678
+ public void sortValues() {
679
+ sortValues(true);
680
+ }
681
+
682
+
683
+ /**
684
+ * Set true to ensure that the order returned is identical. Slightly
685
+ * slower because the tie-breaker for identical values compares the keys.
686
+ * @param stable
687
+ */
688
+ public void sortValues(boolean stable) {
689
+ sortImpl(false, false, stable);
690
+ }
691
+
692
+
693
+ /**
694
+ * @webref floatdict:method
695
+ * @brief Sort by values in descending order
696
+ */
697
+ public void sortValuesReverse() {
698
+ sortValuesReverse(true);
699
+ }
700
+
701
+
702
+ public void sortValuesReverse(boolean stable) {
703
+ sortImpl(false, true, stable);
704
+ }
705
+
706
+
707
+ protected void sortImpl(final boolean useKeys, final boolean reverse,
708
+ final boolean stable) {
709
+ Sort s = new Sort() {
710
+ @Override
711
+ public int size() {
712
+ if (useKeys) {
713
+ return count; // don't worry about NaN values
714
+
715
+ } else if (count == 0) { // skip the NaN check, it'll AIOOBE
716
+ return 0;
717
+
718
+ } else { // first move NaN values to the end of the list
719
+ int right = count - 1;
720
+ while (values[right] != values[right]) {
721
+ right--;
722
+ if (right == -1) {
723
+ return 0; // all values are NaN
724
+ }
725
+ }
726
+ for (int i = right; i >= 0; --i) {
727
+ if (Float.isNaN(values[i])) {
728
+ swap(i, right);
729
+ --right;
730
+ }
731
+ }
732
+ return right + 1;
733
+ }
734
+ }
735
+
736
+ @Override
737
+ public float compare(int a, int b) {
738
+ float diff = 0;
739
+ if (useKeys) {
740
+ diff = keys[a].compareToIgnoreCase(keys[b]);
741
+ if (diff == 0) {
742
+ diff = values[a] - values[b];
743
+ }
744
+ } else { // sort values
745
+ diff = values[a] - values[b];
746
+ if (diff == 0 && stable) {
747
+ diff = keys[a].compareToIgnoreCase(keys[b]);
748
+ }
749
+ }
750
+ return reverse ? -diff : diff;
751
+ }
752
+
753
+ @Override
754
+ public void swap(int a, int b) {
755
+ FloatDict.this.swap(a, b);
756
+ }
757
+ };
758
+ s.run();
759
+
760
+ // Set the indices after sort/swaps (performance fix 160411)
761
+ resetIndices();
762
+ }
763
+
764
+
765
+ /**
766
+ * Sum all of the values in this dictionary, then return a new FloatDict of
767
+ * each key, divided by the total sum. The total for all values will be ~1.0.
768
+ * @return a FloatDict with the original keys, mapped to their pct of the total
769
+ */
770
+ public FloatDict getPercent() {
771
+ double sum = sum();
772
+ FloatDict outgoing = new FloatDict();
773
+ for (int i = 0; i < size(); i++) {
774
+ double percent = value(i) / sum;
775
+ outgoing.set(key(i), (float) percent);
776
+ }
777
+ return outgoing;
778
+ }
779
+
780
+
781
+ /** Returns a duplicate copy of this object. */
782
+ public FloatDict copy() {
783
+ FloatDict outgoing = new FloatDict(count);
784
+ System.arraycopy(keys, 0, outgoing.keys, 0, count);
785
+ System.arraycopy(values, 0, outgoing.values, 0, count);
786
+ for (int i = 0; i < count; i++) {
787
+ outgoing.indices.put(keys[i], i);
788
+ }
789
+ outgoing.count = count;
790
+ return outgoing;
791
+ }
792
+
793
+
794
+ public void print() {
795
+ for (int i = 0; i < size(); i++) {
796
+ System.out.println(keys[i] + " = " + values[i]);
797
+ }
798
+ }
799
+
800
+
801
+ /**
802
+ * Write tab-delimited entries out to
803
+ * @param writer
804
+ */
805
+ public void write(PrintWriter writer) {
806
+ for (int i = 0; i < count; i++) {
807
+ writer.println(keys[i] + "\t" + values[i]);
808
+ }
809
+ writer.flush();
810
+ }
811
+
812
+
813
+ /**
814
+ * Return this dictionary as a String in JSON format.
815
+ */
816
+ public String toJSON() {
817
+ StringList items = new StringList();
818
+ for (int i = 0; i < count; i++) {
819
+ items.append(JSONObject.quote(keys[i])+ ": " + values[i]);
820
+ }
821
+ return "{ " + items.join(", ") + " }";
822
+ }
823
+
824
+
825
+ @Override
826
+ public String toString() {
827
+ return getClass().getSimpleName() + " size=" + size() + " " + toJSON();
828
+ }
829
+ }