File Coverage

blib/lib/GD/Graph/Polar.pm
Criterion Covered Total %
statement 16 18 88.8
branch n/a
condition n/a
subroutine 6 6 100.0
pod n/a
total 22 24 91.6


line stmt bran cond sub pod time code
1             package GD::Graph::Polar;
2 1     1   820 use strict;
  1         2  
  1         36  
3 1     1   6 use warnings;
  1         2  
  1         36  
4 1     1   21 use base qw{Package::New};
  1         2  
  1         1082  
5 1     1   1115 use Geo::Constants qw{PI};
  1         386  
  1         72  
6 1     1   875 use Geo::Functions qw{rad_deg};
  1         1258  
  1         69  
7 1     1   486 use GD qw{gdSmallFont};
  0            
  0            
8             use List::Util qw{first};
9              
10             our $VERSION="0.17";
11              
12             =head1 NAME
13              
14             GD::Graph::Polar - Make polar graph using GD package
15              
16             =head1 SYNOPSIS
17              
18             use GD::Graph::Polar;
19             my $obj=GD::Graph::Polar->new(size=>480, radius=>100);
20             $obj->addPoint (50=>25);
21             $obj->addPoint_rad (50=>3.1415);
22             $obj->addGeoPoint (75=>25);
23             $obj->addGeoPoint_rad (75=>3.1415);
24             $obj->addLine($r0=>$t0, $r1=>$t1);
25             $obj->addLine_rad($r0=>$t0, $r1=>$t1);
26             $obj->addGeoLine($r0=>$t0, $r1=>$t1);
27             $obj->addGeoLine_rad($r0=>$t0, $r1=>$t1);
28             $obj->addArc($r0=>$t0, $r1=>$t1);
29             $obj->addArc_rad($r0=>$t0, $r1=>$t1);
30             $obj->addGeoArc($r0=>$t0, $r1=>$t1);
31             $obj->addGeoArc_rad($r0=>$t0, $r1=>$t1);
32             $obj->addString($r=>$t, "Hello World!");
33             $obj->addString_rad($r=>$t, "Hello World!");
34             $obj->addGeoString($r=>$t, "Hello World!");
35             $obj->addGeoString_rad($r=>$t, "Hello World!");
36             $obj->font(gdSmallFont); #sets the current font from GD exports
37             $obj->color("blue"); #sets the current color from Graphics::ColorNames
38             $obj->color([0,0,0]); #sets the current color [red,green,blue]
39             print $obj->draw;
40              
41             =head1 DESCRIPTION
42              
43             This package is a wrapper arround GD to produce polar graphs with an easy interface. I use this package to display GPS satellites on a graph with data from the L package.
44              
45             =head1 CONSTRUCTOR
46              
47             =head2 new
48              
49             The new constructor.
50              
51             my $obj = GD::Graph::Polar->new( #default values
52             size => 480, #width and height in pixels
53             radius => 1, #scale of the radius
54             ticks => 10, #number of major ticks
55             border => 2, #pixel border around graph
56             rgbfile => "/usr/X11R6/lib/X11/rgb.txt"
57             );
58              
59             =head1 METHODS
60              
61             =head2 addPoint
62              
63             Method to add a point to the graph.
64              
65             $obj->addPoint(50=>25);
66              
67             =cut
68              
69             sub addPoint {
70             my $self = shift;
71             my $r = shift;
72             my $t = rad_deg(shift());
73             return $self->addPoint_rad($r,$t);
74             }
75              
76             =head2 addPoint_rad
77              
78             Method to add a point to the graph.
79              
80             $obj->addPoint_rad(50=>3.1415);
81              
82             =cut
83              
84             sub addPoint_rad {
85             my $self = shift;
86             my $r = shift;
87             my $t = shift;
88             my ($x, $y)=$self->_imgxy_rt_rad($r,$t);
89             my $icon=7;
90             return $self->gdimage->arc($x,$y,$icon,$icon,0,360,$self->color);
91             }
92              
93             =head2 addGeoPoint
94              
95             Method to add a point to the graph.
96              
97             $obj->addGeoPoint(75=>25);
98              
99             =cut
100              
101             sub addGeoPoint {
102             my $self = shift;
103             my $r = shift;
104             my $t = rad_deg(shift());
105             return $self->addGeoPoint_rad($r,$t);
106             }
107              
108             =head2 addGeoPoint_rad
109              
110             Method to add a point to the graph.
111              
112             $obj->addGeoPoint_rad(75=>3.1415);
113              
114             =cut
115              
116             sub addGeoPoint_rad {
117             my $self = shift;
118             my $r = shift;
119             my $t = PI()/2-shift();
120             return $self->addPoint_rad($r,$t);
121             }
122              
123             =head2 addLine
124              
125             Method to add a line to the graph.
126              
127             $obj->addLine(50=>25, 75=>35);
128              
129             =cut
130              
131             sub addLine {
132             my $self = shift;
133             my $r0 = shift;
134             my $t0 = rad_deg(shift());
135             my $r1 = shift;
136             my $t1 = rad_deg(shift());
137             return $self->addLine_rad($r0=>$t0, $r1=>$t1);
138             }
139              
140             =head2 addLine_rad
141              
142             Method to add a line to the graph.
143              
144             $obj->addLine_rad(50=>3.14, 75=>3.45);
145              
146             =cut
147              
148             sub addLine_rad {
149             my $self = shift;
150             my $r0 = shift;
151             my $t0 = shift;
152             my $r1 = shift;
153             my $t1 = shift;
154             my ($x0=>$y0)=$self->_imgxy_rt_rad($r0=>$t0);
155             my ($x1=>$y1)=$self->_imgxy_rt_rad($r1=>$t1);
156             return $self->gdimage->line($x0, $y0, $x1, $y1, $self->color);
157             }
158              
159             =head2 addGeoLine
160              
161             Method to add a line to the graph.
162              
163             $obj->addGeoLine(50=>25, 75=>35);
164              
165             =cut
166              
167             sub addGeoLine {
168             my $self = shift;
169             my $r0 = shift;
170             my $t0 = rad_deg(shift());
171             my $r1 = shift;
172             my $t1 = rad_deg(shift());
173             return $self->addGeoLine_rad($r0=>$t0, $r1=>$t1);
174             }
175              
176             =head2 addGeoLine_rad
177              
178             Method to add a line to the graph.
179              
180             $obj->addGeoLine_rad(50=>3.14, 75=>3.45);
181              
182             =cut
183              
184             sub addGeoLine_rad {
185             my $self = shift;
186             my $r0 = shift;
187             my $t0 = PI()/2-shift();
188             my $r1 = shift;
189             my $t1 = PI()/2-shift();
190             return $self->addLine_rad($r0=>$t0, $r1=>$t1);
191             }
192              
193             =head2 addArc
194              
195             Method to add an arc to the graph.
196              
197             $obj->addArc(50=>25, 75=>35);
198              
199             =cut
200              
201             sub addArc {
202             my $self = shift;
203             my $r0 = shift;
204             my $t0 = rad_deg(shift());
205             my $r1 = shift;
206             my $t1 = rad_deg(shift());
207             return $self->addArc_rad($r0=>$t0, $r1=>$t1);
208             }
209              
210             =head2 addArc_rad
211              
212             Method to add an arc to the graph.
213              
214             $obj->addArc_rad(50=>3.14, 75=>3.45);
215              
216             =cut
217              
218             sub addArc_rad {
219             my $self = shift;
220             my $r0 = shift;
221             my $t0 = shift;
222             my $r1 = shift;
223             my $t1 = shift;
224             my $m = ($r1-$r0) / ($t1-$t0);
225             my $inc = 0.02; #is this good?
226             my $steps = int(($t1-$t0) / $inc);
227             my @array = ();
228             foreach (0..$steps) {
229             my $t=$_ / $steps * ($t1-$t0) + $t0;
230             my $r=$r0 + $m * ($t-$t0);
231             push @array, [$r=>$t];
232             }
233             my @return=();
234             foreach (1..$steps) {
235             push @return, $self->addLine_rad(@{$array[$_-1]}, @{$array[$_]});
236             }
237             return \@return;
238             }
239              
240             =head2 addGeoArc
241              
242             Method to add an arc to the graph.
243              
244             $obj->addGeoArc(50=>25, 75=>35);
245              
246             =cut
247              
248             sub addGeoArc {
249             my $self = shift;
250             my $r0 = shift;
251             my $t0 = rad_deg(shift());
252             my $r1 = shift;
253             my $t1 = rad_deg(shift());
254             return $self->addGeoArc_rad($r0=>$t0, $r1=>$t1);
255             }
256              
257             =head2 addGeoArc_rad
258              
259             Method to add an arc to the graph.
260              
261             $obj->addGeoArc_rad(50=>25, 75=>35);
262              
263             =cut
264              
265             sub addGeoArc_rad {
266             my $self = shift;
267             my $r0 = shift;
268             my $t0 = PI()/2-shift();
269             my $r1 = shift;
270             my $t1 = PI()/2-shift();
271             return $self->addArc_rad($r0=>$t0, $r1=>$t1);
272             }
273              
274             =head2 addString
275              
276             Method to add a string to the graph.
277              
278             =cut
279              
280             sub addString {
281             my $self = shift;
282             my $r = shift;
283             my $t = rad_deg(shift());
284             my $string = shift;
285             return $self->addString_rad($r=>$t, $string);
286             }
287              
288             =head2 addString_rad
289              
290             Method to add a string to the graph.
291              
292             =cut
293              
294             sub addString_rad {
295             my $self = shift;
296             my $r = shift;
297             my $t = shift;
298             my $string = shift;
299             my ($x=>$y)=$self->_imgxy_rt_rad($r=>$t);
300             return $self->gdimage->string($self->font, $x, $y, $string, $self->color);
301             }
302              
303             =head2 addGeoString
304              
305             Method to add a string to the graph.
306              
307             =cut
308              
309             sub addGeoString {
310             my $self = shift;
311             my $r = shift;
312             my $t = rad_deg(shift());
313             my $string = shift;
314             return $self->addGeoString_rad($r=>$t, $string);
315             }
316              
317             =head2 addGeoString_rad
318              
319             Method to add a string to the graph.
320              
321             =cut
322              
323             sub addGeoString_rad {
324             my $self = shift;
325             my $r = shift;
326             my $t = PI()/2-shift();
327             my $string = shift;
328             return $self->addString_rad($r=>$t, $string);
329             }
330              
331             =head1 Objects
332              
333             =head2 gdimage
334              
335             Returns a L object
336              
337             =cut
338              
339             sub gdimage {
340             my $self=shift;
341             $self->{'gdimage'}=shift if @_; #set a base chart or watermark
342             unless ($self->{'gdimage'}) {
343             $self->{'gdimage'}=GD::Image->new($self->size, $self->size);
344              
345             # make the background transparent and interlaced
346             $self->gdimage->transparent($self->color([255,255,255]));
347             $self->gdimage->interlaced('true');
348            
349             # Put a frame around the picture
350             $self->gdimage->rectangle(0, 0, $self->size - 1, $self->size - 1, $self->color([0,0,0]));
351            
352             if ($self->ticks > 0) {
353             $self->color([192,192,192]);
354             foreach (0 .. $self->ticks) {
355             my $c=$self->size / 2;
356             my $r=$self->_width * $_ / $self->ticks;
357             $self->gdimage->arc($c,$c,$r,$r,0,360,$self->color);
358             }
359             }
360            
361             $self->color([192,192,192]);
362             $self->gdimage->line($self->size/2,
363             $self->border,
364             $self->size/2,
365             $self->size-$self->border,
366             $self->color);
367             $self->gdimage->line($self->border,
368             $self->size/2,
369             $self->size-$self->border,
370             $self->size/2,
371             $self->color);
372              
373             #default to black pen color
374             $self->color([0,0,0]);
375             }
376             return $self->{'gdimage'};
377             }
378              
379             =head2 gcnames
380              
381             Returns a L object
382              
383             =cut
384              
385             sub gcnames {
386             my $self=shift;
387             unless (defined $self->{'gcnames'}) {
388             eval 'use Graphics::ColorNames';
389             if ($@) {
390             die("Error: Cannot load Graphics::ColorNames");
391             } else {
392             my $file=$self->rgbfile; #stringify for object support
393             $self->{'gcnames'}=Graphics::ColorNames->new("$file");
394             }
395             }
396             return $self->{'gcnames'};
397             }
398              
399             =head1 Properties
400              
401             =head2 color
402              
403             Method to set or return the current drawing color
404              
405             my $colorobj=$obj->color("blue"); #if Graphics::ColorNames available
406             my $colorobj=$obj->color([77,82,68]); #rgb=>[decimal,decimal,decimal]
407             my $colorobj=$obj->color;
408              
409             =cut
410              
411             sub color {
412             my $self=shift;
413             if (@_) {
414             my $color=shift;
415             if (ref($color) eq 'ARRAY') {
416             my ($r, $g, $b)= @$color;
417             $self->{'color'}=$self->{'colors'}->{$r}->{$g}->{$b}||=$self->gdimage->colorAllocate(@$color);
418             } else {
419             if ($self->gcnames) {
420             my @rgb=$self->gcnames->rgb($color);
421             @rgb=(0,0,0) unless scalar(@rgb) == 3;
422             $self->{'color'}=$self->color(\@rgb);
423             } else {
424             $self->{'color'}=$self->color([0,0,0]);
425             }
426             }
427             }
428             return $self->{'color'};
429             }
430              
431             =head2 font
432              
433             Method to set or return the current drawing font (only needed by the very few)
434              
435             use GD qw(gdGiantFont gdLargeFont gdMediumBoldFont gdSmallFont gdTinyFont);
436             $obj->font(gdSmallFont); #the default
437             $obj->font;
438              
439             =cut
440              
441             sub font {
442             my $self=shift;
443             $self->{'font'}=shift if @_;
444             $self->{'font'}=gdSmallFont unless $self->{'font'};
445             return $self->{'font'};
446             }
447              
448             =head2 size
449              
450             Sets or returns the width and height of the graph in pixels.
451              
452             =cut
453              
454             sub size {
455             my $self=shift;
456             $self->{'size'}=shift if @_;
457             $self->{'size'}=480 unless $self->{'size'};
458             return $self->{'size'};
459             }
460              
461             =head2 radius
462              
463             Sets or returns the radius of the Graph
464              
465             =cut
466              
467             sub radius {
468             my $self=shift;
469             $self->{'radius'}=shift if @_;
470             $self->{'radius'}=1 unless $self->{'radius'};
471             return $self->{'radius'};
472             }
473              
474             =head2 border
475              
476             =cut
477              
478             sub border {
479             my $self=shift;
480             $self->{'border'}=shift if @_;
481             $self->{'border'}=2 unless defined($self->{'border'});
482             return $self->{'border'};
483             }
484              
485             =head2 ticks
486              
487             =cut
488              
489             sub ticks {
490             my $self=shift;
491             $self->{'ticks'}=shift if @_;
492             $self->{'ticks'}=10
493             unless defined($self->{'ticks'});
494             return $self->{'ticks'};
495             }
496              
497             =head2 rgbfile
498              
499             Sets or returns an RGB file.
500              
501             Note: This method will search in a few locations for a file.
502              
503             =cut
504              
505             sub rgbfile {
506             my $self=shift;
507             $self->{'rgbfile'}=shift if @_;
508             unless (defined $self->{'rgbfile'}) {
509             $self->{'rgbfile'}="rgb.txt";
510             my $rgb=first {-r} (qw{/etc/X11/rgb.txt /usr/share/X11/rgb.txt /usr/X11R6/lib/X11/rgb.txt ../rgb.txt});
511             $self->{'rgbfile'}=$rgb if $rgb;
512             }
513             return $self->{'rgbfile'};
514             }
515              
516             =head2 draw
517              
518             Method returns a PNG binary blob.
519              
520             my $png_binary=$obj->draw;
521              
522             =cut
523              
524             sub draw {
525             my $self=shift;
526             return $self->gdimage->png;
527             }
528              
529             #=head2 _scale
530             #
531             #Method returns the parameter scaled to the image.
532             #
533             #=cut
534              
535             sub _scale {
536             my $self = shift;
537             my $r = shift;
538             return $self->_width / 2 / $self->radius * $r;
539             }
540              
541             #=head2 _width
542             #
543             #Method returns the width of the graph.
544             #
545             #=cut
546              
547             sub _width {
548             my $self=shift;
549             return $self->size - $self->border * 2;
550             }
551              
552             #=head2 _imgxy_xy
553             #
554             #Method to convert xy to imgxy cordinates
555             #
556             # $obj->addPoint_rad(50=>3.1415);
557             #
558             #=cut
559              
560             sub _imgxy_xy {
561             my $self = shift;
562             my $x = shift();
563             my $y = shift();
564             my $sz = $self->_width;
565             $x = $sz/2 + $x + $self->border;
566             $y = $sz/2 - $y + $self->border;
567             return ($x, $y);
568             }
569              
570             #=head2 _xy_rt_rad
571             #
572             #Method to convert polar cordinate to Cartesian cordinates.
573             #
574             #=cut
575              
576             sub _xy_rt_rad {
577             my $self = shift;
578             my $r = shift;
579             my $t = shift;
580             my $x = $r*cos($t);
581             my $y = $r*sin($t);
582             return ($x, $y);
583             }
584              
585             #=head2 _imgxy_rt_rad
586             #
587             #Method to convert polar cordinate to Cartesian cordinates.
588             #
589             #=cut
590              
591             sub _imgxy_rt_rad {
592             my $self = shift;
593             my $r = shift;
594             my $t = shift;
595             my ($x,$y)=$self->_xy_rt_rad($self->_scale($r), $t);
596             return $self->_imgxy_xy($x, $y);
597             }
598              
599             =head1 BUGS
600              
601             Please log on RT and send to the author.
602              
603             =head1 SUPPORT
604              
605             DavisNetworks.com supports all Perl applications including this package.
606              
607             =head1 AUTHOR
608              
609             Michael R. Davis qw/perl michaelrdavis com/
610              
611             =head1 LICENSE
612              
613             Copyright (c) 2011 Michael R. Davis (mrdvt92)
614              
615             This library is free software; you can redistribute it and/or modify it under the same terms as Perl itself.
616              
617             =head1 SEE ALSO
618              
619             L, L, L, L
620              
621             =cut
622              
623             1;