=head1 NAME

Lego::Ldraw - Per extension for parsing, modifying, translating and
displaying Ldraw files

=head1 SYNOPSIS

  use Lego::Ldraw;

  my $l = Ldraw->new_from_file($ARGV[0]);
  # do things...

=head1 DESCRIPTION

Ldraw is a CAD drawing program for Lego models. It stores data in text
files with a suffix of ldr or dat.

This extension provides a basis for quickly  parsing, modifying, translating and
displaying them.

=head1 METHODS

=head2 Model methods

=head3 new

  $ldraw_model = Lego::Ldraw->new;

Creates a new Lego::Ldraw object

=head3 new_from_file

  $ldraw_model = Lego::Ldraw->new_from_file("car.ldr");

Creates a new Lego::Ldraw object from a file

=head3 copy

 $ldraw_model = Lego::Ldraw->new_from_file("car.ldr");
 $clone = $ldraw_model->copy

Creates a cloned object

=head3 add

  $ldraw_line = Lego::Ldraw::Line->new
  $ldraw_model->add($ldraw_line)

=head3 splice

  $ldraw_model->splice($ldraw_line, $offset, $length)
  $ldraw_model->splice($another_ldraw_model, $offset, $length)

Inserts a line or a model at an offset, substituting lines if $length is specified.  

=head3 lines

  @lines = $ldraw_model->lines

Returns the lines of a model file as Lego::Ldraw::Line objects

=head3 stringify

  $ldraw = $ldraw_model->stringify

Returns the object as a string. The string is a valid Ldraw file.

=head3 length

  $len = $ldraw_model->length

Returns the number of lines in the model, excluding empty ones.

=head3 subparts

  @subparts = $ldraw_model->subparts

Returns the parts which compose a model, excluding primitives (i.e:
only lines of types 2, 3, 4, and 5).

=head3 colors

  @colors = $ldraw_model->colors

Returns the colors of parts in the model. Does not recurse into the subparts.

=head3 file
  
  $file = $ldraw_model->file

Returns the path of the file that was read into the model. Defaults to
empty for models that were created from scratch.

=head3 name

  $name = $ldraw_model->name

Returns the basename of the file that was read into the model. Defaults to
empty for models that were created from scratch.

=head3 dir

  $dir = $ldraw_model->dir

Returns the directory containing  the file that was read into the model. Defaults to
empty for models that were created from scratch.

=head3 tree

  $tree = $ldraw_model->tree

Returns a HoH of parts and colors contained in the model.

=head3 parts

 @parts = $ldraw_model->parts

Returns a list of the parts used in the model.

=head3 description

 $description = $ldraw_model->description

Returns the description of the model. This is the first comment line in the file.

=head3 partsdirs

See same method in Line methods

=head3 basedir

See same method in Line methods

=head3 build_tree

  $ldraw_model->build_tree( \&callback, \&test );

Traverses the model tree, exploding every part into subparts on the
way if &test($part) returns true, and executing &callback on every
part traversed.

Used mostly in translators, to explode the model into primitives and
translate them into some other format: see the Lego::Ldraw::POV source
for an example.

=head2 Line methods

=head3 new

  $ldraw_line = Lego::Ldraw::Line->new;

Creates a new Lego::Ldraw::Line object.

=head3 new_from_string

  $ldraw_line = Lego::Ldraw::Line->new_from_string('1 1 200 4 170 1 0 0 0 1 0 0 0 1 3004.dat');

Creates a new Lego::Ldraw::Line object from a string.

=head3 new_from_part_name

  $ldraw_line = Lego::Ldraw::Line->new_from_part_name('3004.dat');

Creates a new Lego::Ldraw::Line object from a part name. The part is centered on the origin.

=head3 field access functions

  $x = $ldraw_line->x;
  $color = $ldraw_line->color;
  $part = $ldraw_line->part;

Ldraw line field values can be accessed with the relevant methods. See
the Ldraw specification page at
L<http://www.ldraw.org/modules.php?op=modload&name=News&file=article&sid=45>

=head3 name

=head3 copy

  $copy = $line->copy;

Clones the Line object

=head3 fields

  @fields = $line->fields;

Returns the Line object fields

=head3 model

  $model = $line->model

Returns the model the line belongs to.

=head3 description

Returns the part's description, as listed in the Parts.lst generated at installation.

=head3 values

  @vals = $line->values(qw/x y z/);

Returns the values of the specified fields, or of all fields if none is specified.

