phplot/HorizontalBars - Documentation for experimental new plot types
Last updated for PHPlot-5.1.3 on 2010-08-30
The project home page is http://sourceforge.net/projects/phplot/
-----------------------------------------------------------------------------
Overview:

This file documents new plot types: Horizontal Bars, Horizontal Stacked Bars,
and Horizontal Thinbarline. Horizontal Bars was added to PHPlot in version
5.1.2 as an experimental feature. Horizontal Stacked Bars and Horizontal
Thinbarline were added to PHPlot in version 5.1.3.

    NOTICE:

    These new plot types are experimental. This means anything about this
    may change in future releases, in ways that might be incompatible
    with the current implementation, or the new plot types might even
    be removed completely. The new plot types are not yet documented in
    the PHPlot Reference Manual. This text file is the only documentation.

Feedback on this feature is welcome. Please use the "help & discussion"
forum at http://sourceforge.net/projects/phplot/

-----------------------------------------------------------------------------
Usage:

In horizontal plots, the X axis and Y axis are oriented the same as in
other PHPlot plot types: X axis is horizontal, increasing towards the
right, and Y axis is vertical, increasing towards the top.

    Y
    ^
    |
    |==============
    |
    |=====
    |
    |=========
    |
    +---------------------> X

To make a horizontal bar chart, use the same plot type as vertical bar
charts ('bars'), but use the new data type 'text-data-yx'. The new data
type indicates your data array has a different representation, mapping Y
values to X values (instead of X values to Y values).

A horizontal stacked bar chart looks like a horizontal bar chart, except
the bar segments are stacked (horizontally) instead of being drawn in a
group side-by-side. To make a horizontal stacked bar chart, use the same
plot type as vertical stacked bar chars ('stackedbars'), but use the new
data type 'text-data-yx'.

For a normal (vertical) bar or stacked bar chart, the data array has type
'text-data' and looks like this:
  $data = array(  array('Label1', Y11, Y12, ...),
                  array('Label2', Y21, Y22, ...),
                  ...);
Each entry (row) in the data array represents one group of bars. Each group
has a label and one or more Y values. The X values are implicit: the first
row has the first X value, the second row has the second X value, etc.

For the new horizontal bar and stacked bar charts, the data array has the new
type 'text-data-yx' and looks like this:
  $data = array(  array('Label1', X11, X12, ...),
                  array('Label2', X21, X22, ...),
                  ...);
Each entry (row) in the data array represents one group of bars. Each group
has a label and one or more X values. The Y values are implicit: the first
row has the first Y value, the second row has the second Y value, etc.

As you can see, a vertical bar or stacked bar chart can be changed to a
horizontal chart simply by changing the data type passed to SetDataType()
The data array itself does not change. Other issues with horizontal charts
are discussed below.

This complete script makes a very simple horizontal bar chart:
    <?php
    require 'phplot.php';
    $p = new PHPlot(800, 800);
    $p->SetDataValues(array(array('A', 10, 25), array('B', 30, 5)));
    $p->SetDataType('text-data-yx');
    $p->SetPlotType('bars');
    $p->DrawGraph();

Note that the bars in a horizontal bar or stacked bar chart are ordered
from bottom to top (that is, increasing Y values). In the example above,
the "A" label bar group or stack is drawn below the "B" label bar group or
stack. If you need bars ordered from top to bottom, you will have to change
your data array accordingly.

A Horizontal Thinbarline plot is similar to a horizontal bar chart, except
that instead of horizontal bars you get thin horizontal lines. There are
two supported data types for horizontal thinbarline plots: text-data-yx (as
described above), and data-data-yx which includes the Y value for each row.
A data array with data type 'data-data-yx' looks like this:
  $data = array(  array('Label1', Y1, X11, X12, ...),
                  array('Label2', Y2, X21, X22, ...),
                  ...);

Note that although thinbarline plots (vertical and horizontal) support
multiple Y (or X) values for each X (or Y), as shown in the data array
above, it is rarely useful to have more than one, because the lines would
be drawn on top of each other.

