8 LaTeX::TikZ - Perl object model for generating PGF/TikZ code.
16 our $VERSION = '0.01';
23 my $hline = Tikz->line(-1 => 1);
24 my $vline = Tikz->line([ 0, -1 ] => [ 0, -1 ]);
27 $_->mod(Tikz->color('red')) for $hline, $vline;
31 my $octo = Tikz->closed_polyline(
32 map Math::Complex->emake(1, ($_ * pi)/4), 0 .. 7
35 # Only keep a portion of it
36 $octo->clip(Tikz->rectangle(-0.5*(1+i), 2*(1+i)));
39 $octo->mod(Tikz->pattern(class => 'Dots'));
41 # Create a formatter object
42 my $tikz = Tikz->formatter;
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;
51 This module provides an object model for TikZ, a graphical tookit 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.
56 Traditionnaly, in TikZ, there are two ways of grouping elements, or I<ops>, together :
62 either as a I<sequence>, where each element is drawn in its own line :
64 \draw (0cm,0cm) -- (0cm,1cm) ;
65 \draw (0cm,0cm) -- (1cm,0cm) ;
69 or as a I<path>, where elements are all drawn as one line :
71 \draw (0cm,0cm) -- (0cm,1cm) (0cm,0cm) -- (1cm,0cm) ;
75 This distinction is important because there are some primitves that only apply to paths but not to sequences, and vice versa.
77 Figures are made of ops, path or sequence I<sets> assembled together in a tree.
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.
86 =head3 C<< Tikz->path(@ops) >>
88 Creates a L<LaTeX::TikZ::Set::Path> object out of the ops C<@ops>.
90 # A path made of two circles
100 =head3 C<< Tikz->seq(@kids) >>
102 Creates a L<LaTeX::TikZ::Set::Sequence> object out of the sequences, paths or ops C<@kids>.
104 my $bag = Tikz->seq($sequence, $path, $circle, $raw, $point);
108 Those are the building blocks of your geometrical figure.
110 =head3 C<< Tikz->point($point) >>
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 :
119 If C<$point> isn't given, the point defaults to C<(0, 0)>.
121 my $origin = Tikz->point;
125 If C<$point> is a numish Perl scalar, it is treated as C<($point, 0)>.
127 my $unit = Tikz->point(1);
131 If two numish scalars C<$x> and C<$y> are given, they result in the point C<($x, $y)>.
133 my $one_plus_i = Tikz->point(1, 1);
137 If C<$point> is an array reference, it is parsed as C<< ($point->[0], $point->[1]) >>.
139 my $i = Tikz->point([ 0, 1 ]);
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) >>.
145 my $j = Tikz->point(Math::Complex->emake(1, 2*pi/3));
149 You can define automatic coercions from your user point types to L<LaTeX::TikZ::Point> by writing your own L<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.
152 =head3 C<< Tikz->line($from => $to) >>
154 Creates a L<LaTeX::TikZ::Set::Line> object between the points C<$from> and C<$to>.
156 my $x_axis = Tikz->line(-5 => 5);
157 my $y_axis = Tikz->line([ 0, -5 ] => [ 0, 5 ]);
159 =head3 C<< Tikz->polyline(@points) >>
161 Creates a L<LaTeX::TikZ::Set::Polyline> object that links the successive elements of C<@points> by segments.
163 my $U = Tikz->polyline(
170 =head3 C<< Tikz->closed_polyline(@points) >>
172 Creates a L<LaTeX::TikZ::Set::Polyline> object that cycles through successive eleemnts of C<@points>.
174 my $diamond = Tikz->closed_polyline(
181 =head3 C<< Tikz->rectangle($from => $to), Tikz->rectangle($from => { width => $width, height => $height }) >>
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>.
185 my $square = Tikz->rectangle(
190 =head3 C<< Tikz->circle($center, $radius) >>
192 Creates a L<LaTeX::TikZ::Set::Circle> object of center C<$center> and radius C<$radius>.
194 my $unit_circle = Tikz->circle(0, 1);
196 =head3 C<< Tikz->arc($from => $to, $center) >>
198 Creates a L<LaTeX::TikZ::Set> structure that represents an arc going from C<$from> to C<$to> with center C<$center>.
200 # An arc. The points are automatically coerced into LaTeX::TikZ::Set::Point objects
201 my $quarter = Tikz->arc(
202 [ 1, 0 ] => [ 0, 1 ],
206 =head3 C<< Tikz->arrow($from => $to), Tikz->arrow($from => dir => $dir) >>
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>.
210 # An horizontal arrow
211 my $arrow = Tikz->arrow(0 => 1);
213 =head3 C<< Tikz->raw($content) >>
215 Creates a L<LaTeX::TikZ::Set::Raw> object that will instantiate to the raw TikZ code C<$content>.
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.
222 =head3 C<< Tikz->clip($path) >>
224 Creates a L<LaTeX::TikZ::Mod::Clip> object that can be used to clip a given sequence by the (closed) path C<$path>.
226 my $box = Tikz->clip(
227 Tikz->rectangle(0 => [ 1, 1 ]),
230 Clips can also be directly applied to sets with the C<< ->clip >> method.
232 my $set = Tikz->circle(0, 1.5)
233 ->clip(Tikz->rectangle([-1, -1] => [1, 1]));
235 =head3 C<< Tikz->layer($name, above => \@above, below => \@below) >>
237 Creates a L<LaTeX::TikZ::Mod::Layer> object with name C<$name> and optional relative positions C<@above> and C<@below>.
239 my $layer = Tikz->layer(
244 The default layer is C<main>.
246 Layers are stored into a global hash, so that when you refer to them by their name, you get the existing layer object.
248 Layers can also be directly applied to sets with the C<< ->layer >> method.
250 my $dots = Tikz->rectangle(0 => [ 1, 1 ])
251 ->mod(Tikz->pattern(class => 'Dots'))
254 =head3 C<< Tikz->width($line_width) >>
256 Creates a L<LaTeX::TikZ::Mod::Width> object that sets the line width to C<$line_width> when applied.
258 my $thick_arrow = Tikz->arrow(0 => 1)
259 ->mod(Tikz->width(5));
261 =head3 C<< Tikz->color($color) >>
263 Creates a L<LaTeX::TikZ::Mod::Color>object that sets the line color to C<$color> (given in the C<xcolor> syntax).
265 # Paint the previous $thick_arrow in red.
266 $thick_arrow->mod(Tikz->color('red'));
268 =head3 C<< Tikz->fill($color) >>
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).
272 my $red_box = Tikz->rectangle(0 => { width => 1, height => 1 })
273 ->mod(Tikz->fill('red'));
275 =head3 C<< Tikz->pattern(class => $class, %args) >>
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.
281 my $hatched_circle = Tikz->circle(0 => 1)
282 ->mod(Tikz->pattern(class => 'Lines'));
284 =head3 C<< Tikz->raw_mod($content) >>
286 Creates a L<LaTeX::TikZ::Mod::Raw> object that will instantiate to the raw TikZ mod code C<$content>.
288 my $homemade_arrow = Tikz->line(0 => 1)
289 ->mod(Tikz->raw_mod('->')) # or just ->mod('->')
293 =head3 C<< Tikz->formatter(%args) >>
295 Creates a L<LaTeX::TikZ::Formatter> object that can render a L<LaTeX::TikZ::Set> tree.
297 my $tikz = Tikz->formatter;
298 my ($header, $declarations, $seq1_body, $seq2_body) = $tikz->render($set1, $set2);
300 =head3 C<< Tikz->functor(@rules) >>
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 made of array references whose first element is the class/role to match against and the second the handler to run.
305 # The default is a clone method
306 my $clone = Tikz->functor;
307 my $dup = $set->$clone;
310 my $translate = Tikz->functor(
311 'LaTeX::TikZ::Set::Point' => sub {
312 my ($functor, $set, $x, $y) = @_;
319 label => $set->label,
324 my $shifted = $set->$translate(1, 1);
327 my $strip = Tikz->functor(
328 'LaTeX::TikZ::Mod' => sub { return },
330 my $naked = $set->$strip;
334 use LaTeX::TikZ::Interface;
340 my $name = $args{as};
341 $name = 'Tikz' unless defined $name;
342 unless ($name =~ /^[a-z_][a-z0-9_]*$/i) {
344 Carp::confess('Invalid name');
348 my $const = sub () { 'LaTeX::TikZ::Interface' };
351 *{$pkg . '::' . $name} = $const;
354 LaTeX::TikZ::Interface->load;
361 L<Any::Moose> with L<Mouse> 0.63 or greater.
367 L<Math::Complex>, L<Math::Trig>.
369 L<Scalar::Util>, L<List::Util>, L<Task::Weaken>.
373 PGF/TikZ - L<http://pgf.sourceforge.net>.
377 Vincent Pit, C<< <perl at profvince.com> >>, L<http://www.profvince.com>.
379 You can contact me by mail or on C<irc.perl.org> (vincent).
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.
388 You can find documentation for this module with the perldoc command.
392 =head1 COPYRIGHT & LICENSE
394 Copyright 2010 Vincent Pit, all rights reserved.
396 This program is free software; you can redistribute it and/or modify it under the same terms as Perl itself.
400 1; # End of LaTeX::TikZ