Friday, April 2, 2010

Processing.js – Irregular Apocalypse

Surprise

Just as aliens seek to strike suddenly and disappear before X-COM arrives, so to does this blog arise inexorably from the deeps to... do something and go... somewhere before... Well, perhaps that wasn't such an apt comparison after all.

Nonetheless, it returns with tardy tidings of the past and elusive glimpses of the future.

The Light of Ancient Days: Release 0.7

0.7 was not particularly exciting. The only real coding I did was for ticket #156, which converted the contents of a file into a byte array (actually an array of numbers). This effectively piggy-backed off of the preexisting ajax helper function, which returned the contents of a file as a string. From there each char was converted into a number via String::charCodeAt().



From release 0.6 one may recall how I noticed a little problem concerning the automatic conversion of character arguments into numbers, making it very difficult to pass chars into functions.

Not able to bring myself to let it pass, I took a crack at it. Indeed, the fix seemed simple: remove these two lines from the parser:
// Force characters-as-bytes to work.
aCode = aCode.replace(/('(.){1}')/g, "$1.charCodeAt(0)");

With those lines removed, the tests came back green and it seemed that particular beast was on its way into the cage. But you know what they say about things that seems too easy.

Corban was quick to show that we still needed the auto-conversion facility and if something was to be done, removing those two lines was definitely not the end of the story. Within six hours, he'd come up with a much craftier solution: a Char class. Now, functions could check if an argument was of type Char and act accordingly. Problem solved!



Along the way, Anna poked me to take a look at ticket #360, noting that in this example the yellow letters were appearing white. This was due to the char-to-int conversion issue, and when that was solved, #360 was resolved without any additional work.



All's well that ends well, yes?

A More Recent Note: Release 0.8

The ride on the 0.8 line started innocently enough with the conversion of some visual tests into unit tests. Two failing tests for binary() had to be corrected. One was caused from an incorrect comparison value (Pjs was otherwise returning the right value). The second error was fixed by converting binary() to detect objects of type Char. Along the way boolean() was changed to throw errors on invalid arguments, instead of returning undefined.



There was a short stop at ticket #269, concerning whether or not a cloned ArrayList should contain deep copies of items contained in the original. Processing uses Java's ArrayList, which does not deep copy. Since Pjs' ArrayList already conformed to this, the ticket was resolved as invalid.



A rather longer stop was for printMatrix(). printMatrix() outputs the current transformation matrix to the console. Work started in 0.7 but at the time it only worked when Pjs was working in a 3D context. Why? Because Pjs handles the 3D matrix itself, courtesy of PMatrix3D, and so the values of the 3D transformation matrix were readily accessible. When working in the 2D context, Pjs used canvas' internal matrix. This worked very well, except there was no way to retrieve the values of canvas' transformation matrix, and so there was nothing for printMatrix() to print.



printMatrix() was ultimately made ready for 0.8, thanks to work on a new and wonderful class...

PMatrix2D

During a phone conference in early March I proposed the creation of PMatrix2D to get printMatrix() going. This meant replicating everything canvas already did just to be able to get the transformation matrix values. I was hoping I was missing something and that there was another, easier way, but apparently there was not. At the end of March the green light was given to cobble together PMatrix2D. Maybe the canvas API will be expanded in the future to allow the values to be retrieved.

Choosing where to start implementing PMatrix2D for release 0.8 was easy: I coded just what was needed to convert the existing PMatrix3D and PMatrix3DStack tests and examples into their 2D equivalents.

Rather than creating a new PMatrix2DStack class, it was easier to transform PMatrix3DStack into PMatrixStack which handled both 2D and 3D matrices.



Toward Release 0.9 and 1.0

Things seem pretty clear cut from here on in. For 0.9 I hope to finish off implementing the rest of PMatrix2D's functions. 1.0 will aim to get Pjs actually using it.

Monday, February 15, 2010

Processing.js – Some bits for 0.6 in time for midterm season

The Foundations of the Universe are based upon certain Truths, like: as the time to March break/reading week approaches zero, the frequency of exams and due dates sky rocket. Coincidence? There's got to be a formal proof somewhere on the Internet...

But before the coming crunch time gets real bad, is 0.6! From a developer's standpoint, the big improvement for 0.6 is unit testing. Now, just testing return values no longer requires cobbling together a full Processing program, and the tests may be more easily reused and modified by other developers. Yes, this means “pretty pictures" will appear far less frequently now., but on the whole is that really a bad thing? (Using canvas and Processing just to spit out numbers and letters doesn't do justice to either.)

char(), float(), and str()

First up: enhancing a trio of conversion functions. They may now handle the range of primitive type and array arguments they are supposed to.

