NAME

SVG::Template::Graph - Perl extension for generating template-driven graphs with SVG

SYNOPSIS

 use SVG::Template::Graph;
 $data = [
		{ 
		barGraph=>1,#<barGraph|[lineGraph]>
	  	barSpace=>20,
        	'title'=> '1: Trace 1',
        	'data' => #hash ref containing x-val and y-val array refs
                	{
                	'x_val' => 
				[50,100,150,200,250,
			        300,350,400,450,500,550],
			'y_val' =>
                        	[100,150,100,126,100,
				175,100,150,120,125,100],

                	},
		'format' =>
			{ #note that these values could change for *each* trace
			'lineGraph' => 1,
	        	'x_min' =>      0, 
			'x_max' =>      600, 
			'y_min' =>      50,
			'y_max' =>      200,
			'x_axis' => 1, #draw x-axis
			'y_axis' => 1, #draw y-axis
 
                	#define the labels that provide the data context.
	        	'labels' =>
				{
				#for year labels, we have to center the axis markers
				'x_ticks' =>
					{
					'label' =>[2002,2003,2004],
					'position'=>[100,300,500],
					},
	       			'y_ticks' =>
					{
					#tick mark labels
					'label' => [ -250, 0, 250, 500],
               				#tick mark location in the data space
               				'position' => [50, 100, 150, 200],
               				},
               			},
               		},
		},
 	];


 #construct a new SVG::Template::Graph object with a file handle
 my $tt = SVG::Template::Graph->new($file);

 #set up the titles for the graph
 $tt->setGraphTitle(['Hello svg graphing world','I am a subtitle']);
 
 #generate the traces. 
 $tt->drawTraces($data,$anchor_rectangle_id);
 #serialize and print
 print  $tt->burn();

DESCRIPTION

Template::Graph:SVG is a module for the generation of template-driven graphs using Scalable Vector Graphics (SVG). Using this module, it is possible to define a template SVG document with containers which are populated with correctly scaled plot images.

EXPORT

None by default.

EXAMPLES

Refer to the examples directory inside this distribution for working examples.

new()

#construct a new SVG::Template::Graph object with a file handle
my $tt = SVG::Template::Graph->new($file);

The constructor for the class. Takes a template file name as an argument

burn()

serialise the image. See SVG::xmlify for more details

setGraphTitle

my $svg_element_ref = $tt->setGraphTitle ($string|\@strings, %attributes)

Generate the text for the Graph Title Returns the reference to the text element

setTraceTitle

set the title of a trace

$tt->setTraceTitle( $string|\@strings, %attributes )

setXAxisTitle

Generate the text for the Graph X-Axis Titles Returns the reference to the text element

$tt->setXAxisTitle($axis_number, $string, %attributes)
$tt->setXAxisTitle($axis_number, \@strings, %attributes)

setYAxisTitle

Generate the text for the Graph Y-Axis Titles Returns the reference to the text element

$tt->setYAxisTitle($axis_number, $string,%attributes)
$tt->setYAxisTitle($axis_number, \@strings,%attributes)

_gg

Check that a group exists (is a valid, defined group in the SVG DOM) and create a group in the document if id does not exist. Return the group element This ensures that even if a designer failed to generate a group ID in the drawing, you will get a drawing with the right group names. If type is defined, an element of $type with %attributes is defined.

 my $svg_element = $tt->_gg ($id)
 my $svg_element = $tt->_gg ($id,'rect',width=>10,height=>10,
		x=>10,y=>10,fill=>'none',stroke=>'red')

_setAxisText

Internal method called by setGraphTitle and setAxisTitle to do the actual work. Not really intended to be accessed from the outside but available for advanced users.

$tt->_setAxisText ($id,$text|\@text,%attributes)

struct $struct

