File Coverage

blib/lib/LaTeX/TikZ.pm
Criterion Covered Total %
statement 26 26 100.0
branch 4 4 100.0
condition n/a
subroutine 5 5 100.0
pod n/a
total 35 35 100.0


line stmt bran cond sub pod time code
1             package LaTeX::TikZ;
2              
3 10     10   248502 use strict;
  10         21  
  10         354  
4 10     10   51 use warnings;
  10         18  
  10         1018  
5              
6             =head1 NAME
7              
8             LaTeX::TikZ - Perl object model for generating PGF/TikZ code.
9              
10             =head1 VERSION
11              
12             Version 0.02
13              
14             =cut
15              
16             our $VERSION = '0.02';
17              
18             =head1 SYNOPSIS
19              
20             use LaTeX::TikZ;
21              
22             # A couple of lines
23             my $hline = Tikz->line(-1 => 1);
24             my $vline = Tikz->line([ 0, -1 ] => [ 0, 1 ]);
25              
26             # Paint them in red
27             $_->mod(Tikz->color('red')) for $hline, $vline;
28              
29             # An octogon
30             use Math::Complex;
31             my $octo = Tikz->closed_polyline(
32             map Math::Complex->emake(1, ($_ * pi)/4), 0 .. 7
33             );
34              
35             # Only keep a portion of it
36             $octo->clip(Tikz->rectangle(-0.5*(1+i), 2*(1+i)));
37              
38             # Fill it with dots
39             $octo->mod(Tikz->pattern(class => 'Dots'));
40              
41             # Create a formatter object
42             my $tikz = Tikz->formatter(scale => 5);
43              
44             # Put those objects all together and print them
45             my $seq = Tikz->seq($octo, $hline, $vline);
46             my ($head, $decl, $body) = $tikz->render($seq);
47             print "$_\n" for map @$_, $head, $decl, $body;
48              
49             =head1 DESCRIPTION
50              
51             This module provides an object model for TikZ, a graphical toolkit for LaTeX.
52             It allows you to build structures representing geometrical figures, apply a wide set of modifiers on them, transform them globally with functors, and print them in the context of an existing TeX document.
53              
54             =head1 CONCEPTS
55              
56             Traditionally, in TikZ, there are two ways of grouping elements, or I<ops>, together :
57              
58             =over 4
59              
60             =item *
61              
62             either as a I<sequence>, where each element is drawn in its own line :
63              
64             \draw (0cm,0cm) -- (0cm,1cm) ;
65             \draw (0cm,0cm) -- (1cm,0cm) ;
66              
67             =item *
68              
69             or as a I<path>, where elements are all drawn as one line :
70              
71             \draw (0cm,0cm) -- (0cm,1cm) (0cm,0cm) -- (1cm,0cm) ;
72              
73             =back
74              
75             This distinction is important because there are some primitives that only apply to paths but not to sequences, and vice versa.
76              
77             Figures are made of ops, path or sequence I<sets> assembled together in a tree.
78              
79             I<Modifiers> can be applied onto any set to alter the way in which it is generated.
80             The two TikZ concepts of I<clips> and I<layers> have been unified with the modifiers.
81              
82             =head1 INTERFACE
83              
84             =head2 Containers
85              
86             =head3 C<< Tikz->path(@ops) >>
87              
88             Creates a L<LaTeX::TikZ::Set::Path> object out of the ops C<@ops>.
89              
90             # A path made of two circles
91             Tikz->path(
92             Tikz->circle(0, 1),
93             Tikz->circle(1, 1),
94             )
95             ->mod(
96             Tikz->fill('red'),
97             'even odd rule',
98             );
99              
100             =head3 C<< Tikz->seq(@kids) >>
101              
102             Creates a L<LaTeX::TikZ::Set::Sequence> object out of the sequences, paths or ops C<@kids>.
103              
104             my $bag = Tikz->seq($sequence, $path, $circle, $raw, $point);
105              
106             =head2 Elements
107              
108             Those are the building blocks of your geometrical figure.
109              
110             =head3 C<< Tikz->point($point) >>
111              
112             Creates a L<LaTeX::TikZ::Set::Point> object by coercing C<$point> into a L<LaTeX::TikZ::Point>.
113             The following rules are available :
114              
115             =over 4
116              
117             =item *
118              
119             If C<$point> isn't given, the point defaults to C<(0, 0)>.
120              
121             my $origin = Tikz->point;
122              
123             =item *
124              
125             If C<$point> is a numish Perl scalar, it is treated as C<($point, 0)>.
126              
127             my $unit = Tikz->point(1);
128              
129             =item *
130              
131             If two numish scalars C<$x> and C<$y> are given, they result in the point C<($x, $y)>.
132              
133             my $one_plus_i = Tikz->point(1, 1);
134              
135             =item *
136              
137             If C<$point> is an array reference, it is parsed as C<< ($point->[0], $point->[1]) >>.
138              
139             my $i = Tikz->point([ 0, 1 ]);
140              
141             =item *
142              
143             If C<$point> is a L<Math::Complex> object, the L<LaTeX::TikZ::Point::Math::Complex> class is automatically loaded and the point is coerced into C<< ($point->Re, $point->Im) >>.
144              
145             my $j = Tikz->point(Math::Complex->emake(1, 2*pi/3));
146              
147             =back
148              
149             You can define automatic coercions from your user point types to L<LaTeX::TikZ::Point> by writing your own C<LaTeX::TikZ::Point::My::User::Point> class.
150             See L<LaTeX::TikZ::Meta::TypeConstraint::Autocoerce> for the rationale and L<LaTeX::TikZ::Point::Math::Complex> for an example.
151              
152             =head3 C<< Tikz->line($from => $to) >>
153              
154             Creates a L<LaTeX::TikZ::Set::Line> object between the points C<$from> and C<$to>.
155              
156             my $x_axis = Tikz->line(-5 => 5);
157             my $y_axis = Tikz->line([ 0, -5 ] => [ 0, 5 ]);
158              
159             =head3 C<< Tikz->polyline(@points) >>
160              
161             Creates a L<LaTeX::TikZ::Set::Polyline> object that links the successive elements of C<@points> by segments.
162              
163             my $U = Tikz->polyline(
164             Tikz->point(0, 1),
165             Tikz->point(0, 0),
166             Tikz->point(1, 0),
167             Tikz->point(1, 1),
168             );
169              
170             =head3 C<< Tikz->closed_polyline(@points) >>
171              
172             Creates a L<LaTeX::TikZ::Set::Polyline> object that cycles through successive elements of C<@points>.
173              
174             my $diamond = Tikz->closed_polyline(
175             Tikz->point(0, 1),
176             Tikz->point(-1, 0),
177             Tikz->point(0, -2),
178             Tikz->point(1, 0),
179             );
180              
181             =head3 C<< Tikz->rectangle($from => $to), Tikz->rectangle($from => { width => $width, height => $height }) >>
182              
183             Creates a L<LaTeX::TikZ::Set::Rectangle> object with opposite corners C<$from> and C<$to>, or with anchor point C<$from> and dimensions C<$width> and C<$height>.
184              
185             my $square = Tikz->rectangle(
186             Tikz->point,
187             Tikz->point(2, 1),
188             );
189              
190             =head3 C<< Tikz->circle($center, $radius) >>
191              
192             Creates a L<LaTeX::TikZ::Set::Circle> object of center C<$center> and radius C<$radius>.
193              
194             my $unit_circle = Tikz->circle(0, 1);
195              
196             =head3 C<< Tikz->arc($from => $to, $center) >>
197              
198             Creates a L<LaTeX::TikZ::Set> structure that represents an arc going from C<$from> to C<$to> with center C<$center>.
199              
200             # An arc. The points are automatically coerced into LaTeX::TikZ::Set::Point objects
201             my $quarter = Tikz->arc(
202             [ 1, 0 ] => [ 0, 1 ],
203             [ 0, 0 ]
204             );
205              
206             =head3 C<< Tikz->arrow($from => $to), Tikz->arrow($from => dir => $dir) >>
207              
208             Creates a L<LaTeX::TikZ::Set> structure that represents an arrow going from C<$from> towards C<$to>, or starting at C<$from> in direction C<$dir>.
209              
210             # An horizontal arrow
211             my $arrow = Tikz->arrow(0 => 1);
212              
213             =head3 C<< Tikz->raw($content) >>
214              
215             Creates a L<LaTeX::TikZ::Set::Raw> object that will instantiate to the raw TikZ code C<$content>.
216              
217             =head2 Modifiers
218              
219             Modifiers are applied onto sets by calling the C<< ->mod >> method, like in C<< $set->mod($mod) >>.
220             This method returns the C<$set> object, so it can be chained.
221              
222             =head3 C<< Tikz->clip($path) >>
223              
224             Creates a L<LaTeX::TikZ::Mod::Clip> object that can be used to clip a given sequence by the (closed) path C<$path>.
225              
226             my $box = Tikz->clip(
227             Tikz->rectangle(0 => [ 1, 1 ]),
228             );
229              
230             Clips can also be directly applied to sets with the C<< ->clip >> method.
231              
232             my $set = Tikz->circle(0, 1.5)
233             ->clip(Tikz->rectangle([-1, -1] => [1, 1]));
234              
235             =head3 C<< Tikz->layer($name, above => \@above, below => \@below) >>
236              
237             Creates a L<LaTeX::TikZ::Mod::Layer> object with name C<$name> and optional relative positions C<@above> and C<@below>.
238              
239             my $layer = Tikz->layer(
240             'top'
241             above => [ 'main' ],
242             );
243              
244             The default layer is C<main>.
245              
246             Layers are stored into a global hash, so that when you refer to them by their name, you get the existing layer object.
247              
248             Layers can also be directly applied to sets with the C<< ->layer >> method.
249              
250             my $dots = Tikz->rectangle(0 => [ 1, 1 ])
251             ->mod(Tikz->pattern(class => 'Dots'))
252             ->layer('top');
253              
254             =head3 C<< Tikz->width($line_width) >>
255              
256             Creates a L<LaTeX::TikZ::Mod::Width> object that sets the line width to C<$line_width> when applied.
257              
258             my $thick_arrow = Tikz->arrow(0 => 1)
259             ->mod(Tikz->width(5));
260              
261             =head3 C<< Tikz->color($color) >>
262              
263             Creates a L<LaTeX::TikZ::Mod::Color>object that sets the line color to C<$color> (given in the C<xcolor> syntax).
264              
265             # Paint the previous $thick_arrow in red.
266             $thick_arrow->mod(Tikz->color('red'));
267              
268             =head3 C<< Tikz->fill($color) >>
269              
270             Creates a L<LaTeX::TikZ::Mod::Fill> object that fills the interior of a path with the solid color C<$color> (given in the C<xcolor> syntax).
271              
272             my $red_box = Tikz->rectangle(0 => { width => 1, height => 1 })
273             ->mod(Tikz->fill('red'));
274              
275             =head3 C<< Tikz->pattern(class => $class, %args) >>
276              
277             Creates a L<LaTeX::TikZ::Mod::Pattern> object of class C<$class> and arguments C<%args> that fills the interior of a path with the specified pattern.
278             C<$class> is prepended with C<LaTeX::TikZ::Mod::Pattern> when it doesn't contain C<::>.
279             See L<LaTeX::TikZ::Mod::Pattern::Dots> and L<LaTeX::TikZ::Mod::Pattern::Lines> for two examples of pattern classes.
280              
281             my $hatched_circle = Tikz->circle(0 => 1)
282             ->mod(Tikz->pattern(class => 'Lines'));
283              
284             =head3 C<< Tikz->raw_mod($content) >>
285              
286             Creates a L<LaTeX::TikZ::Mod::Raw> object that will instantiate to the raw TikZ mod code C<$content>.
287              
288             my $homemade_arrow = Tikz->line(0 => 1)
289             ->mod(Tikz->raw_mod('->')) # or just ->mod('->')
290              
291             =head2 Helpers
292              
293             =head3 C<< Tikz->formatter(%args) >>
294              
295             Creates a L<LaTeX::TikZ::Formatter> object that can render a L<LaTeX::TikZ::Set> tree.
296              
297             my $tikz = Tikz->formatter;
298             my ($header, $declarations, $seq1_body, $seq2_body) = $tikz->render($set1, $set2);
299              
300             =head3 C<< Tikz->functor(@rules) >>
301              
302             Creates a L<LaTeX::TikZ::Functor> anonymous subroutine that can be called against L<LaTeX::TikZ::Set> trees to clone them according to the given rules.
303             C<@rules> should be a list of array references whose first element is the class/role to match against and the second the handler to execute.
304              
305             # The default is a clone method
306             my $clone = Tikz->functor;
307             my $dup = $set->$clone;
308              
309             # A translator
310             my $translate = Tikz->functor(
311             'LaTeX::TikZ::Set::Point' => sub {
312             my ($functor, $set, $x, $y) = @_;
313              
314             $set->new(
315             point => [
316             $set->x + $x,
317             $set->y + $y,
318             ],
319             label => $set->label,
320             pos => $set->pos,
321             );
322             },
323             );
324             my $shifted = $set->$translate(1, 1);
325              
326             # A mod stripper
327             my $strip = Tikz->functor(
328             '+LaTeX::TikZ::Mod' => sub { return },
329             );
330             my $naked = $set->$strip;
331              
332             =cut
333              
334 10     10   5078 use LaTeX::TikZ::Interface;
  10         29  
  10         1707  
