In this article, you will learn about the SpiralTrackBar class. This class is a replacement for the .NET Framework and .NET TrackBar control, which displays the track line as a spiral.

## Introduction

*This is release 1.1.0. It uses the new SimpleWidgets2 library, fixes a bug where the marker would not visually update if the position was changed programmatically, and is compiled using .NET Framework 3.5, .NET Framework 6.4.2, and .NET 6.0.*

The `SpiralTrackBar`

class is a replacement for the .NET Windows Forms `TrackBar`

control, which displays the track line as a spiral.

All `public`

and `protected`

classes, methods and properties are fully documented using standard C# XML documentation comments. The project includes help files in both .chm and .mshc formats. Refer to the **Overview** section in the help file for more details on using the class.

All members of the control are fully configurable within Visual Studio Designer for .NET Framework projects.

The `SpiralTrackBar_110_Demo`

download includes:

| `GAW.SpiralTrackBar.Net462.dll` | | Library compiled for .NET Framework 4.6.2. |

| `GAW.SimpleWidgets2.Net462.dll` | | Required SimpleWidgets2 library. |

| `GAW.SpiralTrackBar.ExplorerApp.Net462.exe` | | Sample app demonstrating all of the `SpiralTrackBar` properties. |

The `SpiralTrackBar_110_Library`

download includes the above files, as well as the corresponding files for .NET Framework 3.5 and .NET 6.0 and the help files in both .chm and .mshc formats.

The `SpiralTrackBar_110_Source`

download includes the source for the `SpiralTrackBar`

control and the explorer app as well as the necessary files for building the help files. It does **not** include the source for the `SimpleWidgets2`

library. That is available in a different project.

### Caveats for .NET 6.0

The Windows Forms (WinForms) designer in Visual Studio 2022 only works for .NET Framework, and is not yet available for .NET 6.0. The recommended workaround is to create a .NET Framework 4.6.2 project, create the necessary GUI components, and then copy the generated WinForms code into the .NET 6.0 project.

## Using the Control

The possible values range from `Minimum`

to `Maximum`

in increments of `StepSize`

. The current value is specified by the property `Value`

, which increases as the marker is moved counter clockwise, and decreases as the marker is moved clockwise.

### The Track Line

The size and orientation of the track line is determined by the properties `StartAngle`

, `Rotations`

, `IndentStart`

, and `IndentStop`

.

`StartAngle`

is specified in degrees measured counter clockwise from the x-axis. `Rotations`

is the length of the track line arc (for example, 1.5 would be 540 degrees). The indent values are relative to the size of the control, where 0.0 is defined as the center of the control, and 1.0 is the distance from the center of the control to the nearest edge:

The shape of the track line is determined by the properties `TrackFillSize`

, `TrackBorder`

, `TrackFill`

, and `TrackEnd`

.

### Tick Marks

The length and position of the tick marks is determined by the properties `TickLength`

and `TickStyle`

. The thickness, color, and style of the line is determined by `TickLine`

.

Major ticks occur every `MajorTickFrequency`

steps. Minor ticks occur every `MinorTickFrequency`

steps (there are no minor ticks if this value is zero). Major ticks are `TickLength`

pixels long. Minor ticks are half length.

The spacing of tick marks on the track line is determined by the property `TickSpacing`

. If `TickSpacing`

is `SpiralTrackBarTickSpacing.ArcLength`

, the tick marks are evenly spaced along the track line. If `TickSpacing`

is `SpiralTrackBarTickSpacing.Angular`

, the tick marks are spaced using angular increments. In this case, the tick marks will be closer together at the beginning of the track line, and farther apart near the end.

| |

`Angular` | `ArcLength` |

### Marker

The marker indicates the current value on the track line. It can be dragged with the mouse or moved programmatically.

The shape of the marker is determined by `MarkerShape`

, the border is determined by `MarkerBorder`

, and the interior fill is determined by `MarkerFill`

.

## Spiral Math

This section explains the math for plotting the spiral, drawing the tick marks, and calculating arc length.

The equation of a spiral in polar coordinates is:

$\begin{aligned} r = A + B \theta \end{aligned}$

where \(r\) is the distance from center, and \(\theta\) is the angle, specified in radians measured counter clockwise from the x-axis. The constants \(A\) and \(B\) depend on the size of the control, the indent values, and the start and stop angles:

$\begin{aligned} B & = m (i_1 - i_2) / (r_1 - r_2) \\ A & = m i_1 - B r_1 \end{aligned}$

where:

\(m\) | Minimum of the control width and height |

\(i_1, i_2\) | `IndentStart` , `IndentStop` members |

\(r_1, r_2\) | `StartAngle` , `StopAngle` members in radians |

The formula to convert a point in polar coordinates to Cartesian coordinates is:

