]> git.vpit.fr Git - perl/modules/LaTeX-TikZ.git/blob - lib/LaTeX/TikZ.pm
Document the interface
[perl/modules/LaTeX-TikZ.git] / lib / LaTeX / TikZ.pm
1 package LaTeX::TikZ;
2
3 use strict;
4 use warnings;
5
6 =head1 NAME
7
8 LaTeX::TikZ - Perl object model for generating PGF/TikZ code.
9
10 =head1 VERSION
11
12 Version 0.01
13
14 =cut
15
16 our $VERSION = '0.01';
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;
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 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.
53
54 =head1 CONCEPTS
55
56 Traditionnaly, 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 primitves 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 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.
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 eleemnts 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 made of array references whose first element is the class/role to match against and the second the handler to run.
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 use LaTeX::TikZ::Interface;
335
336 sub import {
337  shift;
338
339  my %args = @_;
340  my $name = $args{as};
341  $name = 'Tikz' unless defined $name;
342  unless ($name =~ /^[a-z_][a-z0-9_]*$/i) {
343   require Carp;
344   Carp::confess('Invalid name');
345  }
346
347  my $pkg   = caller;
348  my $const = sub () { 'LaTeX::TikZ::Interface' };
349  {
350   no strict 'refs';
351   *{$pkg . '::' . $name} = $const;
352  }
353
354  LaTeX::TikZ::Interface->load;
355
356  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