# Implementation

## Grouped Bar Charts

*Kupper*

### Chart Layout

##### Calculating the bar thickness

In the following, a way is presented to numerically find a thickness for the tactile bars such that all groups fit on the available chart area. To use as much of the given area as possible and to minimize big gaps, the software will try to find the maximum possible thickness within the user defined limits `minThickness`

, `maxThickness`

.

The layout of the bars is as described in the conceptual design:

- There are
`g`

groups of an arbitrary number of bars`b[i]`

in each group`i`

, resulting in`b`

total bars - The groups are separated by a padding
`gpad`

, counted in full cells - The bars inside a group are separated by a padding
`bpad`

, also counted in full cells - All bars are of equal
`tickness`

- There are enclosing paddings: Between the axis and its closest bar & between the bar furthest from the axis and the end of the cart area, each 1 exactly 1 cell.
- The paddings contain the bar borders

A sketch for a layout with horizontal bars: ...

For a given value of `thickness`

, the full required size of the chart area can be calculated in the following way:

`reqSize(thickness) = (g-1) * gpad + SUM(0 <= i < g, gSize(i)) + 2`

`(g-1) * gpad`

is the sum of paddings between neighboring groups

`SUM(0 <= i < g, gSize(i))`

is the sum of each groups size

`2`

constant for the enclosing padding

The size of the group i can be calculated:

`gSize(i) = (b[i] - 1) * bpad + b[i] * thickness`

`(b[i] - 1) * bpad`

is the sum of paddings between neighboring bars

`b[i] * tickness`

is the sum of the sizes of the actual textured area inside the bars

Now it is possible to insert `gSize()`

into `reqSize()`

and set `thickness=0`

to calculate a `baseSize`

.

```
baseSize = reqSize(thickness=0) = (g-1) * gpad + SUM(0 <= i < g, (b[i] - 1) * bpad + b[i] * thickness) + 2
= (g-1) * gpad + SUM(0 <= i < g, (b[i] - 1) * bpad + b[i] * 0) + 2
= (g-1) * gpad + SUM(0 <= i < g, (b[i] - 1) * bpad) + 2
// Now the sum term can be replaced
= (g-1) * gpad + SUM(0 <= i < g, (b[i] - 1)) * bpad + 2
= (g-1) * gpad + (SUM(0 <= i < g, b[i]) - g) * bpad + 2
= (g-1) * gpad + (b - g) * bpad + 2
// Simplify term
= g * gpad + (b - g) * bpad + 2 - gpad
= g * gpad - g * bpad + b * bpad + 2 - gpad
= g * (gpad - bpad) + (b * bpad) + 2 - gpad
```

This `baseSize(g, gpad, b, bpad) = g * (gpad - bpad) + (b * bpad) + 2 - gpad`

which does not depend on the actual arrangement of the groups and bars represents the required size for all paddings. The required size can now be represented much simpler as the sum of the base size and the required bar space:

`reqSize(thickness) = baseSize + b * thickness`

Of course a limit for the total size is given by the available chart area `availableSize`

. This means:

```
reqSize(thickness) <= availableSize
baseSize + b * thickness <= availableSize
// minus baseSize
b * thickness <= (availableSize - baseSize)
// divide by total amount of bars b
thickness <= (availableSize - baseSize) / b
// The maximum possible thickness is wanted. But it also must be a whole number.
thickness = floor((availableSize - baseSize) / b)
```

So the software will calculate the baseSize for the given `g, gpad, b, bpad`

and then calculate the actual bar thickness complying with the user defined maximum:

`thickness = min(floor((availableSize - baseSize) / b), maxThickness)`

In the case of `thickness < minThickness`

an exception will be thrown stating that there is not enough space available.

## Floating Dot Area Mode

*Schmidt*

The floating dot area mode enables embossing by defining dots by their x- and y-coordinate. All plotting algorithms must implement the Plotter interface. Points are added iteratively to a FloatingPointData with an x- and a y-coordinate. The list with coordinates are passed to the printer starting with an ESC 70 sequence, separated by commas and ending with a semicolon.

Plotting algorithms for diagrams should extend AbstractPlotter or an abstract child class, which provide basic functionalities such as axes drawing and axes scaling. All dimensions adapt dynamically to the size of the paper or to the range of values, respectively. The user can chose wether a second y-axis should be plotted for scatter and line plots. The user can also chose wether a negative grid should be embossed.

Scatter plots are plotted by adding the points to the diagram and, if desired, plotting a frame around it. Currently three different frames are supported.

Line plots are plotted like scatter plots with additional line plotting between two data points. For this purpose the slope and the y-intercept are calculated. Lines are plotted by taking the x-coordinates between two points and calculating the y-coordinates with y = slope * x + y-intercept. Currently three different line styles are supported. The full line style corresponds with the dot frame. The dashed line style corresponds with the cross frame. The dotted line style corresponds with the circle frame. This may be changed in LinePlotter in drawLines (line 161). Variable i corresponds to the different frames. It is possible for the user to not chose any frame or to chose the dot frame for all data series.

The user can chose wether bar chart data should be plotted as a grouped or a stacked bar chart. Negative values are only supported for grouped bar charts, not for stacked bar charts.

Further documentation can be found in the JavaDoc. The config values for the user settings can be found in Software Design/Configuration Parsing.

### Adding textures, frames and line styles to the floating dot mode

#### Adding textures to bar charts

To add a new texture to bar charts, first implement a texture function in AbstractBarChartPlotter (e.g. fillFullPattern). Then add a new else-if-statement in plotAndFillRectangle with an incremented value for j and the newly defined function in the body. A comment "new textures are added here" will show you the right spot (line 148).

#### Adding frames to scatter and line plots

To add a new frame to scatter and line plots, first implement a frame function in AbstractPointPlotter (e.g. drawDot). Then add a new else-if-statement in drawPoint with an incremented value for i and the newly defined function in the body. A comment "new frames are added here" will show you the right spot (line 283).

#### Adding line styles to line plots.

To add a new line style to line plots, first implement a line function in LinePlotter (e.g. drawFullLine). Then add a new else-if-statement in drawLines with an incremented value for i and the newly defined function in the body. A comment "new line styles are added here" will show you the right spot (line 170).

## Misc

### Notes about the configuration files and parser

*Kupper*

- first thoughts about possible formats: INI, JSON, XML
- readability for normal users?
- easily parsable?
- structure of the files: First section with general properties, following sections with page formats containing format specific properties

INI format:

- windows specific format
- good readability, but:
- no native support in Java, third party lib necessary

JSON & XML:

- not very readable for normal users
- syntax can easily be broken unintentionally -> not parsable if broken

Instead: Java Properties?

- native support (java.util.Properties)
- allows same division into sections
- easy list-like syntax similar to INI -> good readability
- Syntax:
*section.property=value*