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

ES6 Features 14: Modules

This is an entry in the ES6 Features series on my blog here. Check out the full series list here.

1 year and 4 months later, and we're finally seeing es6 modules start to land in a browser near you (currently Chrome, Firefox with a flag, Edge 16+, and Safari). Since I've been having to refer back to several different blog posts on the subject at once just to remind myself of a particular aspect of the new syntax, how it's used, and how it interacts with other parts of the syntax, I thought I'd blog about it here.

Before we begin, a note on enabling it in your browser. In Firefox, you need to visit about:config and set dom.moduleScripts.enabled to true instead of false (or create it if it doesn't exist). In Chrome 60, you need to go to about:flags and enable experimental javascript features or some such similar flag. Other browsers may either have it enabled by default, or require a variant on the above to get it to work.

With that, let's look at what it actually is and what it allows us to do that we couldn't before. Have you ever run into this issue before?

<script src="javascript/Vector.js"></script>
<script src="javascript/engine.js"></script>
<script src="javascript/main.js"></script>
<script src="javascript/LineSimplifier.js"></script>
<script src="javascript/Bezier.js"></script>
<script src="javascript/render.js"></script>
<!-- ... -->

It's a bit of a mess, right? Such is the problem with splitting one's code across multiple files in Javascript without a preprocessor such as Browserify or webpack.

Thankfully, it does not have to be this way! It's ES6 modules to the rescue. ES6 modules let us break our code down into discrete components that describe which other components they require. In this way, these components can be found and loaded by the browser on it's own - instead of us having to specify a whole load of <script /> tags and hope we've got them in the right order.

Let's take it from the top. Here's how you tell the browser you're loading a module and not a regular script:

<script type="module" src="./js/index.js"></script>

The above loads the file ./js/index.js as a module. In there, we cna do things like add an onload event listener to the window object to kick things off - in fact you can do practically anything you could in a normal script. Let's take a look inside an example module:

"use strict";

import Vector from "./lib/Vector.js";
import { Banana, Apple } from "./Fruits.js";

window.addEventListener("load", function(event) {
    // ......
});

Referencing another module is done with an import statement. Currently, most browsers require the ./ (or / or even a fully-qualified URL) at the beginning, and don't allow you to drop the file extension like you can in Node.JS - though this may change in the future.

I've given 2 different examples of import statements above - the first one (line #3) imports the default export and assigns it to Vector, and the second one (line #4) imports a pair of specifically named exports.

The next natural question here is how to export things so that we can import them. That's easy too:

export default Pineapple;
export { Apple, Banana, Kiwi as Coconut };
export function travel(start, finish) {
 // ....
}

As you can see, it's quite flexible actually. You can specify a default export with export default ThingName for use with the default import statement above, and you can export specifically named things - and even give them alternate names! Lastly, you can also export things as you define them - like I have with the travel() function above.

That just about covers everything. I'll leave a bunch of links below that go into more depth than I have here. I can already see the endless possibilities with this - I just wonder if anyone's built a preprocessor that concatenates all your modules into one file - whilst maintaining the ability to debug it effectively.... perhaps I'll have to do some research.

Found this useful? Let me know below! I don't currently have any analytics set up, so your comments are the only way I know if anyone's reading this :P

Sources and Further Reading

Line Simplification: Visvalingam's Algorithm

An screenshot of my demo of my implementation of Visvalingam's Algorithm. (Above: A screenshot of the demo of my implementation of Visvalingam's line simplification algorithm. Link below!)

For a secret project of mine I've been working on since about February time (if I recall correctly), I've discovered that I could make some considerable use of a line simplification algorithm. The tricky thing is though that I need an implementation in both Javascript and C♯ - which will both return identical results.

Initially, I chose the Ramer-Douglas-Peucker Algorithm, but I ended up implementing Visvalingam's Algorithm instead, as I encountered issues with calculating the shortest distance from a point to a line reliably along with other algorithmic problems that I determined weren't worth the time to fix.

Visvalingam's algorithm is actually really simple. Suppose we take a line:

A line with 6 points in it.

