├── .gitattributes
├── .gitignore
├── LICENSE
├── README.md
├── example.png
├── examples
├── Animate
│ ├── Animate.pde
│ └── data
│ │ └── monkey.ndjson
└── Create
│ ├── Create.pde
│ └── data
│ └── monkey.ndjson
├── library.properties
├── library
└── QuickDraw.jar
├── logo.png
└── src
└── cbl
└── quickdraw
├── .classpath
├── .project
└── QuickDraw.java
/.gitattributes:
--------------------------------------------------------------------------------
1 | # Auto detect text files and perform LF normalization
2 | * text=auto
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | .DS_Store
2 | .AppleDouble
3 | ._*
4 | *~
5 | /build/shared/reference.zip
6 | .DS_Store
7 | .DS_Store
8 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | Apache License
2 | Version 2.0, January 2004
3 | http://www.apache.org/licenses/
4 |
5 | TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
6 |
7 | 1. Definitions.
8 |
9 | "License" shall mean the terms and conditions for use, reproduction,
10 | and distribution as defined by Sections 1 through 9 of this document.
11 |
12 | "Licensor" shall mean the copyright owner or entity authorized by
13 | the copyright owner that is granting the License.
14 |
15 | "Legal Entity" shall mean the union of the acting entity and all
16 | other entities that control, are controlled by, or are under common
17 | control with that entity. For the purposes of this definition,
18 | "control" means (i) the power, direct or indirect, to cause the
19 | direction or management of such entity, whether by contract or
20 | otherwise, or (ii) ownership of fifty percent (50%) or more of the
21 | outstanding shares, or (iii) beneficial ownership of such entity.
22 |
23 | "You" (or "Your") shall mean an individual or Legal Entity
24 | exercising permissions granted by this License.
25 |
26 | "Source" form shall mean the preferred form for making modifications,
27 | including but not limited to software source code, documentation
28 | source, and configuration files.
29 |
30 | "Object" form shall mean any form resulting from mechanical
31 | transformation or translation of a Source form, including but
32 | not limited to compiled object code, generated documentation,
33 | and conversions to other media types.
34 |
35 | "Work" shall mean the work of authorship, whether in Source or
36 | Object form, made available under the License, as indicated by a
37 | copyright notice that is included in or attached to the work
38 | (an example is provided in the Appendix below).
39 |
40 | "Derivative Works" shall mean any work, whether in Source or Object
41 | form, that is based on (or derived from) the Work and for which the
42 | editorial revisions, annotations, elaborations, or other modifications
43 | represent, as a whole, an original work of authorship. For the purposes
44 | of this License, Derivative Works shall not include works that remain
45 | separable from, or merely link (or bind by name) to the interfaces of,
46 | the Work and Derivative Works thereof.
47 |
48 | "Contribution" shall mean any work of authorship, including
49 | the original version of the Work and any modifications or additions
50 | to that Work or Derivative Works thereof, that is intentionally
51 | submitted to Licensor for inclusion in the Work by the copyright owner
52 | or by an individual or Legal Entity authorized to submit on behalf of
53 | the copyright owner. For the purposes of this definition, "submitted"
54 | means any form of electronic, verbal, or written communication sent
55 | to the Licensor or its representatives, including but not limited to
56 | communication on electronic mailing lists, source code control systems,
57 | and issue tracking systems that are managed by, or on behalf of, the
58 | Licensor for the purpose of discussing and improving the Work, but
59 | excluding communication that is conspicuously marked or otherwise
60 | designated in writing by the copyright owner as "Not a Contribution."
61 |
62 | "Contributor" shall mean Licensor and any individual or Legal Entity
63 | on behalf of whom a Contribution has been received by Licensor and
64 | subsequently incorporated within the Work.
65 |
66 | 2. Grant of Copyright License. Subject to the terms and conditions of
67 | this License, each Contributor hereby grants to You a perpetual,
68 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable
69 | copyright license to reproduce, prepare Derivative Works of,
70 | publicly display, publicly perform, sublicense, and distribute the
71 | Work and such Derivative Works in Source or Object form.
72 |
73 | 3. Grant of Patent License. Subject to the terms and conditions of
74 | this License, each Contributor hereby grants to You a perpetual,
75 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable
76 | (except as stated in this section) patent license to make, have made,
77 | use, offer to sell, sell, import, and otherwise transfer the Work,
78 | where such license applies only to those patent claims licensable
79 | by such Contributor that are necessarily infringed by their
80 | Contribution(s) alone or by combination of their Contribution(s)
81 | with the Work to which such Contribution(s) was submitted. If You
82 | institute patent litigation against any entity (including a
83 | cross-claim or counterclaim in a lawsuit) alleging that the Work
84 | or a Contribution incorporated within the Work constitutes direct
85 | or contributory patent infringement, then any patent licenses
86 | granted to You under this License for that Work shall terminate
87 | as of the date such litigation is filed.
88 |
89 | 4. Redistribution. You may reproduce and distribute copies of the
90 | Work or Derivative Works thereof in any medium, with or without
91 | modifications, and in Source or Object form, provided that You
92 | meet the following conditions:
93 |
94 | (a) You must give any other recipients of the Work or
95 | Derivative Works a copy of this License; and
96 |
97 | (b) You must cause any modified files to carry prominent notices
98 | stating that You changed the files; and
99 |
100 | (c) You must retain, in the Source form of any Derivative Works
101 | that You distribute, all copyright, patent, trademark, and
102 | attribution notices from the Source form of the Work,
103 | excluding those notices that do not pertain to any part of
104 | the Derivative Works; and
105 |
106 | (d) If the Work includes a "NOTICE" text file as part of its
107 | distribution, then any Derivative Works that You distribute must
108 | include a readable copy of the attribution notices contained
109 | within such NOTICE file, excluding those notices that do not
110 | pertain to any part of the Derivative Works, in at least one
111 | of the following places: within a NOTICE text file distributed
112 | as part of the Derivative Works; within the Source form or
113 | documentation, if provided along with the Derivative Works; or,
114 | within a display generated by the Derivative Works, if and
115 | wherever such third-party notices normally appear. The contents
116 | of the NOTICE file are for informational purposes only and
117 | do not modify the License. You may add Your own attribution
118 | notices within Derivative Works that You distribute, alongside
119 | or as an addendum to the NOTICE text from the Work, provided
120 | that such additional attribution notices cannot be construed
121 | as modifying the License.
122 |
123 | You may add Your own copyright statement to Your modifications and
124 | may provide additional or different license terms and conditions
125 | for use, reproduction, or distribution of Your modifications, or
126 | for any such Derivative Works as a whole, provided Your use,
127 | reproduction, and distribution of the Work otherwise complies with
128 | the conditions stated in this License.
129 |
130 | 5. Submission of Contributions. Unless You explicitly state otherwise,
131 | any Contribution intentionally submitted for inclusion in the Work
132 | by You to the Licensor shall be under the terms and conditions of
133 | this License, without any additional terms or conditions.
134 | Notwithstanding the above, nothing herein shall supersede or modify
135 | the terms of any separate license agreement you may have executed
136 | with Licensor regarding such Contributions.
137 |
138 | 6. Trademarks. This License does not grant permission to use the trade
139 | names, trademarks, service marks, or product names of the Licensor,
140 | except as required for reasonable and customary use in describing the
141 | origin of the Work and reproducing the content of the NOTICE file.
142 |
143 | 7. Disclaimer of Warranty. Unless required by applicable law or
144 | agreed to in writing, Licensor provides the Work (and each
145 | Contributor provides its Contributions) on an "AS IS" BASIS,
146 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
147 | implied, including, without limitation, any warranties or conditions
148 | of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
149 | PARTICULAR PURPOSE. You are solely responsible for determining the
150 | appropriateness of using or redistributing the Work and assume any
151 | risks associated with Your exercise of permissions under this License.
152 |
153 | 8. Limitation of Liability. In no event and under no legal theory,
154 | whether in tort (including negligence), contract, or otherwise,
155 | unless required by applicable law (such as deliberate and grossly
156 | negligent acts) or agreed to in writing, shall any Contributor be
157 | liable to You for damages, including any direct, indirect, special,
158 | incidental, or consequential damages of any character arising as a
159 | result of this License or out of the use or inability to use the
160 | Work (including but not limited to damages for loss of goodwill,
161 | work stoppage, computer failure or malfunction, or any and all
162 | other commercial damages or losses), even if such Contributor
163 | has been advised of the possibility of such damages.
164 |
165 | 9. Accepting Warranty or Additional Liability. While redistributing
166 | the Work or Derivative Works thereof, You may choose to offer,
167 | and charge a fee for, acceptance of support, warranty, indemnity,
168 | or other liability obligations and/or rights consistent with this
169 | License. However, in accepting such obligations, You may act only
170 | on Your own behalf and on Your sole responsibility, not on behalf
171 | of any other Contributor, and only if You agree to indemnify,
172 | defend, and hold each Contributor harmless for any liability
173 | incurred by, or claims asserted against, such Contributor by reason
174 | of your accepting any such warranty or additional liability.
175 |
176 | END OF TERMS AND CONDITIONS
177 |
178 | APPENDIX: How to apply the Apache License to your work.
179 |
180 | To apply the Apache License to your work, attach the following
181 | boilerplate notice, with the fields enclosed by brackets "[]"
182 | replaced with your own identifying information. (Don't include
183 | the brackets!) The text should be enclosed in the appropriate
184 | comment syntax for the file format. We also recommend that a
185 | file or class name and description of purpose be included on the
186 | same "printed page" as the copyright notice for easier
187 | identification within third-party archives.
188 |
189 | Copyright [yyyy] [name of copyright owner]
190 |
191 | Licensed under the Apache License, Version 2.0 (the "License");
192 | you may not use this file except in compliance with the License.
193 | You may obtain a copy of the License at
194 |
195 | http://www.apache.org/licenses/LICENSE-2.0
196 |
197 | Unless required by applicable law or agreed to in writing, software
198 | distributed under the License is distributed on an "AS IS" BASIS,
199 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
200 | See the License for the specific language governing permissions and
201 | limitations under the License.
202 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | 
2 | # Quick, Draw! for Processing
3 |
4 | Quick, Draw! for Processing is a [Processing](https://www.processing.org) library that makes it easy to interface with drawings from [Google's Quick, Draw!](https://quickdraw.withgoogle.com) experiment in your own coding sketches.
5 |
6 | I hope that it enables you to new types of open source art and design as it will for me. If you create something with this library, please let me know [by e-mail](mailto:cblewisnj@gmail.com?subject=I%20Made%20Something%20With%20Quick%20Draw%20for%20Processing) and consider passing it along to [Google](https://aiexperiments.withgoogle.com/submit).
7 |
8 | ## Content
9 |
10 | - [Getting Started](#getting-started)
11 | - [Installing](#installing)
12 | - [Using the Library](#using-the-library)
13 | - [Reference](#reference)
14 | - [create()](#create)
15 | - [mode()](#mode)
16 | - [align()](#align)
17 | - [info()](#info)
18 | - [length()](#length)
19 | - [points()](#points)
20 | - [curves()](#curves)
21 | - [noCurves()](#nocurves)
22 | - [Licenses](#licenses)
23 |
24 | # Getting Started
25 |
26 | To begin, you will need 3 things:
27 |
28 | 1. The latest version of Processing installed, which can be downloaded from [https://www.processing.org/download/](https://www.processing.org/download/).
29 | 2. A copy of this library on your desktop, which you can get by clicking on the download button at [https://github.com/codybenlewis/Quick-Draw-for-Processing](https://github.com/codybenlewis/Quick-Draw-for-Processing) and selecting one of the packages provided. After unzipping the folder, **rename it to "QuickDraw."** The library name needs to match that of the .jar source file inside and will not work with the default download name.
30 | 3. Simplified Drawing Files from [The Google Quick, Draw! Dataset](https://github.com/googlecreativelab/quickdraw-dataset), which can be downloaded from [https://console.cloud.google.com/storage/browser/quickdraw_dataset/full/simplified](https://console.cloud.google.com/storage/browser/quickdraw_dataset/full/simplified). Because of how the data is structured, this library will only work properly with these types of files.
31 |
32 | >**Simplified Drawing files (.ndjson)**
33 | >
34 | >We've simplified the vectors, removed the timing information, and positioned and scaled the data into a 256x256 region. The data is exported in ndjson format with the same metadata as the raw format. The simplification process was:
35 | >
36 | >1. Align the drawing to the top-left corner, to have minimum values of 0.
37 | >2. Uniformly scale the drawing, to have a maximum value of 255.
38 | >3. Resample all strokes with a 1 pixel spacing.
39 | >4. Simplify all strokes using the [Ramer–Douglas–Peucker algorithm](https://en.wikipedia.org/wiki/Ramer%E2%80%93Douglas%E2%80%93Peucker_algorithm) with an epsilon value of 2.0.
40 |
41 | ***Note** that previews of the data available on [the Quick, Draw site](https://quickdraw.withgoogle.com/data/) exclude drawings that were not recognized by machine learning or that may have been flagged as inappropriate by users. Those drawings are still available within the downloadable files, so trying to select specific drawings by referencing the site will potentially return different results or inappropriate content in your programs. For closer results you will have to manually edit local copies of the files to exclude falsely recognized drawings.*
42 |
43 | For convenience, this library's example folders already include truncated versions (1000/127,633 drawings) of the [monkey.ndjson](https://storage.googleapis.com/quickdraw_dataset/full/simplified/monkey.ndjson) file :monkey:.
44 |
45 | ## Installing
46 |
47 | Processing's official [library installation instructions](https://github.com/processing/processing/wiki/How-to-Install-a-Contributed-Library):
48 |
49 | >Contributed libraries may be downloaded separately and manually placed within the libraries folder of your Processing sketchbook. As a reminder, the sketchbook is where your sketches are saved. To find (and change) the Processing sketchbook location on your computer, open the Preferences window from the Processing application (PDE) and look for the "Sketchbook location" item at the top.
50 | >
51 | >Copy the contributed library's folder into the libraries folder at this location. You will need to create the libraries folder if this is your first contributed library.
52 | >
53 | >By default the following locations are used for your sketchbook folder. For Mac users the sketchbook folder is located inside `~/Documents/Processing`. For Windows users the sketchbook folder is located inside folder `Documents/Processing`.
54 | >
55 | >Let's say you downloaded a library with name theLibrary. Then the folder structure of this library inside the libraries folder should look like the one below. The top folder of a library must have the same name as the .jar file located inside a library's library folder (minus the .jar extension):
56 | >
57 | >```
58 | > Documents
59 | > Processing
60 | > your sketch folders
61 | > libraries
62 | > theLibrary
63 | > examples
64 | > library
65 | > theLibrary.jar
66 | > reference
67 | > src
68 | >```
69 | >
70 | >Some folders like examples or src might be missing. After a library has been successfully installed, **restart Processing application**.
71 |
72 | Please read the [the full documentation](https://github.com/processing/processing/wiki/How-to-Install-a-Contributed-Library) on how to install a contributed Library for additional information and troubleshooting tips.
73 |
74 | ## Using the Library
75 |
76 | Once you have finished downloading and installing the library, begin by opening up a new sketch (⌘-n) and importing the library to it.
77 |
78 | ```java
79 | import cbl.quickdraw.*;
80 | ```
81 |
82 | Afterwards, initialize a QuickDraw object from the class
83 |
84 | ```java
85 | QuickDraw qd;
86 | ```
87 |
88 | and call it within `void setup()` in order to construct it.
89 |
90 | ```java
91 | void setup() {
92 | qd = new QuickDraw(this, "filename.ndjson");
93 | }
94 | ```
95 |
96 | Between the double quotes, replace `filename.ndjson` with the actual name of your data file. In order to prevent a *NullPointerException* you'll need to make sure the data file you specify been added to your sketch's data folder before running the program.
97 |
98 | - From the menubar choose File → Add File...
99 | - Find and open your simplified data file
100 |
101 | By default, constructing the object will change the your sketch's `fill()` settings to `noFill()`. If you want to use filled shapes within your sketch, call the `fill()` function anywhere within `void setup()` or `void draw()` below the object's construction.
102 |
103 | That's it! You should be ready to start drawing.
104 |
105 | Now, let's create a simple test using the QuickDraw specific `create()` function within `void draw()`.
106 |
107 | ```
108 | void draw() {
109 | qd.create(width/2, height/2, width/2, height/2);
110 | }
111 | ```
112 |
113 | Run the program (⌘-r).
114 |
115 | Using the [monkey.ndjson](https://storage.googleapis.com/quickdraw_dataset/full/simplified/monkey.ndjson) data file, without any additional lines of code, it should look like:
116 |
117 |  Success! There are at least 127,000 more monkeys to choose from. What you do next with this Library is completely up to you.
118 |
119 | If you have trouble getting to this point, please make sure you've properly followed all the steps above. If it's still not working, contact me [by e-mail](mailto:cblewisnj@gmail.com?subject=Quick%20Draw%20for%20Processing%20Troubleshooting) with specififc details for help with troubleshooting.
120 |
121 | # Reference
122 |
123 | The QuickDraw class has 7 functions for intefacing with the drawing data.
124 |
125 | - [create()](#create)
126 | - [mode()](#mode)
127 | - [align()](#align)
128 | - [info()](#info)
129 | - [length()](#length)
130 | - [points()](#points)
131 | - [curves()](#curves)
132 | - [noCurves()](#nocurves)
133 |
134 | ## create()
135 |
136 | Draws a Google Quick, Draw! drawing to the screen. This function was modeled after Processing's built-in `ellipse()` and `rect()` functions. By default, the first two parameters set the location of the upper-left corner, the third sets the width, and the fourth sets the height. The way these parameters are interpreted, however, may be changed with the `mode()` function.
137 |
138 | The fifth parameter sets the index of the drawing you want to pull data from and is 0 by default. The sixth and seventh parameters set the start and stop position of the drawing and are respectively 0.0 and 1.0 by default.
139 |
140 | #### Syntax
141 |
142 | ```
143 | qd.create(x1, y1, x2, y2)
144 | qd.create(x1, y1, x2, y2, index)
145 | qd.create(x1, y1, x2, y2, index, stop)
146 | qd.create(x1, y1, x2, y2, index, start, stop)
147 | ```
148 |
149 | #### Parameters
150 |
151 | ```
152 | qd QuickDraw: a QuickDraw object
153 | x1 float: x-coordinate of the drawing by default
154 | y1 float: y-coordinate of the drawing by default
155 | x2 float: width of the drawing's bounding box by default
156 | y2 float: height of the drawing's bounding box by default
157 | index int: int between 0 and the object's source file length
158 | start float: float between 0.0 and 1.0
159 | stop float: float between 0.0 and 1.0
160 | ```
161 |
162 | ## mode()
163 |
164 | Modifies the location from which drawings are drawn by changing the way in which parameters given to `create()` are interpreted. This function was modeled after Processing's built-in `ellipseMode()` and `rectMode()` functions.
165 |
166 | The default mode is `mode(CENTER)`, which interprets the first two parameters of `create()` as the shape's center point, while the third and fourth parameters are its width and height.
167 |
168 | `mode(CORNER)` interprets the first two parameters of `create()` as the upper-left corner of the shape, while the third and fourth parameters are its width and height.
169 |
170 | `mode(CORNERS)` interprets the first two parameters of `create()` as the location of one corner, and the third and fourth parameters as the location of the opposite corner.
171 |
172 | The parameter must be written in ALL CAPS because Processing is a case-sensitive language. The built-in variables CENTER, CORNER, and CORNERS equate to the integers 3, 0, and 1 respectively, which can also be input as parameters.
173 |
174 | #### Syntax
175 |
176 | ```
177 | qd.mode(mode)
178 | ```
179 |
180 | #### Parameters
181 |
182 | ```
183 | qd QuickDraw: a QuickDraw object
184 | mode int: CENTER, CORNER, or CORNERS
185 | ```
186 |
187 | ## align()
188 | Modifies the alignment of how drawings are created within their bounding boxes. Controlling the interpretation of the box itself is done using the `mode()` function. This function was modeled after Processing's built-in `textAlign()` function.
189 |
190 | By default drawings have been aligned to their LEFT, TOP corner, scaled until reaching the first constraining border, RIGHT or BOTTOM. Drawings that are taller than they are wide take up the full height of the bounding box and cannot be aligned vertically. Drawings that are wider than they are tall take up the full width of the bounding box and cannot be aligned horizontally. Therefore, while both x and y properties are used, only one will appear active when compared to the original drawing.
191 |
192 | The parameter must be written in ALL CAPS because Processing is a case-sensitive language. The built-in variables LEFT, RIGHT, TOP, BOTTOM, and CENTER equate to the integers 37, 39, and 101, 102, and 3 respectively, which can also be input as parameters.
193 |
194 | #### Syntax
195 |
196 | ```
197 | qd.align(alignX)
198 | qd.align(alignX, alignY)
199 | ```
200 |
201 | #### Parameters
202 |
203 | ```
204 | qd QuickDraw: a QuickDraw object
205 | alignX int: LEFT, RIGHT, or CENTER
206 | alignY int: TOP, BOTTOM, or CENTER
207 | ```
208 |
209 | ## info()
210 |
211 | Returns a String of information about a specified drawing. By default, the function will return all available data on the drawing across multiple lines. Data points include what source file the drawing is found in, what index of the dataset the drawing is found on, how many points the drawing is made from, what word was the drawing is based on, what country the drawing is from, what date and time the drawing was originally created at, and whether or not the drawing was recognized by the machine when it was created.
212 |
213 | When using the String `"length"` as the data point, the function will return the amount of points in the drawing as a String. When using the String `"index"` as the data point, the function will return the index parameter as a String.
214 |
215 | #### Syntax
216 |
217 | ```
218 | qd.info(index)
219 | qd.info(index, "dataPoint")
220 | ```
221 |
222 | #### Parameters
223 |
224 | ```
225 | qd QuickDraw: a QuickDraw object
226 | index int: int between 0 and the object's source file length
227 | dataPoint String: "source", "index", "length", "word", "countrycode", "timestamp", or "recognized"
228 | ```
229 |
230 | ## length()
231 |
232 | Returns an integer amount of drawings in the dataset file or returns amount of lines used within a specific drawing. Used in `info()` to create the data point output as `"length"`.
233 |
234 | #### Syntax
235 |
236 | ```
237 | qd.length()
238 | qd.length(index)
239 | ```
240 |
241 | #### Parameters
242 |
243 | ```
244 | qd QuickDraw: a QuickDraw object
245 | index int: int between 0 and the object's source file length
246 | ```
247 |
248 | ## points()
249 |
250 | Returns an integer amount of points in a specific drawing or returns the amount of points in one of the lines of a specific drawing. Used in `info()` to create the data point output as `"length"`.
251 |
252 | #### Syntax
253 |
254 | ```
255 | qd.points(index)
256 | qd.points(index, line)
257 | ```
258 |
259 | #### Parameters
260 |
261 | ```
262 | qd QuickDraw: a QuickDraw object
263 | index int: int between 0 and the object's source file length
264 | line int: int between 0 and the value of (qd.info(index) - 1)
265 | ```
266 |
267 | ## curves()
268 |
269 | Enables the default geometry used to smooth the lines drawn on screen within `create()`. Note that this behavior is active by default, so it only necessary to call the function to reactivate the behavior after calling `noCurves()`.
270 |
271 | #### Syntax
272 |
273 | ```
274 | qd.curves()
275 | ```
276 |
277 | #### Parameters
278 |
279 | ```
280 | qd QuickDraw: a QuickDraw object
281 | ```
282 |
283 | ## noCurves()
284 |
285 | Disables the default geometry used to smooth the lines drawn on screen via `create()`. Note that `curves()` is active by default, so it is necessary to call `noCurves()` to disable smoothing of lines.
286 |
287 | #### Syntax
288 |
289 | ```
290 | qd.noCurves()
291 | ```
292 |
293 | #### Parameters
294 |
295 | ```
296 | qd QuickDraw: a QuickDraw object
297 | ```
298 |
299 | # Licenses
300 | Licensed under the Apache License, Version 2.0 (the "License");
301 | you may not use this file except in compliance with the License.
302 | You may obtain a copy of the License at
303 |
304 | http://www.apache.org/licenses/LICENSE-2.0
305 |
306 | Unless required by applicable law or agreed to in writing, software
307 | distributed under the License is distributed on an "AS IS" BASIS,
308 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
309 | See the License for the specific language governing permissions and
310 | limitations under the License.
311 |
312 |
313 | The Google Quick, Draw! data has been made available by Google, Inc. under the [Creative Commons Attribution 4.0 International license.](https://creativecommons.org/licenses/by/4.0/)
314 |
--------------------------------------------------------------------------------
/example.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/codybenlewis/quick-draw-for-processing/9347fcce1343c7d8a1e66b9a7c8449c62a93cd87/example.png
--------------------------------------------------------------------------------
/examples/Animate/Animate.pde:
--------------------------------------------------------------------------------
1 | // Import the Quick Draw For Processing Library
2 | import cbl.quickdraw.*;
3 |
4 | // Initialize a QuickDraw object from the library
5 | QuickDraw qd;
6 |
7 | float end, x;
8 |
9 | void setup() {
10 | size(400, 400);
11 |
12 | // We pass "this" to QuickDraw so that it can load files from the
13 | // data directory
14 |
15 | qd = new QuickDraw(this, "monkey.ndjson");
16 | }
17 |
18 | void draw() {
19 | background(255);
20 |
21 | float scale = height/2;
22 |
23 | endUpdate();
24 | qd.create(width/2, height/2, scale, scale, end);
25 | }
26 |
27 | // Update end back and forth between 0 and 1
28 |
29 | void endUpdate() {
30 | float inc = .01;
31 | end = abs(sin(x));
32 | x = x + inc;
33 | }
--------------------------------------------------------------------------------
/examples/Create/Create.pde:
--------------------------------------------------------------------------------
1 | // Import the Quick Draw For Processing Library
2 | import cbl.quickdraw.*;
3 |
4 | // Initialize a QuickDraw object from the library
5 | QuickDraw qd;
6 |
7 | void setup() {
8 | size(400, 400);
9 |
10 | // We pass "this" to QuickDraw so that it can load files from the
11 | // data directory
12 |
13 | qd = new QuickDraw(this, "monkey.ndjson");
14 | }
15 |
16 | void draw() {
17 | background(255);
18 |
19 | int divisor = 8;
20 | float scale = width/divisor*.75;
21 | int index = 0;
22 |
23 | // Increments the coordinates of the drawing
24 | // Draws the drawing to the screen
25 | // Increments the index for which drawing's data is used
26 |
27 | for (int i = 1; i < divisor; i++) {
28 | for (int j = 1; j < divisor; j++) {
29 | qd.create(width/divisor*i, width/divisor*j, scale, scale, index);
30 | index++;
31 | }
32 | }
33 | }
--------------------------------------------------------------------------------
/library.properties:
--------------------------------------------------------------------------------
1 | name = Quick Draw for Processing
2 | authors = [Cody Ben Lewis](http://codybenlewis.com)
3 | url = http://codybenlewis.com/Quick-Draw-for-Processing
4 | categories = Data
5 | sentence = A Processing library that makes it easy to interface drawings from the Google Quick, Draw! data set in your own sketches.
6 | paragraph =
7 | version = 1
8 | prettyVersion = 1.0.1
9 | minRevision = 0
10 | maxRevision = 0
11 |
--------------------------------------------------------------------------------
/library/QuickDraw.jar:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/codybenlewis/quick-draw-for-processing/9347fcce1343c7d8a1e66b9a7c8449c62a93cd87/library/QuickDraw.jar
--------------------------------------------------------------------------------
/logo.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/codybenlewis/quick-draw-for-processing/9347fcce1343c7d8a1e66b9a7c8449c62a93cd87/logo.png
--------------------------------------------------------------------------------
/src/cbl/quickdraw/.classpath:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/src/cbl/quickdraw/.project:
--------------------------------------------------------------------------------
1 |
2 |
3 | quickdraw
4 |
5 |
6 |
7 |
8 |
9 | org.eclipse.jdt.core.javabuilder
10 |
11 |
12 |
13 |
14 |
15 | org.eclipse.jdt.core.javanature
16 |
17 |
18 |
--------------------------------------------------------------------------------
/src/cbl/quickdraw/QuickDraw.java:
--------------------------------------------------------------------------------
1 | package cbl.quickdraw;
2 | import processing.core.*;
3 | import processing.data.*;
4 |
5 | /////////////////////////////////////////////////////////////////
6 |
7 | /**
8 | * A Processing library that makes it easy to interface with drawings from Google's
9 | * Quick, Draw! Experiment dataset in your own sketches.
10 | *
11 | * @example
12 | */
13 |
14 | public class QuickDraw {
15 |
16 | // myParent is a reference to the parent sketch
17 |
18 | PApplet parent;
19 |
20 | String[] source;
21 | String path;
22 |
23 | JSONObject object;
24 | JSONArray array;
25 |
26 | /* An integer CORNER, CORNERS, or CENTER (0, 1, or 3) that specifies how to interpret
27 | * the x1, y1, x2, and y2 data within the `create()` function
28 | */
29 |
30 | int modeSet;
31 |
32 | /* An integer LEFT, RIGHT, or CENTER (37, 39, or 3) that specifies how to modify
33 | * the x1 and x2 data within the `create()` function after being interpreted by the
34 | * `modeSet()` function
35 | */
36 |
37 | int alignXSet;
38 |
39 | /* An integer TOP, BOTTOM, or CENTER (101, 102, or 3) that specifies how to modify
40 | * the y1 and y2 data within the `create()` function after being interpreted by the
41 | * `modeSet()` function
42 | */
43 |
44 | int alignYSet;
45 |
46 | /* An integer not found in any the Google QuickDraw data used to determine the end
47 | * of a stroke in a drawing
48 | */
49 |
50 | int marker = -1;
51 |
52 | /* A boolean used to maintain the way the lines are drawn with or without the
53 | * curveVertex() function. Updated by the curves() and noCurves() functions
54 | */
55 |
56 | boolean curves = true;
57 |
58 | public QuickDraw (PApplet p, String s) {
59 |
60 | parent = p;
61 |
62 | // A Google QuickDraw data file path
63 |
64 | path = s;
65 |
66 | /* Loads all the lines in the file as strings so that each object can be processed
67 | * individually.
68 | */
69 |
70 | source = parent.loadStrings(path);
71 |
72 | // Makes noFill the default drawing mode if no no other is specified in the sketch
73 |
74 | parent.noFill();
75 |
76 | // Sets the default position interpretation to CENTER
77 |
78 | modeSet = PConstants.CENTER;
79 |
80 | // Sets the default drawing alignment interpretation to LEFT and TOP
81 | alignXSet = PConstants.LEFT;
82 | alignYSet = PConstants.TOP;
83 |
84 | // Loads the data for the default index;
85 |
86 | load(0);
87 | }
88 |
89 |
90 | /////////////////////////////////////////////////////////////////
91 |
92 |
93 | /**
94 | * Draws a Google Quick, Draw! drawing to the screen. This function was modeled
95 | * after Processing's built in ellipse() and rect() functions. By default, the
96 | * first two parameters set the location of the upper-left corner, the third sets
97 | * the width, and the fourth sets the height. The way these parameters are interpreted,
98 | * however, may be changed with the mode() function.
99 | *
100 | * The fifth parameter sets the index of the drawing you want to pull data from and
101 | * is 0 by default. The sixth and seventh parameters set the start and stop position
102 | * of the drawing and are respectively 0.0 and 1.0 by default.
103 | *
104 | * @example
105 | *
106 | * @param x1 float: x-coordinate of the drawing by default
107 | * @param y1 float: y-coordinate of the drawing by default
108 | * @param x2 float: width of the drawing's bounding box by default
109 | * @param y2 float: height of the drawing's bounding box by default
110 | * @param index int: int between 0 and the object's source file length
111 | * @param start float: float between 0.0 and 1.0
112 | * @param stop float: float between 0.0 and 1.0
113 | */
114 |
115 | public void create(float x1, float y1, float x2, float y2, int index, float start, float stop) {
116 |
117 | // Loads the data for the specified index of the QuickDraw data
118 |
119 | load(index);
120 |
121 | /* Updates the x1, x2, y1, and y2 values adjust for different drawing modes.
122 | * The default mode is CENTER.
123 | */
124 |
125 | if (modeSet != PConstants.CENTER) {
126 | if (modeSet == PConstants.CORNER) {
127 | x1 += x2/2;
128 | y1 += y2/2;
129 | } else if (modeSet == PConstants.CORNERS) {
130 | x2 = x2 - x1;
131 | y2 = y2 - y1;
132 | x1 += x2/2;
133 | y1 += y2/2;
134 | }
135 | }
136 |
137 | /* Creates arrays to store the combined coordinates of a drawing. This allows the
138 | * drawing loop to simulate a more natural drawing process: One complete line at
139 | * a time at a time instead of piece by piece of every line all at once.
140 | */
141 |
142 | int[] xConcat = new int[0];
143 | int[] yConcat = new int[0];
144 |
145 | // Loops through all the strokes of an individual drawing
146 |
147 | for (int j=0; j < array.size(); j++) {
148 |
149 | /* Creates an JSONarray containing the x and y values of a specified stroke within
150 | * of the the outer array data, "array".
151 | */
152 |
153 | JSONArray values = array.getJSONArray(j);
154 |
155 | /* Creates an integer array out of the x values (0 index) and the y values
156 | * (1 index) of the JSON array "values"
157 | */
158 |
159 | int[] xint = values.getJSONArray(0).getIntArray();
160 | int[] yint = values.getJSONArray(1).getIntArray();
161 |
162 | /* Adds an identifying character/integer after every stroke's completion. This
163 | * character acts as a marker for splitting the drawing of the concatenated array
164 | * into multiple lines.
165 | */
166 |
167 | xint = PApplet.append(xint, marker);
168 | yint = PApplet.append(yint, marker);
169 |
170 | // Adds the finished data to the "xConcat" and "yConcat" array
171 |
172 | xConcat = PApplet.concat(xConcat, xint);
173 | yConcat = PApplet.concat(yConcat, yint);
174 | }
175 |
176 | /* Modifies the start and end position of the drawing based on a 0.0 - 1.0 float
177 | * value percentage provided by the user.
178 | */
179 |
180 | int startAmt = PApplet.round(PApplet.map(start, 0, 1, 0, xConcat.length));
181 | int stopAmt = PApplet.round(PApplet.map(stop, 0, 1, 0, xConcat.length));
182 |
183 | // Iterates a continuous shapes from every point of the concatenated arrays.
184 |
185 | parent.beginShape();
186 |
187 | for (int k = startAmt; k < stopAmt; k++) {
188 |
189 |
190 | /* Determine the difference between the largest x and y values and the edges of
191 | * the bounding box used for padding the different sides of the bounding box to
192 | * realign the drawing inside.
193 | */
194 |
195 | float alignSpaceX = 255 - PApplet.max(xConcat);
196 | float alignSpaceY = 255 - PApplet.max(yConcat);
197 |
198 | /* Stores the x values and re-maps it to the input scale. The simplified data files
199 | * come stored in 255 by 255 coordinate squares. The marker character in xConcat is
200 | * excluded from re-mapping so that it remains unmodified and can be properly used
201 | * below to identify the end of a line.
202 | */
203 |
204 | float x;
205 | x = xConcat[k];
206 | if (x != -1) {
207 | if (alignXSet == PConstants.RIGHT) {
208 | x += alignSpaceX;
209 | } else if (alignXSet == PConstants.CENTER) {
210 | x += (alignSpaceX/2);
211 | }
212 | x = PApplet.map(x, 0, 255, -x2/2, x2/2);
213 | }
214 |
215 | /* Stores the y value and re-maps it to the input scale.The simplified data files
216 | * come stored in 255 by 255 coordinate squares.
217 | */
218 |
219 | float y;
220 | y = yConcat[k];
221 |
222 | if (alignYSet == PConstants.BOTTOM) {
223 | y += alignSpaceY;
224 | } else if (alignYSet == PConstants.CENTER) {
225 | y += (alignSpaceY/2);
226 | }
227 | y = PApplet.map(y, 0, 255, -y2/2, y2/2);
228 |
229 | /* Closes the current drawing and begins a new one for the next line when the
230 | * x coordinate or y coordinate is the marker character/integer. Also Draws
231 | * 2 curveVertex() points at the start and end of a line since the first and last
232 | * points in a series of curveVertex() lines are be used to guide the beginning
233 | * and end of a curve. Prevents out of bounds errors by excluding the start
234 | * and end of the xConcat array which by default is the start and end of a line
235 | */
236 |
237 | if (xConcat[k] != marker) {
238 | if (curves == false) {
239 | parent.vertex(x + x1, y + y1);
240 | } else {
241 | if (k == startAmt || k == stopAmt) {
242 | parent.curveVertex(x + x1, y + y1);
243 | parent.curveVertex(x + x1, y + y1);
244 | } else {
245 | if (xConcat[k+1] == marker || xConcat[k-1] == marker) {
246 | parent.curveVertex(x + x1, y + y1);
247 | parent.curveVertex(x + x1, y + y1);
248 | } else {
249 | parent.curveVertex(x + x1, y + y1);
250 | }
251 | }
252 | }
253 | } else {
254 | parent.endShape();
255 | parent.beginShape();
256 | }
257 | }
258 |
259 | // Finishes drawing whatever the last stroke was
260 |
261 | parent.endShape();
262 | }
263 |
264 |
265 | /* The 5 overload additional functions below provide more convenient options for the
266 | * user so that not every input of the main create() function is required. They take
267 | * the same types of inputs as the main function. The minimum input one can provide in
268 | * any circumstance is x1, y1, x2 (width), and y2 (height)*/
269 |
270 | public void create(float x1, float y1, float x2, float y2,
271 | int index, float stop) {
272 | create(x1, y1, x2, y2, index, 0, stop);
273 | }
274 |
275 |
276 | public void create(float x1, float y1, float x2, float y2,
277 | float start, float stop) {
278 | create(x1, y1, x2, y2, 0, start, stop);
279 | }
280 |
281 |
282 | public void create(float x1, float y1, float x2, float y2,
283 | int index) {
284 | create(x1, y1, x2, y2, index, 0, 1);
285 | }
286 |
287 |
288 | public void create(float x1, float y1, float x2, float y2,
289 | float stop) {
290 | create(x1, y1, x2, y2, 0, 0, stop);
291 | }
292 |
293 |
294 | public void create(float x1, float y1, float x2, float y2) {
295 | create(x1, y1, x2, y2, 0, 0, 1);
296 | }
297 |
298 |
299 | /////////////////////////////////////////////////////////////////
300 |
301 |
302 | /**
303 | * Modifies the location from which drawings are drawn by changing the way in which
304 | * parameters given to create() are interpreted. This function was modeled after
305 | * Processing's built in ellipseMode() and rectMode() functions. The default mode
306 | * is mode(CENTER), which interprets the first two parameters of create() as
307 | * the shape's center point, while the third and fourth parameters are its width and
308 | * height.
309 | *
310 | * mode(CORNER) interprets the first two parameters of rect() as the upper-left
311 | * corner of the shape, while the third and fourth parameters are its width and height.
312 | *
313 | * mode(CORNERS) interprets the first two parameters of rect() as the location
314 | * of one corner, and the third and fourth parameters as the location of the opposite
315 | * corner.
316 | *
317 | * The parameter must be written in ALL CAPS because Processing is a case-sensitive
318 | * language. The built in variables CENTER, CORNER, and CORNERS equate to the integers
319 | * 3, 0, and 1 respectively, which can also be input as parameters.
320 | *
321 | * @param mode int: CENTER, CORNER, or CORNERS
322 | */
323 |
324 |
325 | public void mode(int mode) {
326 | modeSet = mode;
327 | }
328 |
329 |
330 | /////////////////////////////////////////////////////////////////
331 |
332 |
333 | /**
334 | * Modifies the alignment of how drawings are created within their bounding boxes.
335 | * Controlling the interpretation of the box itself is done using the mode() function.
336 | * This function was modeled after Processing's built in textAlign() function.
337 | *
338 | * By default drawings have been aligned to their LEFT, TOP corner, scaled
339 | * until reaching the first constraining border, RIGHT or BOTTOM. Drawings that are
340 | * taller than they are wide take up the full height of the bounding box and cannot
341 | * be aligned vertically. Drawings that are wider than they are tall take up the full
342 | * width of the bounding box and cannot be aligned horizontally. Therefore, while both
343 | * X and Y properties are used, only one will appear active when compared to
344 | * the original drawing.
345 | *
346 | * The parameter must be written in ALL CAPS because Processing is a case-sensitive
347 | * language. The built in variables LEFT, RIGHT, TOP, BOTTOM, and CENTER equate to
348 | * the integers 37, 39, and 101, 102, and 3 respectively, which can also be input as
349 | * parameters.
350 | *
351 | * @param alignX int: LEFT, RIGHT, or CENTER
352 | * @param alignY int: TOP, BOTTOM, or CENTER
353 | */
354 |
355 |
356 | public void align(int alignX, int alignY) {
357 | alignXSet = alignX;
358 | alignYSet = alignY;
359 | }
360 |
361 |
362 | public void align(int alignX) {
363 | alignXSet = alignX;
364 | alignYSet = PConstants.TOP;
365 | }
366 |
367 |
368 | /////////////////////////////////////////////////////////////////
369 |
370 |
371 | /**
372 | * Returns a String of information about a specified drawing. By default, the function
373 | * will return all available data on the drawing across multiple lines. Data points
374 | * include what source file the drawing is found in, what index of the dataset the
375 | * drawing is found on, how many points the drawing is made from, what word was the
376 | * drawing is based on, what country the drawing is from, and what date and time the
377 | * drawing was originally created atwhat date and time the drawing was originally created
378 | * at, and whether or not the drawing was recognized by the machine when it was created.
379 | *
380 | * When using the string "length" as the data point, the function will return the
381 | * amount of points in the drawing as a String. When using the string "index" as the data
382 | * point, the function will return the index parameter as a String.
383 | *
384 | * @param index int: int between 0 and the object's source file length
385 | * @param dataPoint str: "source", "index", "length", "word", "countrycode", "timestamp", or "recognized"
386 | * @return String
387 | */
388 |
389 |
390 | /* Java was used in String conversations within the info() function to prevent
391 | * warnings created from using non-static methods.
392 | */
393 |
394 | public String info(int index, String dataPoint) {
395 |
396 | // Loads the data information of the input index
397 |
398 | object = parent.parseJSONObject(source[index]);
399 |
400 | String word = object.getString("word");
401 | String countrycode = object.getString("countrycode");
402 | String timestamp = object.getString("timestamp");
403 | String recognized = String.valueOf(object.getBoolean("recognized"));
404 |
405 | String d = dataPoint.toLowerCase();
406 |
407 | if (d.equals("") == true
408 | || d.equals(" ") == true
409 | || d.equals("all") == true) {
410 | return ("source: " + path
411 | + "\nindex: " + index + " of " + length()
412 | + "\nlength: " + length(index) + " lines / " + points(index) + " points"
413 | + "\nword: " + word
414 | + "\ncountrycode: " + countrycode
415 | + "\ntimestamp: " + timestamp
416 | + "\nrecognized: " + recognized);
417 | } else if (d.equals("index") == true
418 | || d.equals("line") == true
419 | || d.equals("0") == true) {
420 | return(String.valueOf(index));
421 | } else if (d.equals("source") == true
422 | || d.equals("path") == true
423 | || d.equals("file") == true
424 | || d.equals("1") == true) {
425 | return(path);
426 | } else if (d.equals("word") == true
427 | || d.equals("2") == true) {
428 | return(word);
429 | } else if (d.equals("countrycode") == true
430 | || d.equals("country") == true
431 | || d.equals("code") == true
432 | || d.equals("3") == true) {
433 | return(countrycode);
434 | } else if (d.equals("timestamp") == true
435 | || d.equals("time") == true
436 | || d.equals("stamp") == true
437 | || d.equals("4") == true) {
438 | return(timestamp);
439 | } else if (d.equals("length") == true
440 | || d.equals("5") == true) {
441 | return(String.valueOf(length((index))));
442 | } else if (d.equals("recognized") == true
443 | || d.equals("6") == true) {
444 | return(recognized);
445 | } else {
446 | return ("Unrecognized String Parameter"
447 | + "\nTry using \"source\", "
448 | + "\"index\", "
449 | + "\"length\", "
450 | + "\"word\", "
451 | + "\"countrycode\", "
452 | + "\"timestamp\", "
453 | + "or \"recognized\"");
454 | }
455 | }
456 |
457 |
458 | public String info(int index) {
459 | return(info(index, " "));
460 | }
461 |
462 |
463 | /////////////////////////////////////////////////////////////////
464 |
465 |
466 | /**
467 | * Returns an integer amount of drawings in the dataset file or returns amount of
468 | * lines used within a specific drawing. Used in `info()` to create the data point
469 | * output as `"length"`.
470 | *
471 | * @param index int: int between 0 and the object's source file length
472 | *
473 | * @return int
474 | */
475 |
476 | public int length(int index) {
477 |
478 | /* Repeats logic from the create() and length() functions in order to build arrays
479 | * of x coordinates that can be used to measure the length of drawing "i" without
480 | * actually drawing it on screen.
481 | */
482 |
483 | load(index);
484 |
485 | int[] concat = new int[0];
486 |
487 | for (int j=0; j < array.size(); j++) {
488 |
489 | JSONArray values = array.getJSONArray(j);
490 | int[] xint = values.getJSONArray(0).getIntArray();
491 | concat = PApplet.concat(concat, xint);
492 | }
493 |
494 | return array.size();
495 | }
496 |
497 |
498 | public int length() {
499 | return(source.length -1);
500 | }
501 |
502 |
503 | /////////////////////////////////////////////////////////////////
504 |
505 |
506 | /**
507 | * Returns an integer amount of points in a specific drawing or returns the amount of
508 | * points in one of the lines of a specific drawing. Used in `info()` to create the
509 | * data point output as `"length"`.
510 | *
511 | * @param index int: int between 0 and the object's source file length
512 | * @param line int: int between 0 and the value of (qd.info(index) - 1)
513 | *
514 | * @return int
515 | */
516 |
517 | public int points(int index, int line) {
518 |
519 | load(index);
520 |
521 | // Obtains data directly from the specified line and measures the size of the line.
522 |
523 | JSONArray values = array.getJSONArray(line);
524 | int[] xint = values.getJSONArray(0).getIntArray();
525 | return xint.length;
526 | }
527 |
528 |
529 | public int points(int index) {
530 |
531 | load(index);
532 |
533 | int[] concat = new int[0];
534 |
535 | for (int j=0; j < array.size(); j++) {
536 |
537 | JSONArray values = array.getJSONArray(j);
538 | int[] xint = values.getJSONArray(0).getIntArray();
539 | concat = PApplet.concat(concat, xint);
540 | }
541 |
542 | return concat.length;
543 | }
544 |
545 |
546 | /////////////////////////////////////////////////////////////////
547 |
548 |
549 | /**
550 | * Enables the default geometry used to smooth the lines drawn on screen within
551 | * create(). Note that this behavior is active by default, so it only necessary to call
552 | * the function to reactivate the behavior after calling noCurves().
553 | */
554 |
555 | public void curves() {
556 | curves = true;
557 | }
558 |
559 |
560 | /////////////////////////////////////////////////////////////////
561 |
562 |
563 | /**
564 | * Disables the default geometry used to smooth the lines drawn on screen via create().
565 | * Note that curves() is active by default, so it is necessary to call noCurves() to
566 | * disable smoothing of lines.
567 | */
568 |
569 | public void noCurves() {
570 | curves = false;
571 | }
572 |
573 |
574 | /////////////////////////////////////////////////////////////////
575 |
576 |
577 | /**
578 | * Resets and reloads data information from the source file in order
579 | *
580 | * @param index
581 | */
582 |
583 | private void load(int index) {
584 |
585 | // Loads the data information of the input index
586 |
587 | object = parent.parseJSONObject(source[index]);
588 |
589 | // Processes each line's JSON object and isolate the "drawing" data from the array
590 |
591 | array = object.getJSONArray("drawing");
592 | }
593 | }
594 |
--------------------------------------------------------------------------------