App-HPGL2Cadsoft
view release on metacpan or search on metacpan
lib/App/HPGL2Cadsoft.pm view on Meta::CPAN
# Add stuff here
my $hpgl;
my $fh = IO::File->new( "< " . $self->input_file );
if ( defined $fh ) {
# Slurp the file into the variable
while (<$fh>) {
$hpgl .= $_;
}
}
else {
die "Could not open file '" . $self->input_file . "' for reading";
}
$fh->close();
$self->_hpgl($hpgl);
}
sub _parse_hpgl {
my $self = shift();
my @lines;
my $zero_length_stubs = 0;
my @commands = split( ";", $self->_hpgl() );
my ( $pos_start, $pos_end );
foreach my $command (@commands) {
if ( $command =~ /\s+/) {
next;
}
if ( $command =~ /PU(\d+),(\d+)/ ) {
$pos_start = Grid::Coord->new( $2, $1 );
next;
}
if ( $command =~ /PD(\d+),(\d+)/ ) {
$pos_end = Grid::Coord->new( $2, $1 );
if ( !$pos_start->equals($pos_end) ) {
# Store the position as a line
push( @lines, [ $pos_start, $pos_end ] );
# And update the last location to ensure we create a valid line when the next command is PD again
$pos_start = $pos_end;
}
else {
$zero_length_stubs++;
}
next;
}
if ( $command =~ /IN/ ) {
say "Init sequence found";
next;
}
if ( $command =~ /SP(\d+)/ ) {
say "Selected pen $1";
next;
}
if ( $command =~ /^PU$/) {
# Final PU command
next;
}
carp "HPGL command not parsed: '$command'\n";
}
my $line_count = scalar(@lines);
$self->_hpgl_lines(\@lines);
return ( $line_count, $zero_length_stubs);
}
# Applies the scaling factor to the lines in the data array
sub _scale {
my $self = shift();
# Scale the lines
my @lines_scaled;
foreach my $line (@{$self->_hpgl_lines()}) {
my $start_scaled = Grid::Coord->new( $line->[0]->min_y() / $self->scaling_factor(),
$line->[0]->min_x() / $self->scaling_factor() );
my $stop_scaled = Grid::Coord->new( $line->[1]->min_y() / $self->scaling_factor(),
$line->[1]->min_x() / $self->scaling_factor() );
push( @lines_scaled, [ $start_scaled, $stop_scaled ] );
}
$self->_hpgl_lines(\@lines_scaled);
}
sub run {
my $self = shift();
my ($lines, $zero_stubs)= $self->_parse_hpgl();
say "Found $lines valid segments in HPGL file";
say "Skipped $zero_stubs segments with zero length";
$self->_scale();
$self->_calculate_bbox();
# Report bounding box dimensions, maybe the user wants to change the scaling factor
say "Object bounding box stretches from (x,y) to (x,y) in millimeter:";
say " ("
. sprintf( '%.3f', $self->_bbox->min_x() ) . " "
. sprintf( '%.3f', $self->_bbox->min_y() ) . ") ("
. sprintf( '%.3f', $self->_bbox->max_x() ) . " "
. sprintf( '%.3f', $self->_bbox->max_y() ) . ")";
say
"Total dimensions in x and y directions with scaling factor " . $self->scaling_factor() . " in mm are:";
say " ("
. sprintf( '%.3f', $self->_bbox->max_x() - $self->_bbox->min_x() ) . " "
. sprintf( '%.3f', $self->_bbox->max_y() - $self->_bbox->min_y() ) . ")";
$self->_write_script();
say "Done!";
}
sub _calculate_bbox {
my $self = shift();
# Init min and max values to the first point in the dataset
my $l = $self->_hpgl_lines()->[0]->[0];
# Create bounding box with min and max values to be equal to the first point in the dataset
$self->_bbox(
Grid::Coord->new( $l->min_y(), $l->min_x() => $l->max_y(), $l->max_x() )
);
foreach my $line (@{$self->_hpgl_lines()}) {
my $start = $line->[0];
my $stop = $line->[1];
if ( !$self->_bbox->contains($start) ) {
$self->_grow_bbox( $start );
}
if ( !$self->_bbox->contains($stop) ) {
$self->_grow_bbox( $stop );
}
}
}
sub _grow_bbox {
my $self = shift();
my $point = shift();
my $bbox = \$self->_bbox;
$$bbox->min_y( $point->min_y() ) if ( $point->min_y() < $$bbox->min_y() );
$$bbox->min_x( $point->min_x() ) if ( $point->min_x() < $$bbox->min_x() );
$$bbox->max_y( $point->max_y() ) if ( $point->max_y() > $$bbox->max_y() );
$$bbox->max_x( $point->max_x() ) if ( $point->max_x() > $$bbox->max_x() );
# Safety check
warn "Bbox not updated as expected" if ( !$$bbox->contains($point) );
}
sub _write_script {
my $self = shift();
my $fh = IO::File->new( "> " . $self->output_file );
if ( defined $fh ) {
# Generate the script header
print $fh "# Generated by HPGL2Cadsoft on " . localtime(time) . "\n";
print $fh "grid mm\n";
print $fh "grid 1\n";
print $fh "set wire_bend 2\n";
print $fh "change width 0\n";
# Write the wires
map {
( run in 1.181 second using v1.01-cache-2.11-cpan-ff9377addf4 )