While the functions themselves don't do anything particularly remarkable, their behaviour helped uncover a bug in Pjs. When user code is parsed, Pjs converts chars into numbers. The relevant code is inside the Processing.parse() function:
// Force characters-as-bytes to work.
aCode = aCode.replace(/('(.){1}')/g, "$1.charCodeAt(0)");


The parser finds single characters flanked by single quotation marks and calls charCodeAt() on those characters. What this means is overloading Pjs functions to handle both arguments of type Number and characters (essentially one-character Strings in JavaScript) becomes... difficult.

Take str('A'). This should return the string “A". But because of the parser what actually gets processed is str(65) (the number 65), returning the string “65". Without jumping additional hoops, you can't tell str() whether that 65 is supposed to be a number 65, or if you actually mean that 65 to be representative of the char 'A'.

This causes some str() tests to fail. char() tests are affected although they all pass. For example:
int i = 65;
_checkEqual('A', char(i));

This is evaluated as _checkEqual(65,65), not _checkEqual('A', 'A'). The parser's fudging is masked by the passing tests.

I've filed a ticket with the suggestion that the parser not convert chars to Numbers, and leave functions to do this by themselves. With unit testing now rolling it'll be easier to find which functions rely on the parser's current behaviour. I may very well pick up the ticket for 0.7.

normal()

normal() takes three numeric arguments representing a vector and saves them to global variables. Oh, and it changes a flag. All of these (variables and flag) are supposedly used by other functions, but none of those uses have been implemented yet. (“What came first, normal() or the code that uses normal()?")

Since normal() has no return value, the unit tests content themselves with checking the correct number and type of arguments are present.

smooth()/noSmooth()

char(), float(), str(), and normal() are the good news. Alas, smooth() and noSmooth() fall somewhat short of that mark and probably won't appear in 0.6.

smooth() and noSmooth() are intended to toggle anti-aliasing on and off when painting. Canvas has no built in facility for this. sephr found a Mozilla-only CSS property image-rendering applicable to the canvas tag, and perhaps able to achieve what was desired.

Unfortunately, while image-rendering is good for raster images it doesn't work the same magic on canvas drawings. For the time being, it seems smooth() and noSmooth() will go into hibernation.

Sunday, February 7, 2010

Processing.js - It's a long way to 0.6

“But my heart's right there", or so the song goes. Indeed, it looks like my work is laid out for me. So for this short update, I'll just list what I hope to get done for February 19th (in no particular order):
  • Port normal() (Ticket)
  • Complete porting smooth() and noSmooth() (Ticket)
  • Upgrade char(), float(), str() to accept a multitude of argument types (Ticket)
This will also be the first release where we'll be using automated tests! I wonder if I still have Minefield stashed away somewhere...

Friday, February 5, 2010

Processing.js – int() and Release 0.5

int(), the late passenger

A long time ago, in the forest across the river, where fiery leaves danced upon the crisp winds of pseudo-winter (or in other words: back in the 0.2 release) I finished porting boolean(), a function that converted primitive types to either true or false, over to Processing.js (Pjs). As it transpires, boolean() was just one a gaggle of conversion functions, many which continue to seek the company of a code monkey willing to give them a boost over the wall from Java-land into JavaScript-land.

Yesterday evening, at the behest of The Powers That Be, and against the questionable judgement of my lazy self, I tentatively picked up the rest of these converters. And as I told Anna, the recently promoted Fearless Leader, I'd try to get one of them done for 0.5, whose deadline is today. So, without further ado, I present to you int() for Pjs.

Who wants to write the thousand words?

Lo, see now int() in action in Pjs, and compare it to how the same code renders in Processing:



Your eyes do not deceive you: Pjs' int() fails a test. But don't break out the torches and pitchforks just yet! There's a good reason for this. int() may take a byte or an array of bytes as an argument. In Processing, a byte may have a value from -128 to 127, but more importantly: byte is a static type. Through overloading this allows Processing methods, written in Java, to behave differently to accommodate different variable types.

Things are not so simple in JavaScript. In Pjs a Processing byte and int gets converted into a JavaScript 'number'; effectively there is no distinction between a byte and an int in Pjs. Since there's no distinction, int() cannot be tailored to behave differently when it receives bytes. (floats and doubles are different since you can always check if there's a decimal point in there somewhere.) Therefore, the test fails.

A possible solution may be to add a second parameter to int(), a flag called 'isByte' or something. That might be something to bring up in next week's telephone conference.

int() links



A Quick Recap of 0.5
Just for the record, here are the links to the rest of the stuff I did for 0.5:



I'll be making a (hopefully) shorter post soonish outlining what I hope to accomplish for 0.6. But for now, it's time to switch gears and call it a morning.

Tuesday, February 2, 2010

Processing.js – nf()

Closer to release 0.5