the input structure required by sub drawTraces to generate the graph. Refer to the examples included in this distribution in the examples directory for working samples.

 $struct = [{
	'tracetype' => 'linegraph',
        'title'=> '1: Trace 1',
        'data' => #hash ref containing x-val and y-val array refs
                {
                'x_val' =>
                        [0, 2, 4, 
			6, 8, 10,
			12,14,16,
			18,20],
                'y_val' =>
                        [4, 2, 5, 
			3, 7, 4 , 
			9, 9, 2, 
			4, 3],
                },
        'format' =>
                {
                'x_max' => 600, #or for your case, the date value of the 1st point
                'x_min' => 0, #or for your case, the date value of the last point
                'y_max' => 0.35,
                'y_min' => -0.1,
                'x_title' => 'Calendar Year',
                'y_title' => '% Annual Performance',
		'x_axis' => 0, # do not automatically draw an x-axis
		'y_axis' => 1, #automatically draw a y-axis
                
		#define the labels that provide
                #the data context.
                'labels' =>
                        {
                        #for year labels, we have to center the axis markers
                        'x_ticks' =>
                                {
                                'label'         =>[2002,2003,2004],
                                'position'      =>[100,300,500],
                                },
                        y_ticks =>
                                {
                                #tick mark label
                                'label' => [ '-10.00%', '-5.00%', '0.00%',
					 '5.00%', '10.00%', '15.00%', 
					'20.00%', '25.00%', '30.00%', 
					'35.00%' ],
                                #tick mark location in the data space
                                'position' => [-0.10,-0.5,0,
						-.5,.10,.15,
						.20,.25,.30,
						.35],
                                },
                        },
                },
        legend_title => 'Some Interesting Data',
        },
 ];

getCanvasBoxBoundaries()

if $id_anchor_data is an array reference, then it uses it to describe the extents of the viewbox into which the current drawing will happen. If $id_anchor_data is a string then its associated xml element is assumed to be a rectangle and getCanvasBoxBoundaries uses the rectangle geometry.to define the plot bounding box. hash references are not supported.

Action: set the boundary box data in the object and returns the array reference:

[xmin, ymin, xmax, ymax]

getDataBoxBoundaries (\%struct)

returns the value of the boundary box of the data set which places the graph in the image as an array reference:

[xmin, ymin, xmax, ymax]

drawAxis(<target_group_id>,[x|y|undef]))

draw one or both of axes (zero-value line) of the drawing data space. Draws both axes unless one of the axes is passed as a string.

drawAxis('somegroupid','x') draws the x-axis line into group 'somegroupid'.
drawAxis('somegroupid','y') draws the y-axis line indo group 'somegroupid'
drawAxis('somegroupid') draws both x- and y- axis lines into group 'somegroupid'

construction detail: draws the content into a group.

drawTraces ($data_structure,$insertion_anchor_id)

given a structure describing the incoming drawing parameters, generates the SVG lines, axes, and ticks and returns the number of traces that were handled. If $anchor_id is defined and is a rectangle ID, then the drawing will take place in id.if $anchor_point is defined and it is an array of 4 real numbers, then this will be taken to be the location where the insertion box goes.

The format for the array is: [x0 y0 x1 y1]. in canvas dimension

getTracePointMap $index, polyline|[path]|polygon, $p, $anchor_data, %args

scales the points for lines appropriately and generates the correct polyline or path or polygon element, scaled and inverted to match paper space.

if $anchor_data is defined, then it is either the id of a rectangle whose geometry will contain the results, or it is an array reference which contains the viewbox defilition [x0,y0,x1,y1] where the graph is to be placed.

this is the method in which the generation of the graph is handled

returns the reference of the polyline/path/polygon tag that was generated.

lineGraph index, type, [\@x,\@y], $canvas, %styling_attributes

draw a line graph trace

barGraph()

$g->barGraph( $index, [\@x,\@y], \@canvas, $barSpace, %styling_attributes)

draw a bar graph trace

drawGridLines()

$p->drawGridLines ($target_svg_element_ref,$transformation_ref,$format_structure_ref)

