#!/usr/bin/perl
# Weathermap4rrd 
# Alexandre Fontelle, <afontelle AT free.fr>
# http://weathermap4rrd.tropicalex.net
# based on Network Wearthermap - version 1.1.1 from Panagiotis Christias (http://netmon.grnet.gr/weathermap/)
# modified for RRDTool use and other stuff

$VERSION = "1.1.1g";

use Getopt::Long;
use GD;
use RRDs;

################################################################
#
# Configuration parameters
#
$CONFIG = "weathermap.conf";    # Default value if nothing is specified in config file
$OUTPUTFILE = "weathermap.png"; # Default value if nothing is specified in config file
$DEBUG  = 0;
$WIDTH  = 740; # Default value if nothing is specified in config file
$HEIGHT = 600;  # Default value if nothing is specified in config file
$DATE 	= "now";
################################################################

%optctl=();
GetOptions(\%optctl, "config:s", "output:s", "date:s", "version", "help", "debug", "") || exit(1);

if($optctl{"config"}) { $CONFIG = $optctl{"config"} };

if($optctl{"output"}) { $OUTPUTFILE = $optctl{"output"} };

if($optctl{"date"}) { 
	$DATE =`/bin/date --date="$optctl{"date"}" +%s`; 
} else {
	$DATE = 0;
}

if($optctl{"version"}) { &version; exit; }

if($optctl{"help"}) { &usage; exit; }

if($optctl{"debug"}) { $DEBUG=1; }

if ($DEBUG) { print "Weathermap4rrd $version"; }

&read_config($CONFIG);

if($background){
	open (PNG,"$background") || die "$background: $!\n";
	$map = newFromPng GD::Image(PNG) || die "newFromPng failed.";
	close PNG;
} else {
	$map=new GD::Image($WIDTH,$HEIGHT)
}

$maxColors = $map->colorsTotal;
&alloc_colors;

# Anti-aliasing enable
gdAntiAliased();
$map->setAntiAliased($white);

# to disable anti-aliasing
#$map->setAntiAliasedDontBlend($color,0);

print "Reading rrd files...\n\n" if($DEBUG);
foreach $link (keys %target){
	$data = $target{$link};
	print "FILE: $data\n" if($DEBUG);
	if ( ! $DATE ) {
		$DATE= RRDs::last "$data";
		print "No date specified, last value will be read : ".scalar localtime($DATE)."\n" if ($DEBUG);
	}
	my ($start,$step,$names,$data) = RRDs::fetch "$data","AVERAGE","--start","$DATE","--end","$DATE";
	my $ERR=RRDs::error;
	die "ERROR while reading $target{$link}: $ERR\n" if $ERR;
	print "Start:       ", scalar localtime($start), " ($start)\n"  if($DEBUG);
	print "Step size:   $step seconds\n"  if($DEBUG);
	print "DS names:    ", join (", ", @$names)."\n"  if($DEBUG);
	print "Data points: ", $#$data + 1, "\n"  if($DEBUG);
	foreach my $line (@$data) {
		if(@$line[0] != null) {
			$start += $step;
			$input{$link}=@$line[$inpos{$link}-1]*$coef{$link};
			print "LINK: $link, Input: $input{$link}\n" if($DEBUG);
			print "rrdtool fetch $target{$link} AVERAGE --start=$DATE --end=$DATE\n" if($DEBUG);
			$output{$link}=@$line[$outpos{$link}-1]*$coef{$link};
			print "LINK: $link, Output: $output{$link}\n" if($DEBUG);
		}
	}
}



print "\nCalculating rates...\n\n" if($DEBUG);

