The Software Simpleton

Nomadic cattle rustler and inventor of the electric lasso

Tangent to a Curve on Mousemove With d3.js and math.js

I am available for work right now, if you are interested then email me directly.

Following on from my last post on axes positioning, I have added the functionality to add a tangent to the curve on mousemove. You can see a working example here by dragging the mouse over the svg document.

Below is a screenshot of the end result:

The first steps are to create the elements that I will use to display the tangent indicator and also to hook up an event listener for mousemove on the svg document:

listener.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
    g.append('circle')
      .attr('class', 'diff')
      .attr('cx', 0)
      .attr('cy', 0)
      .attr('r', 7)
      .style('fill', 'red');

    g.append('text')
      .attr('class', 'difflabel');

    g.append('line')
      .style('stroke', 'red')
      .attr('class', 'tangent')
      .attr('x1', xScale(0))
      .attr('y1', yScale(0))
      .attr('x2', xScale(0))
      .attr('y2', yScale(0));

d3.select('svg').on('mousemove', mouseMove);

The above creates a circle to indicate where on the curve the mouse is relative to the x axis. A label is created to display the coordinate that the mouse is currently on with respect to the curve and lastly I create a line that will display the tangent.

Line 19 adds a mousemove handler to the svg element that has been previously created with the code below:

