Blame |
Last modification |
View Log
| RSS feed
###############################################################################
#
# libmapdef.pl - Map definition
#
## Copyright (C) 2009 Rainer Walther (rainerwalther-mail@web.de)
#
# Creative Commons Lizenz mit den Zusaetzen (by, nc, sa)
#
# Es ist Ihnen gestattet:
# * das Werk vervielfältigen, verbreiten und öffentlich zugänglich machen
# * Abwandlungen bzw. Bearbeitungen des Inhaltes anfertigen
#
# Zu den folgenden Bedingungen:
# * Namensnennung.
# Sie müssen den Namen des Autors/Rechteinhabers in der von ihm festgelegten Weise nennen.
# * Keine kommerzielle Nutzung.
# Dieses Werk darf nicht für kommerzielle Zwecke verwendet werden.
# * Weitergabe unter gleichen Bedingungen.
# Wenn Sie den lizenzierten Inhalt bearbeiten oder in anderer Weise umgestalten,
# verändern oder als Grundlage für einen anderen Inhalt verwenden,
# dürfen Sie den neu entstandenen Inhalt nur unter Verwendung von Lizenzbedingungen
# weitergeben, die mit denen dieses Lizenzvertrages identisch oder vergleichbar sind.
#
# Im Falle einer Verbreitung müssen Sie anderen die Lizenzbedingungen, unter welche dieses
# Werk fällt, mitteilen. Am Einfachsten ist es, einen Link auf diese Seite einzubinden.
#
# Jede der vorgenannten Bedingungen kann aufgehoben werden, sofern Sie die Einwilligung
# des Rechteinhabers dazu erhalten.
#
# Diese Lizenz lässt die Urheberpersönlichkeitsrechte unberührt.
#
# Weitere Details zur Lizenzbestimmung gibt es hier:
# Kurzform: http://creativecommons.org/licenses/by-nc-sa/3.0/de/
# Komplett: http://creativecommons.org/licenses/by-nc-sa/3.0/de/legalcode
#
###############################################################################
##
# 2009-03-06 0.0.1 rw created
# 2009-04-01 0.1.0 rw RC1
# 2009-04-18 0.1.1 rw Select default map, if configured map does not exist
# 2009-07-22 0.1.2 rw Offset_x and Offset_y for adjustment of map calibration
# 2009-08-15 0.1.3 rw Tracking Antenne Home position added
# Player home position added
# Read map definition from XML file
# 2009-09-29 0.1.4 rw Read map definition from KML file (GE import)
# Allow Config lines in map definition file (like mkcockpit.xml)
# 2009-11-08 0.1.5 rw Avoid div/0, if P1=P2
# 2010-05-16 0.1.6 rw Check empty Border in XML
# 2010-09-09 0.1.7 rw Load JPEG/PNG containig Geo-Information
# rename map/map.pl --> libmapdef.pl
#
###############################################################################
$Version{'libmapdef.pl'} = "0.1.7 - 2010-09-09";
use XML
::Simple; # http://search.cpan.org/dist/XML-Simple-2.18/lib/XML/Simple.pm
use Image
::ExifTool qw(:Public
); # http://search.cpan.org/~exiftool/Image-ExifTool-8.25/lib/Image/ExifTool.pod
# Load maps from filesystem (XML, KML, JPEG/PNG)
sub MapDefLoad
()
{
%Maps =
(
Default
=> {
'Name' => "Default",
'File' => 'default-800.gif',
# 'Size_X' => '800',
# 'Size_Y => '600',
'P1_x' => '71', # calibration P1, P2
'P1_y' => '472',
'P2_x' => '500',
'P2_y' => '103',
'P1_Lat' => '48.856253',
'P1_Lon' => '2.3500000',
'P2_Lat' => '54.090153',
'P2_Lon' => '12.133249',
# 'Offset_x' => 5, # Optional Pixel offset MK to right
# 'Offset_y' => 5, # Optional pixel offset MK to top
# 'Home_Lat' => '54.090153', # Optional home position for player
# 'Home_Lon' => '12.133249', # Optional home position for player
# 'Poi_Lat' => '54.090153', # Optional POI position for player
# 'Poi_Lon' => '12.133249', # Optional POI position for player
# 'Track_Lat' => '49.685333', # Optional Tracking Antenna pos
# 'Track_Lon' => '10.950134', # Optional Tracking Antenna pos
# 'Track_Alt' => '500', # Optional Tracking Antenna altitude
# 'Track_Bearing' => 10, # Optional Tracking antenne direction
# 'Border' => [ 555, 430, # airfield border
# 516, 555,
# 258, 555,
# 100, 300,
# 580, 260,
# 530, 94,
# 627, 130,
# 735, 300,
# 680, 400,
# 757, 470,
# 720, 515,
# 575, 420,
# ],
},
);
#
# load additional Maps from XML files
#
my $MapDir = $Cfg->{'map'}->{'MapDir'} || "map";
if ( -d
$MapDir )
{
opendir DIR
, $MapDir;
my @Files = readdir DIR
;
@Files = grep /\.xml$/, @Files;
closedir DIR
;
foreach $Xml (@Files)
{
my $MapConfigFile = "$MapDir/$Xml";
if ( -f
$MapConfigFile )
{
my $XmlMap = XMLin
($MapConfigFile);
foreach $Location (keys %{$XmlMap})
{
foreach $Key (keys %{$XmlMap->{$Location}} )
{
my $Value = $XmlMap->{$Location}->{$Key};
if ( $Key =~ /Border/i )
{
$Value =~ s/\s//g;
if ( $Value ne "" )
{
my @Border = split ',', $Value;
@{$Maps{$Location}->{$Key}} = @Border;
}
}
else
{
$Maps{$Location}->{$Key} = $Value;
}
}
}
}
}
}
#
# load additional Maps from KML files
#
my $MapDir = $Cfg->{'map'}->{'MapDir'} || "map";
if ( -d
$MapDir )
{
opendir DIR
, $MapDir;
my @Files = readdir DIR
;
@Files = grep /\.kml$/, @Files;
closedir DIR
;
foreach $Kml (@Files)
{
my $MapConfigFile = "$MapDir/$Kml";
if ( -f
$MapConfigFile )
{
my $KmlMap = XMLin
($MapConfigFile);
my $Name = $KmlMap->{'Document'}->{'Folder'}->{'name'};
my $Desc = $KmlMap->{'Document'}->{'Folder'}->{'description'};
$Maps{$Name}->{'Name'} = $Name;
# Airfield Border
my $Border = "";
my $bBorder = 0;
# parse config lines
@DescLines = split '\n', $Desc;
foreach $Line (@DescLines)
{
if ( $bBorder )
{
# collect border lines
if ( $Line =~ /=/i )
{
# New keyword found. End of multi-line border config
$bBorder = 0;
}
else
{
$Border = "$Border" . "$Line";
}
}
if ( $Line =~ /\s*(\S*)\s*=\s*(.*)/i)
{
my $Key = $1;
my $Value = $2;
chomp $Value;
# search for border keyword
if ($Key =~ /border/i )
{
$Border = $Value;
$bBorder = 1;
}
else
{
$Maps{$Name}->{$Key} = $Value;
}
}
}
if ( $Border ne "" )
{
$Border =~ s/\s//g;
my @Border = split ',', $Border;
@{$Maps{$Name}->{'Border'}} = @Border;
}
# P1 calibration point
my $P1 = $KmlMap->{'Document'}->{'Folder'}->{'Placemark'}->{'P1'}->{'Point'}->{'coordinates'};
my $P1Desc = $KmlMap->{'Document'}->{'Folder'}->{'Placemark'}->{'P1'}->{'description'};
($Maps{$Name}->{'P1_Lon'}, $Maps{$Name}->{'P1_Lat'}) = split ',', $P1;
if ( $P1Desc =~ /\s*x\s*=\s*(\d*)/i) { $Maps{$Name}->{'P1_x'} = $1; } # x=nnn
if ( $P1Desc =~ /\s*y\s*=\s*(\d*)/i) { $Maps{$Name}->{'P1_y'} = $1; } # y=nnn
# P2 calibration point
my $P2 = $KmlMap->{'Document'}->{'Folder'}->{'Placemark'}->{'P2'}->{'Point'}->{'coordinates'};
my $P2Desc = $KmlMap->{'Document'}->{'Folder'}->{'Placemark'}->{'P2'}->{'description'};
($Maps{$Name}->{'P2_Lon'}, $Maps{$Name}->{'P2_Lat'}) = split ',', $P2;
if ( $P2Desc =~ /\s*x\s*=\s*(\d*)/i) { $Maps{$Name}->{'P2_x'} = $1; } # x=nnn
if ( $P2Desc =~ /\s*y\s*=\s*(\d*)/i) { $Maps{$Name}->{'P2_y'} = $1; } # y=nnn
# Home position
if ( $KmlMap->{'Document'}->{'Folder'}->{'Placemark'}->{'Home'}->{'visibility'} ne "0" )
{
my $Home = $KmlMap->{'Document'}->{'Folder'}->{'Placemark'}->{'Home'}->{'Point'}->{'coordinates'};
my $HomeDesc = $KmlMap->{'Document'}->{'Folder'}->{'Placemark'}->{'Home'}->{'description'};
($Maps{$Name}->{'Home_Lon'}, $Maps{$Name}->{'Home_Lat'}) = split ',', $Home;
}
# POI position
if ( $KmlMap->{'Document'}->{'Folder'}->{'Placemark'}->{'POI'}->{'visibility'} ne "0" )
{
my $Poi = $KmlMap->{'Document'}->{'Folder'}->{'Placemark'}->{'POI'}->{'Point'}->{'coordinates'};
my $PoiDesc = $KmlMap->{'Document'}->{'Folder'}->{'Placemark'}->{'POI'}->{'description'};
($Maps{$Name}->{'Poi_Lon'}, $Maps{$Name}->{'Poi_Lat'}) = split ',', $Poi;
}
# Antenna tracker position
if ( $KmlMap->{'Document'}->{'Folder'}->{'Placemark'}->{'Antenna'}->{'visibility'} ne "0" )
{
my $Track = $KmlMap->{'Document'}->{'Folder'}->{'Placemark'}->{'Antenna'}->{'Point'}->{'coordinates'};
my $TrackDesc = $KmlMap->{'Document'}->{'Folder'}->{'Placemark'}->{'Antenna'}->{'description'};
($Maps{$Name}->{'Track_Lon'}, $Maps{$Name}->{'Track_Lat'}) = split ',', $Track;
if ( $TrackDesc =~ /\s*Track_Alt\s*=\s*(\d*)/i) { $Maps{$Name}->{'Track_Alt'} = $1; } # Track_Alt=nnn
if ( $TrackDesc =~ /\s*Track_Bearing\s*=\s*(\d*)/i) { $Maps{$Name}->{'Track_Bearing'} = $1; } # Track_Bearing=nnn
}
if ( $Maps{$Name}->{'P1_x'} == $Maps{$Name}->{'P2_x'} and
$Maps{$Name}->{'P1_y'} == $Maps{$Name}->{'P2_y'} )
{
# Avoid div/0 if P1=P2
$Maps{$Name}->{'P1_x'} += 1;
}
}
}
}
#
# load additional Maps from JPEG/PNG containing Geo-Information
#
my $MapDir = $Cfg->{'map'}->{'MapDir'} || "map";
if ( -d
$MapDir )
{
opendir DIR
, $MapDir;
my @Files = readdir DIR
;
closedir DIR
;
my @ImgFiles;
push @ImgFiles, grep /\.jpg$/, @Files;
push @ImgFiles, grep /\.png$/, @Files;
foreach $Image (@ImgFiles)
{
my $ImgFile = "$MapDir/$Image";
if ( -f
$ImgFile )
{
# take only image files which are not already used in %Maps
$bUsed = "";
foreach $Map (keys %Maps)
{
if ( $Maps{$Map}->{'File'} =~ /^${Image}$/i )
{
$bUsed = "X";
last;
}
}
if ( $bUsed ne "X" )
{
# take image
my ($Width, $Height, $ImgInfo) = &GetImageInfo($ImgFile);
my $Comment = $$ImgInfo{'Comment'};
my $Name = substr ($Image, 0, -4); # remove extension
# Image from Kopter-Tool
my @Fields = split ",", $Comment;
if ( $Fields[0] =~ /Geo-Information/i )
{
my ($RoLat, $RoLon) = split ":", $Fields[1];
my ($LoLat, $LoLon) = split ":", $Fields[2];
my ($RuLat, $RuLon) = split ":", $Fields[3];
my ($LuLat, $LuLon) = split ":", $Fields[4];
$Maps{$Name}->{'Name'} = $Name;
$Maps{$Name}->{'File'} = $Image;
$Maps{$Name}->{'P1_x'} = 0;
$Maps{$Name}->{'P1_y'} = 0;
$Maps{$Name}->{'P2_x'} = $Width;
$Maps{$Name}->{'P2_y'} = $Height;
$Maps{$Name}->{'P1_Lat'} = $LoLat;
$Maps{$Name}->{'P1_Lon'} = $LoLon;
$Maps{$Name}->{'P2_Lat'} = $RuLat;
$Maps{$Name}->{'P2_Lon'} = $RuLon;
}
# GeoMapTool Image for Mission Cockpit
my @Fields = split ";", $Comment;
foreach $Param (@Fields)
{
my ($Key, $Value) = split ":", $Param;
if ( $Key eq "P" )
{
my ($P1_x, $P1_y, $P2_x, $P2_y, $P1_Lat, $P1_Lon, $P2_Lat, $P2_Lon) = split ",", $Value;
$Maps{$Name}->{'P1_x'} = $P1_x;
$Maps{$Name}->{'P1_y'} = $P1_y;
$Maps{$Name}->{'P2_x'} = $P2_x;
$Maps{$Name}->{'P2_y'} = $P2_y;
$Maps{$Name}->{'P1_Lat'} = $P1_Lat;
$Maps{$Name}->{'P1_Lon'} = $P1_Lon;
$Maps{$Name}->{'P2_Lat'} = $P2_Lat;
$Maps{$Name}->{'P2_Lon'} = $P2_Lon;
$Maps{$Name}->{'File'} = $Image;
$Maps{$Name}->{'Name'} = $Name;
}
if ( $Key eq "Home" )
{
my ($Home_Lat, $Home_Lon) = split ",", $Value;
$Maps{$Name}->{'Home_Lat'} = $Home_Lat;
$Maps{$Name}->{'Home_Lon'} = $Home_Lon;
}
if ( $Key eq "Poi" )
{
my ($Poi_Lat, $Poi_Lon) = split ",", $Value;
$Maps{$Name}->{'Poi_Lat'} = $Poi_Lat;
$Maps{$Name}->{'Poi_Lon'} = $Poi_Lon;
}
if ( $Key eq "Border" )
{
my @Border = split ',', $Value;
@{$Maps{$Name}->{'Border'}} = @Border;
}
}
}
}
}
}
# Die verwendete Karte
&MapSetCurrentFromCfg();
}
# Set $Maps{'Current'} from Cfg-Setting
sub MapSetCurrentFromCfg
()
{
# Todo: Karte automatisch anhand der aktuellen GPS Position auswählen
my $MapDefault = $Cfg->{'map'}->{'MapDefault'};
if ( defined $Maps{$MapDefault} )
{
$Maps{'Current'} = $Maps{$MapDefault};
}
else
{
$Maps{'Current'} = $Maps{'Default'};
print "Map \"$MapDefault\" not found in map.pl. Using \"Default\" map\n";
}
# optional map specific Cfg setup from map definition
# Aktuell gültige Karte
my %Map = %{$Maps{'Current'}};
foreach $Key (keys %Map)
{
# Cfg:Section:Keyword
if ( $Key =~ /^Cfg:(\S*):(\S*)/i )
{
$Section = $1;
$Keyword = $2;
$Cfg->{$Section}->{$Keyword} = $Map{$Key};
}
}
# Get size of image
my $ImgFile = "$Cfg->{'map'}->{'MapDir'}/$Map{'File'}";
my ($Width, $Height) = &GetImageInfo($ImgFile);
if ( $Maps{'Current'}->{'Size_X'} eq "" )
{
$Maps{'Current'}->{'Size_X'} = $Width;
}
if ( $Maps{'Current'}->{'Size_Y'} eq "" )
{
$Maps{'Current'}->{'Size_Y'} = $Height;
}
# Option list from map config dialog
@{ $CfgOpt{MapDefault
} } = sort keys %Maps
}
# Get size and EXIF data of Image
sub GetImageInfo
()
{
my ($File) = @_;
my $ExifTool = new Image
::ExifTool;
my $ImgInfo = $ExifTool->ImageInfo($File);
my $Width;
my $Height;
my $ImageSize = $$ImgInfo{'ImageSize'};
($Width, $Height) = split "x", $ImageSize;
if ( $Width eq "" )
{
$Width = $$ImgInfo{'ImageWidth'};
}
if ( $Height eq "" )
{
$Height = $$ImgInfo{'ImageHeight'};
}
if ( $Width eq "" )
{
$Width = $$ImgInfo{'ExifImageWidth'};
}
if ( $Height eq "" )
{
$Height = $$ImgInfo{'ExifImageHeight'};
}
return ($Width, $Height, $ImgInfo);
}
1;
__END__