Starbeamrainbowlabs

Stardust
Blog


Archive


Mailing List Articles Atom Feed Comments Atom Feed Twitter Reddit Facebook

Tag Cloud

3d 3d printing account algorithms android announcement architecture archives arduino artificial intelligence artix assembly async audio automation backups bash batch blender blog bookmarklet booting bug hunting c sharp c++ challenge chrome os cluster code codepen coding conundrums coding conundrums evolved command line compilers compiling compression conference conferences containerisation css dailyprogrammer data analysis debugging defining ai demystification distributed computing dns docker documentation downtime electronics email embedded systems encryption es6 features ethics event experiment external first impressions freeside future game github github gist gitlab graphics guide hardware hardware meetup holiday holidays html html5 html5 canvas infrastructure interfaces internet interoperability io.js jabber jam javascript js bin labs latex learning library linux lora low level lua maintenance manjaro minetest network networking nibriboard node.js open source operating systems optimisation outreach own your code pepperminty wiki performance phd photos php pixelbot portable privacy problem solving programming problems project projects prolog protocol protocols pseudo 3d python reddit redis reference release releases rendering research resource review rust searching secrets security series list server software sorting source code control statistics storage svg systemquery talks technical terminal textures thoughts three thing game three.js tool tutorial twitter ubuntu university update updates upgrade version control virtual reality virtualisation visual web website windows windows 10 worldeditadditions xmpp xslt

Easy circles on the canvas with context.ellipse()

Ripples made using context.ellipse().

A while ago I was building a family tree viewer for an ACW (Assessed CourseWork) at University. Part of this ACW involved drawing faces inside ovals and using circles for various things. The suggested method here was using bezier curves (more on this on Wednesday), but I found another (much easier!) way of doing it that I thought others would find useful, so I am posting about it here.

Instead of using context.bezierCurveTo() and battling with control points, you can just use context.ellipse to add either a circle or an ellipse to the current path. Here's an extract fomr the wonderful MDN:

Syntax

void ctx.ellipse(x, y, radiusX, radiusY, rotation, startAngle, endAngle, anticlockwise);

Parameters

Parameter Explanation
x The x axis of the coordinate for the ellipse's center.
y The y axis of the coordinate for the ellipse's center.
radiusX The ellipse's major-axis radius.
radiusY The ellipse's minor-axis radius.
rotation The rotation for this ellipse, expressed in radians.
startAngle The starting point, measured from the x axis, from which it will be drawn, expressed in radians.
endAngle The end ellipse's angle to which it will be drawn, expressed in radians.
anticlockwise Optional. An Boolean which, if true, draws the ellipse anticlockwise (counter-clockwise), otherwise in a clockwise direction.

For example, here's how you'd draw a 100x200 red ellipse at (0, 0):

function renderEllipse(context)
{
    context.fillStyle = "#ff3300";
    context.beginPath();
    context.ellipse(0, 0, 100, 200, 0, 0, Math.PI * 2, false);
    context.fill();
}

The startAngle and endAngle functions work the same as the context.arc() command - they let you draw just part of a circle or ellipse instead of a full one. In the example above, I'm drawing a full one by starting at 0 and finishing at (360°).

I've built a simple 'ripples' demo that demonstrates context.ellipse() in action. Click anywhere on the screen to create a ripple. The background is made with a few quick radial gradiants that fade from a colour into transparency.

Vector.js: A simple vector class in ES6

Recently I built a vector class in Ecmascript 6 for some coursework that I've been writing, and I thought that I'd share it here. I found out a little while ago that chrome does actually support classes, so long as you enable strict mode. After looking into them, they are actually really useful when writing a HTML5 canvas demo, or writing a reusable library. I'll make a post on how to use them sometime soon (as soon as I have time).

Anyway, the class that I wrote supports addition, subtraction, division, multiplication, length limitation (preserving direction), the dot product, angle from another vector, unit vector calculation, length calculation, and cloning. Here's the code:

(Gist, Raw)

You can create instances of this class as you would any other:

var v = new Vector(100, 100), // Create a new vector for the point (100, 100)
    v2 = new Vector(300, 400); // Vector for the point (300, 400)

// Clone v and subtracts v2 from it, putting the result into v3.
// Note that `add()`, `subtract()`, etc. are _mutators_.
v3 = v.clone().subtract(v2);

If I've missed any functionality, please feel free to leave a request in a comment below. Even better - fork the gist and implement it yourself! I'd love to pull in your changes. Feel free to use this class in your own projects. A link back isn't required, but very much appreciated!

That's about everything I have to say about this class, but I'll be posting a bezier curve class soon that depends on this one - probably sometime next week. Bye!