With a little luck, this should be my the last piece for the 0.5 release of Processing.js (Pjs) . The nf() function should now be able to handle arrays of numbers to be formatted, and float formatting.

There's a few interesting things going on here that the Processing documentation doesn't allude to, but those are more easily revealed once we see the code in action.

A few pixels

Here's the first batch of tests in Pjs (hah, there's no way I'm trying to minify that for the post!) and here's what Processing generates for the same code:



And here's the second batch of tests (arrays) in Pjs, and here's what Processing generates for the same code:



Note the tests use String::equals() which I recently completed and is not yet in the public release.

Also, while the documentation says all arguments should be positive integers, Processing's nf() does handle arguments with values zero or less. So I've coded Pjs' version to do the same.

It's supposed to do that? behaviour.

There are two weirder-than-normal things going on.

In the tests 19 to 32 in the first batch you'll find that depending on whether the one's digit is odd or even, the 'rounding' is different. This required a bit of extra code to replicate.

In the second batch, nf() processes values in the int array “incorrectly"; running through the ints individually results in the expected results. Strangely enough, my code was able to replicate this behaviour right off the bat.http://wobblyretroaction.blogspot.com/2010/01/processingjs-stringequals-or-how-i.html

Links

Sunday, January 31, 2010

Processing.js – String::equals() (or: how I filled something in on the way)

Pothole? What pothole?

Open source development is like driving on a road with potholes where every driver also happens to be a road worker. One day you may just get fed up with driving over the same crater over and over again and decide to do something about it in the most direct way possible: stop the car, get out, and fill it in yourself.

Of course, some holes get away for a while because they're just not that bad, or too deep. Other's scream for immediate rectification. Like the maws that open up suddenly and force you to slam on the breaks less you go careening into the deeps of the Earth. Or the holes just big enough to swallow a wheel and bring the scheduled excursion to a halt.

Well, on the way to giving nf() a nudge I discovered one of those wheel eaters. Like Java, Processing uses an equals() method to compare two Strings. JavaScript gets away with just ==, and for the past while Processing.js (Pjs) has done without equals() and used just ==. This was all well and good... until I started writing tests for nf().

The nf() tests compare the String result of nf() and an expected String result. Depending or not the two Strings are the same the output's colour changes. To ensure the code used for the test in the Processing Development Environment and in Pjs were the same I needed equals(). (Mind you, I could have used == in Pjs, equals() in Processing, and get the same output, but that would have been cheating.)

So with that short story aside, I present a quick and dirty String::equals() for Pjs. May this hole never become deeper.

How the road looks now

So here's how it looks in Pjs. (Again, we'll have to make due with a link. Minifying the code for insertion into the post didn't work out to well.) This example is extended from the Processing example.

And here's how the same code looks like in Processing:



Links

Processing.js – Improving min() and max()

And another brick

So here's another little improvement for Processing.js.

In Processing, the min() and max() functions may take 2 or 3 numeric arguments, or one argument if its an array of numbers. For a while the Pjs implementation could only take two arguments. I have since taken it in hand and the Pjs implementation should now be able to do what the Processing implementation can do.

Well, not exactly. In fact, the Pjs implementation will happily take a great many more numeric arguments than just three. It'll even take one number in a pinch. Passing in non-numeric arguments, aside from a single array, will cause "undefined" to be returned. Trying to be clever and pass in an array as one of two or more arguments will also return "undefined". In Processing these "undefines" would be "thrown exceptions".

My eyes!

This will be another post where I'll provide links to the Pjs tests and comparison Processing images.

Basic Processing example for min() in Pjs, and how it looks in Processing:



Basic Processing example for max() Pjs, and how it looks in Processing:



3 and 4 numeric arguments, and argument type discrimination, for min() in Pjs, and how it looks in Processing. Note that only three arguments is tested in Processing since the rest cause exceptions.



3 and 4 numeric arguments, and argument type discrimination, for max() in Pjs, and how it looks in Processing. Note that only three arguments is tested in Processing since the rest cause exceptions.



For the tests I had to pull a patch or two fixing Ticket #57 Boolean array bug.

Links

Wednesday, January 20, 2010

DPS911 Project – Processing.js – v0.4

A bit of touching up
So here we are: the first release for DPS911 this semester! For this release I've added missing functionality to Processing.js's (Pjs) implementation of text(). Unlike before, the function may now handle the printing of variable of integers, floats, doubles, and bytes, in addition to strings.

Now I wait for a (hopefully) favourable peer review.

Pretty pictures
Here we see a live demo of how it works in Pjs now as shown on this page:



And here we see the same demo as displayed in the Processing Development Environment:


What are we looking at?
The Pjs implementation had to take a few things into account. Processing displays floats and doubles to the thousandths digit, which is easy enough to replicate in JavaScript using toFixed(). But notice how Processing rounds: for 2.7185 it rounds down to 2.718 instead of up to 2.719.