If we create a sliding window with a width of 3 and slide it along the list of points, then we get a set of triangles. To simplify the line, we can calculate the area of each of these triangles, and remove the centre point of the triangle with the smallest area.

The same line with the triangles highlighted.

The same line with a point removed.

Then we can continue removing the centre point of the smallest triangle until we reach a triangle with an area that's above a threshold we set - and this is Visvalingam's Algorithm.

Though I haven't written the C♯ version yet, I've completed the Javascript implementation - and created a demo for you to play around with! Here's a link:

Visvalingam's Algorithm Demo

Note that you'll need to enable ES6 Module support in your browser to get it to work, as I've used ES6 Modules whilst building it.

In Firefox this can be done by setting dom.moduleScripts.enabled to true in about:config, and in chrome by visiting chrome://flags/#enable-javascript-harmony (sorry, hyperlinks don't work for chrome:// urls IIRC!), enabling it, and restarting your browser.

It's open-source, of course - under the Mozilla Public License 2.0. You can find my code on GitLab - and pull requests are welcome :D

Finally, I've released it as an npm package. If you aren't aware of npm, it's really cool. It's the primary package manager for Javascript - I've written a blog post on this here.

Once I've written the C♯ version I'll have another bash at trying to get Nuget to package it. I think I know what the issue has been so far - so hopefully it works this time! If it does I'll blog about that too.

Found this useful? Think it's cool? Let me know in the comments below!

Forgotten Parallax Bicycles

The forgotten parallax bicycles. In June last year (that feels weird to type), I created another one of my little HTML5 Canvas demos - this time of some hills that parallaxly scroll with a bicycle on a road. I actually made it as a (birthday?) present for someone I seem to remember - and I even released it on my website here, but I somehow seem to have forgotten to post about it here on my blog, so I'm doing so now :-)

You can find it here: Parallax Bicycle

At the time the bicycle itself in particular was incredibly fiddly to get working right if I recall correctly. The hills in the background are procedurally generated too - they are on a (seamless!) loop and repeat every so often. The seamless part was also interesting to get working right.

Transform your javascript with Browserify

Tired of battling endless <script> tags in your html files? Fed up with messing with a dozen libraries cluttering up the place? Can't see the wood from the trees? Try browserify (+ rollupify + wzrd)! It's amazing! It's awesome! It tidies up your code for you, so you don't have to (perhaps not :P)!

Seriously though, I've just been playing around with browserify, and it's awesome. It's that missing thing I've been trying to find for a long time. But what does it actually do, you ask?

Well, perhaps it's best to use an example. Consider these (relatively) harmless javascript files:

// SillySay.js
"use strict";

function sillySay(sentence) {
    // Split the sentence up into words
    var words = splitWords(sentence);

    // Loop over all the words in the above array and display them one by one
    for(let i in words) {
        alert(words[i]);
    }
}
// WordSplitter.js
"use strict";
function splitWords(sentence) {
    // Split the sentence on whitespace and return the resulting array
    return sentence.split(/\s+/g);
}

To use our (perfectly ridiculous) example code, we not only have to include SillySay.js, but WordSplitter.js (this could be a library you use for example) as well:

<!DOCTYPE html>
<html>
    <head>
        <meta charset='utf-8' />
        <title>Silly Say Demo</title>
    </head>
    <body>
        <p>Silly Say Demo</p>
        <p>By <a href="https://starbeamrainbowlabs.com/">Starbeamrainbowlabs</a></p>

        <!---------------->
        <script src="WordSplitter.js"></script>
        <script src="SillySay.js" charset="utf-8"></script>
        <script>
            window.addEventListener("load", function(event) {
                sillySay("This is a test");
            });
        </script>

        <style>
            html, body { font-size: 100%; }
            body
            {
                font-family: sans-serif;
            }
        </style>
    </head>
</html>

That's looking a bit messy, but imagine what it'd be like if you added another few libraries? Or a new feature in a separate file? See the problem? Browserify solves just this issue. It analyses the dependencies of the entry point to your app, and bundles up all your code into a single file, nice and neat. You can add extra transforms (like plugins), too, to do extra things like automatically insert your app's version, or include other data files automatically, or transpile other languages to javascript automagically (full list here).