-----------------------------------------------------------------------------
Ticks and Labels:

Since the X axis and Y axis do not change positions for horizontal plots,
the label and tick controls still refer to the X and Y axis.  However, the
independent values are now Y, and the dependent values are now X. Also, the
label strings in your data array are plotted along the Y axis for
horizontal charts, rather than along the X axis for regular charts.

To control the data labels positions, use SetYDataLabelPos(). New option
values have been added to this function, which was previously used only to
position bar chart value labels with the options 'plotin', 'plotstack', or
'none'. With horizontal plots, SetYDataLabelPos() positions the regular
data labels that go along the Y axis. The new option values are 'plotleft',
'plotright', or 'both'.
  'plotleft' : Draw data labels along the left side of the plot area.
  'plotright' : Draw data labels along the right side of the plot area.
  'both' : Draw data labels along both left and right sides.
  'none' : Do not draw data labels.

For bar or stacked bar charts, it makes no sense to have ticks or tick
labels along the independent axis. This is the Y axis for horizontal
charts.  Therefore, you should use SetYTickPos('none') to turn off the tick
marks on the Y axis. You do not normally need to use
SetYTickLabelPos('none') to turn off the tick labels along the Y axis,
since PHPlot will do this automatically if your data array has labels.

To control the presentation of the data labels with horizontal plots, use
the correct functions that refer to the Y data labels, not X data labels as
with vertical bar charts.

   SetYDataLabelAngle() or SetYLabelAngle()
       Set angle of data label text. Default is 0 degrees.

   SetYDataLabelType() or SetYLabelType()
       Select the type of formatting for the data labels.

   SetFont(), SetFontGD(), or SetFontTTF()
       Use the element name 'y_label' for the data labels.

Note that the PHPlot Reference Manual currently says the Y Data Label
functions are only for bar chart data value labels (see Data Value Labels
below regarding this term). That information is out of date. These
functions are now also used for data labels along the axis in horizontal
plots.

-----------------------------------------------------------------------------
Grid:

For horizontal plots, the X grid lines default on, and the Y grid lines
default off. (This is the opposite of normal vertical plots, where the X
grid lines default off, and the Y grid lines default on.)

-----------------------------------------------------------------------------
Y Axis Position:

PHPlot uses a different default for the X axis and the Y axis positions.
This affects horizontal plots if you have any data values which are
less than zero.  The X axis is normally positioned at Y=0, and the Y axis
is normally positioned at the left side of the plot.

For both vertical bar charts and horizontal bar charts, the bars are always
drawn 'outward' from the axis - not from the line with value zero.  This
results in different default appearance when the data contains negative
values, due to the difference in default axis position.

For vertical bar charts, with the X axis at zero (the default), bars with
positive values are drawn upwards and bars with negative values are drawn
downwards.

For horizontal bar charts, with the Y axis in the default position on the
left side, all bars will be drawn to the right whether the values are
positive or negative.

You can use SetYAxisPosition(0) with horizontal bar charts to move the Y
axis to be at X=0. This will result in negative bar values being drawn to
the left of the axis.

Note that negative values are not allowed with stacked bar charts (vertical
or horizontal) because the values in each group are summed. For stacked bar
charts, the bottom margin for the dependent variable (X for horizontal
charts) always defaults to zero, and there will never be negative values.

For thinbarline plots, the lines are drawn in the same way as the bar chart
bars. This means in a horizontal thinbarline plot with negative values, the
Y axis will still default to the left side, and the lines will be drawn
from the left side towards the right, for both positive and negative values.

-----------------------------------------------------------------------------
Scaling:

You can use SetPlotAreaWorld() to explicitly set any or all of the 4 limits
of the plot area. Any limits you do not provide will be calculated for you.
The algorithm is due for replacement, but it will now apply the same
calculations to Y and X values in horizontal plots as it currently applies
to X and Y (respectively) in vertical plots. That is, the range for the
independent variable will be calculated to contain and center the bar
groups, and the range for the dependent variable will include and usually
exceed the actual data range.

