18 May 2022

Dots, lines and whatever fits best

Scalable Vector Graphics

SVG has always been a popular technology with me. Amongst other things, I've used it for making scale drawings for alterations to my house, and for making easily scalable or re-colourable logos for websites. For images which don't contain photographic material SVG files are often tiny in size when compared to compressed bitmaps like JPEG or PNG. But although many (most?) web browsers can render them, it's quite unusual to find them in use.

In my experience, Inkscape is the best GUI editor for SVG graphics, though its output is rather more verbose than that from the Perl SVG module.

Both tasks this week require us to draw lines and points in a 2-dimensional space. Once you've mastered the syntax required, the task is fairly simple, although there is one catch to be surmounted, which is that SVG's geometry is 'left-handed'. The normal convention for Cartesian (ie x and y) coordinates is that the positive direction of the y axis is 90 degrees anti-clockwise from the positive x axis. So in a rectangular container, if you place the origin (x = y = 0) at the bottom left, every point within the container has a positive x and y.

SVG uses the convention that the positive direction of the y axis is 90 degrees clockwise from that of the x axis. That means that in order to get the positive x and y valued points within a rectangle, the origin has to be at the top left, which is upside down to the normal convention.

So, I chose to write my code so that, in SVG terms, it transforms every (x, y) to (x, height - y) where 'height' is the height of the container, which draws the diagram in the way we were all taught at school.

Task 1 simply asks that we plot a number of points and lines, so I chose to draw a house, comprised of 5 points and six lines:

Sadly, Blogger doesn't accept embedded SVG so this is a PNG representation.

Task 2 also asks us to plot points, but asks for a least-squares best fit line. There are several ways to derive such a line, but I used the one most-commonly used experimentally, which is to assume that the errors - that is, the amount by which the points deviate from the line - are in y and not x. So if you draw a vertical line from each point to the least-squares line, we are looking for the line that minimises the sum of the squares of the lengths of these lines.

If the equation of that line is y = a + bx, it can be shown that:

     n * sum(x[i] * y[i]) - sum(x[i]) * sum(y[i])
b =  --------------------------------------------
           (sum(x[i]^2) - sum(x[i])^2) / n

a = (sum(y[i] - b * sum(x[i]) / n

where n is the number of points, and the points have coordinates x[i], y[i].

Again I chose to draw with y increasing in the upward direction and I have shown a rectangle which just encloses the supplied points - ie the bottom is not y = 0 and the left side is not x = 0:

The least squares line is y = 200.1 - 0.3000 x.






 

No comments:

Post a Comment