$\begin{aligned} x = r \cos(\theta) \\ y = r \sin(\theta) \end{aligned}$

### Location of Tick Marks

The tick marks are drawn perpendicular to the tangent of the spiral, so we need to calculated the tangent. The general equation of a tangent on a curve in polar coordinates is:

$\begin{aligned} t = \dfrac{r' \sin(\theta) + r \cos(\theta)} {r' \cos(\theta) - r \sin(\theta)} \end{aligned}$

where \(r '\) is first derivative of \(r\). In the case of spiral,

$\begin{aligned} r' = B \end{aligned}$

So the slope of a tick mark at position \(\theta\) on the spiral is:

$\begin{aligned} m & = \dfrac{-1}{t} \\ & = \dfrac{r \sin(\theta) - B \cos(\theta)} {B \sin(\theta) + r \cos(\theta)} \\ & = \dfrac{(A + B \theta) \sin(\theta) - B \cos(\theta)} {B \sin(\theta) + (A + B \theta) \cos(\theta)} \end{aligned}$

### Arc Length

In order to place tick marks equidistant along the spiral, we need to calculate the arc length of the curve. The general equation for arc length on a curve in polar coordinates is:

$\begin{aligned} L = \int{ \sqrt{ r'^2 + r^2 } } d\theta \end{aligned}$

which expands to:

$\begin{aligned} L & = \int{ \sqrt{ B^2 + r^2 } } d\theta \\ & = \int{ \sqrt{ B^2 + (A + B \theta)^2 } } d\theta \end{aligned}$

The messy solution to this integral comes courtesy of *Handbook of Tables for Mathematics (4th edition)* (page 562 - integral formula #242). After many steps (not shown here), the final equation for the arc length is:

$\begin{aligned} L & = \dfrac{r \sqrt{ B^2 + r^2 }}{2 B} + \dfrac{B \log(2 B (\sqrt{ B^2 + r^2 } + r))} {2} \\ & = \dfrac{(A + B \theta) \sqrt{ B^2 + (A + B \theta)^2 }}{2 B} + \dfrac{B \log(2 B (\sqrt{ B^2 + (A + B \theta)^2 } + (A + B \theta)))} {2} \end{aligned}$

Note that this equation can **not** be inverted. That is, there is **no** function \(f\) such that:

$\begin{aligned} \theta = f(L) \end{aligned}$

So the only to find \(\theta\) for a given arc length \(L\) is through interpolation.

## Points of Interest

After deriving the solution to the arc length formula, my concern was this would be an expensive calculation to be performed repetitively - square root and a log operations were not (computationally) cheap. My plan was to build a table of pre-calculated values to reduce the number of calculations to be done while interpolating. The pre-calculated values would prove to be unnecessary. My computer - purchased in 2008 and equipped with a Pentium D processor - was able to perform over four thousand arc length calculations in under **one millisecond**, or about four million calculations per second.

Further research led me to discovery that Pentium processors have instructions to handle many floating point operations which used to be done in software, such as square root, log, and trigonometric functions. This was, for me, a **WOW** moment. I first learned assembler 40 years ago on the Z-80, an 8-bit processor with some 16-bit capabilities. It's arithmetic instructions were limited adding, subtracting and shifting integers. It didn't even have an instruction for an an 8-bit multiply. We've come a long way.

There are three read-only properties which reveal statistics internal to the control:

`CalcLayoutArcCount`

- Number of arc length calculations performed `CalcLayoutTime`

- Number of milliseconds to calculate the most recent layout `PaintTime`

- Number of milliseconds spent during the most recent paint operation

## Future Changes

Once the issues with Visual Studio Windows Forms Designer for .NET applications has been resolved, SpiralTrackBar will be updated. Hopefully this will happen soon...

## History

- December 6, 2022 - Release 1.1.0
- Added XML serialization.
- Added method
`GenerateCode` method which generates initialization source code. - Fixed a bug whereas the marker would not visually update if the position was changed programmatically.
- Changed project to use
`SimpleWidgets2` library, instead of `SimpleWidgets`. - Changed project so that library was compiled with Visual Studio 2022 for .NET Framework 3.5, .NET Framework 4.6.2, and .NET 6.0.
- Changed help files to work with Sandcastle Help File Builder 2021.11.7.0.
- Fixed issues with the math formatting in the article.

- October 12, 2020 - Release 1.0.3
- Fixed a bug whereas the marker could jump to the wrong track if the starting angle was zero and the number of rotations was greater than 1.0

- September 13, 2014 - Release 1.0.2
- Converted
*.csproj* files to Visual Studio 2013 format - Converted help files to work with SandCastle Help File Builder 2014.5.31.0

- February 5, 2014 - Release 1.0.1
- Fixed missing tags in documentation

- February 2, 2014 - First release

This member has not yet provided a Biography. Assume it's interesting and varied, and probably something to do with programming.