foreach $link (keys %target){
	$outrate=(int(($output{$link}/$maxbytesout{$link}+0.005)*100)>100) ?  100:int(($output{$link}/$maxbytesout{$link}+0.005)*100);
	$inrate=(int(($input{$link}/$maxbytesin{$link}+0.005)*100)>100) ?  100:int(($input{$link}/$maxbytesin{$link}+0.005)*100);


	if($output{$link} != 0 && $outrate == 0) { $outrate=1 }
	if($input{$link} != 0 && $inrate == 0) { $inrate=1 }


	print "$target{$link}: in=$input{$link}/$maxbytesin{$link} out=$output{$link}/$maxbytesout{$link}\n" if($DEBUG);
	print "Maxbytesin($link)=$maxbytesin{$link} Maxbytesout($link)=$maxbytesout{$link}\n" if($DEBUG);
	print "$target{$link}: outrate=$outrate%, inrate=$inrate%\n" if($DEBUG);

	# draw lines...

	$width=4;

	if ($arrow{$link} eq "dot") {
		&draw_arrow_dot(
			$xpos{$nodea{$link}},
			$ypos{$nodea{$link}},
			&middle($xpos{$nodea{$link}},$xpos{$nodeb{$link}}),
			&middle($ypos{$nodea{$link}},$ypos{$nodeb{$link}}),
			$width, 0,1, &select_color($outrate));
		&draw_arrow_dot(
			$xpos{$nodea{$link}},
			$ypos{$nodea{$link}},
			&middle($xpos{$nodea{$link}},$xpos{$nodeb{$link}}),
			&middle($ypos{$nodea{$link}},$ypos{$nodeb{$link}}),
			$width, 0, 0, $black);
	} else {
		# display normal arrow
		&draw_arrow(
			$xpos{$nodea{$link}},
			$ypos{$nodea{$link}},
			&middle($xpos{$nodea{$link}},$xpos{$nodeb{$link}}),
			&middle($ypos{$nodea{$link}},$ypos{$nodeb{$link}}),
			$width, 1, &select_color($outrate));
		&draw_arrow(
			$xpos{$nodea{$link}},
			$ypos{$nodea{$link}},
			&middle($xpos{$nodea{$link}},$xpos{$nodeb{$link}}),
			&middle($ypos{$nodea{$link}},$ypos{$nodeb{$link}}),
			$width, 0, $black);
	}

	&label(&middle($xpos{$nodea{$link}},&middle($xpos{$nodea{$link}},$xpos{$nodeb{$link}})),
		&middle($ypos{$nodea{$link}},&middle($ypos{$nodea{$link}},$ypos{$nodeb{$link}})),
		$outrate . "%", 0);
		
	if ($displayvalue{$link}) {
		if ($output{$link} >=131072) { 
			$coefdisplay=8/(1024*1024);
			$unitdisplay="Mbits";
		} else {
			$coefdisplay=8/1024;
			$unitdisplay="Kbits";
		}

		$todisplay=sprintf ("%.1f",$output{$link}*$coefdisplay). "$unitdisplay";

		&label(&middle($xpos{$nodea{$link}},&middle($xpos{$nodea{$link}},$xpos{$nodeb{$link}})),
		&middle($ypos{$nodea{$link}},&middle($ypos{$nodea{$link}},$ypos{$nodeb{$link}}+70)),
		"$todisplay", 0);

	} else {
		$todisplay="";
	}




	if ($arrow{$link} eq "dot") {
		&draw_arrow_dot(
			$xpos{$nodeb{$link}},
			$ypos{$nodeb{$link}},
			&middle($xpos{$nodea{$link}},$xpos{$nodeb{$link}}),
			&middle($ypos{$nodea{$link}},$ypos{$nodeb{$link}}),
			$width, 0,1, &select_color($inrate));
		&draw_arrow_dot(
			$xpos{$nodeb{$link}},
			$ypos{$nodeb{$link}},
			&middle($xpos{$nodea{$link}},$xpos{$nodeb{$link}}),
			&middle($ypos{$nodea{$link}},$ypos{$nodeb{$link}}),
			$width, 0, 0, $black);
	} else {
		# display normal arrow
			&draw_arrow(
			$xpos{$nodeb{$link}},
			$ypos{$nodeb{$link}},
			&middle($xpos{$nodea{$link}},$xpos{$nodeb{$link}}),
			&middle($ypos{$nodea{$link}},$ypos{$nodeb{$link}}),
			$width, 1, &select_color($inrate));
		&draw_arrow(
			$xpos{$nodeb{$link}},
			$ypos{$nodeb{$link}},
			&middle($xpos{$nodea{$link}},$xpos{$nodeb{$link}}),
			&middle($ypos{$nodea{$link}},$ypos{$nodeb{$link}}),
			$width, 0, $black);
	}
	&label(&middle($xpos{$nodeb{$link}},&middle($xpos{$nodea{$link}},$xpos{$nodeb{$link}})),
		&middle($ypos{$nodeb{$link}},&middle($ypos{$nodea{$link}},$ypos{$nodeb{$link}})),
		$inrate . "%", 0);


	if ($displayvalue{$link}) {
		if ($input{$link} >=131072) { 
			$coefdisplay=8/(1024*1024);
			$unitdisplay="Mbits";
		} else {
			$coefdisplay=8/1024;
			$unitdisplay="Kbits";
		}
		$todisplay=sprintf ("%.1f",$input{$link}*$coefdisplay). "$unitdisplay";
		&label(&middle($xpos{$nodeb{$link}},&middle($xpos{$nodea{$link}},$xpos{$nodeb{$link}})),
		&middle($ypos{$nodeb{$link}},&middle($ypos{$nodea{$link}},$ypos{$nodeb{$link}}+70)),
		$todisplay, 0);

	} else {
		$todisplay=" ";
	}

}
print "\n" if($DEBUG);

