# -*- perl -*- # # $Id: SVG.pm,v 1.14 2005/10/27 00:59:35 eserte Exp $ # Author: Slaven Rezic # # Copyright (C) 2001 Slaven Rezic. All rights reserved. # This program is free software; you can redistribute it and/or # modify it under the same terms as Perl itself. # # Mail: eserte@cs.tu-berlin.de # WWW: http://user.cs.tu-berlin.de/~eserte/ # package BBBikeDraw::SVG; use strict; use base qw(BBBikeDraw); use SVG; use Strassen; # Strassen benutzt FindBin benutzt Carp, also brauchen wir hier nicht zu # sparen: use Carp qw(confess); use vars qw($VERSION @colors %color %style %width %outline_color $sansserif); BEGIN { @colors = qw($grey_bg $white $yellow $red $green $middlegreen $darkgreen $darkblue $lightblue $rose $black); } use vars @colors; $VERSION = sprintf("%d.%02d", q$Revision: 1.14 $ =~ /(\d+)\.(\d+)/); sub init { my $self = shift; my($w, $h) = (640, 480); my $geometry = $self->{Geometry}; if (defined $geometry) { ($w, $h) = split(/x/, $geometry); } my $svg = SVG->new(width => $w, height => $h); $self->{Image} = $svg; # named "Image" for GD compatibility $self->{Width} = $w; $self->{Height} = $h; if (!defined $self->{Outline}) { $self->{Outline} = 1; } $self->allocate_colors_and_fonts; $self->set_category_colors; $self->set_category_styles; # $self->set_category_outline_colors; # $self->set_category_widths; # # grey background # $page->rectangle(@$page_bbox); # $page->set_fill_color(@$grey_bg); # $page->fill; $self->set_draw_elements; $self; } sub allocate_colors_and_fonts { my $self = shift; $self->allocate_colors; $self->allocate_fonts; } sub allocate_colors { my $self = shift; my $im = $self->{Image}; $self->{'Bg'} = '' if !defined $self->{'Bg'}; if ($self->{'Bg'} eq '' || $self->{'Bg'} =~ /^white/) { # Hintergrund weiß: Nebenstraßen werden grau, # Hauptstraßen dunkelgelb gezeichnet $grey_bg = [0.9,0.9,0.9]; $white = [1,1,1]; } elsif ($self->{'Bg'} =~ /^\#([a-f0-9]{2})([a-f0-9]{2})([a-f0-9]{2})/i) { $grey_bg = [hex($1)/255, hex($2)/255, hex($3)/255]; } else { $grey_bg = [0.6,0.6,0.6]; } $white = [1,1,1] if !defined $white; $yellow = [1,1,0] if !defined $yellow; $red = [1,0,0]; $green = [0,1,0]; $darkgreen = [0,0.5,0]; $darkblue = [0,0,0.5]; $lightblue = [0.73,0.84,0.97]; $middlegreen = [0,0.78,0]; $rose = [map { $_/256} 215, 184, 200]; $black = [0,0,0]; } sub cat2svgrgb { my($cat) = @_; my $color = $color{$cat}; if (!defined $color) { warn "No color for category <$cat> found\n"; return undef; } "rgb(" . join(",", map { int($_*255) } @$color) . ")"; } sub set_category_styles { my($self) = @_; %style = ( 'B' => {'stroke' => cat2svgrgb('B'), 'stroke-width' => 2}, 'HH' => {'stroke' => cat2svgrgb('HH'), 'stroke-width' => 2}, 'H' => {'stroke' => cat2svgrgb('H'), 'stroke-width' => 2}, #default: 'N' => {'stroke' => cat2svgrgb('N')}, # default: 'stroke-width' => 1 'NN' => {'stroke' => cat2svgrgb('NN')}, # defaukt: 'stroke-width' => 1}, S => {'stroke' => cat2svgrgb('S')}, SA => {'stroke' => cat2svgrgb('SA')}, SB => {'stroke' => cat2svgrgb('SB')}, SC => {'stroke' => cat2svgrgb('SC')}, R => {'stroke' => cat2svgrgb('R')}, RA => {'stroke' => cat2svgrgb('RA')}, RB => {'stroke' => cat2svgrgb('RB')}, RC => {'stroke' => cat2svgrgb('RC')}, U => {'stroke' => cat2svgrgb('U')}, UA => {'stroke' => cat2svgrgb('UA')}, UB => {'stroke' => cat2svgrgb('UB')}, W => {'stroke' => cat2svgrgb('W')}, W0 => {'stroke' => cat2svgrgb('W0'), 'stroke-width' => 1}, W1 => {'stroke' => cat2svgrgb('W1'), 'stroke-width' => 2}, W2 => {'stroke' => cat2svgrgb('W2'), 'stroke-width' => 3}, 'F:W' => {'fill' => cat2svgrgb('W')}, 'F:W1' => {'fill' => cat2svgrgb('W1')}, 'F:W2' => {'fill' => cat2svgrgb('W2')}, I => {'fill' => 'none'}, # F => $white, 'F:Ae' => {'fill' => cat2svgrgb('Ae')}, 'F:P' => {'fill' => cat2svgrgb('P')}, 'F:Pabove' => {'fill' => cat2svgrgb('Pabove')}, 'F:Forest' => {'fill' => cat2svgrgb('Forest')}, 'F:Forestabove' => {'fill' => cat2svgrgb('Forestabove')}, 'F:Cemetery' => {'fill' => cat2svgrgb('Cemetery')}, 'F:Green' => {'fill' => cat2svgrgb('Green')}, 'F:Orchard' => {'fill' => cat2svgrgb('Orchard')}, 'F:Sport' => {'fill' => cat2svgrgb('Sport')}, 'F:Industrial' => {'fill' => cat2svgrgb('Industrial')}, Z => {'stroke' => cat2svgrgb('Z')}, # '?' => $black, # '??' => $black, Route => {'stroke' => cat2svgrgb('Route')}, # alternierend ); } sub allocate_fonts { my $self = shift; my $im = $self->{Image}; #XXX??? # $sansserif = $self->{PDF}->font('Subtype' => 'Type1', # 'Encoding' => 'WinAnsiEncoding', # 'BaseFont' => 'Helvetica'); } sub draw_map { my $self = shift; my(%args) = @_; my $draw = $args{-draw} || $self->{Draw}; my $im = $self->{Image}; my $transpose = $self->{Transpose}; # XXX use _get_nets # Netze zeichnen my @netz; my @outline_netz; my(%str_draw, $title_draw, %p_draw); foreach (@$draw) { if ($_ eq 'title' && defined $self->{Startname} && $self->{Startname} ne '' && defined $self->{Zielname} && $self->{Zielname} ne '') { $title_draw = 1; } elsif ($_ eq 'ampel') { $p_draw{$_} = 1; } elsif ($_ eq 'strname') { # NOP, done in draw_route } else { $str_draw{$_} = 1; } } # Reihenfolge (von unten nach oben): # Berlin-Grenze, Gewässer, Straßen, U-, S-Bahn foreach ( ['berlin', 'berlin'], ['flaechen', 'flaechen'], ) { push @netz, new Strassen $_->[0] if $str_draw{$_->[1]} } if ($str_draw{'wasser'}) { my $wasser = $self->_get_gewaesser(Strdraw => \%str_draw); push @netz, $wasser; #XXX not yet: erst einmal muss das Zeichnen der outlines auch F: verstehen # push @outline_netz, $wasser; } my $multistr = $self->_get_strassen(Strdraw => \%str_draw); if ($str_draw{'str'}) { push @netz, $multistr; push @outline_netz, $multistr; } foreach ( ['ubahn', 'ubahn'], ['sbahn', 'sbahn'], ['rbahn', 'rbahn'], ) { push @netz, new Strassen $_->[0] if $str_draw{$_->[1]} } if ($str_draw{'Route'}) { push @netz, Strassen->new_from_data ("Route\tRoute " . join(" ", @{$self->{Coords}})); } my $restrict; if ($self->{Restrict}) { $restrict = { map { ($_ => 1) } @{ $self->{Restrict} } }; } if ($self->{Outline}) { foreach my $strecke (@outline_netz) { my $g = $im->group(style=>{ 'stroke'=>'black', 'stroke-width'=>'2', 'fill'=>'none', }); $strecke->init; while(1) { my $s = $strecke->next; last if !@{$s->[1]}; my $cat = $s->[2]; next if $restrict && !$restrict->{$cat}; my @p = map { [map { sprintf "%.2f", $_ } &$transpose(split /,/, $_)] } @{$s->[Strassen::COORDS]}; my $xv = [ map { $_->[0] } @p ]; my $yv = [ map { $_->[1] } @p ]; my $points = $im->get_path (x => $xv, y => $yv, -type => 'polyline', -closed => 'false'); my $style = $style{$cat}; $g->polyline(%$points, (defined $style && defined $style->{'stroke-width'} ? ("stroke-width" => $style->{'stroke-width'}+1) : ()), ); # my($ss, $bbox) = transpose_all($s->[1], $transpose); # next if (!bbox_in_region($bbox, $self->{PageBBox})); # $im->set_line_width(($width{$cat}||1)*1+2); # $im->set_stroke_color(@{ $outline_color{$cat} || [0,0,0] }); # $im->moveto(@{ $ss->[0] }); # for my $xy (@{$ss}[1 .. $#$ss]) { # $im->lineto(@$xy); # } # $im->stroke; } } } foreach my $strecke (@netz) { my $g = $im->group(style=>{ 'stroke'=>'white', 'stroke-width'=>'1', 'fill'=>'none', }); $strecke->init; while(1) { my $s = $strecke->next; last if !@{$s->[1]}; my $cat = $s->[2]; # my($ss, $bbox) = transpose_all($s->[1], $transpose); # next if (!bbox_in_region($bbox, $self->{PageBBox})); # move to first point # $im->moveto(@{ $ss->[0] }); next if $restrict && !$restrict->{$cat}; my @p = map { [map { sprintf "%.2f", $_ } &$transpose(split /,/, $_)] } @{$s->[Strassen::COORDS]}; my $xv = [ map { $_->[0] } @p ]; my $yv = [ map { $_->[1] } @p ]; if ($cat =~ /^F:(.*)/) { my $subcat = $1; my $style = $style{$cat}; if (!defined $style) { $style = $style{$subcat} } # $im->set_line_width(1); # $im->set_stroke_color(@{ $color{$1} || [0,0,0] }); # $im->set_fill_color (@{ $color{$1} || [0,0,0] }); # for my $xy (@{$ss}[1 .. $#$ss]) { # $im->lineto(@$xy); # } # $im->fill; my $points = $im->get_path (x => $xv, y => $yv, -type => 'polygon', ); $g->polygon(%$points, (defined $style ? (style => $style) : ()), ); } elsif ($cat !~ /^[SRU]0$/) { # Ausnahmen: in Bau my $style = $style{$cat}; # $im->set_line_width(($width{$cat} || 1) * 1); # $im->set_stroke_color(@{ $color{$cat} || [0,0,0] }); # for my $xy (@{$ss}[1 .. $#$ss]) { # $im->lineto(@$xy); # } # $im->stroke; if (1) { my $points = $im->get_path (x => $xv, y => $yv, -type => 'polyline', -closed => 'false', ); #my $style = $style{$cat}; $g->polyline(%$points, (defined $style ? (style => $style) : ()), ); } else { for my $i (0 .. $#{$s->[Strassen::COORDS]}-1) { my($x1,$y1) = map { int } &$transpose(split /,/, $s->[Strassen::COORDS][$i]); my($x2,$y2) = map { int } &$transpose(split /,/, $s->[Strassen::COORDS][$i+1]); $g->line(x1 => $x1, y1 => $y1, x2 => $x2, y2 => $y2, ); } } } } } # # $self->{Xk} bezeichnet den Vergrößerungsfaktor # # bis etwa 0.02 ist es zu unübersichtlich, Ampeln zu zeichnen, # # ab etwa 0.05 kann man die mittelgroße Variante nehmen # if ($p_draw{'ampel'} && $self->{Xk} >= 0.02) { # my $lsa = new Strassen "ampeln"; # my $images_dir = $self->get_images_dir; # my $suf = ($self->{Xk} >= 0.05 ? '' : '2'); # my($kl_ampel); # my($kl_andreas); # eval { # $kl_ampel = $self->{PDF}->image("$images_dir/ampel_klein$suf.jpg"); # $kl_andreas = $self->{PDF}->image("$images_dir/andreaskr_klein$suf.jpg"); # }; warn $@ if $@; # warn "weiter..."; # if ($kl_andreas && $kl_ampel) { # $lsa->init; # while(1) { # my $s = $lsa->next_obj; # last if $s->is_empty; # my $cat = $s->category; # my($x, $y) = &$transpose(@{$s->coord_as_list(0)}); # if ($cat eq 'B') { # $im->image(image => $kl_andreas, xpos => $x, ypos => $y, # xalign => 1, yalign => 1); # } else { # $im->image(image => $kl_ampel, xpos => $x, ypos => $y, # xalign => 1, yalign => 1); # } # } # } # } # XXXX hier wird $small_display und $xw/$yw nicht beachtet! my($xw, $yw); my $small_display = 0; if ($self->{Width} < 200 || $self->{Height} < 150) { ($xw, $yw) = (1, 1); $small_display = 1; } else { my($xw1, $yw1) = &$transpose(0, 0); my($xw2, $yw2) = &$transpose(60, 60); # ($xw, $yw) = ($xw2-$xw1, $yw2-$yw1); ($xw, $yw) = (5, 5); } # XXX verschiedene Zeichensatzgrößen für die Orte # my $min_ort_category = ($self->{Xk} < 0.005 ? 4 # : ($self->{Xk} < 0.01 ? 3 # : ($self->{Xk} < 0.02 ? 2 # : ($self->{Xk} < 0.03 ? 1 : 0)))); # my %ort_font = (0 => &GD::Font::Tiny, # 1 => &GD::Font::Small, # 2 => &GD::Font::Small, # 3 => &GD::Font::Large, # MediumBold sieht fetter aus # 4 => &GD::Font::Large, # 5 => &GD::Font::Giant, # 6 => &GD::Font::Giant, # ); if (0) { foreach my $points (['ubahn', 'ubahnhof', 'u'], ['sbahn', 'sbahnhof', 's'], # ['ort', 'orte', 'o'], ) { if ($str_draw{$points->[0]}) { my $p = ($points->[0] eq 'ort' ? $self->_get_orte : new Strassen $points->[1]); my $type = $points->[2]; $p->init; while(1) { my $s = $p->next_obj; last if $s->is_empty; my $cat = $s->category; next if $cat =~ /0$/; my($x0,$y0) = @{$s->coord_as_list(0)}; # Bereichscheck (XXX ist nicht ganz korrekt wenn der Screen breiter ist als die Route) # next if (!(($x0 >= $self->{Min_x} and $x0 <= $self->{Max_x}) # and # ($y0 >= $self->{Min_y} and $y0 <= $self->{Max_y}))); if ($type eq 'u' || ($type eq 's' && $small_display)) { my($x1,$x2,$y1,$y2); # if (!$small_display) { # ($x1, $y1) = &$transpose($x0-30, $y0-30); # ($x2, $y2) = &$transpose($x0+30, $y0+30); # } else { ($x1, $y1) = &$transpose($x0, $y0); # ($x2, $y1) = ($x1+$xw, $y2+$yw); # ($x1, $y2) = ($x1-$xw, $y2-$yw); # } # XXX Farbe bei small_display && s-bahn $im->set_fill_color(@$darkblue); $im->rectangle($x1-2, $y1-2, 5, 5); $im->fill; } elsif ($type eq 's') { # XXX ausgefüllten Kreis zeichnen my($x, $y) = &$transpose(@{$s->coord_as_list(0)}); $im->set_fill_color(@$darkgreen); $im->circle($x, $y, 4); $im->fill; } # } else { # if ($cat >= $min_ort_category) { # my($x, $y) = &$transpose(@{$s->coord_as_list(0)}); # my $ort = $s->name; # # Anhängsel löschen (z.B. "b. Berlin") # $ort =~ s/\|.*$//; # $im->arc($x, $y, 3, 3, 0, 360, $black); # outline_text($im, $ort_font{$cat} || &GD::Font::Small, # $x+4, $y, # patch_string($ort), $white, $darkblue); # } # } } } } } #XXX Straßenbeschriftung # if (ref $self->{StrLabel} && # (defined &GD::Image::stringFT || defined &GD::Image::stringTTF)) { # eval { # # XXX allgemeiner machen # #my $ttf = '/usr/X11R6/share/enlightenment/E-docs/aircut3.ttf'; # my $ttf = '/usr/X11R6/share/enlightenment/E-docs//benjamingothic.ttf'; # my $fontsize = 10; # $Tk::RotFont::NO_X11 = 1; # require Tk::RotFont; # my $ft_method = defined &GD::Image::stringFT ? 'stringFT' : 'stringTTF'; # my $draw_sub = sub { # my($x,$y) = &$transpose($_[0], $_[1]); # if (defined $_[4] and defined $_[5]) { # $x -= $_[4]; # $y -= $_[5]; # } # $im->$ft_method($black, $ttf, $fontsize, -$_[3], $x, $y, $_[2]); # }; # my $extent_sub = sub { # my(@b) = GD::Image->$ft_method($black, $ttf, $fontsize, -$_[3], # &$transpose($_[0], $_[1]), # $_[2]); # ($b[2]-$b[0], $b[3]-$b[1]); # }; # my $strecke = $multistr; # $strecke->init; # while(1) { # my $s = $strecke->next; # last if !@{$s->[1]}; # my $cat = $s->[2]; # next unless $cat eq 'HH' || $cat eq 'H'; # my($x1, $y1, $xe, $ye) = (@{Strassen::to_koord1($s->[1][0])}, # @{Strassen::to_koord1($s->[1][-1])}); # next if (!(($x1 >= $self->{Min_x} and $xe <= $self->{Max_x}) and # ($y1 >= $self->{Min_y} and $ye <= $self->{Max_y}))); # my $str = Strassen::strip_bezirk($s->[0]); # my $coordref = [ map { (split(/,/, $_)) } @{ $s->[1] } ]; # Tk::RotFont::rot_text_smart($str, $coordref, # -drawsub => $draw_sub, # -extentsub => $extent_sub, # -transpose => $transpose, # ); # } # }; # warn $@ if $@; # } $self->{TitleDraw} = $title_draw; $self->draw_scale unless $self->{NoScale}; } # Zeichnen des Maßstabs sub draw_scale { # my $self = shift; # my $im = $self->{Image}; # my $transpose = $self->{Transpose}; # my $x_margin = 10; # my $y_margin = 10; # my $color = $black; # my $bar_width = 4; # my($x0,$y0) = $transpose->(0,0); # my($x1,$y1, $strecke, $strecke_label); # for $strecke (1000, 5000, 10000, 20000, 50000, 100000) { # ($x1,$y1) = $transpose->($strecke,0); # if ($x1-$x0 > 30) { # $strecke_label = $strecke/1000 . "km"; # last; # } # } # $im->set_stroke_color(@$color); # $im->set_line_width(1); # $im->set_fill_color(@$white); # $im->rectangle($self->{Width}-($x1-$x0)-$x_margin, # $y_margin, # ($x1-$x0)/2, # $bar_width); # $im->fill; # $im->set_fill_color(@$color); # $im->rectangle($self->{Width}-($x1-$x0)/2-$x_margin, # $y_margin, # ($x1-$x0)/2, # $bar_width); # $im->fill; # $im->line($self->{Width}-($x1-$x0)-$x_margin, # $y_margin, # $self->{Width}-$x_margin, # $y_margin); # $im->line($self->{Width}-($x1-$x0)-$x_margin, # $y_margin+$bar_width, # $self->{Width}-$x_margin, # $y_margin+$bar_width); # $im->line($self->{Width}-($x1-$x0)/2-$x_margin, # $y_margin, # $self->{Width}-($x1-$x0)/2-$x_margin, # $y_margin+$bar_width); # $im->line($self->{Width}-($x1-$x0)-$x_margin, # $y_margin-2, # $self->{Width}-($x1-$x0)-$x_margin, # $y_margin+$bar_width+2); # $im->line($self->{Width}-$x_margin, # $y_margin-2, # $self->{Width}-$x_margin, # $y_margin+$bar_width+2); # $im->string($sansserif, 10, # $self->{Width}-($x1-$x0)-$x_margin-3, # $y_margin+$bar_width+4, # "0"); # $im->string($sansserif, 10, # $self->{Width}-$x_margin+8-6*length($strecke_label), # $y_margin+$bar_width+4, # $strecke_label); } # XXX fast shot sub draw_route { my $self = shift; $self->draw_map(-draw => ['Route']); } # my $self = shift; # my $im = $self->{Image}; # my $transpose = $self->{Transpose}; # my(@c1) = @{ $self->{C1} }; # my $strnet; # StrassenNetz-Objekt # foreach (@{$self->{Draw}}) { # if ($_ eq 'strname' && $self->{'MakeNet'}) { # $strnet = $self->{MakeNet}->('lite'); # } # } # ##XXX gestrichelte Route # # my $brush; # should be *outside* the next block!!! # # my $line_style; # # if ($self->{RouteWidth}) { # # # fette Routen für die WAP-Ausgabe (B/W) # # $brush = GD::Image->new($self->{RouteWidth}, $self->{RouteWidth}); # # $brush->colorAllocate($im->rgb($black)); # # $im->setBrush($brush); # # $line_style = GD::gdBrushed(); # # } elsif ($brush{Route}) { # # $im->setBrush($brush{Route}); # # $line_style = GD::gdBrushed(); # # } else { # # # Vorschlag von Rainer Scheunemann: die Route in blau zu zeichnen, # # # damit Rot-Grün-Blinde sie auch erkennen können. Vielleicht noch # # # besser: rot-grün-gestrichelt # # $im->setStyle($darkblue, $darkblue, $darkblue, $red, $red, $red); # # $line_style = GD::gdStyled(); # # } # $im->set_stroke_color(@$red); # $im->set_line_width(4); # # Route # if (@c1) { # $im->moveto(map { sprintf "%.2f", $_ } $transpose->(@{ $c1[0] })); # for(my $i = 1; $i <= $#c1; $i++) { # $im->lineto(map { sprintf "%.2f", $_ } $transpose->(@{ $c1[$i] })); # } # $im->stroke; # } # # Flags # if (@c1 > 1) { # $self->{UseFlags} = 0; # XXX don't use this because of missing transparency information in .jpg # if ($self->{UseFlags}) { # my $images_dir = $self->get_images_dir; # my $start_flag = $self->{PDF}->image("$images_dir/flag2_bl.jpg"); # if ($start_flag) { # my($x, $y) = &$transpose(@{ $c1[0] }); # $im->image(image => $start_flag, xpos => $x-5, ypos => $y-15, # xalign => 1, yalign => 1); # } # my $end_flag = $self->{PDF}->image("$images_dir/flag_ziel.jpg"); # if ($end_flag) { # my($x, $y) = &$transpose(@{ $c1[-1] }); # $im->image(image => $end_flag, xpos => $x-5, ypos => $y-15, # xalign => 1, yalign => 1); # } # } # } # # Ausgabe der Straßennnamen # if ($strnet) { # $im->set_stroke_color(@$black); # $im->set_line_width(1); # my(@strnames) = $strnet->route_to_name # ([ map { [split ','] } @{ $self->{Coords} } ]); # my $size = 10; # foreach my $e (@strnames) { # my $name = Strassen::strip_bezirk($e->[0]); # my $f_i = $e->[4][0]; # my($x,$y) = &$transpose(split ',', $self->{Coords}[$f_i]); # my $s_width = $im->string_width($sansserif, $name) * $size; # $im->set_fill_color(@$white); # $im->rectangle($x-2, $y-2, $s_width+4, $size+2); # $im->fill; # $im->rectangle($x-2, $y-2, $s_width+4, $size+2); # $im->stroke; # $im->set_fill_color(@$black); # $im->string($sansserif, $size, $x, $y, $name); # } # } # if ($self->{TitleDraw}) { # my $start = $self->{Startname}; # my $ziel = $self->{Zielname}; # foreach my $s (\$start, \$ziel) { # # Text in Klammern entfernen, damit der Titel kürzer wird # my(@s) = split(m|/|, $$s); # foreach (@s) { # s/\s+\(.*\)$//; # } # $$s = join("/", @s); # } # my $s = "$start -> $ziel"; # my $size = 20; # my $s_width = $im->string_width($sansserif, $s) * $size; # $im->set_stroke_color(@$black); # $im->set_fill_color(@$white); # $im->set_line_width(1); # $im->rectangle(15, 795, $s_width+5+5, $size+5); # $im->fill; # $im->rectangle(15, 795, $s_width+5+5, $size+5); # $im->stroke; # $im->set_stroke_color(@$black); # $im->set_fill_color(@$black); # $im->string($sansserif, $size, 20, 800, $s); # } # } # Draw this first, otherwise the filling of the circle won't work! sub draw_wind { # return; # not yet XXXX # my $self = shift; # return unless $self->{Wind}; # require BBBikeCalc; # BBBikeCalc::init_wind(); # my $richtung = lc($self->{Wind}{Windrichtung}); # if ($richtung =~ /o$/) { $richtung =~ s/o$/e/; } # my $staerke = $self->{Wind}{Windstaerke}; # my $im = $self->{Image}; # my($rad) = 10; # my $col = $darkblue; # $im->set_stroke_color(@$col); # $im->set_fill_color(@$col); # $im->circle($self->{Width}-20, 20, $rad); # $im->fill; # if ($staerke > 0) { # my %senkrecht = # im Uhrzeigersinn # ('-1,-1' => [-1,+1], # '-1,0' => [ 0,+1], # '-1,1' => [+1,+1], # '0,1' => [+1, 0], # '1,1' => [+1,-1], # '1,0' => [ 0,-1], # '1,-1' => [-1,-1], # '0,-1' => [-1, 0], # ); # my($ydir, $xdir) = @{$BBBikeCalc::wind_dir{$richtung}}; # if (exists $senkrecht{"$xdir,$ydir"}) { # my($x2dir, $y2dir) = @{ $senkrecht{"$xdir,$ydir"} }; # my($yadd, $xadd) = map { -$_*15 } ($ydir, $xdir); # $xadd = -$xadd; # korrigieren # $im->line($self->{Width}-20, 20, $self->{Width}-20+$xadd, 20+$yadd); # my $this_tic = 15; # my $i = $staerke; # my $last_is_half = 0; # if ($i%2 == 1) { # $last_is_half++; # $i--; # } # while ($i >= 0) { # my($yadd, $xadd) = map { -$_*$this_tic } ($ydir, $xdir); # $xadd = -$xadd; # my $stroke_len; # if ($i == 0) { # if ($last_is_half) { # # half halbe Strichlänge # $stroke_len = 3; # } else { # last; # } # } else { # # full; volle Strichlänge # $stroke_len = 6; # } # my($yadd2, $xadd2) = map { -$_*$stroke_len } ($y2dir, $x2dir); # $xadd2 = -$xadd2; # $im->line($self->{Width}-20+$xadd, 20+$yadd, # $self->{Width}-20+$xadd+$xadd2, 20+$yadd+$yadd2); # $this_tic -= 3; # last if $this_tic <= 0; # $i-=2; # } # } # } } sub flush { my $self = shift; my %args = @_; my $fh = $args{Fh} || $self->{Fh}; my $im = $self->{Image}; if ($fh == \*STDOUT) { # This is to help CGI::Compress:Gzip print $im->xmlify; } else { print $fh $im->xmlify; } # my %args = @_; # if (!defined $self->{Filename}) { # my $fh = $args{Fh} || $self->{Fh}; # binmode $fh; # } # $self->{PDF}->close; } # use Return => "string" in the constructor for this method sub string { # my($self, %args) = @_; # $self->flush(%args); # if (defined $self->{Filename}) { # open(F, $self->{Filename}) or die "Can't open $self->{Filename}: $!"; # local $/ = undef; # my $buf = scalar ; # close F; # $buf; # } else { # $ {$self->{Fh}->string_ref }; # } } sub empty_image_error { # my $self = shift; # my $im = $self->{Image}; # my $fh = $self->{Fh}; # $im->stringc($sansserif, 24, 300, 400, "Empty image!"); # $self->{PDF}->close; confess "Empty image"; } # return transposed and pdf'ied "strecke" and the bbox sub transpose_all { my($s, $transpose) = @_; # first: my($tx,$ty) = map { sprintf "%.2f", $_ } $transpose->(@{ Strassen::to_koord1($s->[0]) }); my $res = [[$tx, $ty]]; my $bbox = [$tx,$ty,$tx,$ty]; foreach my $xy (@{$s}[1 .. $#$s]) { my($tx,$ty) = map { sprintf "%.2f", $_ } $transpose->(@{ Strassen::to_koord1($xy) }); push @$res, [ $tx, $ty ]; $bbox->[0] = $tx if ($tx < $bbox->[0]); $bbox->[2] = $tx if ($tx > $bbox->[2]); $bbox->[1] = $ty if ($ty < $bbox->[1]); $bbox->[3] = $ty if ($ty > $bbox->[3]); } ($res, $bbox); } # return true if the union is not empty # sub bbox_in_region { # my($bbox, $region) = @_; # return 0 if ($bbox->[0] > $region->[2] || # $bbox->[1] > $region->[3] || # $bbox->[2] < $region->[0] || # $bbox->[3] < $region->[1]); # 1; # } # # Additional PDF::Create methods # package PDF::Create::Page; # use constant PI => 3.141592653; # sub set_stroke_color { # my($page, $r, $g, $b) = @_; # return if (defined $page->{'current_stroke_color'} && # $page->{'current_stroke_color'} eq join(",", $r, $g, $b)); # $page->{'pdf'}->page_stream($page); # $page->{'pdf'}->add("$r $g $b RG"); # $page->{'current_stroke_color'} = join(",", $r, $g, $b); # } # sub set_fill_color { # my($page, $r, $g, $b) = @_; # return if (defined $page->{'current_fill_color'} && # $page->{'current_fill_color'} eq join(",", $r, $g, $b)); # $page->{'pdf'}->page_stream($page); # $page->{'pdf'}->add("$r $g $b rg"); # $page->{'current_fill_color'} = join(",", $r, $g, $b); # } # sub set_line_width { # my($page, $w) = @_; # return if (defined $page->{'current_line_width'} && # $page->{'current_line_width'} == $w); # $page->{'pdf'}->page_stream($page); # $page->{'pdf'}->add("$w w"); # $page->{'current_line_width'} = $w; # } # sub circle { # my($page, $x, $y, $r) = @_; # my @coords; # for(my $i = 0; $i < PI*2; $i+=PI*2/$r/2) { # my($xi,$yi) = map { $_*$r } (sin $i, cos $i); # push @coords, $x+$xi, $y+$yi; # } # push @coords, @coords[0,1]; # @coords = map { sprintf "%.2f", $_ } @coords; # $page->moveto(shift @coords, shift @coords); # for(my $i = 0; $i <= $#coords; $i+=2) { # $page->lineto($coords[$i], $coords[$i+1]); # } # } 1;