APEX@IGP

Infogrid Pacific-The Science of Information

24

SVG Primitives. Arcs, Angles, Labels and Ticks

The small details on any geometry or science illustration are the things that take time to get right. This article gives some shortcuts and tools to make that process easier. Modified: 27 October 2013

When doing intensive geometry and trigonometry illustrations it is the details that matter, and that takes the time. Here we present a few techniques and tools we have developed to get those details created and in-place fast and reliably.

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

Visit our new  Interactive SVG Tutorial Site here ►.

Scaling

We have to consider the deadly 1px line. The idea of SVG Primitives is illustration components that can be resized and positioned onto a new drawing. This includes scaling various components. The default canvas size is 400px X 400px which will generally be too large for many concept illustrations.

For this reason the 1px line is not recommended. SVG rendering does anti-alias 1px lines if you reduce them but they then pick up a blurred look. Stroke-width is an important consideration for on-screen clarity on all desktops and devices.

If your SVG is going to be scaled down (and it nearly always is) it is recommended to create illustrations with a 2 pixel line minimum.

Text labels is another consideration. Where an 8pt character may work on a printed page, on a lower resolution desktop monitor it will be blurred and hard to read. This can be seen in the following SVG example.

1px, 2px and 3px lines line Same lines and text scaled 50%

ALWAYS THINK SCALABLE AND REUSE WHEN
CREATING SVG ILLUSTRATIONS FOR DIGITAL TEXTBOOKS

Arcs and Angles

There is a set of symbols in <defs> that handle a set of standard angle arcs. However these are not very useful when creating angles for problem solving and every other angle!

Fig 1. r=45px

You need to be able to quickly and easily create an angle arc. Here is how we do it.

We create our angle arcs in a 100px box with the center as the origin. We treat the arcs as if they were drawn with cartesian coordinates. That means angles increase in the anti-clockwise direction (See fig 1). This box approach allows us to draw acute and obtuse angles easily using the same approach.

The default radius of the arc circle is 45px. It can be set to anything. This stops the arc being clipped up to 10px stroke-width. The arc is an SVG path. let's look at the path required to make a simple arc.

Fig 2. M

<path d="<strong>M</strong>95,50 <strong>A</strong> 45, 45, 0, 0, 0, <strong>63</strong>, <strong>7</strong>" />

Fig 2. shows the position of M at 95,50 is with respect to the rectangle origin. All paths have to start with an M (Move) point.

The A (arc) is the start of the arc definition. Paths can do ellipsis arches but because we want a circle the two radiuses are the same at 45. The arc is going to be drawn from M with a radius of 45 to our target coordinates.

Next we have three 0's (zeros) which instruct the SVG how to draw an arc. We will look at these properties later.

Fig 3. M A

Finally we have the hard job. Calculating the arc end coordinates. These can be calculated with a bit of basic trigonometry but to make this easier we have a spreadsheet calculator available.

We are going to make an arc for 73 degrees. The calculator shows the arc-end coordinates for 73 degrees and a radius of 45px is x=63px and y=7 pixels within the arc 100px square.

For this example we are showing a rotated construction line where the arc should end.

alt

SVG Tools

We have created a little spreadsheet calculator to take the pain out of calculating the end coordinates. Just enter the angle you want and the spreadsheet will return the coordinates.

You can enter up to three arc radiuses if you need to.

Download the SVG Arc CoOrdinate calculator:

Libre Office - ODS       Microsoft Office XLS

The SVG Arc CoOrdinate calculator. Enter the arc-radiuses and angle you want on the left side. Copy the X and Y CoOrdinates from the right side and paste them into your path Arc definition.

 Placing and Rotating Angle Arcs

We are now up to the last step on this journey. Getting these arc things where we need them. The easiest way to do this consistently is to put the angle arcs into a <g> (Group) element. If you have multiple arcs on an angle they all go in together.

<g class="linearc" transform="translate(150, 15) rotate(-120 50 50)">
<path d="M95,50 A 45, 45, 0, 0, 0, 63, 7" />
</g>

 You can now position the<g> element anywhere you want it. You just have to remember that you want to place the center at the target point so you have to subtract 50 from the x and y translate coordinates.