draw the gridlines for a graph as defined in the formatting data structure for each trace.

handleFurnishings()

$p->handleFurnishings( $orientation, $format, \%anchor_refs);

single point for handling grid lines, gridline lables, and gridline tickmarks this method is a factory method for generating vertical or horizontal furnishings for the trace the anchor hash reference contains the following keys:

line
label
tick

parameters

gridline orientation

$orientation = 'x' or 'y' 

Gridline context-format hash reference

$format - hash reference

defines what is shown and what is not.

whose values are svg element object references where the respective entities are to be appended as children.

drawGridLine()

draw a single grid line

drawTick()

$p->drawTick( ['x'|'y'], $index, $tick, $args, %attrs);

tickmark-generation handler

drawGridLabel()

grid lable generator

getTick($label_ref $oation)

return the front and back extensions to lines based on the definition (or lack of) tickmarks in the label construct

Example of a label definition:

$label = {
    'y_ticks' => {
         'style' => {
              'right' => '10'
          },
         'position' => [
              '150',
              '100',
              '0',
              '-75'
          ],
         'label' => [
              'Much',
              'Some',
              'None',
              'Lost'
          ]
     },
     'x_ticks' => {}
 };

D

$self->D()

returns the SVG Document object

T($name)

$self->T($name)

returns the currently invoked transformation object. Returns transformation object $name if requested by name

setGraphTarget $targetid, $elementType <rect>, %element_attributes

define the graph target (currently only rectangles are accepted) on top of which the data will be drawn

getGraphTarget

returns the current graph target

autoGrid (int $min, int $max, int $count)

generates a reference to an array of $count+1 evenly distributed values ranging between $min and $max

$tt->autoGrid(0,100,10);

Format

format an array of values according to formatting rules

$tt->Format \@array,$format,$format_attribute[,@more_format_attributes]

$format can be 'time' or 'printf'

for 'time', uses the Time::localtime

example 1: formatting to print the verbose date

$a = [
  '0',
  '2.75',
  '5.5',
  '8.25',
  '11'
];

my $b = $tt->Format($a,'time',"%a %b %e %H:%M:%S %Y");

returns

$b = [
  'Thu Jan  1 01:00:00 1970',
  'Thu Jan  1 01:00:02 1970',
  'Thu Jan  1 01:00:05 1970',
  'Thu Jan  1 01:00:08 1970',
  'Thu Jan  1 01:00:11 1970'
];

Format uses POSIX function b<strftime> Refer to POSIX for more information on time formating.

example 2: formatting to print to three decimal places using sprintf

$tt->Format([1.123,2.1234,3.12345,4.123456],'sprintf','%.3f'); 

example 3: formatting to print a percent sign

$tt->Format([1.123,2.1234,3.12345,4.123456],'sprintf','%%'); 

mapTemplateId string $id

setTemplateIdMap hash template_pairs

assign the definitions between the internal keys and the ids in the template at hand. This method need not be called as all IDs automatically get run through if the default IDs specified below are used.

simpleGraph string $id, string $type, hash %attrs

TEMPLATE

To draw a graph, a template is required which contains two key datasets: a rectangle which will contain the inserted graph data and a group containing child group elements with the IDs expected by SVG::Template::Graph

REQUIRED RECT ELEMENT

REQUIRED GRAPH TRACE HANDLER

The svg snippet below provides the required groups for the generation of the first trace (trace intex 0)

Because SVG uses the Painter's model, the image rendering order follows the XML document order. For the snippet below, the rendering order is the following:

data,grid,ticks,
axes:x,y,
axes values:
x,y,
axes text:
x,y,
axes titles:
x,y

Trace generation snippet

