APEX@IGP

28

SVG Primitives. Parabolas

How to create perfect parabolas with SVG quadratic bezier curves. Modified: 20 December 2015.

Note: This page uses MathML without MathJax fallback at present. If you do not have a MathML capable browser (Firefox or Safari) you will not see the equations but they will still be readable-ish as they are all quadratic equations or parts thereof.

At about year eight or nine in the K-12 curriculum trigonometry kicks in with a bang. For a year or so that means drawing more graphs than most normal people will ever draw in their lives again.

Do you want or need to learn how to make great handcrafted SVG?

We have recently worked on a lot of maths textbooks with publishers in China, the Philippines, India and New Zealand doing the production on IGP:Digital Publisher and in most cases for distribution using AZARDI:Content Fulfilment. These books 100+ annotated drawings of parabolas and bits of parabolas. All of this is required to match the equations being discussed in the lesson narrative. With page area consumers like graphs there is a "paper economy" that has to work for print books with the number of examples and exercises given to keep the page count under control.

So far the SVG Primitive tutorials have addressed relatively simple graphs, shapes and drawings. Now we move into the more challenging 2D landscape of the mighty parabola.

When delivering trigonometry e-books using images, even images optimized using advanced indexed-image techniques, the file size of the book grows very fast. So does the packaging complexity. SVG lowers the file size to almost nothing, radically increases digital content quality AND sets the stage for interactivity and animation.

Enter SVG Primitives. Parabolas. But first...

The Coordinate System

All of these examples use the Cartesian Coordinate mapping outlined on the SVG Primitives. Graphs, Grids and Coordinates article.

This helps make the challenge of drawing parabolas a lot easier to understand and learn. Now we are ready to plot and draw parabolas.

SVG has quadratic and cubic bezier curves in the path properties. Quadratic beziers make it incredibly easy to draw parabolas. The clue is the term "quadratic".

This simple 500 Bytes of SVG code...

<path d="M-160,1280 Q0,-1280 160,1280" />

... delivers this parabola. That is not a lot of SVG. (We put a little path animation on it for fun and to hint at the possibilities of SVG rather than images or Javascript canvas renditions. However this topic is about static parabola drawings.)

You can deliver 100 SVG parabolas in 5 KBytes, much less than the file size of one image parabola. Notice the Q in there stating this is a "quadratic bezier". Q is now more than just James Bond's gadget supplier!

To draw a parabola you need...