Next you can rotate the<g> element by any number of degrees remembering again that it is based on a 100px square, so the center coordinates are x=50 andy=50.

There is no actual square. It is just the way the coordinates have been used.

Angle Arcs

Angle arcs are not that difficult once the construction method has been learned. 

There are two things to do when creating and placing angle arcs.

1. For each arc you have to remember to change the two radius values and the arc terminating coordinates.

2. Remember the arc starts in the center of a 100px square, so the position offset must account for that as you place and rotate the arc.

View the SVG

alt

Production Note on the Layout Graph

Webkit does not support repeating-linear-gradient but does have -webkit-repeating-linear-gradient that uses percentages only in this attribute. The result you will see is a set of blurred lines instead of a grid.

repeating-linear-gradient works reliably in Firefox and IE10. If you want to see/use this grid technique you will have to use a supporting browser right now.

Because the layout graphs are only normally present in the IGP:Writer authoring mode and not the final output images we haven't bothered with cross-browser adjustments. We just use the right tools for the job!

Labels

It is necessary to be able to put letters, angles and other labels onto the illustration to match a narrative or problem statement.

It is important to be able to place and position these quickly and accurately with sizing, colour emphasis, size and weight applied equally easily.

Text Position

One of the particularly nice things about SVG text is positioning. Text has simple x and y positioning properties and these can be enhanced with other properties.

Position Start Position Mid Position End

It is important to know that text coordinates refer to the baseline position by default (shown by the gray horizontal line in the margin illustration). That means when you are positioning text you are positioning the baseline, not the top of the box as with CSS.

The property options for horizontal placement are:

text-position="start | middle | end"

Start is the default. This can be seen with the margin example. All text is lined up on x=80px but present very differently.

SVG Primitives have CSS styles available to apply the position mark. These are:

class="t-start | t-mid | t-end"

When applying angle descriptors

SCALENE TRIANGLE A B C a b c A B C All sides different lengths All angles are different

Labels

This shows a scalene triangle with vertices, lines and angle markers applied. There are also two descriptive labels.

 A A and a have position-middle applied.

B, c and C have position-end applied.

C, B and b have position-start applied.

This approach makes them very easy to align using the CSS graph metrics.

View the SVG

Line Tick Marks

Line tick marks are used to indicate similarity and differences of lines.

These are easy to create and use and positioning is similar to angle arcs except of course you are targeting the center of a line.

Tick Marks

This demostration is just to show the SVG behind an arc intensive illustration. It shows to some degree how easy it is to draw and place multiple arcs thanks to the end-coordinate calculator.

In addition the standard CSS styles have been applied to provide appropriate highlighting if required.

 

View the SVG

 

 Bringing It All Together

Here is a simple scalene triangle with angle arcs, labels and ticks applied.

SCALENE TRIANGLE {C}{C}{C} {C}{C}{C} A B C {C}{C}{C} a b c {C}{C}{C} A B C {C}{C}{C} All sides different lengths All angles are different {C}{C}{C} {C}{C}{C} {C}{C}{C} {C}{C}{C} A B C {C}{C}{C} a b c {C}{C}{C} A B C {C}{C}{C} All sides different lengths All angles are different

All together

Here is a final geometrical illustration with all of the above applied. A simple scalene triangle fully marked up and ready to work.

In addition the standard CSS styles have been applied to provide appropriate highlighting if required. The use of colour is easy in digital content and if it provides additional clarity it should be used. Pythagoras would have used colour if he had SVG!

There is a copy of the main image in the top right corner. This has been scaled to 70%. This allows you assess the scaling effect on the choice off lines, text, angles and labels in the master SVG Primitive and before it is applied to a textbook.

View the SVG

 

<svg height="400" width="400" x="0" y="0" viewBox="0 0 400 400" overflow="hidden">
<rect class="f-yellow" opacity="1" x="0" y="0" width="400" height="400" />
<text class=" t24 t-mid bold f-blue" x="200" y="30">SCALENE TRIANGLE</text>
<g opacity="1" transform="scale(1) translate(0, 0)">
<path class="l4 f-white s" d="M125,100 L350,300 L50,300 z" />
<!-- ANGLE ARCS-->
<g  class="l3 s-magenta f-none">
<g transform="translate(75, 50) rotate(-250 50, 50)">
<path d="M95,50 A 45, 45, 0, 0, 0, 65, 8 " />  
</g>
<g transform="translate(0, 250) ">
<path d="M95,50 A 45, 45, 0, 0, 0, 65, 8
    M85,50 A 35, 35, 0, 0, 0, 62, 17 " />              