foreach(keys %xpos){
	&label($xpos{$_},$ypos{$_},$label{$_}, 3);
}


&annotation;

# print image...
print "Generating image file $OUTPUTFILE...\n\n" if($DEBUG);
open(PNG,">$OUTPUTFILE")||die("$OUTPUTFILE: $!\n");
if ( $^O eq 'MSWin32' )
{
    binmode ( PNG ) ;
}

print PNG $map->png;
close PNG;

# hint, resizing the image could make it look better

exit;


# print labels
sub label{
	my($xpos,$ypos,$label,$pad)=@_;
	my($strwidth)=gdLargeFont->width*length($label);
	my($strheight)=gdLargeFont->height;
	$map->filledRectangle(
		$xpos-$strwidth/2-$pad-2, $ypos-$strheight/2-$pad+1,
		$xpos+$strwidth/2+$pad+1, $ypos+$strheight/2+$pad,
		$black);
	$map->filledRectangle(
		$xpos-$strwidth/2-$pad-1, $ypos-$strheight/2-$pad+2,
		$xpos+$strwidth/2+$pad, $ypos+$strheight/2+$pad-1,
		$white);
	$map->string(gdLargeFont,
		$xpos-$strwidth/2, $ypos-$strheight/2+1,
		$label, $black)
}


# print annotation
sub annotation{
	my($title)="Traffic load";
        $strwidth=gdLargeFont->width*length($label{$_});
	$strheight=gdLargeFont->height;

	#$t=localtime(time);
	$t=localtime($DATE);
	#	$t=gmtime(time);
	$map->string(gdLargeFont, $titlexpos, $titleypos, $titlegraph, $black);
	$map->string(gdSmallFont, $titlexpos, $titleypos+20, "Last update on $t", $black);

	$map->filledRectangle($keyxpos,$keyypos,
		$keyxpos+gdLargeFont->width*length($title)+10,
		$keyypos+gdLargeFont->height*($scales+1)+gdTinyFont->height*2.5,
		$black);
		
	$map->filledRectangle($keyxpos,$keyypos,
		$keyxpos+gdLargeFont->width*length($title)+10,
		$keyypos+gdLargeFont->height*($scales+1)+10,
		$gray);
	$map->rectangle($keyxpos,$keyypos,
		$keyxpos+gdLargeFont->width*length($title)+10,
		$keyypos+gdLargeFont->height*($scales+1)+gdTinyFont->height*2.5,
		$black);

	$map->string(gdLargeFont,
		$keyxpos+4,
		$keyypos+4,
		"Traffic load",  $black);

	my($i)=1;
	foreach(sort {$scale_low{$a}<=>$scale_low{$b}} keys %scale_low){
		$map->filledRectangle(
			$keyxpos+6,
			$keyypos+gdLargeFont->height*$i+8,
			$keyxpos+6+16,
			$keyypos+gdLargeFont->height*$i+gdLargeFont->height+6,
			$color{$_});
		$map->string(gdLargeFont,
			$keyxpos+6+20,
			$keyypos+gdLargeFont->height*$i+8,
			"$scale_low{$_}-$scale_high{$_}%", $black);
		$i++
	}
	#$map->string(gdTinyFont,$keyxpos+2,$keyypos+gdLargeFont->height*$i+8,"Weathermap4RRD $VERSION",$black);
	$map->string(
	gdTinyFont,
	$keyxpos+(((gdLargeFont->width)*length($title)+10)-((gdTinyFont->width)*length("Weathermap4RRD $VERSION")))/2+2,
	$keyypos+gdLargeFont->height*($i)+11,
	"Weathermap4RRD $VERSION",
	$white);
}