Update 24th January 2016: I've replaced the original code with an embedded version of the gist in order to keep it up to date, since I've revised it slightly sinec writing this blog post.

Easy Quadratic Ease In/Out Algorithm

Recently I wanted to add an ease in / out effect to an animation that I was writing. I searched the internet, but couldn't find anything particularly useful that actually explained how the algorithm worked, so I am writing this post.

The formula I ended up using works by taking an input between 0 and 1, and spitting out an adjusted output which is also between 0 and 1, but has the easing function applied. For easing both in and out, there are two formulae.

To ease in, for $y < 0.5$: $$ y = 2x^2 $$

To ease out, for $y >= 0.5$: $$ y = -1 + x(4 - 2x) $$

If you want to only ease in or ease out, go ahead and use just one of the above equations, and forget about the other one. Or, you can combine them to ease in and out at the same time.

Initially, I wrote my implementation in C♯ while I was testing the equations. Here's what I came up with:

using System;
using System.Threading;

namespace EasingTest
{
    class MainClass
    {
        static int width = 75;
        static int frameDelay;

        public static float QuadEaseInOut(float time)
        {
            return time < 0.5f ? 2.0f * time * time : -1.0f + (4.0f - 2.0f * time) * time;
            //return t<.5 ? 2*t*t : -1+(4-2*t)*t
        }

        public static void displayEase(float time)
        {
            float ease = QuadEaseInOut(time);

            int nextWidth = (int)(ease * width);
            Console.Write("{0}{2}{1}\r", new string(' ', nextWidth), new String(' ', width - nextWidth), 'o');
        }

        public static void Main(string[] args)
        {
            Console.Write("Enter the frame delay: ");
            frameDelay = int.Parse(Console.ReadLine());

            int count = 0;
            float step = 0.01f;
            bool dir = false; // false = right->left, true = left->right
            while(count < 10)
            {
                if(!dir)
                {
                    for(float t = step; t < 1; t += step)
                    {
                        displayEase(t);
                        Thread.Sleep(frameDelay);
                    }
                    dir = true;
                }
                else
                {
                    for(float t = 1; t > 0; t -= step)
                    {
                        displayEase(t);
                        Thread.Sleep(frameDelay);
                    }
                    dir = false;
                }

                count++;

            }
        }
    }
}

(Pastebin, Raw)

Here's an example run of the above code:

The important stuff happens in the QuadEaseInOut function on line #11. If you just want the easing function, here it is in multiple languages:

C Sharp

public static float QuadEaseInOut(float time)
{
    return time < 0.5f ? 2.0f * time * time : -1.0f + (4.0f - 2.0f * time) * time;
}

Javascript

function (t)
{
    return t<.5 ? 2*t*t : -1+(4-2*t)*t;
}

The above can easily be ported to other languages if you aren't using C♯ or Javascript.

Sources

I originally got this algorithm from gre's wonderful gist, which also contains a number of other easing functions that you might be interested in.

End of ES6 Features Series

This post marks the end of my Ecmascript 6 features series of posts for now. While there are a few more topics I could cover, I don't feel that there is enough support in today's javascript engines to do them justice. At some point in the future I will come back to this series and finish off those topics that I've skipped out on this time.

Before I end this series though, I found a Javascript feature support table that you might find useful. It shows you which ES5/6/7 features are supported by which browsers and preprocessors.

Ecmascript compatibility table

That's all for now! Here's a list of all the posts that I've made so far in this series.

Ecmascript 6 Features 12: Strings

Welcome to another ES6: Features post. I think I might be getting to the end of this series soon! Anyway, this week's post is going to be on the new string related additions that have been made in Ecmascript 6. First up is a neww utility method called repeat(). As the name suggests, it duplicates a string a specified number of times:

> "e".repeat(10)
'eeeeeeeeee'
> "=-".repeat(4)
'=-=-=-=-'
> "Precarious Porcupine".repeat(3)
'Precarious PorcupinePrecarious PorcupinePrecarious Porcupine'

No more abusing new Array(length + 1).join(number)! It looks like one of those functions that should have been added a long time ago. As usual, the MDN has a polyfill that you can use.

Next up is a set of functions that make searching for things in strings much easier. There's startsWith, endsWidth and includes, and they all return a boolean:

"porcupine".startsWith("p"); // true
"porcupine".startsWith("pine", 5); // true

startsWith has an optional second argument, which lets you specify an offset from which to begin searching. endsWidth also has an optional second argument, but it lets you limit the number of characters that are searched:

"erroneous elephant".startsWith("waterfront"); // false
"erroneous elephant".endsWith("neous"); // false
"erroneous elephant".endsWith("neous", 9); // true

