FindClosest (7)

, under actionscript.

findClosestWho follows me on twitter already noticed I’ve created a little app inspired by scribbler from zefrank. I also found another cool version of Mario Klingemann aka Quasimondo called scribblerToo. But the one where it all started is the javascript version of Mr.Doob. I wanted to try this in flash, and called it findClosest. It’s not as great as the other versions, but I really think there are some interesting things in here.

See it in action
» FindClosest

The trick in this little application is to store each mouse position, locate the mouse position and find the closest points around it (from the stored data) and draw some lines between those points. Well that code isn’t very exiting, because most people know how to find the distance between 2 points, and basically there are 2 ways find this: [as]// option 1: Using the build-in function
var distance:Number = Point.distance( point1, point2 );

// option 2: Using Math
var distance:Number = Math.sqrt( point1.x * point2.x + point1.y * point2.y );[/as]The results are amazing and I love the fact that even if you can’t draw, it looks really cool 🙂

Store lines as small as you can

I was already trying to find a way to store lines in a format I can reuse for my artworks. Most artworks are random but I am looking for a way to have more control. The first step would be the ability to control the (what I call) movements. So in this little experiment I’ve tried to find a way to store the lines into a compact file, which can be redrawed by the app. I’m really exited about this. So I’ve started to save as a plain-text file writing something like this:

{x:100,y:300},{x:110,y:340},{x:125,y:350},{x:125,y:350}

It’s readable code, and easy to These are 56 chars for 4 points. So I tried to make it more smaller using this:

{100,300},{110,340},{125,350},{125,350}

I’ve removed the x and y from the file, because I know that it’s always a pair of x and y values. Alright.. now I have 40 chars which represents 4 points, so that saves me 16 chars. Can this be done more smaller?

100,300,110,340,125,350,125,350

Yes, sometimes basic is the best. I removed the brackets. I know the odds are the x values, and the evens are the y values. It’s always x,y,x,y,x,y,x,y etc. So now I have 32 chars to store 4 points.

The application doesn’t know where I start pressing and releasing the mousebuttons. I have to know this, otherwise all my lines are just 1 big line instead of multiple lines. When pressing the mouse, I want to start with an graphics.moveTo function.

So what I did is this:

100,300,110,340,125,350,125,350&m=0,2

&m=0,2 means I have released the mouse on point 0 and point 2. A point referrers to the x and y position.

I think this is almost the smallest I can get. It’s easily to revert these values back to usable values using String.split().

But.. In real life there aren’t ints, but Numbers. The values mostly looks like 452.12070158. I stripped the value, and only use decimals. You don’t actually see the difference when redrawing between 10.04 and 10.042. This saves me a lot of chars too.

Compress it!
When saving the file, I push the data into a ByteArray using the bytes.writeUTFBytes() function. I realized ByteArrays can be compressed, so I also use the bytes.compress(); to make the file smaller again. This saves me about 50%! When importing the lines, I used bytes.uncompress(); to make it a normal string again.

This flower is 14kb 🙂 Import this file in the app to see how I haved drawed it. You can also load it from an url: http://projects.stroep.nl/findClosest/flower2.stroep
flower
flower on Flickr

Well this is a next step and I hope to create one day an editor for simple lines and merge this into my artwork process. I think it needs to be more complex but for now this will work. I hope you like it.

7 responses to “FindClosest”

  1. Ronny says:

    I love the redraw function that show the replay of you drawing it!
    I’ve been building something similar not too long ago! Love the result!
    Good job!

  2. Yoz says:

    hi Mark, you could save even more data:
    “100,300” as string in your case contains 7*8 = 56 bites
    but 100 as small integer can be stored in one byte (via writeByte()) = 8 bites + omitting separator + 300 (another 8 bites) you get 16 bites instead of 56… that way you can achieve 71% data save.
    … if you need to go beyound 8 bit numbers (255 max) you can always use 2 bytes per number (enough max) with sufficient (42%) save

  3. Mr.doob says:

    For a project I’ve been working for the past few months I also had to record a drawing. The approach I got the best results with was deltas+bytes+compress():

    Only save the first stroke position as absolute. I you did mouse down at 200,200. Then the next values are deltas. If the next position of your mouse was 201,201, you convert it to 1, 1, if the position after was 202,202, relative to the previous position will be again 1,1. If you moved your mouse back to 200,200 then it would be -2,-2. Just so you get an idea, your example data will become this:

    100,300,10,40,15,10,0,0

    You store the first 2 values as ints and the deltas as bytes. Just be careful a delta isn’t bigger than 127 or smaller than -128. In that case the only solution is to split it. Write all that into a ByteArray and compress() it.

  4. Lawrie says:

    Really nice Mark – the replay of the drawing’s awesome. Interesting to see your thoughts on data storage and compression too – thanks for sharing.

  5. I’m also trying to adapt Mr Doobs algorithm. I’ve already published one attempt, but I’m not happy with it yet – there’s another one in the works. My situation is more complex, in that e2vector already employs pretty good smoothing and reduction in the number of points to represent a drawn line. I’m working on splines, where the points are not close together. If I used Mr Doobs algorithm as-is, the number of points would probably choke the application when the user subsequently edits their artwork.

    I’m puzzled by some of the decisions you took to compress your file. Binary Coded Decimal isn’t small. Something like ByteArray.writeUnsignedShort(), or FileStream.writeUnsignedShort(), would have saved each number as two bytes. I see Mr Doobs left a comment about using deltas. That’s the next thing I was going to suggest to reduce each value to one byte. A drawn line ISN’T random points. There’s a whole lot of correlation. If you really wanted to go to town with experimenting with data compression – you might look at predictive encoding. Like ADPCM. But that might be over-kill.

  6. Mark says:

    Hi Daniel, thanks for sharing! Let me know when you have finished that version you are working on. I’d love to see it.

  7. cesarullo says:

    Hy.
    Forgive my english.
    I have not much experience with flash.
    I’m trying to create an application similar to the one created by you.
    I would be enormously useful to have. fla of your application, so i can study it and create the functions that I need from it.
    you can share files with me?
    I would be grateful.

Say something interesting

Please link to code from an external resource, like gist.github.com.