sub select_color {
	my($rate)=($_[0]>100) ? 100:$_[0];
	if($rate=="0"){return($darkgray)}
	foreach(sort {$scale_high{$a}<=>$scale_high{$b}} keys %scale_high){
		if($scale_low{$_}<=$rate && $rate<=$scale_high{$_}){
			return($color{$_});
		}
	}
}

sub alloc_colors {

	if ( ($black=$map->colorAllocate(0,0,0)) =="-1") {
		$black=$map->colorClosest(0,0,0);
		print "**** Warning ****\n";
		print "Background picture is using a 8-bit indexed palette. Unable to allocate new color to palette.\n";
		print "Colors needed by Weathermap4rrd will be based on existing colors. Few of them could be bad displayed.\n";
		print "To get right color displayed, you should convert background picture to 24-bit truecolor mode.\n";
		print "********\n";
	}
	if ( ($white=$map->colorAllocate(255,255,255)) =="-1") {
		$white=$map->colorClosest(255,255,255);
	}
	if ( ($gray=$map->colorAllocate(248,248,248)) =="-1") {
		$gray=$map->colorClosest(248,248,248);
	}
	
	if (($red=$map->colorAllocate(255,0,0)) =="-1") {
		$red=$map->colorClosest(255,0,0);
	}
	if (($green=$map->colorAllocate(64,255,128)) =="-1") {
		$green=$map->colorClosest(64,255,128);
	}
	if (($darkgray=$map->colorAllocate(128,128,128)) =="-1") {
		$darkgray=$map->colorClosest(128,128,128);
	}

	foreach(keys %scale_red){
		if (($color{$_} = $map->colorAllocate($scale_red{$_},$scale_green{$_},$scale_blue{$_})) =="-1" ) {
		$color{$_} = $map->colorClosest($scale_red{$_},$scale_green{$_},$scale_blue{$_});
		}
	}

}