<!-- trace insertion takes place here -->
    <g id="group.trace.1" fill="none"
       stroke="black" stroke-width="2">
            <!-- draw the data below the gridlines -->
            <g id="group.trace.data.1"  
               stroke="#333333" stroke-width="0.5" 
               fill="#411DA4"/>
            <g id="group.trace.grid.1" 
               stroke="gray" stroke-width="1"/>
            <g id="group.trace.tick.1" 
               stroke="black" stroke-width="1.5"/>
            <g id="group.trace.axes.1" 
               stroke="none" fill="black">
                    <g id="group.trace.axes.x.1" stroke="gray" 
                       fill="none" stroke-width="1"/>
                    <g id="group.trace.axes.y.1" stroke="gray" 
                       fill="none" stroke-width="1"/>
                    <g id="group.trace.axes.values.x.1" text-anchor="middle" 
                       stroke="none" fill="black" transform="translate(0,265)"/>
                    <g id="group.trace.axes.values.y.1" stroke="none" 
                       fill="black" text-anchor="start" transform="translate(-40,0)"/>
                    <g id="group.trace.axes.title.x.1" text-anchor="middle" 
                       transform="translate(365,370)" font-size="12" 
                       fill="#411DA4" font-weight="Bold"/>
                    <g id="group.trace.axes.title.y.1.c" text-anchor="end" 
                       transform="translate(40,200)">
                            <g id="group.trace.axes.title.y.1" 
                               transform="rotate(-90)" font-weight="Bold" 
                               font-size="12" fill="#411DA4"/>
                    </g>
            </g>
    </g>
<!-- end of trace insertion 1 -->

In order to show the trace in front of the gridlines, the above snippet changes to:

<!-- trace insertion takes place here -->
    <g id="group.trace.1" fill="none"
       stroke="black" stroke-width="2">
            <g id="group.trace.grid.1"
               stroke="gray" stroke-width="1"/>
            <g id="group.trace.tick.1"
               stroke="black" stroke-width="1.5"/>
            <g id="group.trace.axes.1"
               stroke="none" fill="black">
                    <g id="group.trace.axes.x.1" stroke="gray"
                       fill="none" stroke-width="1"/>
                    <g id="group.trace.axes.y.1" stroke="gray"
                       fill="none" stroke-width="1"/>
                    <g id="group.trace.axes.values.x.1" text-anchor="middle"
                       stroke="none" fill="black" transform="translate(0,265)"/>
                    <g id="group.trace.axes.values.y.1" stroke="none"
                       fill="black" text-anchor="start" transform="translate(-40,0)"/>
                    <g id="group.trace.axes.title.x.1" text-anchor="middle"
                       transform="translate(365,370)" font-size="12"
                       fill="#411DA4" font-weight="Bold"/>
                    <g id="group.trace.axes.title.y.1.c" text-anchor="end"
                       transform="translate(40,200)">
                            <g id="group.trace.axes.title.y.1"
                               transform="rotate(-90)" font-weight="Bold"
                               font-size="12" fill="#411DA4"/>
                    </g>
            </g>
            <!-- draw the data on top of the gridlines -->
            <g id="group.trace.data.1" stroke="#333333" stroke-width="0.5" fill="#411DA4"/>
    </g>
<!-- end of trace insertion 1 -->

EXAMPLES

Refer to the examples directory inside this distribution for working examples.

SEE ALSO

SVG::Parser SVG::Manual Expat SAX SVG::TT:Graph Tramsform::Canvas http://www.roitsystems.com http://www.roitsystems.com

AUTHOR

Ronan Oger, <ronan.oger@roitsystems.com<gt> http://www.roitsystems.com http://www.roitsystems.com

CREDITS

This library was developed and written by Ronan Oger, ROIT Systems Gmbh, under contract to Digital Craftsmen.

COPYRIGHT

Copyright (C) 2004 by Ronan Oger, ROIT Systems GmbH, Zurich, Switzerland

Copyright (C) 2004 by Digital Craftsmen Ltd, London, UK

LICENSE

This library is free software; you can redistribute it and/or modify it under the same terms as Perl itself, either Perl version 5.8.3 or, at your option, any later version of Perl 5 you may have available.