The example under Usage above will produce an auto-calculated Y range of 4
to 33, with the X range set to center the two bar groups. If you change
'text-data-yx' to 'text-data', you will get a vertical bar chart with the
same automatic range.

-----------------------------------------------------------------------------
Data Value Labels:

Data Value labels for horizontal bar charts were implemented in PHPlot-5.1.3.
These are the text labels within the plot that identify the X value for each
bar.  (See Example 5.19 "Bar Chart with Data Labels" in the manual for an
example of data value labels for vertical bar charts.)

Data Value labels are enabled and controlled in the same way for horizontal
bar charts as for vertical bar charts, except the 'X' control functions are
used instead of 'Y' control functions.

Data Value labels (both at the ends of the bars and within the bar stacks)
are implemented for horizontal stacked bars.

To enable data value labels on horizontal bar charts:
    $plot->SetXDataLabelPos('plotin');
Note this is the same function used to enable X data labels for normal
(vertical) plots, but a new option 'plotin' enables the data value labels
and positions them inside the plot. This is the only valid argument value
(other than the default 'none') for horizontal bar charts.

To enable data value labels on horizontal stacked bar charts:
    $plot->SetXDataLabelPos('plotin');
 or $plot->SetXDataLabelPos('plotstack');
The option 'plotin' enables the data value labels which show the total for
each stack and is drawn at the end of the bar stack. The option 'plotstack'
enables both those labels and labels within the stack showing the value of
each segment. This works exactly the same as in vertical stacked bars,
except that X data labels are being used rather than Y data labels.

You can control the angle and formatting type for data value labels using:
    SetXDataLabelAngle($angle)         SetXLabelAngle($angle)
    SetXDataLabelType($type, ...)      SetXLabelType($type, ...)
See the manual for more information, but note that the manual does not yet
document that these apply to data value labels.  Also note that the label
angle defaults to 0, not 90 degrees.

The font and color for data value labels are set with SetFont('x_label', ...)
and SetTextColor(...), but note these also apply to other elements as well.

Data value labels in horizontal bar charts and horizontal stacked bar
charts are drawn at the ends of the bars (and within the stacks,
optionally, for horizontal stacked bar charts). This is to the right or
left, depending on which way the bar extends from the Y axis. As discussed
above under "Y Axis Position", the behavior differs from vertical bar
charts because the Y axis does not default to X=0. If you have a horizontal
bar chart with negative values, and you do not reposition the Y axis, bars
for those negative values will still be drawn from the left side towards
the right, with the Y axis position having a negative X value. The data
values labels will still be drawn to the right of the bar end in that case.
(Stacked horizontal bars never have negative values, so the labels at the
ends of the bars are always drawn to the right of the bars.)

Note: Data Value Labels are currently referred to in the manual as Y Data
Labels. This will be changed to call them 'Data Value Labels'. This is
necessary to avoid confusion with X Data Labels and Y Data Labels.

There are no data value labels at all for thinbarline plots.

-----------------------------------------------------------------------------
Other Plot Types Not Available:

There are currently no corresponding horizontal analogs for any plot type
other than bars, stacked bars, and thinbarline.  Using data type
'text-data-yx' with other plot types will fail.  Using data type
'data-data-yx' with any plot type other than thinbarline will fail.
(Starting with 5.1.2, PHPlot always checks that the selected data type is
supported for the selected plot type.)

-----------------------------------------------------------------------------
Implementation Notes:

The following is a summary of the changes made to PHPlot to implement
horizontal plots.

(Phase 1 implemented horizontal bar charts only, with no data labels.
This was released in PHPlot-5.1.2.)

1) Do not initialize y_tick_label_pos or y_data_label_pos. The defaults
have to be dynamically calculated for horizontal bar charts, so tick labels
can be suppressed. (This was already being done for X labels.) Existing
internal function CheckLabels() was extended to do this for Y also.

2) Do not initialize the X and Y grid setting variables. The defaults have
to be dynamically calculated because they differ with swapped data arrays.
New internal function CalcGridSettings() does this.

