diff options
Diffstat (limited to 'CAMM.pm')
-rw-r--r-- | CAMM.pm | 66 |
1 files changed, 58 insertions, 8 deletions
@@ -64,11 +64,13 @@ package CAMM::Commands { #our $escape_char = "\003"; sub header { # escape_char - my $escape_char = $_[0]//"\003"; - "\003\015\012\015\012\015\012\015\012\015\012". - ";IN;PU;PA0,0;IW0,0,47000,64000;VS30;DT$escape_char;\n"; - # PA isn't a good idea: - #";IN;PA0,0;IW0,0,47000,64000;VS30;DT$escape_char;\n"; + my ($escape_char,$win_w,$win_h) = @_; + $escape_char //= "\003"; + $win_w //= 40*1330; # 133cm is the width of the plotter + $win_h //= 40*10000; # 10m + # max is (1<<26)-1, but we don't want to upset the viewing code... + sprintf "\003\015\012\015\012\015\012\015\012\015\012". + ";IN;PU;PA0,0;IW0,0,%.2f,%.2f;VS30;DT%s;\n", $win_w,$win_h,$escape_char; } sub set_escape_char { my $escape_char = $_[0]; @@ -327,7 +329,28 @@ sub from_polylines { #my $self = (@_ && ref $$_[0] eq __PACKAGE__) ? shift : $global_object; my ($paths,%options) = @_; @options{qw(header footer)} = (1,1) if $options{headerfooter}; - $self->header() if $options{header}; + my $winsize = $options{window_size}; + if (!defined $winsize) { + if ($options{window_from_bbox}) { + my $offs = $options{offset}//0; + my @bbox; + for (@$paths) { + for my $p (@{$$_[1]}) { + for (0,1) { + $bbox[$_] = $$p[$_] + if !defined $bbox[$_] || $bbox[$_] > $$p[$_]; + $bbox[$_+2] = $$p[$_] + if !defined $bbox[$_+2] || $bbox[$_+2] < $$p[$_]; + } + } + } + $winsize = [@bbox[2,3]]; + $_ += 40 + $offs for @$winsize; # add 1mm to be sure. + } else { + $winsize = [undef,undef]; + } + } + $self->header(undef,@$winsize) if $options{header}; $self->set_speed($options{speed}) if defined $options{speed}; my $eps = $options{epsilon}//0.00001; # since the knife follows the machine's current (pen) position by an offset, @@ -716,8 +739,9 @@ our $svg_path_template = <<'EOSVG'; EOSVG #use Time::HiRes; +# $bbox_out only gets a coarse bbox (does not include arcs properly). sub to_svgpath { - my ($self,$camm,$splittable) = @_; + my ($self,$camm,$splittable,$bbox_out) = @_; $self = $self->new unless ref $self; my %defcontext = ( escape_char => "\003", @@ -725,6 +749,16 @@ sub to_svgpath { d => "", ); $self->{$_} //= $defcontext{$_} for keys %defcontext; + my @bbox; + if (defined $bbox_out) { + my $p = $self->{p}; + for (0,1) { + $bbox[$_] = $$p[$_] + if !defined $bbox[$_] || $bbox[$_] > $$p[$_]; + $bbox[$_+2] = $$p[$_] + if !defined $bbox[$_+2] || $bbox[$_+2] < $$p[$_]; + } + } _parse_tokens($camm,$self,sub { my ($slf,$cmd,$args,$pos) = @_; @@ -734,6 +768,15 @@ sub to_svgpath { if ($splittable && !$slf->{down}) { $slf->{d} .= " M ".join(",",@{$slf->{p}})." "; } + if (defined $bbox_out) { + my $p = $self->{p}; + for (0,1) { + $bbox[$_] = $$p[$_] + if !defined $bbox[$_] || $bbox[$_] > $$p[$_]; + $bbox[$_+2] = $$p[$_] + if !defined $bbox[$_+2] || $bbox[$_+2] < $$p[$_]; + } + } } else { warn "ignoring unknown command \"$cmd\""; } @@ -761,6 +804,7 @@ sub to_svgpath { # #my $t3 = time; # #$timings{cmd} += $t3-$t2; # } + @$bbox_out = @bbox if defined $bbox_out; my $d = $self->{d}; delete $self->{d}; #print STDERR join(", ",map "$_ = $timings{$_}", sort keys %timings),"\n"; @@ -777,13 +821,19 @@ sub to_svg { #$self = $self->new unless ref $self; $self = $self->new(output => sub {}); #print STDERR "to_svgpath: ".time()."\n"; - my $d = $self->to_svgpath($camm,$split); + my $coarse_bbox = [0,0,0,0]; + my $d = $self->to_svgpath($camm,$split,$coarse_bbox); #print STDERR "splitting: ".time()."\n"; my $win = $self->{input_window}; my @origin = (0,0); my @size = (100,100); my $scale = 1/$units_per_px; if (defined $win) { + for (0,1) { + if ($$win[$_+2] > 400000 && $$coarse_bbox[1][$_]*2 < $$win[$_+2]) { + $$win[$_+2] = $$coarse_bbox[2+$_]*2; + } + } @origin = @$win[0,3]; $_ = -$_ for @origin; @size = (($$win[2]-$$win[0])*$scale,($$win[3]-$$win[1])*$scale); |