NAME

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

SYNOPSIS

use Lego::Ldraw;

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

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.

METHODS

Model methods

new

$ldraw_model = Lego::Ldraw->new;

Creates a new Lego::Ldraw object

new_from_file

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

Creates a new Lego::Ldraw object from a file

copy

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

Creates a cloned object

add

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

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.

lines

@lines = $ldraw_model->lines

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

stringify

$ldraw = $ldraw_model->stringify

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

length

$len = $ldraw_model->length

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

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).

colors

@colors = $ldraw_model->colors

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

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.

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.

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.

tree

$tree = $ldraw_model->tree

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

parts

@parts = $ldraw_model->parts

Returns a list of the parts used in the model.

description

$description = $ldraw_model->description

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

partsdirs

See same method in Line methods

basedir

See same method in Line methods

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.

Line methods

new

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

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

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.

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.

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 http://www.ldraw.org/modules.php?op=modload&name=News&file=article&sid=45

name

copy

$copy = $line->copy;

Clones the Line object

fields

@fields = $line->fields;

Returns the Line object fields

description

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

values

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

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

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).

points

$points = $line->points;

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

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.

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.

format

$string = $line->format

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

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;

normalize

$line->normalize

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

partfile

$filename = $line->partfile;

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

explode

$ldraw_model = $line->explode;

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

traslate

$line->traslate($x, $y, $z);

Traslates the line by the amounts specified.

traslate

$line->rotate($axis, $degrees);

Rotates the line around the axis (first argument) by the amount specified in degrees (second argument).

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.

stringify

config

basedir

partsdirs

primitives

DISPLAY AND TRANSLATION

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.

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;

Requirements

This part requires the OpenGL package that can be found at 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.

Callbacks

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.

Interaction with other event loops

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

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

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

$MW = MainWindow->new;

# more Tk stuff here...
$idle = sub { $MW->update };

$d->init($idle);

You can pass a reference to a sub as the first argument to the init method, and the sub will be executed during OpenGL's idle cycle. the example above shows how to use Tk in conjunction with the OpenGL display.

Camera and lookat positioning

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

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

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

$MW = MainWindow->new;

# more Tk stuff here...
$idle = sub { $MW->update };

$d->init($idle);
$d->move('camera', 's', 'z', +12);

You can move the camera and the point it's looking at (lookat) with the "move" method.

$d->move($point, $movement_type, $axis, $distance)

$point is either 'camera' or 'lookat'.

$movement_type is either 'x' for axial (move along an axis) or 's' for spherical, which moves on a sphere around the reference point. The reference point is the camera if you move lookat and lookat if you move the camera.

$axis determines the axis along which you move and it can be 'x' 'y' or 'z'.

TO DO

  • Matrix correction for singular matrixes in POV

  • Better header generation in POV

  • Better color handling in Display and POV

  • Perl macro comments in POV

SEE ALSO

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

Pov-ray: http://www.povray.org/

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

AUTHOR

Simone Cesano

THANKS

Thanks to Lars C. Hassing for letting me use his primitives in the Lego::Ldraw::POV module.

COPYRIGHT AND LICENSE

Copyright (C) 2005 by Simone Cesano

The primitives the Lego::Ldraw::POV module are Copyright (C) 1998-2001 Lars C. Hassing