</g>
<g transform="translate(300, 250) rotate(-140 50, 50)">
<path d="M95,50 A 45, 45, 0, 0, 0, 85, 20
    M85,50 A 40, 40, 0, 0, 0, 78, 27
    M105,50 A 50, 50, 0, 0, 0, 92, 15" />  
</g>
</g>
</svg>
<svg height="400" width="400" x="0" y="0" viewBox="0 0 400 400" overflow="hidden">
<text class=" t24 t-mid bold f-blue" x="200" y="30">SCALENE TRIANGLE</text>
<g opacity="1" transform="scale(1) translate(0, 0)">
<path class="l4 f-white s" d="M125,100 L350,300 L50,300 z" />
<!-- VERTICES LABELS-->
<g class="f-dblue bold t24">
<text class="t-mid" x="125" y="90">A</text>
<text class="t-end" x="40" y="310">B</text>
<text class="t-start" x="360" y="310">C</text>
</g>
<!-- LINES LABELS-->
<g class="f-dgreen italic t24">
<text class="t-mid" x="200" y="330">a</text>
<text class="t-start" x="240" y="180">b</text>
<text class="t-end" x="70" y="200">c</text>
</g>
<!-- ANGLE LABELS-->
<g class="f-dred italic t24">
<text class="t-mid" x="135" y="165">A</text>
<text class="t-start" x="90" y="270">B</text>
<text class="t-end" x="290" y="280">C</text>
</g>
<!-- GENERAL LABELS-->
<g class="f-black t20">
<text x="25" y="120">All sides</text>
<text x="25" y="140">different </text>
<text x="25" y="160">lengths</text>
<text x="270" y="200">All angles</text>
<text x="270" y="220">are different</text>
</g>
</g>
</svg>
<svg height="400" width="400" x="0" y="0" viewBox="0 0 400 400" overflow="hidden">
<g opacity="1" transform="scale(1) translate(0, 0)">
<path class="l4 f-white s" d="M125,100 L350,300 L50,300 z" />
<!-- LINE TICKS -->
<g  class="l3 s-magenta f-none">
<g transform="translate(200, 285) ">
<path d="M 0,0 L 0,30"
transform="rotate(0 15)"  />  
</g>
<g transform="translate(215, 175) ">
<path d="M 0,0 L 0,30 M 10,0 L 10,30"
transform="rotate(38 10 15)"  />  
</g>
<g transform="translate(70, 180) ">
<path d="M 0,0 L 0,30 M 10,0 L 10,30 M 20,0 L 20,30"
transform="rotate(-70 20 15)"  />  
</g>
</g>
</svg>
<svg height="400" width="400" x="0" y="0" viewBox="0 0 400 400" overflow="hidden">
<rect class="f-yellow" opacity="0.5" x="0" y="0" width="400" height="400" />
<text class=" t24 t-mid bold f-blue" x="200" y="30">SCALENE TRIANGLE</text>
<g opacity="1" transform="scale(1) translate(0, 60)">
<path class="l4 f-white s" d="M125,100 L350,300 L50,300 z" />
<!-- ANGLE ARCS-->
<g transform="translate(75, 50) rotate(-250 50, 50)">
<path class="linearc" d="M95,50 A 45, 45, 0, 0, 0, 65, 8 " />  
</g>
<g transform="translate(0, 250) ">
<path class="linearc" d="M95,50 A 45, 45, 0, 0, 0, 65, 8
                M85,50 A 35, 35, 0, 0, 0, 62, 17 " />              
</g>
<g transform="translate(300, 250) rotate(-140 50, 50)">
<path class="linearc" d="M95,50 A 45, 45, 0, 0, 0, 85, 20
                M85,50 A 40, 40, 0, 0, 0, 78, 27
                M105,50 A 50, 50, 0, 0, 0, 92, 15" />  