Lastly, there's includes. It works as you might expect it to, with the optional second argument specifying the offset from which to search:

"catastrophic crocodile".includes("croc"); // true
"catastrophic crocodile".includes("cat", 8); // false

This trio of functions should make complex string manipulation much easier to understand as you don't have to use any more complex indexOf tests anymore.

That concludes thsi ES6: Features post on strings. It seems that readability is a running theme throughout ES6. I hope that in time this makes everyone's javascript much easier to read and debug :)

Ecmascript 6 Features 11: Numbers and Math

Welcome to this week's (rather late - sorry about that! I've been out for much of the week) ES6:Features post. This week, I'll be looking at the ne wadditions to the Number and Math objects.

Firstly, there's a pair of new utility functions that have vbeen added to the Number object called Number.isNaN() and Number.isFinite(), and they can be used (as you might expect) to check to see whether a given number is not actually a number or is infinitely large respectively. Here's a few examples:

Number.isNaN(NaN); // true
Number.isNaN(359); // false
Number.isFinite(9478); // false
Number.isFinite(Infinity); // true
Number.isFinite(-Infinity); // true

The next addition is another checking function that you can use to make sure that a number is within a 'safe' range. The way that javascript interpreters or compilers work means that numbers arree manipulated with a fixed number of bits allocated to represent them. This means that there will be a limit to the size of the number that the interpreter or compiler can accurately represent. Since we have both 32 and 64 bit machines at the moment, this limit moves around from machine to machine - hence the addtion of the following function:

Number.isSafeInteger(56); // true
Number.isSafeInteger(39458634957629746293846); // false

A word of warning though: isSafeInteger, as the name implies, works only with whole numbers - so you'll probably need to run any floats through Math.floor() first, or the next new function that's been added: Math.trunc().

Math.trunc() will drop the fractional part (i.e. anything after the decimal point) of any number passed into it. This can be useful for all sorts of things, including using the function above. At first glance you might think that this function is similar to Math.floor(), but it's not. The difference is that if you feed it a negative number, it still chops the fractional part off, rather than rounding it to the next number down:

Math.trunc(-44.44); // -44
Math.floor(-44.44); // -45

After running a test on jsperf.com, I discovered that the new function is a bit slower than Math.floor and Math.ceil (108M ops/sec vs 116M ops/sec), but this is to be expected with a new function, and the difference shouldn't really be noticeable unless you are doing something really extreme :)

The last new addition is the Number.sign() function. This function is another one for convience. It returns 1 if the number is greater than 0, -1 if the number is less than 0, and 0 if the number is 0 exactly. Here are a few examples:

Number.sign(768); // 1
Number.sign(-356); // -1
Number.sign(0); // 0

That concludes this post about the new number related functions added in ES6. Most of them are for convienence, but they should improve the readability of your code a little bit. At least they aren't as confusing as Symbols! Next time I will probably be looking at the new functions added to the String object.

EcmaScript Features 10: Set

This week's ES6 feature is the Set. If you know C♯, you'll find the ES6 set to be very similar to C♯'s List class. If not, all will be explained below.

Javascript's Set is essentially a list, with a few differences here and there. You can add things to a set using the .add(thing) function, check whether a Set contains a specific value with the .has(thing) function, and get iterable object full of [key, value] pairs with the .entries() function:

> set = new Set()
Set {}
> set.add("apples")
Set { 'apples' }
> set.add("milk")
Set { 'apples', 'milk' }
> set.add("bronze pineapples")
Set { 'apples', 'milk', 'bronze pineapples' }
> set.has("milk")
true
> set.has("grapefruit")
false
> for(var item of set.entries()) { console.log(item); }
[ 'apples', 'apples' ]
[ 'milk', 'milk' ]
[ 'bronze pineapples', 'bronze pineapples' ]
undefined

Since a Set doesn't really use key value pairs, both the key and the value will be the same, unlike C♯'s List, which uses numbers as the keys for every element inside the List. This leads to an interesting situation. Suppose you try to add two identical things to a list:

> set = new Set()
Set {}
> set.add(1)
Set { 1 }
> set.add(3)
Set { 1, 3 }
> set.add(5)
Set { 1, 3, 5 }
> set.add(5)
Set { 1, 3, 5 }

You would probably expect to see the 5 appear twice in the above example, but it only appears once. What is going on here?

Since the Set uses the values you add to it as the keys when it stores the data for you, it means that if a value you give it is the same as one that you have added before, the key for the new value is the same as the key for the previous value. The result: an iterable object of unique items. You could use the new Set to ensure that your program doesn't have any duplicate entries.