=head3 coords

  @xyz = $line->coords

Returns the values of all coordinate points on the line (x, y, z if
its type is 1, more x1, y1, z1 etc. in other cases).

=head3 points

  $points = $line->points;

Returns the number of points that define the line: 1 for a part (type 1), 2 for a line, etc..

=head3 transform_matrix

  @matrix = $line->transform_matrix

Returns the transform matrix (i.e.: fields x, y, z and a to i) of a
part (type 1). Returns undef in all other cases.

=head3 point

  ($x2, $y2, $z2) = $line->point(2)

Returns the coordinates of the specified point for the line, or the
coordinates of the part for a line of type 1.

=head3 format

  $string = $line->format

Returns a nicely formatted string of the line's fields. Coordinates
are rounded at 2 decimals.

=head3 eval

  $line->eval('%x += 2 if %color == 3');
  $line->eval('&normalize if %x > 12');

This function enables complex on-the-fly edits to a line. First all
strings beginning with % in the argument are translated into field
accessors. Then all strings beginning with & in the argument are
transformed into methods. Then the string is evaluated, thus editing
the line.

For example:

  $line->eval('%x += 2 if %color == 3');

translates into:

  $line->x += 2 if $line->color == 3;

and 

  $line->eval('&normalize if %x > 12');

translates into 

  $line->normalize if $line->x > 12;

=head3 normalize

  $line->normalize

Re-centers the line on the origin and deletes all rotations.

=head3 partfile

  $filename = $line->partfile;

Returns the full path to the file corresponding to the line's part.

=head3 explode

  $ldraw_model = $line->explode;

Returns a Lego::Ldraw object of the corresponding to the line's part. 

=head3 transform

  $line->transform($another_line)

Traslates and rotates the line with the transformation matrix of the
Lego::Ldraw::Line object passed as an argument.

Tipically used in:

  $ldraw = $line->explode;
  for (@$ldraw) {
    $_->transform($line)	
  }

which provides a mechanism to reduce a model to its primitives.

=head3 stringify

=head3 config

=head3 basedir

=head3 partsdirs

=head3 primitives

=head1 DISPLAY AND TRANSLATION

=head2 Pov-ray translation

Rudimentary support for Ldraw to Pov-ray translation is provided:

  use Lego::Ldraw;
  use Lego::Ldraw::POV;

  $\ = "\n";

  my $l = Lego::Ldraw->new_from_file($ARGV[0]);

  print $l->POVdesc;

Features here are very much in flux and can be changed without notice.

=head2 OpenGL display

Rudimentary support for OpenGL display of Ldraw models is provided:

  use Lego::Ldraw;
  use Lego::Ldraw::Display;

  $, = " "; $\ = "\n";

  my $l = Lego::Ldraw->new_from_file($ARGV[0]);
  print $l->dir;

  $d = Lego::Ldraw::Display->new(300, 400, $l);
  $d->init;

There is also limited callback support: import OpenGL constants, and
use the bindspec method to bind callbacks. For example:

  use OpenGL qw/ :all /;

  # code omitted very much like above

  $d->bindspec(GLUT_KEY_UP,   GLUT_ACTIVE_SHIFT, sub { shift->{lookat}->[1] -= 5; });
  $d->bindspec(GLUT_KEY_DOWN, GLUT_ACTIVE_SHIFT, sub { shift->{lookat}->[1] += 5; });

  # etc.

These features are likely to change to provide support for Tk
interaction.

This part requires the OpenGL package that can be found at
L<http://www.bribes.org/perl/wopengl.html>. Install the ppm binary
provided by entering the following command  at the console:

  ppm install http://www.bribes.org/perl/ppm/OpenGL.ppd

Despite my efforts, Linux is not supported.

=head1 TO DO

=over

=item * Tidy up config files lookup all over.

=item * Provide callback mechanism for OpenGL idle function in display.

=item * Matrix correction for singular matrixes in POV

=item * Better header generation in POV

=item * Bounding box calculation

=item * Better color handling in Display and POV

=item * Perl macro comments in POV

=back

=head1 SEE ALSO

Ldraw, the start of it all: L<http://www.ldraw.org/index.php>

Pov-ray: L<http://www.povray.org/>

L3P, a more mature Ldraw to pov-ray translator: L<http://www.hassings.dk/l3/l3p.html>

=head1 AUTHOR

Simone Cesano

=head1 COPYRIGHT AND LICENSE

Copyright (C) 2005 by Simone Cesano

=cut