toFixed(), by itself, rounds 2.7185 to 2.719, so a little bit of extra code was needed to alter this, like so:

if ( (val*1000) - Math.floor( val * 1000 ) == 0.5 ) {
val = val - 0.0001;
}
val = val.toFixed(3);

So for 2.7185 we craftily modify it to 2.7184 before sending it to toFixed().

Pertinent links

Sunday, January 17, 2010

Thoughts on the Proper Care and Feeding of Git Repos on GitHub

The nature of the problem

Last semester I and the other students working on Processing.js (Pjs) started using GitHub. We all made our own branch of the Pjs trunk repo and started hacking away. Over time we committed to our branches and some of our improvements went into trunk.

But our very success started to have some unintended consequences. Trunk advanced but our branches did not gain the improvements merged into trunk. This made our antiquated branches increasingly poor bases to produce patches for trunk. Needless to say, this inconvenience was not appreciated by anybody.

After a bit of experimentation I managed to find a way to keep my branch up to date without deleting it and starting fresh. Mickael Medel (aSydik), one of my classmates, has requested I spread the joy and blog about what I did. So here it is.

Fractional-reserve coding

In five easy steps most, if not all, problems, may be averted.

Step 1 – Pull from trunk to the branch on your local system

Before making any changes locally make sure you have the latest version of trunk. Pulling from trunk every time it changes isn't such a bad idea: it's much easier for Git to automatically merge code when the difference is small or simple. If the difference is too complex Git may cry "conflict!" and make you sort out the mess. Not good.

For us monkeys working on Pjs, I believe the pertinent pull command is:

git pull git://github.com/jeresig/processing-js.git master

Now, if you have more than one development system (as I do: desktop at home, and laptop) you may need to pull from your own repo instead of trunk. In that case the pertinent command is something like:

git pull git@github.com:yourusername/processing-js.git master

Step 2 – Hack on your local branch

So now have a totally updated version on your local system and the time has come for you to work your magic. Hack, surf, and make merry!

Step 3 – Commit on your local branch

After many hours of fruitful hacking you look out the window and the sun has been suspiciously replaced by the moon. It's time to call it a morning and push things back to your GitHub repo. But wait! Remember to commit the changes first, otherwise you'll have nothing to push.

I guess that Step 2 and 3 are just reminders, right?

Step 4 – Push your local commits to your online repo

Now comes the culmination of your efforts, fuelled by countless grams of caffeine and other tasty goodies: the big push. At this point you need to update your online repo to match the local repo. Not to hard, just plug in something that looks like this:

git push git+ssh://git@github.com/yourusername/processing-js.git

If all goes well the local commits will flood across cyberspace, and you shall know balance and harmony...

Step 5 – Back to Step 1

… for a little while. When you're ready to go at it again, collect your $200 and sally back to Step 1.

Opposites attract, but sometimes we wish they wouldn't

The above works very well if your branch is kept up to date. But if you're sitting on some really old revision chances are Git will be unable to do the merge in Step 1. It'll cry "conflict!" and you'll have to sort it out. By this I mean you'll need to do the merge manually (yes, lots of copying and pasting and what not.)

If the situation is really bad you may simply want to kill and remake your branch from scratch, keeping in mind to regularly update the resuscitated branch this time round.

If you slog through the manual merge, then commit changes to finish the merge. Committing will also tell Git the conflict has been resolved and you'll be back in business. At least, that's what I think happened when I resolved my first (and so far only) conflict.

Only now, at the end, do you understand.

I hope that was helpful for those in need.

I apologize to Mickael for the tardy post. He asked for this last Thursday and it took me a while to cobble this together. You see, I use an unholy combination of the command line and the EGit plugin for Eclipse to interface with GitHub so I wasn't quite sure what the exact commands were. I tested them with my latest commit to GitHub so I hope they work for everybody else.

Yes, I use Eclipse to hack Processing.js, but only because EGit appeals to my laziness. Otherwise I'd do what sane people do and use a "regular" text editor.

Thursday, January 14, 2010

2010, DPS911, and more Processing.js!

The Times They Are a-Changin'
Last semester in 2009 (so long!) I wandered into DPS909 and busied myself porting some functions over from Processing to Processing.js (Pjs).
For more on what Pjs is about check out a previous ancient post.
In a fitting continuity of events , this semester in 2010 (hello!) I've wandered into DPS909's follow-on, DPS911 and will continue futzing around with Pjs. The work done for DPS909 were released as 0.1 to 0.3, so not surprisingly the work for DPS911 will be released as 0.4 to the big 1.0.

The Plan
For v0.4 to v1.0, I hope to port over some new functions in addition to fixing existing bugs. The prospective task list and timeline is given below:

Obligatory List of Relevant Links