Because the key and the value or any given entry are the same, it means that you have to pass a given entry to the delete function instead of it's index (which it doesn't have) in order to delete it:

> set = new Set()
Set {}
> set.add("piano")
Set { 'piano' }
> set.add("viola")
Set { 'piano', 'viola' }
> set.add("trombone")
Set { 'piano', 'viola', 'trombone' }
> set.delete("viola")
true
> set
Set { 'piano', 'trombone' }

That concludes this post on the ES6: Set. Next time, I will probably take a look at the new strign searching functions and the new number / math related functions.

Ecmascript 6 Features 9: Map

Welcome to the 9th postin my weekly ES6: Features series. Today, I will be taking a look at Map, and its counterpart, the WeakMap.

At the simplest level, a Map in Javascript is a set of key-value pairs. You can do things like this:

> var map = new Map();
undefined
> map.set("Sticky Swamp", { x: 5, y: 7 });
Map { 'Sticky Swamp' => { x: 5, y: 7 } }
> map.set("Frosty Mountain", { x: 3, y: 4 });
Map {
'Sticky Swamp' => { x: 5, y: 7 },
'Frosty Mountain' => { x: 3, y: 4 } }
> map.set("Piranha Pond", { x: 7, y: 2 });
Map {
'Sticky Swamp' => { x: 5, y: 7 },
'Frosty Mountain' => { x: 3, y: 4 },
'Piranha Pond' => { x: 7, y: 2 } }
> map.get("Frosty Mountain").x
3
> map.has("Treasure")
false
> map.has("Piranha Pond")
true

Maps can also be iterated. With a bit of destructuring wizardry, we can list the content of a map like this:

> for(var [ key, value ] of map) { console.log(`Name: ${key} Location: (${value.x}, ${value.y})`); }
Name: Sticky Swamp Location: (5, 7)
Name: Frosty Mountain Location: (3, 4)
Name: Piranha Pond Location: (7, 2

If you only want to iterate over the keys or the values, you can get an iterable object of them with .keys() and .values() respectively.

> for(var key of map.keys()) { console.log(key); }
Sticky Swamp
Frosty Mountain
Piranha Pond
undefined
> for(var key of map.values()) { console.log(key); }
{ x: 5, y: 7 }
{ x: 3, y: 4 }
{ x: 7, y: 2 }
undefined

Note that you can't use .forEach() or any related functions (such as .map() or .filter()) on this object, and it's contents doesn't show up in the developer tools either.

Another cool feature of Maps is that you can use anything is the key. This allows you to create empty objects (for example), like so:

> map = new Map();
Map {}
> a = {}
{}
> b = {}
{}
> a == b
false
> map.set(a, "this is a")
Map { {} => 'this is a' }
> map.set(b, "this is b");
Map { {} => 'this is a', {} => 'this is b' }
> map.get(a)
'this is a'
> map.get(b)
'this is b'

This probably won't make too much sense with a normal Map, but mixing this with the WeakMap leads to some powerful data storage mechanisms.

WeakMaps

The WeakMap is the cousin of the Map, and is largely the same, but with a few important differences. Firstly, it isn't iterable, and you can't get a list a keys from it either. If you need sa list of keys, you should maintain it yourself.

This means that if you are using objects as your keys (as described above), and you loose all the references to that object, the garbage collector can not only come and collect the object you lost all references to, but also the value that it was tied to in the WeakMap. This helps you to avoid memory leaks if you don't actually need to iterate over the map at any point.

> wmap = new WeakMap()
{}
> a = {};
{}
> b = {};
{}
> wmap.set(a, "This is a")
{}
> wmap.set(b, "This is b");
{}
> wmap.get(a)
'This is a'
> wmap.get(b)
'This is b'
> delete a
true
> wmap.get(b)
'This is b'
> wmap.get(a)
ReferenceError: a is not defined

In the example above, once we delete a, we also loose our only connection with the data that it was tied to in the WeakMap, allowing the garbage collector to come over and clean thing up for us.

Other than that, the WeakMap acts much the same as the Map - it has the same get(), set() and has() methods that the Map does.

That concludes the 9th post in this series (sorry it was rather late)! Next time, I will probably take a look at Set.

A Distributed solution to /r/dailyprogrammer Challenge #223

A little while ago, I wrote my first distributed computing program to solve the second optional challenge to /r/dailyprogrammer's #223rd problem. I wrote it in Javascript, because I know really know how to utilise the tcp/ip networking stack in any other language yet :(

Anyway, if you want to check out my source code, I have put it up on GitHub. Below I will explain how you can get started with the pair for scripts I wrote, and how they work

Getting Started

Getting started is easy. Just clone the repository & cd into the new directory:

git clone https://github.com/sbrl/dailyprogrammer-223.git
cd dailyprogrammer-223

Then install the dependency:

npm install

Then you can start a server like so:

node server.js 4321 # starts a new server on port 4321

Or you can start a client like this:

node client.js starbeamrainbowlabs.com:9999

Note that I have used some ES6 features (check out my ES6: Features series), so if you are using Node.js and not io.js, you will need to tack on the --harmony flag in order to get them to work.

It works by mapping the search space (aaaaa to zzzzz) to a set of numbers, starting at 0. I used an ES6 generator to keep track of where we have got up to, wrapped in a function that handles reallocating work units that haven't been completed within a certain time limit. Each work unit consist of 16 words by default (though it can be changed), with the time limit set to 5 times the number of words in the block.

Next time, I will write the client so that it is compatible with a conventional browser - this should make it much easier for people to contribute their CPU time!

Ecmascript 6 Features 8: Symbols

This week's ES6 post is about a rather strange (but useful) feature that I have only just discovered: Symbols. Before I explain to you how they work, be warned: I don't understand them fully myself yet.

Symbols are like unique keys and can be used as properties so you can use to ensure that you don't clash with any other property in an object. When creating one, you can optionally give it a 'name' so you know what it is - this can be any data type, but Symbol() will call .toString() on it first. Note that two symbols created with the same name aren't the same:

> sym1 = Symbol("starbeamrainbowlabs")
Symbol(starbeamrainbowlabs)
> sym2 = Symbol("starbeamrainbowlabs")
Symbol(starbeamrainbowlabs)
> sym1 == sym2
false

Strange, right?! This can be very useful though. You could use this to attach extra data to an object that you have been given by a library to identify it, for example, or you can use it to store something in a browser's localStorage without clashing with any other scripts running on the same domain (but this apparently doesn't persist across page reloads):

