Details | Last modification | View Log | RSS feed
Rev | Author | Line No. | Line |
---|---|---|---|
810 | - | 1 | ############################################################################### |
2 | # |
||
3 | # libmapdef.pl - Map definition |
||
4 | # |
||
5 | ## Copyright (C) 2009 Rainer Walther (rainerwalther-mail@web.de) |
||
6 | # |
||
7 | # Creative Commons Lizenz mit den Zusaetzen (by, nc, sa) |
||
8 | # |
||
9 | # Es ist Ihnen gestattet: |
||
10 | # * das Werk vervielfältigen, verbreiten und öffentlich zugänglich machen |
||
11 | # * Abwandlungen bzw. Bearbeitungen des Inhaltes anfertigen |
||
12 | # |
||
13 | # Zu den folgenden Bedingungen: |
||
14 | # * Namensnennung. |
||
15 | # Sie müssen den Namen des Autors/Rechteinhabers in der von ihm festgelegten Weise nennen. |
||
16 | # * Keine kommerzielle Nutzung. |
||
17 | # Dieses Werk darf nicht für kommerzielle Zwecke verwendet werden. |
||
18 | # * Weitergabe unter gleichen Bedingungen. |
||
19 | # Wenn Sie den lizenzierten Inhalt bearbeiten oder in anderer Weise umgestalten, |
||
20 | # verändern oder als Grundlage für einen anderen Inhalt verwenden, |
||
21 | # dürfen Sie den neu entstandenen Inhalt nur unter Verwendung von Lizenzbedingungen |
||
22 | # weitergeben, die mit denen dieses Lizenzvertrages identisch oder vergleichbar sind. |
||
23 | # |
||
24 | # Im Falle einer Verbreitung müssen Sie anderen die Lizenzbedingungen, unter welche dieses |
||
25 | # Werk fällt, mitteilen. Am Einfachsten ist es, einen Link auf diese Seite einzubinden. |
||
26 | # |
||
27 | # Jede der vorgenannten Bedingungen kann aufgehoben werden, sofern Sie die Einwilligung |
||
28 | # des Rechteinhabers dazu erhalten. |
||
29 | # |
||
30 | # Diese Lizenz lässt die Urheberpersönlichkeitsrechte unberührt. |
||
31 | # |
||
32 | # Weitere Details zur Lizenzbestimmung gibt es hier: |
||
33 | # Kurzform: http://creativecommons.org/licenses/by-nc-sa/3.0/de/ |
||
34 | # Komplett: http://creativecommons.org/licenses/by-nc-sa/3.0/de/legalcode |
||
35 | # |
||
36 | ############################################################################### |
||
37 | ## |
||
38 | # 2009-03-06 0.0.1 rw created |
||
39 | # 2009-04-01 0.1.0 rw RC1 |
||
40 | # 2009-04-18 0.1.1 rw Select default map, if configured map does not exist |
||
41 | # 2009-07-22 0.1.2 rw Offset_x and Offset_y for adjustment of map calibration |
||
42 | # 2009-08-15 0.1.3 rw Tracking Antenne Home position added |
||
43 | # Player home position added |
||
44 | # Read map definition from XML file |
||
45 | # 2009-09-29 0.1.4 rw Read map definition from KML file (GE import) |
||
46 | # Allow Config lines in map definition file (like mkcockpit.xml) |
||
47 | # 2009-11-08 0.1.5 rw Avoid div/0, if P1=P2 |
||
48 | # 2010-05-16 0.1.6 rw Check empty Border in XML |
||
49 | # 2010-09-09 0.1.7 rw Load JPEG/PNG containig Geo-Information |
||
50 | # rename map/map.pl --> libmapdef.pl |
||
51 | # |
||
52 | ############################################################################### |
||
53 | |||
54 | $Version{'libmapdef.pl'} = "0.1.7 - 2010-09-09"; |
||
55 | |||
56 | use XML::Simple; # http://search.cpan.org/dist/XML-Simple-2.18/lib/XML/Simple.pm |
||
57 | use Image::ExifTool qw(:Public); # http://search.cpan.org/~exiftool/Image-ExifTool-8.25/lib/Image/ExifTool.pod |
||
58 | |||
59 | |||
60 | # Load maps from filesystem (XML, KML, JPEG/PNG) |
||
61 | sub MapDefLoad() |
||
62 | { |
||
63 | |||
64 | %Maps = |
||
65 | ( |
||
66 | Default => { |
||
67 | 'Name' => "Default", |
||
68 | 'File' => 'default-800.gif', |
||
69 | # 'Size_X' => '800', |
||
70 | # 'Size_Y => '600', |
||
71 | |||
72 | 'P1_x' => '71', # calibration P1, P2 |
||
73 | 'P1_y' => '472', |
||
74 | 'P2_x' => '500', |
||
75 | 'P2_y' => '103', |
||
76 | 'P1_Lat' => '48.856253', |
||
77 | 'P1_Lon' => '2.3500000', |
||
78 | 'P2_Lat' => '54.090153', |
||
79 | 'P2_Lon' => '12.133249', |
||
80 | |||
81 | # 'Offset_x' => 5, # Optional Pixel offset MK to right |
||
82 | # 'Offset_y' => 5, # Optional pixel offset MK to top |
||
83 | |||
84 | # 'Home_Lat' => '54.090153', # Optional home position for player |
||
85 | # 'Home_Lon' => '12.133249', # Optional home position for player |
||
86 | |||
87 | # 'Poi_Lat' => '54.090153', # Optional POI position for player |
||
88 | # 'Poi_Lon' => '12.133249', # Optional POI position for player |
||
89 | |||
90 | # 'Track_Lat' => '49.685333', # Optional Tracking Antenna pos |
||
91 | # 'Track_Lon' => '10.950134', # Optional Tracking Antenna pos |
||
92 | # 'Track_Alt' => '500', # Optional Tracking Antenna altitude |
||
93 | # 'Track_Bearing' => 10, # Optional Tracking antenne direction |
||
94 | |||
95 | # 'Border' => [ 555, 430, # airfield border |
||
96 | # 516, 555, |
||
97 | # 258, 555, |
||
98 | # 100, 300, |
||
99 | # 580, 260, |
||
100 | # 530, 94, |
||
101 | # 627, 130, |
||
102 | # 735, 300, |
||
103 | # 680, 400, |
||
104 | # 757, 470, |
||
105 | # 720, 515, |
||
106 | # 575, 420, |
||
107 | # ], |
||
108 | }, |
||
109 | ); |
||
110 | |||
111 | |||
112 | # |
||
113 | # load additional Maps from XML files |
||
114 | # |
||
115 | my $MapDir = $Cfg->{'map'}->{'MapDir'} || "map"; |
||
116 | if ( -d $MapDir ) |
||
117 | { |
||
118 | opendir DIR, $MapDir; |
||
119 | my @Files = readdir DIR; |
||
120 | @Files = grep /\.xml$/, @Files; |
||
121 | closedir DIR; |
||
122 | |||
123 | foreach $Xml (@Files) |
||
124 | { |
||
125 | my $MapConfigFile = "$MapDir/$Xml"; |
||
126 | if ( -f $MapConfigFile ) |
||
127 | { |
||
128 | my $XmlMap = XMLin($MapConfigFile); |
||
129 | |||
130 | foreach $Location (keys %{$XmlMap}) |
||
131 | { |
||
132 | foreach $Key (keys %{$XmlMap->{$Location}} ) |
||
133 | { |
||
134 | my $Value = $XmlMap->{$Location}->{$Key}; |
||
135 | if ( $Key =~ /Border/i ) |
||
136 | { |
||
137 | $Value =~ s/\s//g; |
||
138 | if ( $Value ne "" ) |
||
139 | { |
||
140 | my @Border = split ',', $Value; |
||
141 | @{$Maps{$Location}->{$Key}} = @Border; |
||
142 | } |
||
143 | } |
||
144 | else |
||
145 | { |
||
146 | $Maps{$Location}->{$Key} = $Value; |
||
147 | } |
||
148 | } |
||
149 | } |
||
150 | } |
||
151 | } |
||
152 | } |
||
153 | |||
154 | |||
155 | # |
||
156 | # load additional Maps from KML files |
||
157 | # |
||
158 | my $MapDir = $Cfg->{'map'}->{'MapDir'} || "map"; |
||
159 | if ( -d $MapDir ) |
||
160 | { |
||
161 | opendir DIR, $MapDir; |
||
162 | my @Files = readdir DIR; |
||
163 | @Files = grep /\.kml$/, @Files; |
||
164 | closedir DIR; |
||
165 | |||
166 | foreach $Kml (@Files) |
||
167 | { |
||
168 | my $MapConfigFile = "$MapDir/$Kml"; |
||
169 | if ( -f $MapConfigFile ) |
||
170 | { |
||
171 | my $KmlMap = XMLin($MapConfigFile); |
||
172 | |||
173 | my $Name = $KmlMap->{'Document'}->{'Folder'}->{'name'}; |
||
174 | my $Desc = $KmlMap->{'Document'}->{'Folder'}->{'description'}; |
||
175 | |||
176 | $Maps{$Name}->{'Name'} = $Name; |
||
177 | |||
178 | # Airfield Border |
||
179 | my $Border = ""; |
||
180 | my $bBorder = 0; |
||
181 | |||
182 | # parse config lines |
||
183 | @DescLines = split '\n', $Desc; |
||
184 | foreach $Line (@DescLines) |
||
185 | { |
||
186 | if ( $bBorder ) |
||
187 | { |
||
188 | # collect border lines |
||
189 | if ( $Line =~ /=/i ) |
||
190 | { |
||
191 | # New keyword found. End of multi-line border config |
||
192 | $bBorder = 0; |
||
193 | } |
||
194 | else |
||
195 | { |
||
196 | $Border = "$Border" . "$Line"; |
||
197 | } |
||
198 | } |
||
199 | |||
200 | if ( $Line =~ /\s*(\S*)\s*=\s*(.*)/i) |
||
201 | { |
||
202 | my $Key = $1; |
||
203 | my $Value = $2; |
||
204 | chomp $Value; |
||
205 | |||
206 | # search for border keyword |
||
207 | if ($Key =~ /border/i ) |
||
208 | { |
||
209 | $Border = $Value; |
||
210 | $bBorder = 1; |
||
211 | } |
||
212 | else |
||
213 | { |
||
214 | $Maps{$Name}->{$Key} = $Value; |
||
215 | } |
||
216 | } |
||
217 | } |
||
218 | |||
219 | if ( $Border ne "" ) |
||
220 | { |
||
221 | $Border =~ s/\s//g; |
||
222 | my @Border = split ',', $Border; |
||
223 | @{$Maps{$Name}->{'Border'}} = @Border; |
||
224 | } |
||
225 | |||
226 | # P1 calibration point |
||
227 | my $P1 = $KmlMap->{'Document'}->{'Folder'}->{'Placemark'}->{'P1'}->{'Point'}->{'coordinates'}; |
||
228 | my $P1Desc = $KmlMap->{'Document'}->{'Folder'}->{'Placemark'}->{'P1'}->{'description'}; |
||
229 | ($Maps{$Name}->{'P1_Lon'}, $Maps{$Name}->{'P1_Lat'}) = split ',', $P1; |
||
230 | if ( $P1Desc =~ /\s*x\s*=\s*(\d*)/i) { $Maps{$Name}->{'P1_x'} = $1; } # x=nnn |
||
231 | if ( $P1Desc =~ /\s*y\s*=\s*(\d*)/i) { $Maps{$Name}->{'P1_y'} = $1; } # y=nnn |
||
232 | |||
233 | # P2 calibration point |
||
234 | my $P2 = $KmlMap->{'Document'}->{'Folder'}->{'Placemark'}->{'P2'}->{'Point'}->{'coordinates'}; |
||
235 | my $P2Desc = $KmlMap->{'Document'}->{'Folder'}->{'Placemark'}->{'P2'}->{'description'}; |
||
236 | ($Maps{$Name}->{'P2_Lon'}, $Maps{$Name}->{'P2_Lat'}) = split ',', $P2; |
||
237 | if ( $P2Desc =~ /\s*x\s*=\s*(\d*)/i) { $Maps{$Name}->{'P2_x'} = $1; } # x=nnn |
||
238 | if ( $P2Desc =~ /\s*y\s*=\s*(\d*)/i) { $Maps{$Name}->{'P2_y'} = $1; } # y=nnn |
||
239 | |||
240 | # Home position |
||
241 | if ( $KmlMap->{'Document'}->{'Folder'}->{'Placemark'}->{'Home'}->{'visibility'} ne "0" ) |
||
242 | { |
||
243 | my $Home = $KmlMap->{'Document'}->{'Folder'}->{'Placemark'}->{'Home'}->{'Point'}->{'coordinates'}; |
||
244 | my $HomeDesc = $KmlMap->{'Document'}->{'Folder'}->{'Placemark'}->{'Home'}->{'description'}; |
||
245 | ($Maps{$Name}->{'Home_Lon'}, $Maps{$Name}->{'Home_Lat'}) = split ',', $Home; |
||
246 | } |
||
247 | |||
248 | # POI position |
||
249 | if ( $KmlMap->{'Document'}->{'Folder'}->{'Placemark'}->{'POI'}->{'visibility'} ne "0" ) |
||
250 | { |
||
251 | my $Poi = $KmlMap->{'Document'}->{'Folder'}->{'Placemark'}->{'POI'}->{'Point'}->{'coordinates'}; |
||
252 | my $PoiDesc = $KmlMap->{'Document'}->{'Folder'}->{'Placemark'}->{'POI'}->{'description'}; |
||
253 | ($Maps{$Name}->{'Poi_Lon'}, $Maps{$Name}->{'Poi_Lat'}) = split ',', $Poi; |
||
254 | } |
||
255 | |||
256 | # Antenna tracker position |
||
257 | if ( $KmlMap->{'Document'}->{'Folder'}->{'Placemark'}->{'Antenna'}->{'visibility'} ne "0" ) |
||
258 | { |
||
259 | my $Track = $KmlMap->{'Document'}->{'Folder'}->{'Placemark'}->{'Antenna'}->{'Point'}->{'coordinates'}; |
||
260 | my $TrackDesc = $KmlMap->{'Document'}->{'Folder'}->{'Placemark'}->{'Antenna'}->{'description'}; |
||
261 | ($Maps{$Name}->{'Track_Lon'}, $Maps{$Name}->{'Track_Lat'}) = split ',', $Track; |
||
262 | if ( $TrackDesc =~ /\s*Track_Alt\s*=\s*(\d*)/i) { $Maps{$Name}->{'Track_Alt'} = $1; } # Track_Alt=nnn |
||
263 | if ( $TrackDesc =~ /\s*Track_Bearing\s*=\s*(\d*)/i) { $Maps{$Name}->{'Track_Bearing'} = $1; } # Track_Bearing=nnn |
||
264 | } |
||
265 | |||
266 | if ( $Maps{$Name}->{'P1_x'} == $Maps{$Name}->{'P2_x'} and |
||
267 | $Maps{$Name}->{'P1_y'} == $Maps{$Name}->{'P2_y'} ) |
||
268 | { |
||
269 | # Avoid div/0 if P1=P2 |
||
270 | $Maps{$Name}->{'P1_x'} += 1; |
||
271 | } |
||
272 | } |
||
273 | } |
||
274 | } |
||
275 | |||
276 | # |
||
277 | # load additional Maps from JPEG/PNG containing Geo-Information |
||
278 | # |
||
279 | my $MapDir = $Cfg->{'map'}->{'MapDir'} || "map"; |
||
280 | if ( -d $MapDir ) |
||
281 | { |
||
282 | opendir DIR, $MapDir; |
||
283 | my @Files = readdir DIR; |
||
284 | closedir DIR; |
||
285 | |||
286 | my @ImgFiles; |
||
287 | push @ImgFiles, grep /\.jpg$/, @Files; |
||
288 | push @ImgFiles, grep /\.png$/, @Files; |
||
289 | |||
290 | foreach $Image (@ImgFiles) |
||
291 | { |
||
292 | my $ImgFile = "$MapDir/$Image"; |
||
293 | if ( -f $ImgFile ) |
||
294 | { |
||
295 | # take only image files which are not already used in %Maps |
||
296 | $bUsed = ""; |
||
297 | foreach $Map (keys %Maps) |
||
298 | { |
||
299 | if ( $Maps{$Map}->{'File'} =~ /^${Image}$/i ) |
||
300 | { |
||
301 | $bUsed = "X"; |
||
302 | last; |
||
303 | } |
||
304 | } |
||
305 | |||
306 | if ( $bUsed ne "X" ) |
||
307 | { |
||
308 | # take image |
||
309 | my ($Width, $Height, $ImgInfo) = &GetImageInfo($ImgFile); |
||
310 | my $Comment = $$ImgInfo{'Comment'}; |
||
311 | my $Name = substr ($Image, 0, -4); # remove extension |
||
312 | |||
313 | # Image from Kopter-Tool |
||
314 | my @Fields = split ",", $Comment; |
||
315 | if ( $Fields[0] =~ /Geo-Information/i ) |
||
316 | { |
||
317 | my ($RoLat, $RoLon) = split ":", $Fields[1]; |
||
318 | my ($LoLat, $LoLon) = split ":", $Fields[2]; |
||
319 | my ($RuLat, $RuLon) = split ":", $Fields[3]; |
||
320 | my ($LuLat, $LuLon) = split ":", $Fields[4]; |
||
321 | |||
322 | $Maps{$Name}->{'Name'} = $Name; |
||
323 | $Maps{$Name}->{'File'} = $Image; |
||
324 | $Maps{$Name}->{'P1_x'} = 0; |
||
325 | $Maps{$Name}->{'P1_y'} = 0; |
||
326 | $Maps{$Name}->{'P2_x'} = $Width; |
||
327 | $Maps{$Name}->{'P2_y'} = $Height; |
||
328 | $Maps{$Name}->{'P1_Lat'} = $LoLat; |
||
329 | $Maps{$Name}->{'P1_Lon'} = $LoLon; |
||
330 | $Maps{$Name}->{'P2_Lat'} = $RuLat; |
||
331 | $Maps{$Name}->{'P2_Lon'} = $RuLon; |
||
332 | } |
||
333 | |||
334 | # GeoMapTool Image for Mission Cockpit |
||
335 | my @Fields = split ";", $Comment; |
||
336 | foreach $Param (@Fields) |
||
337 | { |
||
338 | my ($Key, $Value) = split ":", $Param; |
||
339 | if ( $Key eq "P" ) |
||
340 | { |
||
341 | my ($P1_x, $P1_y, $P2_x, $P2_y, $P1_Lat, $P1_Lon, $P2_Lat, $P2_Lon) = split ",", $Value; |
||
342 | $Maps{$Name}->{'P1_x'} = $P1_x; |
||
343 | $Maps{$Name}->{'P1_y'} = $P1_y; |
||
344 | $Maps{$Name}->{'P2_x'} = $P2_x; |
||
345 | $Maps{$Name}->{'P2_y'} = $P2_y; |
||
346 | $Maps{$Name}->{'P1_Lat'} = $P1_Lat; |
||
347 | $Maps{$Name}->{'P1_Lon'} = $P1_Lon; |
||
348 | $Maps{$Name}->{'P2_Lat'} = $P2_Lat; |
||
349 | $Maps{$Name}->{'P2_Lon'} = $P2_Lon; |
||
350 | |||
351 | $Maps{$Name}->{'File'} = $Image; |
||
352 | $Maps{$Name}->{'Name'} = $Name; |
||
353 | } |
||
354 | if ( $Key eq "Home" ) |
||
355 | { |
||
356 | my ($Home_Lat, $Home_Lon) = split ",", $Value; |
||
357 | $Maps{$Name}->{'Home_Lat'} = $Home_Lat; |
||
358 | $Maps{$Name}->{'Home_Lon'} = $Home_Lon; |
||
359 | } |
||
360 | if ( $Key eq "Poi" ) |
||
361 | { |
||
362 | my ($Poi_Lat, $Poi_Lon) = split ",", $Value; |
||
363 | $Maps{$Name}->{'Poi_Lat'} = $Poi_Lat; |
||
364 | $Maps{$Name}->{'Poi_Lon'} = $Poi_Lon; |
||
365 | } |
||
366 | if ( $Key eq "Border" ) |
||
367 | { |
||
368 | my @Border = split ',', $Value; |
||
369 | @{$Maps{$Name}->{'Border'}} = @Border; |
||
370 | } |
||
371 | } |
||
372 | } |
||
373 | } |
||
374 | } |
||
375 | } |
||
376 | |||
377 | # Die verwendete Karte |
||
378 | &MapSetCurrentFromCfg(); |
||
379 | } |
||
380 | |||
381 | |||
382 | # Set $Maps{'Current'} from Cfg-Setting |
||
383 | sub MapSetCurrentFromCfg() |
||
384 | { |
||
385 | |||
386 | # Todo: Karte automatisch anhand der aktuellen GPS Position auswählen |
||
387 | |||
388 | my $MapDefault = $Cfg->{'map'}->{'MapDefault'}; |
||
389 | if ( defined $Maps{$MapDefault} ) |
||
390 | { |
||
391 | $Maps{'Current'} = $Maps{$MapDefault}; |
||
392 | } |
||
393 | else |
||
394 | { |
||
395 | $Maps{'Current'} = $Maps{'Default'}; |
||
396 | print "Map \"$MapDefault\" not found in map.pl. Using \"Default\" map\n"; |
||
397 | } |
||
398 | |||
399 | # optional map specific Cfg setup from map definition |
||
400 | # Aktuell gültige Karte |
||
401 | my %Map = %{$Maps{'Current'}}; |
||
402 | |||
403 | foreach $Key (keys %Map) |
||
404 | { |
||
405 | # Cfg:Section:Keyword |
||
406 | if ( $Key =~ /^Cfg:(\S*):(\S*)/i ) |
||
407 | { |
||
408 | $Section = $1; |
||
409 | $Keyword = $2; |
||
410 | $Cfg->{$Section}->{$Keyword} = $Map{$Key}; |
||
411 | } |
||
412 | } |
||
413 | |||
414 | # Get size of image |
||
415 | my $ImgFile = "$Cfg->{'map'}->{'MapDir'}/$Map{'File'}"; |
||
416 | my ($Width, $Height) = &GetImageInfo($ImgFile); |
||
417 | if ( $Maps{'Current'}->{'Size_X'} eq "" ) |
||
418 | { |
||
419 | $Maps{'Current'}->{'Size_X'} = $Width; |
||
420 | } |
||
421 | if ( $Maps{'Current'}->{'Size_Y'} eq "" ) |
||
422 | { |
||
423 | $Maps{'Current'}->{'Size_Y'} = $Height; |
||
424 | } |
||
425 | |||
426 | # Option list from map config dialog |
||
427 | @{ $CfgOpt{MapDefault} } = sort keys %Maps |
||
428 | } |
||
429 | |||
430 | |||
431 | # Get size and EXIF data of Image |
||
432 | sub GetImageInfo() |
||
433 | { |
||
434 | my ($File) = @_; |
||
435 | |||
436 | my $ExifTool = new Image::ExifTool; |
||
437 | my $ImgInfo = $ExifTool->ImageInfo($File); |
||
438 | |||
439 | my $Width; |
||
440 | my $Height; |
||
441 | |||
442 | my $ImageSize = $$ImgInfo{'ImageSize'}; |
||
443 | ($Width, $Height) = split "x", $ImageSize; |
||
444 | |||
445 | if ( $Width eq "" ) |
||
446 | { |
||
447 | $Width = $$ImgInfo{'ImageWidth'}; |
||
448 | } |
||
449 | if ( $Height eq "" ) |
||
450 | { |
||
451 | $Height = $$ImgInfo{'ImageHeight'}; |
||
452 | } |
||
453 | |||
454 | if ( $Width eq "" ) |
||
455 | { |
||
456 | $Width = $$ImgInfo{'ExifImageWidth'}; |
||
457 | } |
||
458 | if ( $Height eq "" ) |
||
459 | { |
||
460 | $Height = $$ImgInfo{'ExifImageHeight'}; |
||
461 | } |
||
462 | |||
463 | return ($Width, $Height, $ImgInfo); |
||
464 | } |
||
465 | |||
466 | |||
467 | 1; |
||
468 | |||
469 | __END__ |