sub read_config {
my($config)=shift;
my($node,$link);

print "\nReading configuration file...\n\n" if($DEBUG);

$scales=0;
open(CONF,$config) or die "$config: $!\n";
while(<CONF>){
	if(/^\s*BACKGROUND\s+(\S+)/i){
		if(-s "$1"){
			$background=$1;
			print "found BACKGROUND: $background\n" if($DEBUG);
		}
	}
	if(/^\s*WIDTH\s+(\d+)/i){
		if("$1" ne ""){
			$WIDTH=$1;
			print "found WIDTH: $WIDTH\n" if($DEBUG);
		}
	}
	if(/^\s*HEIGHT\s+(\d+)/i){
		if("$1" ne ""){
			$HEIGHT=$1;
			print "found HEIGHT: $HEIGHT\n" if($DEBUG);
		}
	}
	if(/^\s*NODE\s+(\S+)/i){
		$node=$1;
		print "found NODE: $node\n" if($DEBUG);
	}
	if(/^\s*POSITION\s+(\d+)\s+(\d+)/i){
		$xpos{$node}=$1;
		$ypos{$node}=$2;
		print "found NODE: $node XPOS: $xpos{$node} YPOS: $xpos{$node}\n" if($DEBUG);
	}
	if(/^\s*LABEL\s+(\S+)/i){
		$label{$node}=$1;
		print "found NODE: $node LABEL: $label{$node}\n" if($DEBUG);
	}

	if(/^\s*LINK\s+(\S+)/i){
		$link=$1;
		print "found LINK: $link\n" if($DEBUG);
	}
	if(/^\s*NODES\s+(\S+)\s+(\S+)/i){
		$nodea{$link}=$1;
		$nodeb{$link}=$2;
		print "found LINK: $link NODEA: $nodea{$link} NODEB: $nodeb{$link}\n" if($DEBUG);
	}

	if(/^\s*ARROW\s+(\S+)/i){
		$arrow{$link}=$1;
		print "found ARROW: $link ARROW: $arrow{$link}\n" if($DEBUG);
	}



	if(/^\s*TARGET\s+(\S+)/i){
		$target{$link}=$1;
		print "found LINK: $link TARGET: $target{$link}\n" if($DEBUG);
	}


	# If only one value is set for bandwidth. IN=OUT bandwidth.
	if(/^\s*BANDWIDTH\s+(\d+)/i){
		    $bandwidth{$link}=$1;
			$maxbytesin{$link}=$bandwidth{$link}*1024/8;
			$maxbytesout{$link}=$maxbytesin{$link};
			print "found LINK: $link BANDWIDTH: $bandwidth{$link}\n" if($DEBUG);
	}

	if(/^\s*BANDWIDTH\s+(\S+)\s+(\S+)/i){
	        $bandwidthin{$link}=$1;
			$maxbytesin{$link}=$bandwidthin{$link}*1024/8;
			$bandwidthout{$link}=$2;
			$maxbytesout{$link}=$bandwidthout{$link}*1024/8;
			print "found LINK: $link BANDWIDTH IN: $bandwidthin{$link} BANDWIDTH OUT: $bandwidthout{$link}\n" if($DEBUG);
	}


	if(/^\s*WIDTH\s+(\d+)/i){
		$WIDTH=$1;
		print "found LINK: WIDTH : $WIDTH\n" if($DEBUG);
	}

	if(/^\s*HEIGHT\s+(\d+)/i){
		$HEIGHT=$1;
		print "found LINK: HEIGHT : $HEIGHT\n" if($DEBUG);
	}

	
	if(/^\s*OUTPUTFILE\s+(\S+)/i){
		$OUTPUTFILE=$1;
		print "found OUTPUTFILE: $OUTPUTFILE\n" if($DEBUG);
	}


	if(/^\s*UNIT\s+(\S+)/i){
		$unit{$link}=$1;
		if ( $unit{$link} eq "Mbits" ) {
			$coef{$link}=1024*1024/8;
		}
		if ( $unit{$link} eq "Kbits" ) {
			$coef{$link}=1024/8;
		}

		if ( $unit{$link} eq "bits" ) {
			$coef{$link}=1/8;
		}

		if ( $unit{$link} eq "Mbytes" ) {
			$coef{$link}=1024*1024;
		}

		if ( $unit{$link} eq "Kbytes" ) {
			$coef{$link}=1024;
		}

		if ( $unit{$link} eq "bytes" ) {
			$coef{$link}=1;
		}
		print "found LINK: $link COEF: $coef{$link}\n" if($DEBUG);
	}

	if(/^\s*INPOS\s+(\d+)/i){
		$inpos{$link}=$1;
		print "found LINK: $link INPOS : $inpos{$link}\n" if($DEBUG);
	}
	if(/^\s*OUTPOS\s+(\d+)/i){
		$outpos{$link}=$1;
		print "found LINK: $link OUTPOS : $outpos{$link}\n" if($DEBUG);
	}
	if(/^\s*DISPLAYVALUE\s+(\d+)/i){
		$displayvalue{$link}=$1;
		print "found LINK: $link DISPLAYVALUE : $displayvalue{$link}\n" if($DEBUG);
	}
	
	if(/^\s*TITLE\s+\"(.+)\"/i){
		$titlegraph="$1";
		print "found LINK: $link TITLE : --$titlegraph--\n" if($DEBUG);
	}

	if(/^\s*KEYPOS\s+(\d+)\s+(\d+)/i){
		$keyxpos=$1;
		$keyypos=$2;
		print "found KEY POSITION: $keyxpos $keyypos\n" if($DEBUG);
	}
	
	if(/^\s*TITLEPOS\s+(\d+)\s+(\d+)/i){
		$titlexpos=$1;
		$titleypos=$2;
		print "found TITLE POSITION: $titlexpos $titleypos\n" if($DEBUG);
	}

	if(/^\s*SCALE\s+(\d+)\s+(\d+)\s+(\d+)\s+(\d+)\s+(\d+)/i){
		$scale_low{"$1:$2"}=$1;
		$scale_high{"$1:$2"}=$2;
		$scale_red{"$1:$2"}=$3;
		$scale_green{"$1:$2"}=$4;
		$scale_blue{"$1:$2"}=$5;
		$scales++;
		print "found SCALE DATA: $1:$2 $3:$4:$5\n" if($DEBUG);
	}
}
print "\n" if($DEBUG);
}