> localStorage[Symbol("bobs-rockets")] = "Some data";
"Some data"
> localStorage[Symbol("bobs-rockets")] = "Some data";
"Some data"
> localStorage
Storage { Symbol(bobs-rockets): "Some data", Symbol(bobs-rockets): "Some data" }

While this is cool, this raises the issue of retrieving the data we stored when we next load the page. If we try to create a new symbol with the same name that we used before, the browser returns undefined because the symbol we just created is not the same as the one we created the last time we loaded the page, as we discovered above.

Our next thought might be to iterate over the object and try to work out which one is ours:

> Object.keys(data).forEach(function(key) {
... console.log(`${key}: ${value}`);
... });
some-key: some-data
some-other-key: some-other-data
undefined

But weirdly, the Symbols we used don't show up! Object.keys() only returns an array of string based keys, and completely ignores the Symbols we created. This calls for a special function: Object.getOwnPropertySymbols(). This returns an array of all the Symbol based properties in an object. Then you can iterate over them like so:

> Object.getOwnPropertySymbols(data).forEach(function(key) {
... console.log(`${key.toString()}: ${value}`);
... });
Symbol(bobs-rockets): some-data
Symbol(bobs-rockets): some-data
undefined

Note the .toString() call here. If you try and convert a Symbol to a string, an exception is thrown:

TypeError: Cannot convert a Symbol value to a string

The same goes for if you accidentally use the new keyword when creating a Symbol:

> var sym = new Symbol();
TypeError: Symbol is not a constructor

There is an ever better way to recreate the same symbol across page loads though. You can use the Symbol.for() function:

> bobsSymbol = Symbol.for("bobs-rockets")
Symbol(bobs-rockets)
> bobsSymbol2 = Symbol.for("bobs-rockets")
Symbol(bobs-rockets)
> bobsSymbol == bobsSymbol2
true
> Symbol.for("bobs-rockets") == Symbol.for("bills-boosters")
false

This also allows two libraries to share the same symbol - but make sure that the string you pass to Symbol.for() is unique. This brings me onto the last thing I found out - you can reverse engineer a Symbol you obtained through Symbol.for() to work out the string used to create it with Symbol.keyFor():

> bobsSymbol = Symbol.for("bobs-rockets")
Symbol(bobs-rockets)
> Symbol.keyFor(bobsSymbol)
'bobs-rockets'

That concludes this ES6: Features post. To summarise, Symbols are unique keys that can be used to avoid conflicts in property names of objects. Every time you create one, you make a brand new Symbol that is completely different to any created before, except if Symbol.for() was used. Symbols created with Symbol.for() can be reverse-engineered to extract the string used to create it. Next time, I will probably look at well known symbols.

Art by Mythdael