3) SetYDataLabelPos() accepts the new arguments plotleft, plotright, and
both. Old compatibility code that passed these values to SetYTickLabelPos()
has been removed.

4) SetDataType() accepts a new value: 'text-data-yx'.

5) FindDataLimits() was changed to properly calculate minimum and maximum
values from text-data-yx data arrays. The arrays data_miny and data_maxy
were renamed to just data_min and data_max, since they now describe limits
of either X or Y values, depending on the data type.

6) Changes were made to CalcMargins() to account for the labels in the data
array being drawn on the Y axis instead of X axis, in the text-data-yx
case.

7) CalcPlotAreaWorld() is extended to calculate defaulted plot ranges
correctly for the swapped X/Y case. The algorithm is the same (and due for
replacement). It applies a fixed range to Y and an extended range to X. It
is also ready for possible future expansion to include swapped X/Y plots
with explicit Y values.

8) Changed CalcBarWidths() to use either the plot area width or height,
depending on the bar directions, when calculating the bar widths.

9) Extended CalcMaxDataLabelSize() to work with both X and Y labels.
Before, it returned the maximum height of the data labels. Now it can
instead return the maximum width of the data labels; this is used for
horizontal bar charts.  It also has to pick the proper font, angle, and
format code for X or Y.

10) New internal function DrawYDataLabel() to draw data labels for
horizontal bar charts.

11) New internal function DrawHorizBars() draws the horizontal bar chart.

12) DrawGraph() now decides to draw a bar or horizontal bar chart based on
the data type (text-data or text-data-yx).


(Phase 2 changes were made after PHPlot-5.1.2, CVS as of 2010-07-26)

13) Change SetXDataLabelPos to accept 'plotin' for data value labels.

14) Add an argument $format_specifier to the internal function DrawDataLabel.
This allows data value labels for horizontal bar charts to use the 'xd'
format specifier instead of the 'yd' format specifier. The argument
defaults to 'yd' so no existing caller needs to change.
[Note this change was obsoleted below]

15) Add code to DrawHorizBars to draw the data value labels if enabled.


(Phase 3 changes were made after PHPlot-5.1.2, CVS as of 2010-08-03)

16) Removed internal function DrawDataLabel().

17) New internal function DrawDataValueLabel() replaces DrawDataLabel(). It
supports checking if the label fits in the available space, and accepts a
single argument 'x' or 'y' to control font, angle, format, and color of the
text, rather than using separate arguments.

18) Change SetXDataLabelpos() to accept 'plotstack'. This enables both end-
and in-stack- data value labels for horizontal stacked bars.

19) New internal function DrawHorizStackedBars() implements horizontal
stacked bars.


(Phase 4 changes were made after PHPlot-5.1.2, CVS as of 2010-08-14)

20) SetDataType() accepts a new value: 'data-data-yx'.

21) DecodeDataType() is extended to handle the new data type.

22) DrawThinBarLine is extended to handle horizontal as well as vertical
plots.  Note that since the thinbarline drawing is much simpler than bars or
stacked bars, it was not necessary to have a separate function to handle the
horizontal plotting in this case.

-----------------------------------------------------------------------------
History:

2010-06-26 First version, for PHPlot-5.1.2

2010-07-26 Update for CVS changes pending for next release after PHPlot-5.1.2.
  Data Value Labels are now implemented for horizontal bar charts. These
  display the value of each bar to the right (or left) of the end of the bar.

  Corrected the description under "Y axis position". Bars are not drawn from
  zero outwards, but from the Y axis - wherever it is.

2010-08-04 Update for CVS changes pending for next release.
  Horizontal stacked bar plots are now implemented, including data value
  labels above the bars and in-stack data value labels.

2010-08-14 Update for CVS changes pending for next release.
  Horizontal thinbarline plots are now implemented, along with a new data
  type 'data-data-yx'.

2010-08-29 No additional changes for PHPlot-5.1.3

-----------------------------------------------------------------------------