sub middle{
	return int( $_[0] + ($_[1]-$_[0])/2 )
}

sub dist{
	return int( sqrt( $_[0]*$_[0] + $_[1]*$_[1] ) )
}

sub newx{
	my($a,$b,$x,$y)=@_;
	return int( cos( atan2($y,$x) + atan2($b,$a) ) * sqrt( $x*$x + $y*$y ) );
}

sub newy{
	my($a,$b,$x,$y)=@_;
	return int( sin( atan2($y,$x) + atan2($b,$a) ) * sqrt( $x*$x + $y*$y ) );
}

sub dist_bw_points{
	my($x1,$y1,$x2,$y2)=($_[0],$_[1],$_[2],$_[3]);
	return int(sqrt(($x2-$x1)*($x2-$x1)+($y2-$y1)*($y2-$y1)));
}

sub getposy_line {
	my($x,$x1,$y1,$x2,$y2)=($_[0],$_[1],$_[2],$_[3],$_[4]);
    $a=($y2-$y1)/($x2-$x1);
	$b=$y1-$a*$x1;

	return int($a*$x+$b);
}

sub getposx_line {
	my($y,$x1,$y1,$x2,$y2)=($_[0],$_[1],$_[2],$_[3],$_[4]);
	$c=($x2-$x1)/($y2-$y1);
	$d=$x1-$c*$y1;
	return int($c*$y+$d);
}
						