svg.js
1
2
3
4
5
6
7
8
9
10
componentDidMount() {
  const el = this.refs.curve;

  const dimensions = this.getDimensions();

  this.svg = d3.select(el).append("svg")
        .attr("width", dimensions.width + dimensions.margin.left + dimensions.margin.right)
        .attr("height", dimensions.height + dimensions.margin.top + dimensions.margin.bottom)
        .append("g")
        .attr("transform", "translate(" + dimensions.margin.left + "," + dimensions.margin.top + ")");

The goal of the mousemove handler is to draw the tangent of the curve with respect to the x axis as the mouse moves over the svg document.

In geometry, the tangent line to a plane curve at a given point is the straight line that just touches the curve at that point.

I can get the x for the tangent line from the mouse coordinates of the mousemove function:

xcoordinate.js
1
2
3
4
const mouseMove = function() {
  const m = d3.mouse(d3.select('.curve').node());

  let x = m[0];

With this, I can use mathematical differential calculus to work out the tangent line. If I was to perform these steps with pen and paper, I would take the following steps:

  • Find the derivative of the curve
  • Substitute the x retreived from the mousemove event into the derivative to calculate the gradient (or slope for the US listeners) of the line.
  • Substitute the gradient of the tangent and the coordinates of the given point into the equation of the line in the format y = mx + c.
  • Solve the equation of the line for y.

What was surprising and enjoyable for me was that the steps on paper transferred into machine instructions quite well which is not always the case.

Before I plot the line, I want to position my circle and label onto the curve. I am already using the excellent mathjs library to get the coordinates to draw the curve:

data.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
getDataFromProps(expr) {
  const expression = math.parse(expr);


  const fn = (x) => {
    return expression.eval({x: x});
  };

  return d3.range(-10, 11).map( (d) => {
    return {x:d, y:fn(d)};
  });
}

drawCurve(data) {
  const xScale = this.xScale;
  const yScale = this.yScale;
  const svg = this.svg;

  const line = d3.svg.line()
          .interpolate('basis')
          .x( (d) => {return xScale(d.x);})
          .y( (d) => {return yScale(d.y);});

Line 2 of the above code uses mathjs’s parse function to create an expression from the string input of the form:

Once I have the expression, I can evaluate it with different values. Lines 5 and line 9 evaluates the expression for each x value in a predetermined range of values. Line 19 plots the line.

As I know what x is from the mouse event, I can use mathjs to parse my expression with respect to x and get the y coordinate to position my label on the curve:

ycoordinate.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
const mouseMove = function() {
  const m = d3.mouse(d3.select('.curve').node());

  let x = m[0];

  let y = yScale(math.parse(me.props.expression).eval({
    x: xScale.invert(x)
  }));

  const point = {
    x: xScale.invert(x),
    y: yScale.invert(y)
  };

  if(point.x > maxX) {
    point.x = maxX;
    point.y = maxY;

    x = xScale(maxX);
    y = yScale(maxY);
  }

  g.select('.diff')
    .attr('cx', x)
    .attr('cy', y);

  g.select('.difflabel')
    .text( function() {
      const xLabel = Math.round(point.x);
      const yLabel = Math.round(point.y);

      return `(${xLabel}, ${yLabel})`;
    })
    .attr('dx', x + 10)
    .attr('dy', y + 8);

Lines 2 and 4 retrive x from the mouse event and line 6 evaluates y by parsing and evaluating the equation of the curve with respect to x. I then use the x and y coordinates to position my label elements.

Mathjs does not come with its own differentiation module to work out the derivative of the user entered expression but I found this plugin that seems to work out well for this task.

Armed with this module, it was plain sailing to create an equation for the tangent line that I could use to find out y values for the tangent.

tangent.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
const derivative = math.diff(math.parse(me.props.expression), "x");

const gradient = derivative.eval({x: point.x});

const yIntercept = getYIntercept(point, gradient);

const lineEquation = math.parse("m * x + c");

const getTangentPoint = (delta) => {
  const deltaX = xScale.invert(x + delta);

  const tangentPoint = {
    x: deltaX,
    y: lineEquation.eval({
      m: gradient,
      x: deltaX,
      c: yIntercept
    })
  };

  return tangentPoint;
};

const length = xScale(200);

const tangentPoint1 = getTangentPoint(+ length);
const tangentPoint2 = getTangentPoint(- length);

g.select('.tangent')
  .attr('x1', xScale(tangentPoint1.x))
  .attr('y1', yScale(tangentPoint1.y))
  .attr('x2', xScale(tangentPoint2.x))
  .attr('y2', yScale(tangentPoint2.y));
  • Line 1 creates a derivative function from the equation of the curve.
  • The derivative function is evaluted to get the gradient or slope for the US viewers on line 3.
  • The c constant or y-intercept of the equation of the line y = mx + c is retrieved on line 5.
  • Mathjs is employed to create an expression in the format of y = mx + c.
  • A getTangentPoint function is created that will be used to get the points at either end of the function.
  • Lines 24 - 26 create 2 points for x that will be far off the length and height of the svg document to give the impression of stretching off to infinity.
  • Each point gets its y value by calling the getTangentPoint funtion on line 9 that in turn will solve for x for the equation of the line function previously created on line 7.
  • Once we have the pair of points, the line can be plotted on lines 29 - 33.

You can see the end result here.

The following util function will return the y-intercept for a point and gradient:

yintercpet.js
1
2
3
export function getYIntercept(vertex, slope) {
  return vertex.y - (slope * vertex.x);
}

I am available for work right now, if you are interested then email me directly.

Negative Axes and Axes Positioning With d3.js

I am available for work right now, if you are interested then email me directly.

Up until now when I have been dealing with d3.js’s axes components, I have always kept the axes positive, i.e. both the x and y axes where showing values greater than 0.

I have been hacking around with this fun side project that takes the input of an algebraic expression and plots a graph for a sample range of values for x. You can checkout the source code here if you are interested.

Below is a screenshot of the end result:

It quickly became apparent that in order to show the curve of the expression properly, I would need to construct negative and positive x and y axes.

I have the following function below that constructs the data of x and y coordinates to plot the curve against which uses the excellent mathjs library to transform the string algebraic expression into a javascript function (line 2). I then create a sample range for x values ranging from -10 to 11 and evaluate the y coordinate for each item in the range by applying the function on line 5 to each item:

expression.js
1
2
3
4
5
6
7
8
9
10
11
12
  getDataFromProps(expr) {
    const expression = math.parse(expr);


    const fn = (x) => {
      return expression.eval({x: x});
    };

    return d3.range(-10, 11).map( (d) => {
      return {x:d, y:fn(d)};
    });
  }

Armed with this data, I can now construct my axes.

I first create the axis against a scale that is in proportion with the viewport dimensions.

axes.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
    const dimensions = this.getDimensions();

    xScale = d3.scale.linear()
          .range([0, dimensions.width]);

    yScale = d3.scale.linear()
          .range([dimensions.height, 0]);

    const xAxis = d3.svg.axis()
            .scale(xScale);

    const yAxis = d3.svg.axis()
            .orient('left')
            .scale(yScale);

The domain function of d3 allows you to specify a minimum and maximum value as the range of values that we can use for a particular axis.

Below I am using d3’s extent function that returns the minum and maximum values of an array and is equivalent to calling d3.min and d3.max simultaneously.

extent.js
1
this.xScale.domain(d3.extent(data, function (d) {return d.x;}));

As I am supplying the values for the range of x values in the code above, I know that I will always have negative x values and positive x values.

The y coordinates are different depending on the function generated from the algebraic expression. Depending on the expression, there are basically 3 conditions I want to capture when displaying a curve.

The first case is when there are only positive y values:

The next case is when there are both negative and positive y values;

Lastly, only negative y values:

With this in mind, the code below creates a domain based on the minimum values of y and the maximum values of y:

minimamaxima.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
const minY = d3.min(data, (d) => { return d.y; });
const maxY = d3.max(data, (d) => { return d.y; });

const nonNegativeAxis = minY >= 0 && maxY >= 0;
const positiveAndNegativeAxis = minY < 0 && maxY > 0;

let yScaleDomain, xAxisPosition;

if(nonNegativeAxis) {
  yScaleDomain = [0, d3.max(data, (d) => {return d.y;})];
}  else {
  yScaleDomain = d3.extent(data, (d) => {return d.y;});
}

this.yScale.domain(yScaleDomain);

this.svg.append('g')
  .attr('class', 'axis')
  .attr('transform', 'translate(' + dimensions.width/2 + ',0)')
  .call(yAxis);

I either start my domain at 0 or use d3.extent again to get the maximum and minimum values for y like I did before for x.

The last problem to solve was to position the x axis. In the 3 code samples below, I am capturing the domain for y and the x axis position for each condition.

This is easy if I only have negative or positive values for y. I can simply place the x axis at the bottom for only positive values:

pos.js
1
2
yScaleDomain = [0, d3.max(data, (d) => {return d.y;})];
xAxisPosition = dimensions.height;

When I have only negative values, then I can place the x axis at the top of the document:

neg.js
1
2
yScaleDomain = d3.extent(data, (d) => {return d.y;});
xAxisPosition = 0;

The interesting case was when I have both positive and negative values for y.

What I ended up doing was selecting all the ticks or labels from the y axis and finding the label that had 0 against it and from that I could use d3 to to select its position and then use that for my x axis position.

Below is the code that does that:

both.js
1
2
3
4
5
xAxisPosition = this.svg.selectAll(".tick").filter((data) => {
    return data === 0;
}).map((tick) => {
    return d3.transform(d3.select(tick[0]).attr('transform')).translate[1];
});

In the code above, I filter out all the other ticks apart from the 0 label. The zero tick is then passed into the map function which selects the transform attribute of the tick which might look something like this translate(0,280). The second value of translate, 280 in this instance gives me the position of the 0 label in the y axis. I can use this value to position my x axis.

Once I have the position of 0 in the y axis, I can position the axis to the document:

xaxis.js
1
2
3
4
this.svg.append('g')
    .attr('class', 'axis')
    .attr('transform', 'translate(0,' + xAxisPosition + ')')
    .call(xAxis);

When it comes to positioning the y axis, I simply divide the width by 2 and position it there:

ypos.js
1
2
3
4
this.svg.append('g')
  .attr('class', 'axis')
  .attr('transform', 'translate(' + dimensions.width/2 + ',0)')
  .call(yAxis);

I am available for work right now, if you are interested then email me directly.

Resize to Scale With d3.js

I am available for work right now, if you are interested then email me directly.

Following on from my last two posts, Perpendicular Bisectors of a Triangle With d3.js and Altitude of a Triangle With d3.js, I want to document how I ensured that my svg tranformation is resized to scale during a resize event or if the user selection can change.

Below is the end result of the last two blog posts:

You can see the result at this url.

You can change the current triangle effects by changing the radio buttons at the top. You can also drag and drop the triangle vertices by dragging the red circles at each triangle endpoint or vertex. This led to an interesting problem, which was how to how to maintain the current state or coordinates of all the shapes when the user selects a new effect from the radio buttons.

Another, more challening problem was to make sure that everything resized to the current ratio or scale if the browser window is resized. If you go to this url and resize the browser, you can see that everything re-renders nicely to scale. This does not happen out of the box. You need to code for this eventuality.

The bulk of the work takes place in the render method below:

render.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
function render(state = {}) {
  if(state.resizeFunc) {
    window.removeEventListener("resize", state.resizeFunc);
  }

  const viewportDimensions = availableViewPort();

  const availableHeight = viewportDimensions.h - 50;
  const availableWidth = availableHeight * 1.32;

  const margin = {top: 20, right: 100, bottom: 30, left: 100},
        width = availableWidth - margin.left - margin.right,
        height = availableHeight - margin.top - margin.bottom;

  d3.select("body").select("svg").remove();

  d3.selectAll('label').remove();
  d3.selectAll('input[type=radio]').remove();

  const xScale = d3.scale.linear()
          .domain([0, 20])
          .range([0, width]);

  const yScale = d3.scale.linear()
          .domain([0, 20])
          .range([height, 0]);

  let points;

  if(state.points) {
    points = {
      a: {
        x: xScale(state.xScale.invert(state.points.a.x)),
        y: yScale(state.yScale.invert(state.points.a.y))
      },
      b: {
        x: xScale(state.xScale.invert(state.points.b.x)),
        y: yScale(state.yScale.invert(state.points.b.y))
      },
      c: {
        x: xScale(state.xScale.invert(state.points.c.x)),
        y: yScale(state.yScale.invert(state.points.c.y))
      }
    };
  } else {
    points = {
      a: {x: xScale(0), y: yScale(0)},
      b: {x: xScale(6), y: yScale(18)},
      c: {x: xScale(16), y: yScale(2)}
    };
  }

  const xAxis = d3.svg.axis()
          .scale(xScale)
          .orient("bottom");

  const yAxis = d3.svg.axis()
          .scale(yScale)
          .orient("left");

  const svg = d3.select("body").append("svg")
          .attr("width", width + margin.left + margin.right)
          .attr("height", height + margin.top + margin.bottom)
          .append("g")
          .attr("transform", "translate(" + margin.left + "," + margin.top + ")");

  svg.append('g')
    .attr('class', 'x axis')
    .attr("transform", "translate(0," + height + ")")
    .call(xAxis);

  svg.append('g')
    .attr('class', 'y axis')
    .call(yAxis);

  const area = {
    xScale: xScale,
    yScale: yScale
  };

  area.currentEffect = state.currentEffect || drawMedians;

  area.points = points;

  addRadioButtons(area);

  const g = svg.append('g');

  area.g = g;
  area.svg = svg;

  const vertices = [
    {point: area.points.a, label: 'a'},
    {point: area.points.b, label: 'b'},
    {point: area.points.c, label: 'c'}
  ];

  drawTriangle(points, g);

  addCurrentEffects(area);

  addPointLabels(area, vertices);

  addGrabbers(area, vertices);

  const resizeFunc = render.bind(null, area);

  area.resizeFunc = resizeFunc;

  window.addEventListener("resize", area.resizeFunc);
}

The render function as you might expect, creates the svg document and renders all the shapes onto their specific coordinates as I outlined in the previous blog posts here and here. I use this function to both initially draw the shapes and also as the function that is attached to the resize event.

Below is the end of the render function that creates a hash that will keep track of the current state of the document or the coordinates of the all the shapes at any given time.

render2.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
  const area = {
    xScale: xScale,
    yScale: yScale
  };

  area.currentEffect = state.currentEffect || drawMedians;

  area.points = points;

  addRadioButtons(area);

  const g = svg.append('g');

  area.g = g;
  area.svg = svg;

  const vertices = [
    {point: area.points.a, label: 'a'},
    {point: area.points.b, label: 'b'},
    {point: area.points.c, label: 'c'}
  ];

  drawTriangle(points, g);

  addCurrentEffects(area);

  addPointLabels(area, vertices);

  addGrabbers(area, vertices);

  const resizeFunc = render.bind(null, area);

  area.resizeFunc = resizeFunc;

  window.addEventListener("resize", area.resizeFunc);

Lines 1 to 3 create a the hash and assign the xScale and yScale d3 scale objects that allow you to deal with a finer granuated scale than pixels. The x and y axis in the documment were created using these scale objects and you can think in terms of placing these objects at coordinates on these scales, e.g. (1, 1).

Lines 6 to 29 assign properties to this area hash such as the vertices of the triangle that will be used to read and write to when drawing the shapes. I pass this structure into most functions.

Line 31 uses the lesser known partial application properties of the bind function to create a new version of the render function. This partial function when called, will always be called with the area hash as an argument, that contains all the information we need to reconstruct the document. Line 33 adds this function to the hash, we will use this to remove the event listener each time it is called or else there will be a memory leak. LIne 35 creates an event listener for the resize event and assigns the new version of render to this event.

The beginning of the render function below uses the new es6 default paramaters feature to allow render to be called with no arguments or called from the resize event with an argument. If it is called in response to a resize event then there will be a state argument. Lines 2 to 5 remove the event listener each time it is called.

render3.js
1
2
3
4
function render(state = {}) {
  if(state.resizeFunc) {
    window.removeEventListener("resize", state.resizeFunc);
  }

Everytime render is called, I create new xScale and yScale objects that reflect the current window size on line 15 - 21 below:

render5.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
  const viewportDimensions = availableViewPort();

  const availableHeight = viewportDimensions.h - 50;
  const availableWidth = availableHeight * 1.32;

  const margin = {top: 20, right: 100, bottom: 30, left: 100},
        width = availableWidth - margin.left - margin.right,
        height = availableHeight - margin.top - margin.bottom;

  d3.select("body").select("svg").remove();

  d3.selectAll('label').remove();
  d3.selectAll('input[type=radio]').remove();

  const xScale = d3.scale.linear()
          .domain([0, 20])
          .range([0, width]);

  const yScale = d3.scale.linear()
          .domain([0, 20])
          .range([height, 0]);

Below is the code that will reassign the points of the triangle to scale from the state hash:

render3.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
  if(state.points) {
    points = {
      a: {
        x: xScale(state.xScale.invert(state.points.a.x)),
        y: yScale(state.yScale.invert(state.points.a.y))
      },
      b: {
        x: xScale(state.xScale.invert(state.points.b.x)),
        y: yScale(state.yScale.invert(state.points.b.y))
      },
      c: {
        x: xScale(state.xScale.invert(state.points.c.x)),
        y: yScale(state.yScale.invert(state.points.c.y))
      }
    };
  } else {
    points = {
      a: {x: xScale(0), y: yScale(0)},
      b: {x: xScale(6), y: yScale(18)},
      c: {x: xScale(16), y: yScale(2)}
    };
  }

If we have a state hash then the invert method of the scale objects is used to get the value in pixels before using the scale to recreate the new x and y coordinates that are in scale with the new browser dimensions.

I also use partial application when adding the drag and drop event to the red circles at the vertices of the triangle on line 22 of the below:

drag.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
function addPointLabels(area, vertices) {
  area.g.selectAll('text')
    .data(vertices)
    .enter().append('text')
    .attr("x", function(d){return d.point.x + 10;})
    .attr("y", function(d){return d.point.y + 10;})
    .attr('class', function(d) {return "label " + d.label;})
    .text( function(d) {
      const x = Math.round(area.xScale.invert(d.point.x));
      const y = Math.round(area.yScale.invert(d.point.y));

      return `${d.label.toUpperCase()} (${x}, ${y})`;
    })
    .attr("font-family", "sans-serif")
    .attr("font-size", "24px")
    .attr("fill", "black");
}

function addGrabbers(area, vertices) {
  const drag = d3.behavior
        .drag()
        .on("drag", draggable.bind(null, area));

After all this, I take great pleasure in resizing the window and watching everything beautifully scale.

You can checkout the github repo that contains all the code for this.

I am available for work right now, if you are interested then email me directly.

Perpendicular Bisectors of a Triangle With d3.js

Following up from my last post on how to draw the altitude of a side of a triangle through a vertex, I wanted to draw the 3 perpendicular bisectors of a triangle and the circumcircle of the triangle.

Let us get some definitions for these terms, the perpendicular bisectors of a circle are described as:

the lines passing through the midpoint of each side of which are perpendicular to the given side.

Below is a triangle with one perpendicular bisector running through side AB .

The circumcircle of a triangle is:

The point of concurrency of the 3 perpendicular bisectors of each side of the triangle.

The centre point of the circumcircle is the point of intersection of all the perpendicular bisectors of a triangle.

Below is a triangle with all 3 perpendicular bisectors and the circumcircle drawn with d3.js.

The first step was to draw one perpendicular bisector of a triangle.

I chose 3 arbitary points for the vertices of the triangle.

points.js
1
2
3
4
5
const points = {
  a: {x: xScale(1), y: yScale(1)},
  b: {x: xScale(5), y: yScale(19)},
  c: {x: xScale(17), y: yScale(6)}
};

This is all the information I need, to calculate the perpendicular bisectors and the circumcircle.

If I wanted to find the perpendicular bisector of AB using pen and paper, I would perform the following steps:

  • I would find the gradient or slope (for US readers) of the point AB.
  • I would then find the perpendicular gradient or slope which would give me the ratio of rise over run that the perpendicular line flows through. If lines are perpendicular then M1 x M2 = -1.
  • I would find the midpoint of the line using the distance formula ((x1 + x2 / 2), (y1 + y2 / 2)).
  • I could then plug these values into the equation of a line which takes the form of y = mx + c.

I have blogged previously in this post about how to set up the graduated x and y axis and a more managable scale for positioning vertices etc.

My first step was to find the perpendicular bisector of the line AB.

Below are two helper functions that take javascript point objects as arguments with x and y properties that map to coordinates and return either a gradient/slope or the perpendicular gradient/slope that occurrs between the 2 coordinates:

gradient.js
1
2
3
4
5
6
7
const gradient = function(a, b) {
  return ((b.y - a.y) / (b.x - a.x));
};

const perpendicularGradient = function (a, b) {
  return -1 / gradient(a, b);
};

Below is a helper function to find the midpoint between two vertices or points:

midpoint.js
1
2
3
const midpoint = function(a, b) {
return {x: ((a.x + b.x) / 2), y: ((a.y + b.y) / 2)};
};

Using these values, I can then find the y-intercept or the point where the perpendicular line will cut the y-axis.

Below is a function that will find the y-intercept given a vertex and a gradient/slope:

yintercept.js
1
2
3
function getYIntercept(vertex, slope) {
  return vertex.y - (slope * vertex.x);
}

You can think of the above function as rearranging y = mx + c to solve for c or c = y - mx.

All that is left is to find the x-intercept or the point where the bisector line cuts the x-axis.

Below is the code that brings this all together:

perpendicular-bisector.js
1
2
3
4
5
function perpendicularBisector(a, b) {
  const slope = perpendicularGradient(a, b),
        midPoint = midpoint(a, b),
        yIntercept = getYIntercept(midPoint, slope),
        xIntercept =  - yIntercept / (slope);

The x-intercept on line 5 is again re-arranging the equation of the line formula y = mx + c to solve for x.

The finshed function looks like this and there are a number of if statements I had to add for the conditions when the slope or gradient function might end up undefined or equalling infinity when it encounters horizontal or vertical values that have catches with the formula. I would love to know if there is an algorithm that will avoid such checks:

perpendicularBisector.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
function perpendicularBisector(a, b) {
  const slope = perpendicularGradient(a, b),
        midPoint = midpoint(a, b),
        yIntercept = getYIntercept(midPoint, slope),
        xIntercept =  - yIntercept / (slope);

  if((yIntercept === Infinity || yIntercept === -Infinity)) {
    return drawTriangleLine(g, {
      x1: xScale(midPoint.x),
      y1: yScale(0),
      x2: xScale(midPoint.x),
      y2: yScale(20)
    });
  }

  if((a.x === b.x) || isNaN(xIntercept)) {
    return drawTriangleLine(g, {
      x1: xScale(0),
      y1: yScale(midPoint.y),
      x2: xScale(20),
      y2: yScale(midPoint.y)
    });
  }

  if(xIntercept < 0 || yIntercept < 0) {
    return drawTriangleLine(g, {
      x1: xScale(xIntercept),
      y1: yScale(0),
      x2: xScale(20),
      y2: yScale((slope * 20) + yIntercept)
    });
  }

  drawTriangleLine(g, {
      x1: xScale(xIntercept),
      y1: yScale(0),
      x2: xScale(0),
      y2: yScale(yIntercept)
    });

  return {vertex: midPoint, slope: slope};
}

The drawTriangleLine function looks like this and simply adds a d3.js line:

drawTriangleLine.js
1
2
3
4
5
6
7
8
9
const drawTriangleLine = function drawTriangleLine(group, vertices) {
  group.append('line')
    .style('stroke', 'green')
    .attr('class', 'line')
    .attr('x1', vertices.x1)
    .attr('y1', vertices.y1)
    .attr('x2', vertices.x2)
    .attr('y2', vertices.y2);
};

Every time I call the perpendicularBisector function, I return an object that contains a vertex and point that I can use to draw the circumcircle.

return.js
1
return {vertex: midPoint, slope: slope};

All that is left is to draw the circumcircle and here is the function I wrote to do just that:

circumcircle.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
function drawCirumCircle(lineA, lineB) {
  if(!lineA || !lineB) {
    return;
  }

  const x1 = - lineA.slope,
      y1 = 1,
      c1 = getYIntercept(lineA.vertex, lineA.slope),
      x2 = - lineB.slope,
      y2 = 1,
      c2 = getYIntercept(lineB.vertex, lineB.slope);

  const matrix = [
    [x1, y1],
    [x2, y2]
  ];

  const circumCircleCentre = solveMatrix(matrix, [c1, c2]),
      dist = distance(convertPoint(points.b), circumCircleCentre);

  g.append('circle')
   .attr('cx', xScale(circumCircleCentre.x))
   .attr('cy', yScale(circumCircleCentre.y))
   .attr('r', xScale(dist))
   .attr('class', 'circumcircle')
   .attr('fill-opacity', 0.0)
   .style('stroke', 'black');
}

In order to find the centre of the circumcirle or the point of intersection of the perpendicular bisectors, the function takes two arguments lineA and lineB which are two of the perpendicular bisectors of the traingle. The function then arranges these line objects into y = mx + c format on lines 6 to 11 of the above. I then solve these equations simulataneously using matrices and specifically using cramer’s rule to find the point where the line intersect.

Once I have the 2x2 matrix assembled on lines 13-16, I then pass it to the solveMatrix function with the 2 y-intercept values that will apply cramer’s rule:

solveMatrix.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
function det(matrix) {
  return (matrix[0][0]*matrix[1][1])-(matrix[0][1]*matrix[1][0]);
}

function solveMatrix(matrix, r) {
   const determinant = det(matrix);
   const x = det([
      [r[0], matrix[0][1]],
      [r[1], matrix[1][1]]
    ]) / determinant;

   const y = det([
     [matrix[0][0], r[0]],
     [matrix[1][0], r[1]]
   ]) / determinant;

  return {x: Math.approx(x), y: Math.approx(y)};
}

I now have the point of intersection of the perpendicular bisectors. All I need to know now is the radius of the circle. The calculation I used is to use the distance formula. From the point of intersection we just found to one of the vertices of the triangle.

Below is a helper function for the distance formuala:

distance.js
1
2
3
function distance(a, b) {
  return Math.floor(Math.sqrt(Math.pow((b.x - a.x), 2) + Math.pow((b.y - a.y), 2)));
}

All I have to do now is draw the circle from the two knowns, i.e. the point of intersection and the radius:

circle.js
1
2
3
4
5
6
7
8
9
10
  const circumCircleCentre = solveMatrix(matrix, [c1, c2]),
      dist = distance(convertPoint(points.b), circumCircleCentre);

  g.append('circle')
   .attr('cx', xScale(circumCircleCentre.x))
   .attr('cy', yScale(circumCircleCentre.y))
   .attr('r', xScale(dist))
   .attr('class', 'circumcircle')
   .attr('fill-opacity', 0.0)
   .style('stroke', 'black');

Here is a working jsbin that illustrates all I have wrote about.

I have also added drag and drop so you can drag the vertices around by the red circles and watch it all redraw.

Please leave a comment below if I could have achieved this in a more efficient way.

Altitude of a Triangle With d3.js

I’m back at college learning the maths that I should have learned a long time ago. I am also trying to kill 2 birds with one stone by using what I’ve learned to help me learn d3.js at the same time. The task I set myself this week was to draw the altitude of a triangle through a point.

In geometry, an altitude of a triangle is a line segment through a vertex (point) and perpendicular (i.e. forming a right angle with) a line containing the base (the opposite side of the triangle). This line containing the opposite side is called the extended base of the altitude.

My first steps are to create a scale that is of much lower resolution than the finely grained pixels and below is the code that creates both the scale and the axis. I blogged about scales in more detail in my last blog post:

scale.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
var margin = {top: 20, right: 100, bottom: 30, left: 100},
    width = 660 - margin.left - margin.right,
    height = 500 - margin.top - margin.bottom;

var xScale = d3.scale.linear()
    .domain([0, 20])
    .range([0, width]);

var yScale = d3.scale.linear()
    .domain([0, 20])
    .range([height, 0]);

var xAxis = d3.svg.axis()
    .scale(xScale)
    .orient("bottom");

var yAxis = d3.svg.axis()
    .scale(yScale)
    .orient("left");

var svg = d3.select("body").append("svg")
    .attr("width", width + margin.left + margin.right)
    .attr("height", height + margin.top + margin.bottom)
    .append("g")
    .attr("transform", "translate(" + margin.left + "," + margin.top + ")");

svg.append('g')
    .attr('class', 'x axis')
    .attr("transform", "translate(0," + height + ")")
    .call(xAxis);

svg.append('g')
    .attr('class', 'y axis')
    .call(yAxis);

I then created 3 arbitrary vertices for my triangle that would fill the x and y axis as much as possible:

points.js
1
2
3
var a = {x: xScale(1), y: yScale(1)},
    b = {x: xScale(6), y: yScale(18)},
    c = {x: xScale(14), y: yScale(6)};

My next task was to then try and draw a triangle from these points. Below is what I ended up with before I explain the solution:

After a bit of trial and error by first of all trying to draw lines with the line function, I came across d3’s path function:

path.js
1
2
3
4
5
6
7
8
svg.append('path')
    .attr('d', function(d) {
      return 'M ' + a.x +' '+ a.y +
             ' L' + b.x + ' ' + b.y +
             ' L' + c.x + ' ' + c.y +
             ' z';
    })
    .style('stroke', 'blue');

This is effectively a DSL or mini-language for drawing shapes.

I’ll add a translation for each line:

  • 'M ' + a.x +' '+ a.y + - This means place a point at the x and y coordinates of the point I previously created with var a = {x: xScale(1), y: yScale(1)}. This is analgous to the starting point where you might place your pen.
  • ' L' + b.x + ' ' + b.y + - This means draw a line created from the point created above to the point b that was declared like this b = {x: xScale(6), y: yScale(18)}. Because we are using scales, we can pick nice friendly points like (6,18) rather than the harshness of pixels.
  • ' L' + c.x + ' ' + c.y + - draw a line to the c point
  • the z command closes the path.

I really like the path function as it is how a human would draw a triangle with pen and paper and is very easy to grok.

With the easy bit done, I now wanted to draw the altitude through point A that would be perpendicular to line BC.

If I was doing this with pen and paper, I would perform the following steps:

  1. I would find the gradient (or slope for those of you from the US) of the line BC.
  2. I would use this gradient/slope to create the equation of the line in y = mx + c format.
  3. I would find the perpendicular gradient/slope of BCthat I can use to create an equation of the line that will go through point A and will be perpendicular to point C in y = mx + c format.
  4. I would then solve these simultaneously to find the point of intersection from point A to the point on BC that was perpendicular to point A.

What I quickly found out was that transfering pen to paper calculations to machine instructions or javascript was extremelly difficult and different. Here are the steps I took:

Like in the pen and paper version, I found the grandient of BC and created this function:

gradient.js
1
2
3
var gradient = function(a, b) {
  return (b.y - a.y) / (b.x - a.x);
};

I then created a function to find the perpendicular gradient using the graident found in point 1:

perpendicular.js
1
2
3
var perpendicularGradient = function (a, b) {
  return -1 / gradient(a, b);
};

In order to get both line equations into y = mx + c, I needed a function that would take a point and a gradient and give me the y-intercept or the point where the line cuts the y-axis:

y-intercept.js
1
2
3
function getYIntercept(vertex, slope) {
  return vertex.y - (slope * vertex.x);
}

I could then get the y, mx and c values of y + mx = c for both lines so I could solve the equations simultaneously.

points.js
1
2
3
4
5
6
7
8
  var slope = gradient(a, b),
      x1 = - slope,
      y1 = 1,
      c1 = getYIntercept(a, slope),
      perpendicularSlope = perpendicularGradient(a, b),
      x2 = - perpendicularSlope,
      y2 = 1,
      c2 = getYIntercept(vertex, perpendicularSlope);

I would use the substitution method or the addition method to solve a series of equations with pen in paper but writing it in code was a different matter and matrices seemed like the obvious fit. Please write a comment below if there is a more efficient way. There is cramer’s law which seemed ideal for my needs. I needed to get my vars into the following format:

matrix.js
1
2
[x1, y1] [x]  = [c1]
[x2, y2] [y]  = [c2]

Below is my altitude function that gets the values into matrices before passing to a function that will use cramer’s law to find the point of intersection.

altitude.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
function altitude(vertex, a, b) {
  var slope = gradient(a, b),
      x1 = - slope,
      y1 = 1,
      c1 = getYIntercept(a, slope),
      perpendicularSlope = perpendicularGradient(a, b),
      x2 = - perpendicularSlope,
      y2 = 1,
      c2 = getYIntercept(vertex, perpendicularSlope);

  var matrix = [
    [x1, y1],
    [x2, y2]
  ];

  var result = solveMatrix(matrix, [c1, c2]);

Below is the function I used to first of all find the determinant of the matrix before applying cramer’s law:

cramer.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
function det(matrix) {
  return (matrix[0][0]*matrix[1][1])-(matrix[0][1]*matrix[1][0]);
}

function solveMatrix(matrix, r) {
   var determinant = det(matrix);
   var x = det([
      [r[0], matrix[0][1]],
      [r[1], matrix[1][1]]
    ]) / determinant;

   var y = det([
     [matrix[0][0], r[0]],
     [matrix[1][0], r[1]]
   ]) / determinant;

  return {x: Math.approx(x), y: Math.approx(y)};
}

The above returns a point that I can then use to join point A to the point of intersection returned from the solveMatrix function.

line.js
1
2
3
4
5
6
7
  g.append('line')
    .style('stroke', 'red')
    .attr('class', 'line')
    .attr('x1', xScale(vertex.x))
    .attr('y1', yScale(vertex.y))
    .attr('x2', xScale(result.x))
    .attr('y2', yScale(result.y));

I want to add drag and drop to rotate the triangle so I’ll probably need to put checks in for vertical and horizontal values for x and y but this will do for now.

Below is the end result of my troubles with the altitudes of all three vertices shown.

The hardest part was to solve the simultaneous equations and I belive there is a better and more efficient way that uses vectors to work this out but I have not covered this with my course as yet.

Here is a working jsbin of my efforts.

Grid Lines and the Equation of a Line With d3.js

I’ve recently gone back to college to do a higher maths class at night and I want to use some of the concepts I am learning in my programming to enforce what I have learned so far. I’ve been meaning to learn d3 for some time so this seems like a perfect opportunity to kill two birds with one stone. I thought I would start with something simple and have a draggble line that shows the equation of a straight line with respect to the two coordinates at the end of each line. The equation of a line may still exist in the memories of your shool days.

Here is a jsbin with the product of my fumblings. You can drag the line by either of the red circles at each end and the calculations will recalculate.

Below is the end result

I will now breakdown the code:

The first code blocks create an x and a y scale that will scale from 0 to 20 units in each axis which is preferable to using the much more granular pixels. These scales are used to create the labels on the x and y axis and also make positioning elements much, much easier.

scale.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
var margin = {top: 20, right: 100, bottom: 30, left: 100},
    width = 960 - margin.left - margin.right,
    height = 500 - margin.top - margin.bottom;

var xScale = d3.scale.linear()
    .domain([0, 20])
    .range([0, width]);

var yScale = d3.scale.linear()
    .domain([0, 20])
    .range([height, 0]);

var xAxis = d3.svg.axis()
    .scale(xScale)
    .orient("bottom")
    .innerTickSize(-height)
    .outerTickSize(0)
    .tickPadding(10);

var yAxis = d3.svg.axis()
    .scale(yScale)
    .orient("left")
    .innerTickSize(-width)
    .outerTickSize(0)
    .tickPadding(10);
  • Lines 1 to 3 simply define some dimensions for the document and a margin.
  • Line 5 - 7 and lines 8 - 11 create an x axis and y axis respectively which will use the available width and height to spread out the 20 units of scale across each axis.

Scales

The definition of a scale from the d3 wiki is:

Scales are functions that map from an input domain to an output range.

Scales transform a number in a certain interval (called the domain) into a number in another interval called the range. If we look at the code used to create the x axis scale:

x-scale.js
1
2
3
var xScale = d3.scale.linear()
    .domain([0, 20])
    .range([0, width]);

The code above returns a converter function and binds it to the variable xScale. We will use this function a lot to convert the x coordinate of a point from the real pixel value into the 0 - 20 output range scale we have specified. The code specifies that the scale is linear and that it has a minum value of 0 and a maximum value of 20. This is achieved by passing the array [0, 20] as an argument to the domain function on line 2 of the above. The code on line 2 then specifies the range that is used to equally space out the 0 to 20 units. In this example we are using the available width of the svg document.

The exact same logic is used to create a converter function for the y scale but this time, the height of the svg document is used as the range.

y-scale.js
1
2
3
var yScale = d3.scale.linear()
    .domain([0, 20])
    .range([height, 0]);

The next step is to draw the x and y axis complete with graduated labels. The following code creates the x axis:

The x-axis looks like this:

x-axis.js
1
2
3
4
5
6
var xAxis = d3.svg.axis()
    .scale(xScale)
    .orient("bottom")
    .innerTickSize(-height)
    .outerTickSize(0)
    .tickPadding(10);
  • The call to d3.svg.axis on line 1 unsurprisingly returns an instance of the axis object.
  • Line 2 makes a call to the scale function and passes in our xScale converter reference we created earlier. The labels or ticks as they are known as in d3 speak will be graduated with respect to the [0, 20] domain array of min and max values we specified.
  • Line 3 positions the axis at the bottom of the document.
  • On line 4 the innerTickSize function of the axis object is called to create the horizontal lines that are vertically aligned from each label or tick. I struggled with a good way of creating the gridlines for a long time and it turns out you need to pass in a negarive argument like -height in line 2 of the above because we want the lines to fill the full document and if we do not pass a negative value then grid lines flow down from the labels and not up. You can see this by adding and removing the line from the jsbin.

The yAxis is created in a similar fashion only the horizontal grid lines are creating by passing in -width into innerTickSize to create the horizontal lines.

Positioning the line and circles was very easy after I had my grid created and my scales set up. The line is created below:

line.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
var line = {
    start: {x: 2, y: 3, type: 'start'},
    finish: {x: 14, y: 6, type: 'finish'}
  };

var g = svg.append('g');

g.append('line')
    .style('stroke', 'blue')
    .attr('class', 'line')
    .attr('x1', xScale(line.start.x))
    .attr('y1', yScale(line.start.y))
    .attr('x2', xScale(line.finish.x))
    .attr('y2', yScale(line.finish.y));
  • Line 6 creates an svg g element or container that can be used to group shapes together.
  • Lines 11 to 14 specify the start and end points of the line. What is important about this is that the xScale and yScale converter functions are used to place the line on the 0..20 scale.

The circle and text label objects that specify the coordinates of the end points follow a similar approach:

circle.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
var lineData = [line.start, line.finish];

var circles = g
     .selectAll('circle')
     .data(lineData)
     .enter().append("circle")
     .attr('class', function(d){ return "circle " + d.type;})
     .attr('cx', function(d){return xScale(d.x);})
     .attr('cy', function(d){return yScale(d.y);})
     .attr('r', 10)
     .style('fill', 'red')
     .call(drag);

var text = g
     .selectAll('text')
     .data(lineData)
     .enter().append('text')
     .attr("x", function(d){return xScale(d.x);})
     .attr("y", function(d){return yScale(d.y + 1);})
     .attr('class', function(d) {return "text" + d.type;})
     .text( function (d) { return "( " + d.x  + ", " + d.y +" )"; })
     .attr("font-family", "sans-serif")
     .attr("font-size", "14px")
     .attr("fill", "red");

What is interesting about the above code is the data function call on lines 5 and 16. I liken this to data binding and a circle or text object is created for each element in the lineData array on line 1.

What I found confusing about the above code when I first encountered it is that selectAll works on elements that you are going to create rather than what you have created. The enter function on lines 6 and 17 is used to add the new elements to the document as the data changes.

All that is left is to display the code that handles the drag events:

drag.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
var drag = d3.behavior
     .drag()
     .on("drag", function(d) {
        var circle = d3.select(this),
            line = d3.select('.line'),
            isStart = circle.classed('start'),
            textClass = isStart ? ".textstart" : ".textfinish",
            lineX = isStart ? 'x1' : 'x2',
            lineY = isStart ? 'y1' : 'y2',
            text = d3.select(textClass),
            title = d3.select('.title'),
            xStart = d3.format(",.0f")(xScale.invert(line.attr('x1'))),
            yStart = d3.format(",.0f")(yScale.invert(line.attr('y1'))),
            xFinish = d3.format(",.0f")(xScale.invert(line.attr('x2'))),
            yFinish = d3.format(",.0f")(yScale.invert(line.attr('y2')));

        text.text( function (d) { return "( " + d3.format(",.0f")(xScale.invert(d.x))  + ", " + d3.format(",.0f")(yScale.invert(d.y)) +" )"; });

        line.attr(lineX, d3.event.x).attr(lineY, d3.event.y);
        text.attr('x', d3.event.x).attr('y', d3.event.y - 20);
        circle.attr("cx", d.x = d3.event.x).attr("cy", d.y = d3.event.y);

        title.text(equationOfLine({x: xStart, y: yStart}, {x: xFinish, y: yFinish}));
     });

The above code creates a drag function that I can attach to elements of the document.

I struggled for a while with getting the correct text for labels of the coordinates of the end points of the line and the main header label. The drag event handler on line 3 gets passed a d argument which is a d3 behaviour object that has the x and y mouse cooridinates of where the mouse was dragged to. I had to use xScale.invert and yScale.invert to get the correct scaled cooridinates for the text labels. The invert function returns the inverse mapping of range to domain. The rest of the code just positions the elements to the new mouse positions.

The drag function is then attached to each circle as it is created on the last line of the code below;

circle.js
1
2
3
4
5
6
7
8
9
10
var circles = g
     .selectAll('circle')
     .data(lineData)
     .enter().append("circle")
     .attr('class', function(d){ return "circle " + d.type;})
     .attr('cx', function(d){return xScale(d.x);})
     .attr('cy', function(d){return yScale(d.y);})
     .attr('r', 10)
     .style('fill', 'red')
     .call(drag);

Emberjs - Detail View Without Switching Routes

Rendering long lists of tabular data on the client is something I have spent a lot of time on and this dates back to my backbone days. You need to at the very least employ infinite scrolling which opens up other cans of worms. What if my tabular data has a cell with a link and I click the link and then click the back button. Unless I spend a lot of engineering effort, I will have lost my place in the infinitely scrolled list.

This was a problem I recently faced on the application that I am working on. We have a large table of infinitely scrolled rows of contact data that had links to the detail of each contact on each row. We started off with the links redirecting to a new route that displayed the individual contact’s details. This meant that when you clicked the back button from the detail view, the table would be re-renderd from scratch.

I came up with quite a nice and not so technical solution that avoided many dark hours of development. I came up with the idea of sliding out the view of the contact detail from the same route that contains the table. This means the user never loses their place in the table. Throw in some css3 animations and I am very happy with the solution. Below is an animated gif that shows what I have christened the x-drawer component:

Here is a working jsbin which shows the code in action. The x-drawer component is a container for other components and is declared in its nested form and any component can be placed inside it:

I actually use the component helper in the production app as I now use the drawer a lot but in the above gist I simply have a property showDetail that when set to true will activate the drawer.

The x-drawer component is actually very simple and the sliding animation is achieved with css3 animations and specifically css transitons that enables the drawer to slide out slowly rather than just appear. I used a combination of translateX and transform to slide out the view.

Another requirement that I had thrust apon me was to make sure the drawer was closed if the user clicked anywhere outside of the drawer. Below is the code that creates an overlay on the remaining screen real estate that when clicked sends the action to close the drawer:

overlay.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
  _setup: Ember.on('didInsertElement', function() {
    var addOverlay, el, self;
    this._super.apply(this, arguments);
    el = this.$();
    self = this;
    addOverlay = function() {
      var overlay, rect;
      rect = el.get(0).getBoundingClientRect();
      overlay = $("<div class='drawer-overlay'></div>");
      overlay.css({
        position: "absolute",
        top: rect.top + "px",
        left: (rect.right - 10) + "px",
        height: rect.height + "px"
        }).appendTo('body');

      return overlay.one('click',function(e) {
        self.send("closeDrawer");
        e.stopPropagation();
        return e.preventDefault();
      });
    };

    el.one($.support.transition.end, addOverlay);

    el.get(0).offsetWidth;
    return el.addClass('open');
  }),

This was actually quite a simple solution to a difficult problem. My first thoughts where that I need to work on the performance of rendering the table but with this solution, the table is always present as we don’t have to naviagate away.

Functional JavaScript in the Browser and Why I Should Care

Why should you care about functional javascript? I’d heard of the merits of functional programming for a while now and up until recently, I thought that the main benefits of functional programming where really only applicable when dealing with highly concurrent programs when functional programming can help guarantee thread safety. Writing side effect free functions that use immutable data structures rules out interaction problems between threads that mutate data. All well and good but why should I care about any of this in the single threaded realm of the browser?

The pendulum between server heavy app and client heavy app. has swung back to the client again for this epoch and single page applications are all the rage. This would have seemed like insanity at the turn of the century but advances in browser technology and a demand for more ambitious applications has led us to the now infamous SPA. Our programs live a lot longer in the browser than they used to. Gone are the days when we could rely on a browser refresh to reboot the browser code and rebuild clear all our objects from memory. reactjs has come up with a beautfiul top down, one way data push that can simulate this behaviour by abstracting away that gargantuan side effect known as the DOM into a virtual DOM to diff against the previous state. Reactjs has embraced functional programming and so should you.

Side effects, function Purity and Referential Transparency

Functional programming favours functions that, for a given input, will consistently return the same output. A pure function does not depend on and does not modify the state of variables outside of its scope. When a function performs any other action, apart from calculating its return value, the function is impure. A program or function is said to have side effects if it can produce different outputs given the same input.

A very simple example of a pure function is below:

mult.js
1
const mult = (a, b) => a * b;

Referential transparency is the ability to freely replace an expression with its value and not change the behaviour of the program. We can show that the mult function is both pure and referentially transparent with the code below:

rf.js
1
2
3
4
5
6
7
8
9
const mult = (a, b) => a * b;

const result = mult(2, 3) + mult(4, 5);

const result1 = 6 + mult(4, 5);

const result2 = 6 + 20;

console.log(result == result1 == result2);

Replacing the call to mult with the result does not alter the output of the computation.

Below is an example of a function that relies on a global variable to calculate its output:

sideeffect.js
1
2
3
4
5
6
7
8
9
10
11
12
let number = 0;

const inc = (n) => {
  number = number + n;

  return number;
}

const result1 = inc(1);  //=> 1
const result2 = inc(1);  //=> 2

console.log(result1 === result2);

We can clearly see that providing the same input each time does not give us the same output each time.

Side effects are functions that rely on the outside OR can be functions that alter the outside world. The ubiquitous Hello World program is actually a side effect because it alters the state of the output on the screen. A call to console.log is a side effect. All IO is side effect laden, reading a file from a disk is a side effect because it might throw an exception because the network is unavailable. We therefore cannot guarantee the result of calling the function.

Any function that does not return a value will more than likely have side effects because it is probably mutating some external state.

Our programs would not be very practical without side effects and the goal of functional programming is not to eliminate side effects but instead we want to limit them and also more importantly, isolate them. How can we limit side effects in the sea of mutation that is javascript? The first thing we can do is to use immutable data structrues.

Immutable Data Structures

I think the penny is starting to drop with many in the javascript world about how sensible immutable data structures are. A data structure is immutable if it cannot be changed after it has been created.

In the chaotic realm of the single page application, I find it very reassuring to know that after I have created an object or assigned a value to a variable, it will not be changed by some well meaning code outside of my control. A lot of SPA frameworks use two way data binding to bind objects to DOM elements or other structures. I have also had hellish results with using observation through Object.observe or some other mechanism of reacting to state changes, I now consider this to be an anti-pattern.

es6 has introduced the const keyword which is analogous to final in java, it does not mean that all data structures defined with the const keyword are immuable but it does mean they cannot be reassigned once they have been assigned. The code sample below will illustrate this:

const.js
1
2
3
4
5
6
7
8
9
10
11
const number = 3;

number = 4; // => error: Attempting to override 'number' which is a constant.

const person = {name: 'Paul Cowan'};

person.name = 'Bob Cowan'; // mutate away

console.log(person.name);

person = {name: 'Paul Cowan'}; //=> error:  "person" is read-only

If we want full immutability then we can use something like immutable-js or mori. Both libraries provide persistent data structures for your use. The data structures are called persistent because they always presist a previous version of themselves when modified.

Below is an example of immutable-js that illustrates this:

immutable.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
let list1 = Immutable.List.of(1, 2);
let list2 = Immutable.List.of(1, 2);

console.log(Immutable.is(list1, list2) === true);  // => true, equality by value and not reference

let map1 = Immutable.Map({a: 1, b: 2, c: 3});
let map2 = map1.set('b', 2);

console.log(map1 === map2); // => true, map2 returns a reference to map1 because no change was made

let map3 = map1.set('b', 50);

console.log(map1 !== map3);

console.log(map1.toJS()); //=> {a: 1, b: 2, c: 3}, map1 is unchanged
console.log(map3.toJS()); //=> {a: 1, b: 50, c: 3}

You can see from the above that we can check equality by value and not reference on line4 when comparing list1 and list2.

Also illustrated is how map2 returns a reference to map1 on line 7 because no change was made to the underlying hash and on line 11, map1 remains unchanged and a new version of the data structure is returned after changing or adding a new value to part of the data strurcture. I hope you can see how we could use persistent data structures to trivially hookup undo and redo functionality (more on this later).

Statelessness

Imperative programming works by changing programming state to produce answers. Conversely, functional programming produces answers through stateless operations.

This brings us back to function purity, our programs are easier to reason about if we can be sure that given the same input, we get the same output. We want to avoid functions that reference member variables or any thing outside of the functions environment wherever possible.

Back to the Real world

Here are some things to consider everytime you create a function in javascript:

  • Are my functions dependant on the context in which they are called, or are they pure and independent?
  • Can I write these functions in such a way that I could depend on them always returning the same result for a given input?
  • Am I sure that these functions won’t modify anything outside of themselves?
  • Pass values as parameters, don’t store state in member variables.

I blogged here here about using a real world example to limit side effects in an emberjs application and here about how you can use persistent data structures in an emberjs application to implement basic undo and redo functionality.

Higher Order Functions

A higher order function is either:

  • A function that takes a function as an argument
  • A function that returns a function

I am going to concentrate on the latter and I am going to first of all use partial application.

Wikipedia gives the following definition of partial application:

partial application (or partial function application) refers to the process of fixing a number of arguments to a function, producing another function of smaller arity

If we return to our mult function that I showed in the beginning, we can create a new function double by using partial application:

double.js
1
2
3
4
5
const mult = (a, b) => a * b;

const double = mult.bind(null, 2);

console.log(double(3)); // => 6

On line 3 of the above, I am using the lesser known property of bind that after the first argument where you can specify a context, every parameter after the first will be prepended to the list of parameters when invoking the bound function.

We could rewrite the double to return a function like this:

double2.js
1
2
3
4
5
6
7
8
9
10
11
const mult = (a, b) => a * b;

const makeMultiplier = (a) => {
  return (b) => {
    return mult(a, b);
  }
}

const double = makeMultiplier(2);

console.log(double(3)); // => 6

We now have a makeMultiplier that can create many different types of functions based on mult.

A more practical use of a higher order function is the maybe function below that can take a function and return a null safe version:

maybe.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
const maybe = (fn) => {
  return (input) => {
    if(!input) {
      return;
    }

    return fn.call(this, input);
  };
};

const toLower = i => i.toLowerCase();

console.log(toLower("henry"));

let nullString;

console.log(toLower(nullString)); // TypeError: Cannot read property 'toLowerCase' of undefined

const nullSafeToLower = maybe(toLower);

console.log(nullSafeToLower(nullString)); // returns undefined, no exception

Here we create a new null save function that is returned from the maybe function. We can now create other functions from this maybe function that will handle null values.

Composability

Another benefit of higher order functions is to take 2 or more functions and combine them into one. Below is an and function that will perform a logical and on the output of two functions:

and.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
const isEven = (number) => number %2 === 0;

const isPositive = (number) => number >= 0;

const and = (f, g) => {
  return function() {
    return f.apply(this, arguments) && g.apply(this, arguments);
  }
};

isPositiveAndEven = and(isPositive, isEven);

console.log(isPositiveAndEven(6)); // => true
console.log(isPositiveAndEven(-4)); // => false

Further down the rabbit Hole

There are a number libraries that go much further with respect to functional programming:

  • omniscientjs
    • Built on top of reactjs
    • Top down rendering
    • Immutable Data
  • OM
    • Built on top of reactjs
    • Written clojurescript
    • ClojureScript’s immutable data types
  • Purescript
    • Inspired by haskell
    • Type system
    • Bindings for reactjs and angular
  • Elm
    • Compiles to HTML and javascript
    • Compiler guarantees no runtime exceptions

Clojure - Idiomatic Refactor From Recursion

I’ve become addicted to solving programming challenges that you might find at hackerrank or 4clojure. I spend most of my day job in emberjs and as much as I find myself agreeing with reactjs's take on things, I simply don’t have the energy or the will to learn another javascript framework. I also think it is bad to learn another way to do the same thing in your spare time. You need to push your brain into interesting and new avenues.

I’m using clojure to solve these programs and it is quite nice to not have to worry about persisting data or learning the latest du jour framework.

I have found myself using the same pattern over and over again when iterating a sequence that might decrease due to some condition and accumulating a value while doing this. Below was my bog standard way of doing this:

recursion.clj
1
2
3
4
5
6
7
(defn process [acc sticks]
  (let [smallest (apply min sticks)
        cuts (filter #(> % 0) (map #(- % smallest) sticks))]

    (if (empty? cuts)
      acc
      (process (conj acc (count cuts)) cuts))))

The above code reduces each item in the sequence by the smallest value and then filters out any values that are zero or less (lines 2 and 3). If there are any values left, the function recursively calls itself until the sequence is empty. On each call to the function, the count of remaining elements in the sequence is added to an accumulator argument acc.

I have been using this pattern for a while now but it did not seem to me to be idiomatic clojure. I did some research and the refactoring below is a huge improvement in terms of modularity, readibility and being more idiomatic:

iterate.clj
1
2
3
4
5
6
7
8
(defn cuts [sticks]
  (let [smallest (apply min sticks)]
    (filter pos? (map #(- % smallest) sticks))))

(defn process [sticks]
  (->> (iterate cuts sticks)
       (map count)         ;; count each sticks
       (take-while pos?))) ;; accumulate while counts are positive

The first step was to isolate in a new function the logic that performs the filtering on the sequence. I have created a cuts function on line 1. This improves the modularity.

The process function on line 5 uses the thread last macro. Both the thread macro -> and the thread last macro ->> make the code easier to read by allowing you to use an imperative style rather than nesting the calls. The thread last macro inserts the first argument that you pass to it as the last argument to each of the forms. Below are some simpler examples of the thread last macro that should illustrate how the argument fills in the last argument for each of the forms:

last.clj
1
2
3
4
5
6
7
8
9
10
(->> x
     f)
;; (f x)
(->> x
     f
     g)
;; (g (f x))
(->> x
     (f y))
;; (f y x)

If we return to our example, we can use macroexpand to expand out the macro to its nested reality:

macro.clj
1
2
3
4
(macroexpand '(->>
              (iterate cuts [1 2 3 4 3 3 2 1])
              (map count)
              (take-while pos?)))

Below is the output of the macroexpand call:

result.clj
1
(take-while pos? (map count (iterate cuts [1 2 3 4 3 3 2 1])))

The first argument in this case is supplied via the iterate function on line 6 that generates an infinite lazy sequence by taking two parameters, a function and a seed value. The seed value in this case is the vector [1 2 3 4 3 3 2 1] and this is initially passed to the cuts function. iterate will then infinitely call cuts passing in as an argument, the previous call to cuts.

map is used to apply a function to each item returned from the iterate form and we use count as the function to transform the result of each call to cuts. take-while is used to constrain the infinite nature of iterate and as soon as the pos? function returns false, the results are returned to the calling function. We use pos? to check whether there are are any elements that are not zero. take-while will also accumulate the count results and return them to the calling function instead of using an accumulator argument like I used in my original example.

I really like how this turned out and it is definitely more idiomatic clojure than my original version and I think this is a good barrier to get past in my journey into clojure.

Emberjs - Computed Properties and Promises…..don’t

A question I see coming up time and time again is how to return a resolved promise from a computed property.

There are a number of ways of doing this and I, like many have tried to solve this problem myself before realising that it is not a path you should go down.

I can flesh this out with an example that I originally solved using a computed property that resolved a promise.

I inherited a nasty bit of code on the server or API side of the project that I was working on that stored the relationship of different types af object in a generic postgres database column that used serialized yaml as the format to compound the uselessness. This is particularly wrong for a number of reasons such as you can’t query the sucker unless you use regular expressions. It is completely unmaintainable and you should never, ever do this and Edgar F. Codd who gave us relational database theory would be turning in his grave.

An example where this was used is in a user’s activity feed that contains audited events for a user of the application. For example if the user or contact sent an email then their activity feed would contain an item like this:

1
2
3
4
5
6
7
8
{
"activities": [{
    "id":210849,
    "tag":"user",
    "event":"sent_email",
    "time":"2015-06-06T17:01:51Z",
    "meta":{"email_id":607149}
}]

The meta field on line 7 comes from the serialized yaml column and is used as a generic bucket that can contain different types of relationships or other junk, making it extremely difficult to work with. The answer to how to deal with this is refactor the server code and never, ever use serialized YAML but if you are stuck with this type of nonsense then how would you satisfy the email property of the template below? We need to somehow or somewhere load the email instance from the meta.email_id property.

When I first encountered this problem, my answer was to use a computed property that resolved a promise and then set itself:

cp.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
email: Ember.computed('activity.meta.email_id', function(){
  var store = this.get('store'),
      emailId = this.get('activity.meta.email_id'),
      self = this;

  if(!emailId) {
    return;
  }

  store.find('email', emailId).then(function(email) {
    self.set('email', email);
  }).catch(function(error) {
    //handle error
  });
})

On line 11 of the above, I set the property when the property resolves.

This will more or less work and here is a jsbin that shows an example of how to do this.

There are a number of things wrong with this approach, namely we are trying to treat something that is inherently synchronous in an asynchronous manner. The cp will fire a number of times due to the promise resolving and I have had a lot of pain with ember and observing dependent keys. This can lead to the property referencing a partially resolved object or you can get cascading events on other cps and observers that reference a key firing in a sometimes recursive manner. These are situations I now avoid like the plague and if you have any sense, you will heed my battle weary tone and avoid them too.

I’ve also seen computed properties that reference promise objects or have dependent keys on the state of the promise, but that is far too contrived to be credible and will lead to pain. You will have partially resolved data and cascading events triggered. Don’t do this.

I develop with ember a lot different now than I did this time 12 months ago.

If you feel you need a computed property that will resolve a promise and you have read this, the answer is…….DON’T.

So what do we do?

Subscribing to data events throughout your application by using observers or waiting for computed property keys to update and trigger actions creates overhead but more importantly makes your application difficult to reason about and in my experience causes unreliable and inconsistent behaviour for reasons I have been writing about for a while now.

When data is passed from above rather than being subscribed to, we can react only when we know something has changed. React’s flux has popularised the top down approach and it makes nothing but sense.

So the answer is to let the resolved property be passed in from above in a top down fashion rather than listening for it to happen. Ember is on board with this philosophy and it goes by the meme data up and actions down although I think this could do with some better fleshing out.

So the first refactoring is to create a service that will be charged with resolving the activity instance and taking care of unwrapping this horrible meta hash that can contain all kinds of junk. I want this encapsulated and ready to use anywhere in my code. With this in mind, I have created an ActivityService that is injected into all components through this initializer:

initialize.js
1
2
3
4
5
6
7
8
9
10
11
12
Ember.Application.initializer({
  name: 'load-services',
  initialize: function(container, application) {
    var activityService = App.ActivityService.create({
      store: container.lookup('store:main')
    });
    application.register('activity-service:current', activityService, {
      instantiate: false
    });
    application.inject('component', 'ActivityService', 'activity-service:current');
  }
});

A scaled down version of the ActivityService is below that takes care of loading the activity and unpacking this now infamous meta field:

activity_service.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
App.ActivityService = Ember.Service.extend({
  resolveActivity: function(activityId) {
    var self = this,
        store = this.store;

    return new Ember.RSVP.Promise(function(resolve, reject) {
      store.find('activity', activityId).then(function(result) {
        var activity = result.shallowCopy();

        store.find('email', result.get('meta.email_id')).then(function(result) {
          activity.email = result.shallowCopy();
          resolve(activity);
        });
      });
    });
  }
});

The above code returns a promise that when resolved, will return a simple hash rather than the resolved ember-data instance. I prefer not to bind or work directly with the ember-data instances and I discussed this the benefits of this in this post. I have created a simple shallowCopy extension to the DS.Model class that creates a shallow copy of the ember-data instance:

shallowcopy.js
1
2
3
4
5
6
7
8
9
10
11
12
13
DS.Model.reopen({
  shallowCopy: function(){
    var type = this.constructor,
        self = this,
        hash = {};

    type.eachAttribute(function(key, meta) {
      hash[key] = self.get(key);
    });

    return hash;
  }
});

In the original example, I iterated over the user’s activities like this:

I will replace this with a component:

The ActivityFeedComponent creates an array of activity hashes by calling out to the ActivityService and only pushing the resolved instances onto the activities array when the service has done what it needs to do:

ActivityFeedComponent.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
App.ActivityFeedComponent = Ember.Component.extend({
  activities: Ember.A(),
  _initialize: Ember.on('init', function(){
    var self = this;

    this.get('user.activities').forEach(function(a) {
      self.ActivityService.resolveActivity(a.get('id'))
      .then(function(activity){
        self.get('activities').addObject(activity);
      }).catch(function(error) {
        // handle error
      });
    });
  }),
  _tearDown: Ember.on('willDestroyElement', function(){
    this.get('activities').clear();
  })
});

This will give me so many fewer problems than resolving the promise in a computed property as I did in the original example. I only push onto the activities array when the service has done what it needs to do. I am also working with copies of the ember-data instance which will curtail any unwanted side effects that I might encounter. I will sleep better with this code.

The activity-feed component’s template simply looks like this:

Here is a jsbin that brings it all together.

So my message is clear, don’t resolve promises in your computed properties, nor should you have dependent keys on isFulfilled as I see some advocating.

You have been warned.