1. A quadratic equation. Something like .
2. Two selected points on a y chord which is at right angles to the vertical line of symmetry. In the SVG above that is the M-160, 1280 coordinate (the starting point and the last coordinate 160, 1280 (the ending point which must have the same y value as the starting point.
3. Next you need to know the coordinates of the vertex. These are not shown in the SVG but are used to calculate...
4. The bezier control point plotted on the vertical line of symmetry and two times the distance from the y chord to the vertex. This is the value immediately after the Q. IE. in this example 0,-1280.

You are using just these three points to draw the parabola. You can see them plotted as black dots with the margin figure. The outlined box is the SVG viewBox that is actually visible to the end user. The red horizontal line at the top is the Y chord line and way down the bottom in outer SVG space is the bezier control point on the green vertical line of symmetry.

This graph was created with  from -8 to +8. That gives cartesian coordinates (-8, 64) and (8, 64) for the top points with the vertex at (0, 0).

Of course the raw calculated coordinates have to be multipled by the grid scaling factor you are using. In all these examples that is 20px X 20px. You can do this arithmetic in your head, or use the supplied calculator.

 -8 -6 -4 -3 -2 -1 0 1 2 3 4 6 8 64 36 16 9 4 1 0 1 4 9 16 36 64

The coordinates for our parabola.

Only two coordinates with the same positive and negative value are required. In this example we used -8 and +8.

The x=8 has y=64. When we multiply these by our 20px grid we get SVG plotting coordinates x=160 and y=1280.

When the origin is 0, 0, the bezier control point is positioned the same distance beneath the origin as the y-chord line is above. Therefore the bezier control point becomes 0, -1280.

That is all we need. These can now be put into our SVG path statement as a quadratic bezier.

<path d="M-160,1280 Q0,-1280 160,1280" />

So let's take a look at that.

Drawing a simple Parabola

The parabola is plotted into the correct position on the origin.

To show that this is a real parabola (for the doubters) we have plotted the calculated coordinate points as well.

So you can see more of the coordinates we have panned the viewBox up 180px. We could also increase the area covered by the viewBox with an effective "zoom-out".

View the SVG

The Parabola Plotting Coordinates

The shape and direction of a parabola is determined by the  part of the equation. The position of the vertex is determined by the part. To make rendering and positioning a parabola easy the parabola drawing problem is divided and conquerored. This avoids descending into wild calculations trying to discover x given y!

1. Use the   calculated x points and draw the parabola to the required x coordinates centered on the origin.
2. Use the origin coordinates with an SVG translate to move the parabola origin to the correct position.

For example here is .

Drawing and Positioning a Parabola

1. First create the parabola. Get the coordinates from the calculator by deciding which x values to use. In this example we are using x=-10 and x=10. The calculated coordinates for ax^2 are (-200, 1500) and (200, 1500) respectively.
2. The calculator gives (0, -1500) as the bezier control point. We draw and position the (blue) parabola on the origin.
3. The calculator gives the full equation vertex coordinates as (-27, -87). Using the transform-translate property either on a <g> wrapping the path statement, or directly on the path. <path transform="translate(-27, -87)" ... />
4. The (red) parabola is now in its correct vertex position.
5. Again we have plotted the coordinates to make sure it is the parabola we wanted. We have put in the focus (magenta) and vertex (green).

View the SVG

Using the Parabola Coordinate Calculator

We have prepared a coordinate calculation spreadsheet that makes it a little easier to get plotting more complex parabola equations.

Setup

1. Graph Pixels Per Unit. Set the number of pixels you are using on the grid in the X and Y directions. Default is 20.

2. Vertex Control Point Plot. This is the distance you will be using to set the Bezier curve control point.

A. Quadratic Equation Constants. Enter the a, b and c values of your quadratic equation. Note that a must not be set to zero. If there is no a value use 1.

B. Vertex Coordinates. The vertex coordinates will immediately be calculated. You will need to transfer these to a <path> element.

C. Select a Y-Chord value from the C.A^2 coordinate row in SVG Coordinates and the X Row. You will be using the same value at both ends of the quadratic curve.

You now create the SVG Path with the Vertex coordinates in the center, and the negative Y-Chord coordinate at the left and the positive Y-Chord coordinate at the right.

Update these numbers into the SVG Primitive <path> you are using.

With the screen grab if you decided to use Calculated Coordinate X as 10, the SVG coordinates will be:

-200,2000 and 200,2000

The vertex control point is 0,-2000

Enter these into the path statement

<path d="M-200,2000 Q0,-2000 200,2000" />

Use the standard SVG Coordinates X and Y for adding coordinate points if required.

Summary

Non-linear graphs such as parabolas are difficult to create even for print material. Often screen grabs of interactive applications are used. Desktop lineart tools tend to use cubic bezier curves which can only be used to make an approximation of a parabola.  Hopefully this tutorial will open some doors to allow more beautifully presented parabolas in all those digital maths textbooks out there.

Of course the parabola is one of the first big maths abstract concepts the young learner is exposed to. It needs to be taught and learnt well so the learner can move forward enthusiastically in the crazy world of functions differentials and integrals.

Remember SVG has both SMIL and Javascript Interactive potential to power-up the learning process.

ALL-IN Learning Objects includes a Parabola Explorer that can be easily customized for any specific publisher requirement and included in an iteractive ePub3.

The IGP SVG Primitives approach uses a high level of manual production because it is so much faster than using desktop graphic tools. The mechanics of production is made easy with the SVG and MathML editors built into IGP:Digital Publisher.

The real challenge is using the power of these tools to create new and better learning opportunities for the children of the world, irrespective of language.

Posted by Richard Pipe

All-IN Learning Objects has a Parabola explorer that allows the student to interactively understand the effect of changing the constants. ALL-IN Learning Objects are licensed at no cost with IGP:Digital Publisher

<svg height="400" viewBox="0 -180 400 400" width="400">
<defs>
<pattern height="20" id="grid" patternUnits="userSpaceOnUse" width="20">
<rect fill="white" height="21" stroke="gray" stroke-width="-.5" width="21"></rect>
</pattern>
</defs>
<!--This is graph and background colour-->
<rect fill="white" height="800" width="800" y="-200"></rect>
<rect fill="url(#grid)" height="800" width="800" y="-200"></rect>
<!--These are the axis lines -->
<g transform="translate(0,0) scale(1, 1)">
<line class="l1 s-black" x1="-200" y1="200" x2="800" y2="200"></line>
<line class="l1 s-black" x1="200" y1="-200" x2="200" y2="800"></line>
</g>
<!--This is the Cartesian coordinate conversion -->
<g transform="translate(200, 200) scale(1,-1)">
<!--This is the parabola path statement-->
<path class="l2 s-blue f-none" d="M-160,1280 Q0,-1280 160,1280"></path>
<!--These are the coordinate circles -->
<circle class="l1 s-red f-red" cx="20" cy="20" r="3"></circle>
<circle class="l1 s-red f-red" cx="-20" cy="20" r="3"></circle>
<circle class="l1 s-red f-red" cx="40" cy="80" r="3"></circle>
<circle class="l1 s-red f-red" cx="-40" cy="80" r="3"></circle>
<circle class="l1 s-red f-red" cx="60" cy="180" r="3"></circle>
<circle class="l1 s-red f-red" cx="-60" cy="180" r="3"></circle>
<circle class="l1 s-red f-red" cx="80" cy="320" r="3"></circle>
<circle class="l1 s-red f-red" cx="-80" cy="320" r="3"></circle>
</g>
</svg>
<svg height="400" viewBox="0 0 400 400" width="400">
<defs>
<pattern height="20" id="grid" patternUnits="userSpaceOnUse" width="20">
<rect fill="white" height="21" stroke="gray" stroke-width="-.5" width="21"></rect>
</pattern>
</defs>
<rect fill="white" height="800" width="800" y="0"></rect>
<rect fill="url(#grid)" height="800" width="800" y="0"></rect>
<g transform="translate(0,0) scale(1, 1)">
<line class="l1 s-black " x1="-200" x2="800" y1="200" y2="200"></line>
<text class="t10 f-black t-start" dx="17" textLength="173" x="200" y="214"> 1 2 3 4 5 6 7 8 9</text>
<text class="t10 f-black t-end" dx="-17" textLength="173" x="200" y="214">-9 -8 -7 -6 -5 -4 -3 -2 -1</text>
<line class="l1 s-black " stroke="black" strokeWidth="2" x1="200" x2="200" y1="-200" y2="800"></line>
</g>
<g transform="translate(200, 200) scale(1,-1)">
<path class="l1 s-blue f-none" d="M-200,1500 Q 0,-1500 200,1500"></path>
<g transform="translate(-27, -87)">
<path class="l2 s-red f-none" d="M-200,1500 Q 0,-1500 200,1500"></path>
</g>
<circle class="l1 s-magenta f-magenta" cx="-27" cy="-67" r="3"></circle>
<circle class="l1 s-green f-green" cx="-27" cy="-87" r="3"></circle>
<circle class="l1 s-red f-red" cx="0" cy="-60" r="3"></circle>
<circle class="l1 s-red f-red" cx="20" cy="-5" r="3"></circle>
<circle class="l1 s-red f-red" cx="40" cy="80" r="3"></circle>
<circle class="l1 s-red f-red" cx="60" cy="195" r="3"></circle>
<circle class="l1 s-red f-red" cx="-20" cy="-85" r="3"></circle>
<circle class="l1 s-red f-red" cx="-40" cy="-80" r="3"></circle>
<circle class="l1 s-red f-red" cx="-60" cy="-45" r="3"></circle>
<circle class="l1 s-red f-red" cx="-80" cy="20" r="3"></circle>
<circle class="l1 s-red f-red" cx="120" cy="240" r="3"></circle>
</g>
</svg>