sub draw_arrow {
	my($x1,$y1,$x2,$y2,$w,$solid,$color)=($_[0],$_[1],$_[2],$_[3],$_[4],$_[5],$_[6]);
	my($arrow)=new GD::Polygon;

	$arrow->addPt(
		$x1 + &newx($x2-$x1, $y2-$y1, 0, $w),
		$y1 + &newy($x2-$x1, $y2-$y1, 0, $w)
		);

	$arrow->addPt(
		$x2 + &newx($x2-$x1, $y2-$y1, -4*$w, $w),
		$y2 + &newy($x2-$x1, $y2-$y1, -4*$w, $w)
		);

	$arrow->addPt(
		$x2 + &newx($x2-$x1, $y2-$y1, -4*$w, 2*$w),
		$y2 + &newy($x2-$x1, $y2-$y1, -4*$w, 2*$w)
		);

	$arrow->addPt( $x2, $y2);

	$arrow->addPt(
		$x2 + &newx($x2-$x1, $y2-$y1, -4*$w, -2*$w),
		$y2 + &newy($x2-$x1, $y2-$y1, -4*$w, -2*$w)
		);

	$arrow->addPt(
		$x2 + &newx($x2-$x1, $y2-$y1, -4*$w, -$w),
		$y2 + &newy($x2-$x1, $y2-$y1, -4*$w, -$w)
		);

	$arrow->addPt(
		$x1 + &newx($x2-$x1, $y2-$y1, 0, -$w),
		$y1 + &newy($x2-$x1, $y2-$y1, 0, -$w)
		);

	if($solid){
		$map->filledPolygon($arrow,$color);
	}else{
		$map->polygon($arrow,$color);
	}
}
sub draw_arrow_dot{
	my($x1,$y1,$x2,$y2,$w,$step,$solid,$color)=($_[0],$_[1],$_[2],$_[3],$_[4],$_[5],$_[6],$_[7]);
	$dif_horizontal=abs($x1-$x2);
	$dif_vertical=abs($y1-$y2);
			
	if ($dif_horizontal>$dif_vertical) {
		if ( ($x1 < $x2) ) {
			for ($xi = $x1+$w; dist_bw_points($xi,$yi,$x2,$y2)>4*$w; $xi=$xi+2*$w+$step) {
				$yi=getposy_line($xi,$x1,$y1,$x2,$y2);
				if ($solid) {
					$map->filledEllipse($xi,$yi,2*$w, 2*$w,$color);
				} else {
					$map->ellipse($xi,$yi,2*$w, 2*$w,$color);
				}
			}
		} else {
			for ($xi = $x1-$w; dist_bw_points($xi,$yi,$x2,$y2)>4*$w; $xi=$xi-2*$w-$step) {
				$yi=getposy_line($xi,$x1,$y1,$x2,$y2);
				if ($solid) {
					$map->filledEllipse($xi,$yi,2*$w, 2*$w,$color);
				} else {
					$map->ellipse($xi,$yi,2*$w, 2*$w,$color);
				}
			}
		}
	} else {
		if ( ($y1<$y2) ) {
			for ($yi = $y1+$w; dist_bw_points($xi,$yi,$x2,$y2)>4*$w; $yi=$yi+2*$w+$step) {
				$xi=getposx_line($yi,$x1,$y1,$x2,$y2);
				if ($solid) {
					$map->filledEllipse($xi,$yi,2*$w, 2*$w,$color);
				} else {
					$map->ellipse($xi,$yi,2*$w, 2*$w,$color);
				}
			}
		} else {
			for ($yi = $y1-$w; dist_bw_points($xi,$yi,$x2,$y2)>4*$w; $yi=$yi-2*$w-$step) {
				$xi=getposx_line($yi,$x1,$y1,$x2,$y2);
				if ($solid) {
					$map->filledEllipse($xi,$yi,2*$w, 2*$w,$color);
				} else {
					$map->ellipse($xi,$yi,2*$w, 2*$w,$color);
				}

			}
		}
	}
	my($arrow)=new GD::Polygon;

	$arrow->addPt(
		$x2 + &newx($x2-$x1, $y2-$y1, -4*$w, $w),
		$y2 + &newy($x2-$x1, $y2-$y1, -4*$w, $w)
		);

	$arrow->addPt(
		$x2 + &newx($x2-$x1, $y2-$y1, -4*$w, 2*$w),
		$y2 + &newy($x2-$x1, $y2-$y1, -4*$w, 2*$w)
		);

	$arrow->addPt( $x2, $y2);

	$arrow->addPt(
		$x2 + &newx($x2-$x1, $y2-$y1, -4*$w, -2*$w),
		$y2 + &newy($x2-$x1, $y2-$y1, -4*$w, -2*$w)
		);

	$arrow->addPt(
		$x2 + &newx($x2-$x1, $y2-$y1, -4*$w, -$w),
		$y2 + &newy($x2-$x1, $y2-$y1, -4*$w, -$w)
		);

	if($solid){
		$map->filledPolygon($arrow,$color);
	}else{
		$map->polygon($arrow,$color);
	}

}


sub version {
        print <<EOM;
Wearthermap4RRD v$VERSION - http://weathermap4rrd.tropicalex.net
EOM
}

sub usage {
        print <<EOM;
Wearthermap4RRD v$VERSION - http://weathermap4rrd.tropicalex.net
based on Network Weathermap v$VERSION 
Usage: $0 [OPTION]...

 -c, --config=FILE  configuration file (default $CONFIG)
 -o, --output=FILE  output image file default (default $OUTPUTFILE)
     --date "dd/mm/yyyy hh:mm" (default "now")
 -v, --version      print version
 -h, --help         print this text
 -d, --debug        enable debug output

EOM
}