Sounds cool yet? Let me give you a quick tutorial on how I set up Browserify, with Rollupify and Wzrd.

Firstly, we need to set things up. If you don't have Node.js installed, do that now. You'll also get npm - Node's (perfectly awesome!) package manager. Next, let's create a quick project and paste in the code above. I've recorded an asciicast (as you may have seen a few times before here) of me going through the process:

(Can't see the asciicast above? Try viewing it here

If you'd like to take a look at the final result, as written in the asciicast above, you can find it over here. Questions and comments are welcome below :-)

ES6 Features 13: Classes

Almost a year ago I finished a series on the new features of Ecmascript 6, the next version of Javascript. At the time there were one or two features remaining that I hadn't covered, but I didn't feel that today's browsers supported them well enough for me to write a blog post on them. Today, however, that has changed, for classes at least. In this blog post I'll explain by example how classes work in ES6.

Originally, I was against the idea of having classes in javascript. After using them for a while, I've decided to change my mind. They can bring organisation to an otherwise rather cluttered project, especially since the modules syntax hasn't yet landed.

If you've you're familiar C♯, then ES6 classes will feel a little bit familiar. Here's a simple example:


"use strict";
class Bicycle
{
    constructor(inPosition, inColour)
    {
        this.pos = inPosition;
        this.colour = inColour;
        this.wheelCount = 2;
        this.setup();
    }

    setup()
    {

    }

    update(dt)
    {
    }

    render(context)
    {
        // Do rendering stuff
    }
}

Very familiar (I hope). Classes in ES6 are defined using the class Tree { } syntax, with everything belonging to that class inside a set of curly braces, just like in C♯. Because javascript isn't a typesafe language, method declarations look a bit different. Essentially they are the same as a C♯ method declaration, just with the type names taken out.

The "use strict"; at the top is important - today's browsers don't let you use classes without it. I'll omit it in later examples for sake of simplicity, but you'll always need to remember to include it when using ES6 classes.

The constructor() method is, as you've probably guessed, the constructor of your class. Strange way of doing things, I know, but that's how it's declared. Note also that all variable initialisation is done in the constructor and not in the class body. Apparently class definitions are supposed to define an object's capabilities and not its members.

Calling a method from inside is an ES6 is easy too (see highlighted line #8), but it's important to understand what the this variable is in this context first (I could write a whole separate blog post about this). this is a special variable in javascript that holds the current context. In the case of an ES6 class, it holds the current instance of the current class. This is identical to C♯, but the difference is that you'd normally never need to use this in C♯ and it's required in ES6 - for both method access and variable access.

class Tree
{
    grow(dt, rate)
    {
        this.classMethodA(4, dt, this.someVariable);
    }

    // ...
}

White noise

Update: It turns out that ES6 does indeed support static methods (but not variables I don't think) natively via the static keyword. Here's an example:


class Tree
{
    constructor()
    {
        this.something = Tree.doComplicatedStuff();
        this.somethingElse = this.constructor.doComplicatedStuff();
    }

    static doComplicatedStuff()
    {
        // ...!
    }
}

Native static methods can be called in two ways (highlighted above). One is practically the same as the C♯ way of doing things, and the other is useful if for whatever reason you don't have the name of your own class handy.

Original sectional text

You can define static variables and methods too, although it's a little bit of a hack. Imagine I have this class:

class NoiseGenerator
{
    constructor()
    {
        // ...!
    }

    GetNoise(amount)
    {
        // ...!
    }
}
Let's pretend that we want all our noise generated with our class to use the same seedable random number generator. How about rand = new MyPRNG();? Or window.rand = new MyPRNG();? Or even this.rand = new MyPRNG()? Unfortunately, all of these methods have at least one problem with them (if you know what's wrong with them, comment down below!). Don't despair though, because we can exploit the fact that classes themselves are objects - and aren't read-only. With this knowledge, we can do something like this:

NoiseGenerator.rand = new MyPRNG(someSeed);
Remember to put the above _after_ the class definition - ES6 classes are a little bit like C++ classes in that they don't exist until the interpreter has executed them (unlike regular old functions). Then in the body of a method, you can access it with something like `NoiseGenerator.rand.nextInt(0, 10);`.

Too many classes

ES6 classes do infact support inheritance under the guise of sub classing. A good example is worth a thousand words I think:

class Vehicle
{
    constructor()
    {
        // ...
    }

    move()
    {
        console.log("Moving vehicle...");
    }

    start() { console.log("Starting..."); }
    stop() { console.log("Stopping."); }
}

class Train extends Vehicle
{
    move()
    {
        super.move();
        console.log("Moving train...");
    }
}

As demonstrated in the example above, classes can inherit from one another with the extends keyword instead of C♯'s colon. The super word replaces the functionality of C♯'s base keyword too. Other than that, there really isn't a lot more to say about inheritance in ES6 besides the fact that almost everything not described works as you'd expect it to in C♯.

That concludes my whirlwind tour of classes in ES6. If I explained in detail every little feature, you'd be here all week reading about it (and I'd be here for the better part of a month writing this post!). ES6 classes also support getters and setters, overriding the default constructor, and more.

Sources and further reading

SnoozeSquad.js - Finally a decent lazy image loader

It's been on my todo list for positively ages, but I've finally gotten around to replacing the existing lazy image loading on this website (not on the blog yet, sorry!) with a new one of my own devising.

Lazy image loading is a technique in which you only load images no a given webpage if they are near the user's field of view. This saves bandwidth by preventing images that are never seen from being downloaded.

Since I've been unable to find a good, solid, reliable lazy image loading script on the web, I thought it best to post about it here so that you can use it too.

Link: SnoozeSquad (Direct download)

Drawing (rotating) shapes

Rotating shapes.

After writing the smooth line class last week I wanted to write another one, and I decided to write a class to aid the drawing regular shapes. While writing the library I found myself with some rather nice looking rotating shapes that I thought would make a good blog post here.

Before I go any further, here's the demo:

See the Pen Rotating shapes by Starbeamrainbowlabs (@sbrl) on CodePen.

The background is a just a set of fancy css3 radial and linear gradients layered on top of one another. The interesting part is the calculating of the points in each shape - let me explain with a hexagon.

Shape drawing explained.

In the above, the hexagon I am drawing is shown in red, and a circle in green. In order to work out the co-ordinates for each corner (or vertex) of the hexagon, we can walk around a circle and note down our location at regular intervals (shown by the blue lines). I learnt this trick from this stack overflow answer. They can explain it much better than I probably could:

Let's assume you want to draw an N-sided polygon of radius r, centred at (0,0). Then the n vertices are given by:

x[n] = r * cos(2*pi*n/N)
y[n] = r * sin(2*pi*n/N)

where 0 <= n < N. Note that cos and sin here are working in radians, not degrees (this is pretty common in most programming languages).

If you want a different centre, then just add the coordinates of the centre point to each (x[n], y[n]). If you want a different orientation, you just need to add a constant angle. So the general form is:

x[n] = r * cos(2*pi*n/N + theta) + x_centre
y[n] = r * sin(2*pi*n/N + theta) + y_centre

By Answerer Avatar Oliver Charlesworth. Source: Stack Overflow

Anyway, here's the code I came up with:

I can't think of anything else I wanted to say, so I think I'll end this post here. Please comment down below if you have anything you want to say :)