335              
336             sub import {
337 12     12   1553 shift;
338              
339 12         46 my %args = @_;
340 12         36 my $name = $args{as};
341 12 100       72 $name = 'Tikz' unless defined $name;
342 12 100       113 unless ($name =~ /^[a-z_][a-z0-9_]*$/i) {
343 1         10 require Carp;
344 1         243 Carp::confess('Invalid name');
345             }
346              
347 11         33 my $pkg = caller;
348 11         27 my $const = sub () { 'LaTeX::TikZ::Interface' };
349             {
350 10     10   64 no strict 'refs';
  10         92  
  10         996  
  11         25  
351 11         32 *{$pkg . '::' . $name} = $const;
  11         76  
352             }
353              
354 11         45 LaTeX::TikZ::Interface->load;
355              
356 11         26586 return;
357             }
358              
359             =head1 DEPENDENCIES
360              
361             L<Any::Moose> with L<Mouse> 0.63 or greater.
362              
363             L<Sub::Name>.
364              
365             L<Scope::Guard>.
366              
367             L<Math::Complex>, L<Math::Trig>.
368              
369             L<Scalar::Util>, L<List::Util>, L<Task::Weaken>.
370              
371             =head1 SEE ALSO
372              
373             PGF/TikZ - L<http://pgf.sourceforge.net>.
374              
375             =head1 AUTHOR
376              
377             Vincent Pit, C<< <perl at profvince.com> >>, L<http://www.profvince.com>.
378              
379             You can contact me by mail or on C<irc.perl.org> (vincent).
380              
381             =head1 BUGS
382              
383             Please report any bugs or feature requests to C<bug-latex-tikz at rt.cpan.org>, or through the web interface at L<http://rt.cpan.org/NoAuth/ReportBug.html?Queue=LaTeX-TikZ>.
384             I will be notified, and then you'll automatically be notified of progress on your bug as I make changes.
385              
386             =head1 SUPPORT
387              
388             You can find documentation for this module with the perldoc command.
389              
390             perldoc LaTeX::TikZ
391              
392             =head1 COPYRIGHT & LICENSE
393              
394             Copyright 2010 Vincent Pit, all rights reserved.
395              
396             This program is free software; you can redistribute it and/or modify it under the same terms as Perl itself.
397              
398             =cut
399              
400             1; # End of LaTeX::TikZ