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:
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 

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

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:
1 2 3 4 5 6 7 8 

This is effectively a DSL or minilanguage 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 withvar 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 pointb
that was declared like thisb = {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:
 I would find the gradient (or slope for those of you from the US) of the line
BC
.  I would use this gradient/slope to create the equation of the line in
y = mx + c
format.  I would find the perpendicular gradient/slope of
BC
that I can use to create an equation of the line that will go through pointA
and will be perpendicular to pointC
iny = mx + c
format.  I would then solve these simultaneously to find the point of intersection from point
A
to the point onBC
that was perpendicular to pointA
.
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:
1 2 3 

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

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 yintercept
or the point where the line cuts the yaxis:
1 2 3 

I could then get the y, mx and c values of y + mx = c
for both lines so I could solve the equations simultaneously.
1 2 3 4 5 6 7 8 

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:
1 2 

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.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 

Below is the function I used to first of all find the determinant of the matrix before applying cramer’s law:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 

The above returns a point that I can then use to join point A
to the point of intersection returned from the solveMatrix
function.
1 2 3 4 5 6 7 

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.