Easy Smooth Lines with Bezier Curves

The smooth line class in action.

A while ago I wrote a vector class and a bezier curve class for my 2D graphics University ACW (Assessed CourseWork). After packaging them up and posting them here, I thought it a good idea to take a step further and write a smooth line class too, to start building up a library of implementations of various different algorithms.

While I was searching for a good alternative to jsbin (it doesn't let me use tabs instead of spaces), I came across Codepen again, and finally decided to take a look. Apparently you can do quite a bit with a free account, so I signed up and posted about new my account on this blog.

Since the quality of the content on Codepen is considerably high, and you can see who has done what, I've decided to put more time into the visual effects of the things that I put up on there.

Anyway, here's a demo of my SmoothLine class in action:

See the Pen Smooth Lines by Starbeamrainbowlabs (@sbrl) on CodePen.

Click to add a point. A line will show up when you have 3 points. Here's the class itself:

Note that it depends on my earlier Vector and BezierCurve classes (links above).

The code is actually really simple. You create a new instance of the SmoothLine class, add some Vector points with the add() method (it takes both a single vector and an array of vectors), and then call the line() method when you are reading to add the SmoothLine to your drawing context path.

Here's some example code:

// Creation code
var smoothLine = new SmoothLine();
smoothline.add(new Vector(138, 330));
this.smoothLine.add([
    new Vector(161, 10),
    new Vector(561, 111),
    new Vector(890, 254),
    new Vector(1088, 254),
    new Vector(1152, 130),
    new Vector(1186, 55),
    new Vector(1230, 21)
]);

// Rendering code
context.beginPath();
// Do stuff here
smoothline.line(context, 16);
// Do stuff here
context.stroke();

Over the next few months if I can possibly manage it I want to implement a bunch of other useful algorithms in order to build up a library of code that I can just drop into a project and use. Suggestions for the next algorithm are welcome!

A first look a fractals - Shapes

My fractal shape generator.

Recently I took a little look at fractals, and in order to get my head around the recursive nature of drawing fractals, I wrote a small demo that draws a fractal like thing with shapes. It starts with a triangle, and draws a square at each corner. Then at the corner of each square, it draws a pentagon, and so the pattern continues. I thought it looked interesting, so I decided to share it here.

You can find it here: fractal shapes

You can also find it under the labs section of my homepage.

If anyone is interested in a more detailed explanation of how it works, I'd be happy to write a blog post about it. Comment below if you would like one.

Easy Bezier Curves on the HTML5 Canvas

This is a follow up post to the vector.js post that I made last week, and depends on the vector class I released then. Please take a look at that post first.

Last week, I released a simple Ecmascript 6 vector class that I wrote. It's mildly interesting on its own, but this post is the real reason I wrote that other one. Using that vector class, I then went ahead and wrote my own bezier curve class, that supports an arbitrary number of control points. Before I continue, here's the code:

(Gist, Raw)

I was surprised by how easy the bezier curve algorithm was to implement. Basically, you loop over all your control points, finding the point that lies in a specific percentage of the distance between the current point and the next one. You then repeat this process until you have just a single point remaining. This results in a smooth curve that is skewed towards all of the given control points.

In my implementation, I did it recursively, with all the magic happening in the interpolate() function. It performs the above algorithm given a time between 0 and 1, and spits out the interpolated value. I called it a time here because bezier curves are often used to smooth out animations, and I travel along the line in the curve() function when applying it to the given canvas rendering context.

To use it, you first create an instance like so:

var bz = new BezierCurve([
    new Vector(38, 41),
    new Vector(96, 302),
    new Vector(807, 12)
]);

Then, in your rendering function, you can ask your new bezier curve to add itself to any given canvas rendering context like this:

// ...

context.beginPath();
// ...
bz.curve(context, 32);
// ...
context.stroke();

// ...

The segmenting algorithm in action.

The second argument in the curve() call above is the number of segments to use when rendering. This tells the bezier curve class how many different points along the line it should calculate. More segments make it smoother, but will consume more processing power when first calculated. Pick just enough that you can't tell that the bezier curve is made up of lines - this is different for every curve.

I added a caching function to it too, so if you call the curve() function with the same number of segments more than once, it uses the interpolated values it calculated previously instead of calculating them all over again. This isn't the case if you call it with a different number of segments each time, however. If you want to do this, I suggest that you create a new instance for each different segment number that you need.

That concludes this post on my own bezier curve class. It's a little bit buggy in places (see the gif above), but I haven't managed to track down the issue. It should work fine for most purposes, though. If you do manage to spot the mistake, please let me know!

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.

Art by Mythdael