</g>
<!-- LINE TICKS -->
<g transform="translate(200, 285) ">
<path class="linearc" d="M 0,0 L 0,30"
transform="rotate(0 15)"  />  
</g>
<g transform="translate(215, 175) ">
<path class="linearc" d="M 0,0 L 0,30 M 10,0 L 10,30"
transform="rotate(38 10 15)"  />  
</g>
<g transform="translate(70, 180) ">
<path class="linearc" d="M 0,0 L 0,30 M 10,0 L 10,30 M 20,0 L 20,30"
transform="rotate(-70 20 15)"  />  
</g>
<!-- VERTICES LABELS-->
<g class="f-dblue t24">
<text class="t-mid" x="125" y="90">A</text>
<text class="t-end" x="40" y="310">B</text>
<text class="t-start" x="360" y="310">C</text>
</g>
<!-- LINES LABELS-->
<g class="f-dgreen italic t24">
<text class="t-mid" x="200" y="330">a</text>
<text class="t-start" x="240" y="180">b</text>
<text class="t-end" x="70" y="200">c</text>
</g>
<!-- ANGLE LABELS-->
<g class="f-dred italic t24">
<text class="t-mid" x="135" y="165">A</text>
<text class="t-start" x="90" y="270">B</text>
<text class="t-end" x="290" y="280">C</text>
</g>
<!-- GENERAL LABELS-->
<g class="f-black t20">
<text x="25" y="120">All sides</text>
<text x="25" y="140">different </text>
<text x="25" y="160">lengths</text>
<text x="270" y="200">All angles</text>
<text x="270" y="220">are different</text>
</g>
<!-- SCALED COPY ============== -->
<g opacity="1"  transform="scale(0.6) translate(260, -100) ">
<path class="l4 f-white s" d="M125,100 L350,300 L50,300 z" />
<!-- ANGLE ARCS-->
<g transform="translate(75, 50) rotate(-250 50, 50)">
<path class="linearc" d="M95,50 A 45, 45, 0, 0, 0, 65, 8 " />  
</g>
<g transform="translate(0, 250) ">
<path class="linearc" d="M95,50 A 45, 45, 0, 0, 0, 65, 8
                M85,50 A 35, 35, 0, 0, 0, 62, 17 " />              
</g>
<g transform="translate(300, 250) rotate(-140 50, 50)">
<path class="linearc" d="M95,50 A 45, 45, 0, 0, 0, 85, 20
                M85,50 A 40, 40, 0, 0, 0, 78, 27
                M105,50 A 50, 50, 0, 0, 0, 92, 15" />  
</g>
<!-- LINE TICKS -->
<g transform="translate(200, 285) ">
<path class="linearc" d="M 0,0 L 0,30"
transform="rotate(0 15)"  />  
</g>
<g transform="translate(215, 175) ">
<path class="linearc" d="M 0,0 L 0,30 M 10,0 L 10,30"
transform="rotate(38 10 15)"  />  
</g>
<g transform="translate(70, 180) ">
<path class="linearc" d="M 0,0 L 0,30 M 10,0 L 10,30 M 20,0 L 20,30"
transform="rotate(-70 20 15)"  />  
</g>
<!-- VERTICES LABELS-->
<g class="f-dblue t24">
<text class="t-mid" x="125" y="90">A</text>
<text class="t-end" x="40" y="310">B</text>
<text class="t-start" x="360" y="310">C</text>
</g>
<!-- LINES LABELS-->
<g class="f-dgreen italic t24">
<text class="t-mid" x="200" y="330">a</text>
<text class="t-start" x="240" y="180">b</text>
<text class="t-end" x="70" y="200">c</text>
</g>
<!-- ANGLE LABELS-->
<g class="f-dred italic t24">
<text class="t-mid" x="135" y="165">A</text>
<text class="t-start" x="90" y="270">B</text>
<text class="t-end" x="290" y="280">C</text>
</g>
<!-- GENERAL LABELS-->
<g class="f-black t20">
<text x="25" y="120">All sides</text>
<text x="25" y="140">different </text>
<text x="25" y="160">lengths</text>
<text x="270" y="200">All angles</text>
<text x="270" y="220">are different</text>
</g>
</svg>

 

comments powered by Disqus