<?xml version="1.0"?>
<?xml-stylesheet type="text/css" href="http://geoqo.org/wiki/skins/common/feed.css?301"?>
<feed xmlns="http://www.w3.org/2005/Atom" xml:lang="en">
		<id>http://geoqo.org/wiki/index.php?title=Breakdown_of_the_KML_Plugin&amp;feed=atom&amp;action=history</id>
		<title>Breakdown of the KML Plugin - Revision history</title>
		<link rel="self" type="application/atom+xml" href="http://geoqo.org/wiki/index.php?title=Breakdown_of_the_KML_Plugin&amp;feed=atom&amp;action=history"/>
		<link rel="alternate" type="text/html" href="http://geoqo.org/wiki/index.php?title=Breakdown_of_the_KML_Plugin&amp;action=history"/>
		<updated>2013-05-24T13:08:04Z</updated>
		<subtitle>Revision history for this page on the wiki</subtitle>
		<generator>MediaWiki 1.17.0</generator>

	<entry>
		<id>http://geoqo.org/wiki/index.php?title=Breakdown_of_the_KML_Plugin&amp;diff=1767&amp;oldid=prev</id>
		<title>Yamar at 06:50, 9 December 2007</title>
		<link rel="alternate" type="text/html" href="http://geoqo.org/wiki/index.php?title=Breakdown_of_the_KML_Plugin&amp;diff=1767&amp;oldid=prev"/>
				<updated>2007-12-09T06:50:14Z</updated>
		
		<summary type="html">&lt;p&gt;&lt;/p&gt;
&lt;a href=&quot;http://geoqo.org/wiki/index.php?title=Breakdown_of_the_KML_Plugin&amp;amp;diff=1767&amp;amp;oldid=1766&quot;&gt;Show changes&lt;/a&gt;</summary>
		<author><name>Yamar</name></author>	</entry>

	<entry>
		<id>http://geoqo.org/wiki/index.php?title=Breakdown_of_the_KML_Plugin&amp;diff=1766&amp;oldid=prev</id>
		<title>Yamar at 05:54, 9 December 2007</title>
		<link rel="alternate" type="text/html" href="http://geoqo.org/wiki/index.php?title=Breakdown_of_the_KML_Plugin&amp;diff=1766&amp;oldid=prev"/>
				<updated>2007-12-09T05:54:18Z</updated>
		
		<summary type="html">&lt;p&gt;&lt;/p&gt;
&lt;p&gt;&lt;b&gt;New page&lt;/b&gt;&lt;/p&gt;&lt;div&gt;== KML Code overview ==&lt;br /&gt;
&lt;br /&gt;
The KML export code is shown in full below (at least a snapshot of it&lt;br /&gt;
at one point in time, namely near December 2007).&lt;br /&gt;
&lt;br /&gt;
This is written up below in sections in hope that people may learn&lt;br /&gt;
from it (note that the KML plugin does more complex things than most plugins).&lt;br /&gt;
&lt;br /&gt;
== Header Section ==&lt;br /&gt;
&lt;br /&gt;
This section of code simply imports a bunch of other needed modules,&lt;br /&gt;
declares the version, etc.&lt;br /&gt;
&lt;br /&gt;
  # Copyright (C) 2007 Wes Hardaker&lt;br /&gt;
  # License: GNU GPLv2.  See the COPYING file for details.&lt;br /&gt;
  package GeoDB::Export::Kml;&lt;br /&gt;
  &lt;br /&gt;
  use strict;&lt;br /&gt;
  use GeoDB::Export;&lt;br /&gt;
  use GeoDB::Utils;&lt;br /&gt;
  use GeoDB::Export::Density;&lt;br /&gt;
  use IO::File;&lt;br /&gt;
  use QWizard;&lt;br /&gt;
&lt;br /&gt;
  our $VERSION = &amp;quot;0.95&amp;quot;;&lt;br /&gt;
&lt;br /&gt;
Here we specify that we're a child class of two other modules, the&lt;br /&gt;
''GeoDB::Export'' and ''GeoDB::Export::Density'' modules.  Since we're&lt;br /&gt;
an export plugin, we must inherit from the first.  The second is a&lt;br /&gt;
second code file that contains the actual KML density calculating bits&lt;br /&gt;
(and eventually it should be a generic density system that could be&lt;br /&gt;
used to output things other than KML, but right now it isn't).&lt;br /&gt;
&lt;br /&gt;
In perl, the @ISA variable is what defines your parent classes:&lt;br /&gt;
&lt;br /&gt;
  our @ISA = qw(GeoDB::Export GeoDB::Export::Density);&lt;br /&gt;
&lt;br /&gt;
=== KML Option Definitions ===&lt;br /&gt;
&lt;br /&gt;
The following is an array of keyword/human-string pairs we use just a&lt;br /&gt;
bit later.&lt;br /&gt;
&lt;br /&gt;
  our @altitudeValues =&lt;br /&gt;
    (relativeToGround =&amp;gt; 'relative to the ground',&lt;br /&gt;
     absolute =&amp;gt; 'absolute height above sea level');&lt;br /&gt;
&lt;br /&gt;
The GEOOPTIONS array is a geoqo special variable that is looked for by&lt;br /&gt;
code much higher up.  This is where we declare all the options to the&lt;br /&gt;
given plugin.  The KML plugin has more than it's fair share of options&lt;br /&gt;
(more than any other) so this section is pretty long.  The array&lt;br /&gt;
contains a list of perl hashes, where each hash contains keyword/value&lt;br /&gt;
pairs describing information about the option.&lt;br /&gt;
&lt;br /&gt;
These options are used by many other parts of the geoqo code.  They&lt;br /&gt;
automatically turn into the [[GUI]] help screen, they automatically&lt;br /&gt;
get used by the ''-d help:export/kml'' help output, the defaults are&lt;br /&gt;
all set by things above, the command line parsing (eg: ''-e&lt;br /&gt;
kml:dataname=blah:file.kml'') is all handled elsewhere based on the&lt;br /&gt;
data in this array.  All good geoqo plugins should use this special&lt;br /&gt;
array name to declare their options to take advantage of these&lt;br /&gt;
features.  (even the [http://www.geoqo.org/usage.html geoqo manual&lt;br /&gt;
page] takes information from this!)&lt;br /&gt;
&lt;br /&gt;
  our @GEOOPTIONS =&lt;br /&gt;
    (&lt;br /&gt;
&lt;br /&gt;
The first option is a label that is printed to user:&lt;br /&gt;
&lt;br /&gt;
     { name =&amp;gt; 'bogus',&lt;br /&gt;
       type =&amp;gt; 'label',&lt;br /&gt;
       text =&amp;gt; 'Basic Settings:',&lt;br /&gt;
     },&lt;br /&gt;
&lt;br /&gt;
This second one is a normal text box in the GUI that just needs a name&lt;br /&gt;
(and it's indented slightly.  It's default value, if the user doesn't&lt;br /&gt;
pick one, is ''Export from GeoQO'':&lt;br /&gt;
&lt;br /&gt;
     { name =&amp;gt; 'dataname',&lt;br /&gt;
       text =&amp;gt; 'Name to call the results:',&lt;br /&gt;
       default =&amp;gt; 'Export from GeoQO',&lt;br /&gt;
       indent =&amp;gt; 1,&lt;br /&gt;
     },&lt;br /&gt;
&lt;br /&gt;
These three are ''checkbox'' options and the resulting value stored in&lt;br /&gt;
the ''dowaypoints'', etc... option variables and will be a 1 or a 0&lt;br /&gt;
based on ifit's checked or not.  The ''refresh_on_change'' token is&lt;br /&gt;
needed to make the gui screen redraw after the user changes the value&lt;br /&gt;
(we'll see why in a second).&lt;br /&gt;
&lt;br /&gt;
     { name =&amp;gt; 'dowaypoints',&lt;br /&gt;
       text =&amp;gt; 'Include waypoint/geocache markers:',&lt;br /&gt;
       type =&amp;gt; 'checkbox',&lt;br /&gt;
       refresh_on_change =&amp;gt; 1,&lt;br /&gt;
       default =&amp;gt; 1,&lt;br /&gt;
     },&lt;br /&gt;
     { name =&amp;gt; 'dodensity',&lt;br /&gt;
       text =&amp;gt; 'Create a density map:',&lt;br /&gt;
       type =&amp;gt; 'checkbox',&lt;br /&gt;
       refresh_on_change =&amp;gt; 1,&lt;br /&gt;
       default =&amp;gt; 1,&lt;br /&gt;
     },&lt;br /&gt;
     { name =&amp;gt; 'dojail',&lt;br /&gt;
       text =&amp;gt; 'Show .1 mile radius circles',&lt;br /&gt;
       type =&amp;gt; 'checkbox',&lt;br /&gt;
       refresh_on_change =&amp;gt; 1,&lt;br /&gt;
       default =&amp;gt; 0,&lt;br /&gt;
     },&lt;br /&gt;
&lt;br /&gt;
This just puts a blank line for a separator:&lt;br /&gt;
&lt;br /&gt;
     &amp;quot;&amp;quot;,&lt;br /&gt;
&lt;br /&gt;
And we start a new section with a new label.  Here note that the&lt;br /&gt;
''doif'' section tests the results of the ''dowaypoints'' variable&lt;br /&gt;
above.  If it's set, then this widget is shown.  If not, then it's&lt;br /&gt;
hidden (and the ''refresh_on_change'' mentioned above forces this to&lt;br /&gt;
hide and unhide when the user clicks on the checkbox or not).  All of&lt;br /&gt;
the following options make use of this feature.&lt;br /&gt;
&lt;br /&gt;
We'll show a bunch of options in a row now, and you can see the&lt;br /&gt;
general point by simply studying them for a bit.  Note that the second&lt;br /&gt;
option is also a menu when shown in the GUI:&lt;br /&gt;
&lt;br /&gt;
These all relate to saving each waypoint in the output file.&lt;br /&gt;
&lt;br /&gt;
     { name =&amp;gt; 'bogus',&lt;br /&gt;
       type =&amp;gt; 'label',&lt;br /&gt;
       text =&amp;gt; 'Configuration of the Waypoints:',&lt;br /&gt;
       doif =&amp;gt; sub {qwparam('dowaypoints') eq '1'},&lt;br /&gt;
     },&lt;br /&gt;
     { name =&amp;gt; 'waypointstyle',&lt;br /&gt;
       type =&amp;gt; 'menu',&lt;br /&gt;
       text =&amp;gt; 'Waypoint Style',&lt;br /&gt;
       labels =&amp;gt; ['geoqo' =&amp;gt; 'Unique icons per difficulty and waypoint type',&lt;br /&gt;
  		'pushpin' =&amp;gt; 'A single pushpin at each waypoint',&lt;br /&gt;
  		],&lt;br /&gt;
       default =&amp;gt; 'geoqo',&lt;br /&gt;
       indent =&amp;gt; 1,&lt;br /&gt;
       doif =&amp;gt; sub {qwparam('dowaypoints') eq '1'},&lt;br /&gt;
     },&lt;br /&gt;
     { name =&amp;gt; 'waypointheight',&lt;br /&gt;
       text =&amp;gt; 'Waypoint Altitude',&lt;br /&gt;
       default =&amp;gt; 150,&lt;br /&gt;
       indent =&amp;gt; 1,&lt;br /&gt;
       helpdesc =&amp;gt; '(0 means on the ground)',&lt;br /&gt;
       doif =&amp;gt; sub {qwparam('dowaypoints') eq '1'},&lt;br /&gt;
     },&lt;br /&gt;
     { name =&amp;gt; 'waypointmode',&lt;br /&gt;
       text =&amp;gt; 'Altitude mode',&lt;br /&gt;
       type =&amp;gt; 'menu',&lt;br /&gt;
       labels =&amp;gt; \@altitudeValues,&lt;br /&gt;
       default =&amp;gt; 'relativeToGround',&lt;br /&gt;
       doif =&amp;gt; sub {qwparam('dowaypoints') eq '1'},&lt;br /&gt;
       indent =&amp;gt; 1,&lt;br /&gt;
     },&lt;br /&gt;
     { name =&amp;gt; 'waypointextrude',&lt;br /&gt;
       type =&amp;gt; 'checkbox',&lt;br /&gt;
       text =&amp;gt; 'Draw a line to the ground:',&lt;br /&gt;
       indent =&amp;gt; 1,&lt;br /&gt;
       default =&amp;gt; 1,&lt;br /&gt;
       doif =&amp;gt; sub {qwparam('dowaypoints') eq '1'},&lt;br /&gt;
     },&lt;br /&gt;
     { name =&amp;gt; 'includedescriptions',&lt;br /&gt;
       type =&amp;gt; 'checkbox',&lt;br /&gt;
       text =&amp;gt; 'Include cache descriptions in output:',&lt;br /&gt;
       indent =&amp;gt; 1,&lt;br /&gt;
       default =&amp;gt; 1,&lt;br /&gt;
       doif =&amp;gt; sub {qwparam('dowaypoints') eq '1'},&lt;br /&gt;
     },&lt;br /&gt;
&lt;br /&gt;
Then we move on to the options relating to density plots.&lt;br /&gt;
&lt;br /&gt;
     &amp;quot;&amp;quot;,&lt;br /&gt;
     { name =&amp;gt; 'bogus',&lt;br /&gt;
       type =&amp;gt; 'label',&lt;br /&gt;
       text =&amp;gt; 'Configuration of the density grid:',&lt;br /&gt;
       doif =&amp;gt; sub {qwparam('dodensity') eq '1'},&lt;br /&gt;
     },&lt;br /&gt;
     { name =&amp;gt; 'squareratio',&lt;br /&gt;
       default =&amp;gt; '1',&lt;br /&gt;
       type =&amp;gt; 'checkbox',&lt;br /&gt;
       text =&amp;gt; 'Use a square grid',&lt;br /&gt;
       indent =&amp;gt; 1,&lt;br /&gt;
       refresh_on_change =&amp;gt; 1,&lt;br /&gt;
       doif =&amp;gt; sub {qwparam('dodensity') eq '1'},&lt;br /&gt;
     },&lt;br /&gt;
     { name =&amp;gt; 'size',&lt;br /&gt;
       default =&amp;gt; 200,&lt;br /&gt;
       indent =&amp;gt; 1,&lt;br /&gt;
       title =&amp;gt; 'Number of squares on a side of the density plot',&lt;br /&gt;
       help =&amp;gt; 'Creates a plot where there are SIZE by SIZE squares of colored rectangles',&lt;br /&gt;
       doif =&amp;gt; sub {qwparam('squareratio') eq '1' &amp;amp;&amp;amp; qwparam('dodensity') eq '1'},&lt;br /&gt;
     },&lt;br /&gt;
     { name =&amp;gt; 'width',&lt;br /&gt;
       indent =&amp;gt; 1,&lt;br /&gt;
       title =&amp;gt; 'Width in squares of the rectangular density plot',&lt;br /&gt;
       help =&amp;gt; 'Normally equal to the size value but can be set independently.  It specifies the width (in squares) of the density plot.',&lt;br /&gt;
       doif =&amp;gt; sub {qwparam('squareratio') ne '1' &amp;amp;&amp;amp; qwparam('dodensity') eq '1'},&lt;br /&gt;
     },&lt;br /&gt;
     { name =&amp;gt; 'height',&lt;br /&gt;
       indent =&amp;gt; 1,&lt;br /&gt;
       title =&amp;gt; 'Height in squares of the rectangular density plot',&lt;br /&gt;
       help =&amp;gt; 'Normally equal to the size value but can be set independently.  It specifies the height (in squares) of the density plot.',&lt;br /&gt;
       doif =&amp;gt; sub {qwparam('squareratio') ne '1' &amp;amp;&amp;amp; qwparam('dodensity') eq '1'},&lt;br /&gt;
     },&lt;br /&gt;
     { name =&amp;gt; 'spread',&lt;br /&gt;
       title =&amp;gt; 'Spreading Distance',&lt;br /&gt;
       indent =&amp;gt; 1,&lt;br /&gt;
       help =&amp;gt; 'Sets the spread that determines the number of neighboring squares that a given cache will effect.  EG, a spread of 5 will affect a circle of density squares in a radius of 5.  This generally should be a low value of probably not more than 5 or so.',&lt;br /&gt;
       default =&amp;gt; 5,&lt;br /&gt;
       doif =&amp;gt; sub {qwparam('dodensity') eq '1'},&lt;br /&gt;
     },&lt;br /&gt;
     { name =&amp;gt; 'doempty',&lt;br /&gt;
       title =&amp;gt; 'Include empty squares in the density plot:',&lt;br /&gt;
       help =&amp;gt; 'If set to 1, even empty squares will be colored (red).  Otherwise the empty squares are removed from the plot leaving the plane ground underneath.',&lt;br /&gt;
       indent =&amp;gt; 1,&lt;br /&gt;
       type =&amp;gt; 'checkbox',&lt;br /&gt;
       default =&amp;gt; 0,&lt;br /&gt;
       doif =&amp;gt; sub {qwparam('dodensity') eq '1'},&lt;br /&gt;
     },&lt;br /&gt;
  &lt;br /&gt;
  &lt;br /&gt;
     &amp;quot;&amp;quot;,&lt;br /&gt;
     { name =&amp;gt; 'bogus',&lt;br /&gt;
       type =&amp;gt; 'label',&lt;br /&gt;
       text =&amp;gt; 'Configuration Parameters for shape style:',&lt;br /&gt;
       doif =&amp;gt; sub {qwparam('dodensity') eq '1'},&lt;br /&gt;
     },&lt;br /&gt;
     { name =&amp;gt; 'altitude',&lt;br /&gt;
       title =&amp;gt; 'Altitude of density plot squares',&lt;br /&gt;
       indent =&amp;gt; 1,&lt;br /&gt;
       help =&amp;gt; 'The altitude to set the density plot squares at.',&lt;br /&gt;
       default =&amp;gt; 1000,&lt;br /&gt;
       doif =&amp;gt; sub {qwparam('dodensity') eq '1'},&lt;br /&gt;
     },&lt;br /&gt;
     { name =&amp;gt; 'densitymode',&lt;br /&gt;
       text =&amp;gt; 'Altitude mode:',&lt;br /&gt;
       type =&amp;gt; 'menu',&lt;br /&gt;
       labels =&amp;gt; \@altitudeValues,&lt;br /&gt;
       default =&amp;gt; 'relativeToGround',&lt;br /&gt;
       doif =&amp;gt; sub {qwparam('dodensity') eq '1'},&lt;br /&gt;
       indent =&amp;gt; 1,&lt;br /&gt;
     },&lt;br /&gt;
     { name =&amp;gt; 'extrude',&lt;br /&gt;
       title =&amp;gt; 'Extrude the density plot to the ground:',&lt;br /&gt;
       help =&amp;gt; 'Whether or not to extrude the density plot squares down to the ground.',&lt;br /&gt;
       type =&amp;gt; 'checkbox',&lt;br /&gt;
       indent =&amp;gt; 1,&lt;br /&gt;
       default =&amp;gt; 0,&lt;br /&gt;
       doif =&amp;gt; sub {qwparam('dodensity') eq '1'},&lt;br /&gt;
     },&lt;br /&gt;
     { name =&amp;gt; 'opaque',&lt;br /&gt;
       title =&amp;gt; 'Opaqueness of the density squares:',&lt;br /&gt;
       helpdesc =&amp;gt; '(0-100; 0 being completely see-through)',&lt;br /&gt;
       help =&amp;gt; 'The opacity of the density squares.  Must be between 0 and 100, with 0 being completely see-through (and thus completely useless).',&lt;br /&gt;
       indent =&amp;gt; 1,&lt;br /&gt;
       default =&amp;gt; 20,&lt;br /&gt;
       doif =&amp;gt; sub {qwparam('dodensity') eq '1'},&lt;br /&gt;
     },&lt;br /&gt;
     { name =&amp;gt; 'linewidth',&lt;br /&gt;
       title =&amp;gt; 'Line width:',&lt;br /&gt;
       help =&amp;gt; 'The width of the border lines to draw (0-4).  0 means don\'t draw borders on the squares.',&lt;br /&gt;
       indent =&amp;gt; 1,&lt;br /&gt;
       default =&amp;gt; 0,&lt;br /&gt;
       doif =&amp;gt; sub {qwparam('dodensity') eq '1'},&lt;br /&gt;
     },&lt;br /&gt;
&lt;br /&gt;
These options relate to doing a 528 foot circle around each cache&lt;br /&gt;
(which I refer to as a &amp;quot;jail&amp;quot; since it prevents other caches from&lt;br /&gt;
being placed near it):&lt;br /&gt;
&lt;br /&gt;
     &amp;quot;&amp;quot;,&lt;br /&gt;
     { name =&amp;gt; 'bagus',&lt;br /&gt;
       type =&amp;gt; 'label',&lt;br /&gt;
       text =&amp;gt; 'Configure .1 mile radius circles:',&lt;br /&gt;
       doif =&amp;gt; sub {qwparam('dojail') eq '1'},&lt;br /&gt;
     },&lt;br /&gt;
     { name =&amp;gt; 'jailaltitude',&lt;br /&gt;
       text =&amp;gt; 'Altitude of the circles:',&lt;br /&gt;
       default =&amp;gt; '100',&lt;br /&gt;
       doif =&amp;gt; sub {qwparam('dojail') eq '1'},&lt;br /&gt;
       indent =&amp;gt; 1,&lt;br /&gt;
     },&lt;br /&gt;
     { name =&amp;gt; 'jailmode',&lt;br /&gt;
       text =&amp;gt; 'Altitude mode:',&lt;br /&gt;
       type =&amp;gt; 'menu',&lt;br /&gt;
       labels =&amp;gt; \@altitudeValues,&lt;br /&gt;
       default =&amp;gt; 'relativeToGround',&lt;br /&gt;
       doif =&amp;gt; sub {qwparam('dojail') eq '1'},&lt;br /&gt;
       indent =&amp;gt; 1,&lt;br /&gt;
     },&lt;br /&gt;
  &lt;br /&gt;
And finally, some extra options that let you limit the input data by a&lt;br /&gt;
square boundary:&lt;br /&gt;
&lt;br /&gt;
     &amp;quot;&amp;quot;,&lt;br /&gt;
     { name =&amp;gt; 'bogus',&lt;br /&gt;
       type =&amp;gt; 'label',&lt;br /&gt;
       text =&amp;gt; 'Limit the input data:',&lt;br /&gt;
     },&lt;br /&gt;
     { name =&amp;gt; 'limitdata',&lt;br /&gt;
       default =&amp;gt; '1',&lt;br /&gt;
       type =&amp;gt; 'checkbox',&lt;br /&gt;
       indent =&amp;gt; 1,&lt;br /&gt;
       text =&amp;gt; 'Use all the data from the search set',&lt;br /&gt;
       refresh_on_change =&amp;gt; 1,&lt;br /&gt;
     },&lt;br /&gt;
     { name =&amp;gt; 'nmax',&lt;br /&gt;
       title =&amp;gt; 'Maximum North coordinate:',&lt;br /&gt;
       indent =&amp;gt; 1,&lt;br /&gt;
       help =&amp;gt; 'The maximum north coordinate value to created the grid over.  Normally this is automatically set by the maximum value found in the data, but can be overridden',&lt;br /&gt;
       doif =&amp;gt; sub {qwparam('limitdata') ne '1'},&lt;br /&gt;
     },&lt;br /&gt;
     { name =&amp;gt; 'nmin',&lt;br /&gt;
       title =&amp;gt; 'Minimum North coordinate:',&lt;br /&gt;
       indent =&amp;gt; 1,&lt;br /&gt;
       help =&amp;gt; 'The minimum north coordinate value to created the grid over.  Normally this is automatically set by the minimum value found in the data, but can be overridden',&lt;br /&gt;
       doif =&amp;gt; sub {qwparam('limitdata') ne '1'},&lt;br /&gt;
     },&lt;br /&gt;
     { name =&amp;gt; 'wmax',&lt;br /&gt;
       title =&amp;gt; 'Maximum West coordinate:',&lt;br /&gt;
       indent =&amp;gt; 1,&lt;br /&gt;
       help =&amp;gt; 'The maximum west coordinate value to created the grid over.  Normally this is automatically set by the maximum value found in the data, but can be overridden',&lt;br /&gt;
       doif =&amp;gt; sub {qwparam('limitdata') ne '1'},&lt;br /&gt;
     },&lt;br /&gt;
     { name =&amp;gt; 'wmin',&lt;br /&gt;
       title =&amp;gt; 'Minimum West coordinate:',&lt;br /&gt;
       indent =&amp;gt; 1,&lt;br /&gt;
       help =&amp;gt; 'The minimum west coordinate value to created the grid over.  Normally this is automatically set by the minimum value found in the data, but can be overridden',&lt;br /&gt;
       doif =&amp;gt; sub {qwparam('limitdata') ne '1'},&lt;br /&gt;
     }&lt;br /&gt;
    );&lt;br /&gt;
&lt;br /&gt;
Whew.  Done.&lt;br /&gt;
&lt;br /&gt;
=== The Actual KML Export Magic ===&lt;br /&gt;
&lt;br /&gt;
First a simple subroutine called _x() which just replaces &amp;amp;gt;, &amp;amp;lt;&lt;br /&gt;
and &amp;amp;amp; with legal values in XML (&amp;amp;gt; becomes &amp;amp;amp;gt;):&lt;br /&gt;
  &lt;br /&gt;
  sub _x {&lt;br /&gt;
      return GeoDB::Export::_add_basic_entity(@_);&lt;br /&gt;
  }&lt;br /&gt;
&lt;br /&gt;
Here's the actual function that gets called by geoqo when someone&lt;br /&gt;
wants to export to KML.  The GUI screen showing all of the options&lt;br /&gt;
above may have already been called at this point, or command line&lt;br /&gt;
option processing may have been.  Either way, the function only needs&lt;br /&gt;
to assume that it's all been dealt with.  &lt;br /&gt;
&lt;br /&gt;
Every export module needs to implement the ''export_it'' function.&lt;br /&gt;
The function passed 3 arguments: A ''self'' reference to the KML&lt;br /&gt;
export object, a file name to put the results in, and a GeoQO [[set]]&lt;br /&gt;
that is the waypoint data it should be exporting.&lt;br /&gt;
  &lt;br /&gt;
  sub export_it {&lt;br /&gt;
      my ($self, $file, $set) = @_;&lt;br /&gt;
&lt;br /&gt;
Open the file and set the ''$fh'' variable as the filehandle to write to:&lt;br /&gt;
  &lt;br /&gt;
      GEODEBUG(1,&amp;quot;writing file: $file\n&amp;quot;);&lt;br /&gt;
      my $fh = new IO::File &amp;quot;&amp;gt;$file&amp;quot;;&lt;br /&gt;
&lt;br /&gt;
Print the starting XML header to the file:&lt;br /&gt;
&lt;br /&gt;
      print $fh &amp;quot;&amp;lt;?xml version=\&amp;quot;1.0\&amp;quot; encoding=\&amp;quot;utf-8\&amp;quot;?&amp;gt;&lt;br /&gt;
  &amp;lt;kml xmlns=\&amp;quot;http://earth.google.com/kml/2.2\&amp;quot;&amp;gt;&lt;br /&gt;
  &amp;lt;Document&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The next line shows the use of the ''dataname'' option variable,&lt;br /&gt;
which was one of the first in the ''GEOOPTIONS'' variable above&lt;br /&gt;
describing the options that can be passed.&lt;br /&gt;
&lt;br /&gt;
    &amp;lt;name&amp;gt;$self-&amp;gt;{'options'}{'dataname'}&amp;lt;/name&amp;gt;&lt;br /&gt;
    &amp;lt;open&amp;gt;1&amp;lt;/open&amp;gt;&lt;br /&gt;
    &amp;lt;description&amp;gt;This file was created using GeoQO, which is available from http://www.geoqo.org/&amp;lt;/description&amp;gt;&lt;br /&gt;
  &amp;quot;;&lt;br /&gt;
  &lt;br /&gt;
We set up some basic variables that remember the possible icons&lt;br /&gt;
(shapes), difficulty levels (diffs):&lt;br /&gt;
&lt;br /&gt;
      # these match dist/makeicons&lt;br /&gt;
      my @shapes = ('micro', 'small', 'regular', 'large', 'nosize', 'multi',&lt;br /&gt;
  		  'virtual', 'unknown', 'solved', 'webcam', 'event', 'earth');&lt;br /&gt;
      my @diffs = (qw(1 1.5 2 2.5 3 3.5 4 4.5 5));&lt;br /&gt;
  &lt;br /&gt;
      my %shapes;&lt;br /&gt;
  &lt;br /&gt;
If the style they selected in the ''waypointstyle'' option was&lt;br /&gt;
''geoqo'' (the default) then they want a different icon per cache type&lt;br /&gt;
and difficulty level combination.  We need to output all the style&lt;br /&gt;
definitions into the KML file, so we do that next and it goes near the&lt;br /&gt;
top of the KML file.&lt;br /&gt;
&lt;br /&gt;
It does this by writing a section of KML for each difficulty for each&lt;br /&gt;
shape.  These link to icons stored on the geoqo website:&lt;br /&gt;
&lt;br /&gt;
      # define the styles needed&lt;br /&gt;
      if ($self-&amp;gt;{'options'}{'waypointstyle'} eq 'geoqo') {&lt;br /&gt;
  	foreach my $shape (@shapes) {&lt;br /&gt;
  	    $shapes{$shape} = 1; # cache for later check if we can do it&lt;br /&gt;
  	    foreach my $diff (@diffs) {&lt;br /&gt;
  		$diff =~ s/\.//;&lt;br /&gt;
  		print $fh &amp;quot;  &amp;lt;Style id=\&amp;quot;$shape$diff\&amp;quot;&amp;gt;&lt;br /&gt;
      &amp;lt;IconStyle&amp;gt;&lt;br /&gt;
        &amp;lt;Icon&amp;gt;&lt;br /&gt;
          &amp;lt;href&amp;gt;http://www.geoqo.org/images/icons/geocaches-$shape-$diff.png&amp;lt;/href&amp;gt;&lt;br /&gt;
        &amp;lt;/Icon&amp;gt;&lt;br /&gt;
      &amp;lt;/IconStyle&amp;gt;&lt;br /&gt;
    &amp;lt;/Style&amp;gt;&lt;br /&gt;
  &amp;quot;;&lt;br /&gt;
  	    }&lt;br /&gt;
  	}&lt;br /&gt;
      }&lt;br /&gt;
  &lt;br /&gt;
Now that we have the styles created, we have to create the top level&lt;br /&gt;
folder structure in the KML language:&lt;br /&gt;
&lt;br /&gt;
      print $fh &amp;quot;&amp;lt;Folder&amp;gt;&lt;br /&gt;
    &amp;lt;name&amp;gt;$self-&amp;gt;{'options'}{'dataname'}&amp;lt;/name&amp;gt;&lt;br /&gt;
    &amp;lt;description&amp;gt;$self-&amp;gt;{'options'}{'dataname'}&amp;lt;/description&amp;gt;\n&amp;quot;;&lt;br /&gt;
&lt;br /&gt;
Now we just process a bunch of options above into local variables;&lt;br /&gt;
this is not strictly necessary, but it's a bit faster to refer to&lt;br /&gt;
local variables a bunch of times than repeatedly look into the&lt;br /&gt;
$self-&amp;gt;{'options'}{'....'} structure for each look up if we're going&lt;br /&gt;
to do it a lot:&lt;br /&gt;
&lt;br /&gt;
      # remember options&lt;br /&gt;
      my $geoqostyle = 0;&lt;br /&gt;
      $geoqostyle = 1 if ($self-&amp;gt;{'options'}{'waypointstyle'} eq 'geoqo');&lt;br /&gt;
      my $doextrude = &amp;quot;&amp;quot;;&lt;br /&gt;
      my $doextrude = &amp;quot;\n      &amp;lt;extrude&amp;gt;1&amp;lt;/extrude&amp;gt;&amp;quot;&lt;br /&gt;
        if ($self-&amp;gt;{'options'}{'waypointextrude'});&lt;br /&gt;
      my $height = $self-&amp;gt;{'options'}{'waypointheight'};&lt;br /&gt;
      my $mode = $self-&amp;gt;{'options'}{'waypointmode'};&lt;br /&gt;
  &lt;br /&gt;
      my $dodescriptions = $self-&amp;gt;{'options'}{'includedescriptions'};&lt;br /&gt;
&lt;br /&gt;
=== Waypoint Creation ===&lt;br /&gt;
&lt;br /&gt;
We only export the waypoints themselves if the ''dowaypoints''&lt;br /&gt;
option (checkbox) was set:&lt;br /&gt;
&lt;br /&gt;
      # nopoints is historic...&lt;br /&gt;
      if ($self-&amp;gt;{'options'}{'dowaypoints'} &amp;amp;&amp;amp; !$self-&amp;gt;{'options'}{'nopoints'}) {&lt;br /&gt;
&lt;br /&gt;
If so, then we need to create a sub-folder within the KML file and&lt;br /&gt;
name it appropriately:&lt;br /&gt;
&lt;br /&gt;
  	print $fh &amp;quot;  &amp;lt;Folder&amp;gt;&lt;br /&gt;
      &amp;lt;name&amp;gt;$self-&amp;gt;{'options'}{'dataname'}: Waypoints&amp;lt;/name&amp;gt;\n&amp;quot;;&lt;br /&gt;
&lt;br /&gt;
This starts setting up the progress bar and sets the maximum number&lt;br /&gt;
that we're going to call it.  In this case, we're going to set it to&lt;br /&gt;
the number of waypoint points in the set.  Note that not all the GUI&lt;br /&gt;
backends support progress bars (EG, Tk doesn't which means windows&lt;br /&gt;
users won't see it):&lt;br /&gt;
  &lt;br /&gt;
  	my $count = 0;&lt;br /&gt;
  	my $next = 0;&lt;br /&gt;
  	$self-&amp;gt;setup_progress($set-&amp;gt;num(), &amp;quot;Creating Waypoints&amp;quot;);&lt;br /&gt;
&lt;br /&gt;
The GeoDB::Set object that we were passed which is full of waypoints&lt;br /&gt;
has a nice ''foreach'' function that can be called.  You pass it a&lt;br /&gt;
reference to another function (in this case, a function declared right&lt;br /&gt;
inside the argument list).  Basically, all the code starting with the&lt;br /&gt;
''sub {'' and beyond gets called once per waypoint.  The subroutine is&lt;br /&gt;
passed a GeoDB::Waypoint object as the option.&lt;br /&gt;
&lt;br /&gt;
This bit of code prints each waypoint one at a time as the subroutine&lt;br /&gt;
defined gets called multiple times.  The $_[0] statement refers to the&lt;br /&gt;
GeoDB::Waypoint object.  All the waypoint data in one of these objects&lt;br /&gt;
is stored in the $object-&amp;gt;{'data'} hash.  EG, the latitude is stored&lt;br /&gt;
in: $object-&amp;gt;{'data'}{'lat'}&lt;br /&gt;
&lt;br /&gt;
  	$set-&amp;gt;foreach(sub {&lt;br /&gt;
  			  $next = $self-&amp;gt;set_progress($count++)&lt;br /&gt;
  			    if ($count &amp;gt;= $next);&lt;br /&gt;
  			  my $style = ($geoqostyle) ? get_tomtom_style($_[0])&lt;br /&gt;
  			    : &amp;quot;#khStyle652&amp;quot;;&lt;br /&gt;
  			  my $c=$_[0]{'data'};&lt;br /&gt;
  			  my $type = ($c-&amp;gt;{'subtype'} ? &amp;quot;$c-&amp;gt;{'type'}|$c-&amp;gt;{'subtype'}&amp;quot; : $c-&amp;gt;{'type'});&lt;br /&gt;
  &lt;br /&gt;
  			  my $description = &amp;quot;&amp;quot;;&lt;br /&gt;
  			  if ($dodescriptions) {&lt;br /&gt;
  			      $description = &amp;quot;&amp;lt;description&amp;gt;&amp;lt;![CDATA[&amp;quot;;&lt;br /&gt;
  			      if ($c-&amp;gt;{'groundspeak_short_description_html'} eq 'True') {&lt;br /&gt;
  				  $description .=&lt;br /&gt;
  				    $c-&amp;gt;{'groundspeak_short_description'};&lt;br /&gt;
  			      } else {&lt;br /&gt;
  				  $description .=&lt;br /&gt;
  				    &amp;quot;&amp;lt;pre&amp;gt;&amp;quot; .&lt;br /&gt;
  				      _x($c-&amp;gt;{'groundspeak_short_description'}) .&lt;br /&gt;
  					&amp;quot;&amp;lt;/pre&amp;gt;&amp;lt;br /&amp;gt;&amp;quot;;&lt;br /&gt;
  			      }&lt;br /&gt;
  &lt;br /&gt;
  			      if ($c-&amp;gt;{'groundspeak_long_description_html'} eq 'True') {&lt;br /&gt;
  				  $description .=&lt;br /&gt;
  				    $c-&amp;gt;{'groundspeak_long_description'}&lt;br /&gt;
  			      } else {&lt;br /&gt;
  				  $description .=&lt;br /&gt;
  				    &amp;quot;&amp;lt;pre&amp;gt;&amp;quot; .&lt;br /&gt;
  				      _x($c-&amp;gt;{'groundspeak_long_description'}) .&lt;br /&gt;
  					&amp;quot;&amp;lt;/pre&amp;gt;&amp;quot;;&lt;br /&gt;
  			      }&lt;br /&gt;
  			      $description .= &amp;quot;]]&amp;gt;&amp;lt;/description&amp;gt;&amp;quot;;&lt;br /&gt;
  			  }&lt;br /&gt;
  &lt;br /&gt;
  			  print $fh &amp;quot;&lt;br /&gt;
    &amp;lt;Placemark&amp;gt;&lt;br /&gt;
      &amp;lt;name&amp;gt;&amp;quot; . _x($c-&amp;gt;{'ident'} . &amp;quot;: &amp;quot; . $c-&amp;gt;{'urlname'}) . &amp;quot;&amp;lt;/name&amp;gt;$description&lt;br /&gt;
      &amp;lt;styleUrl&amp;gt;$style&amp;lt;/styleUrl&amp;gt;&lt;br /&gt;
      &amp;lt;Point&amp;gt;$doextrude&lt;br /&gt;
        &amp;lt;tessellate&amp;gt;0&amp;lt;/tessellate&amp;gt;&lt;br /&gt;
        &amp;lt;altitudeMode&amp;gt;$mode&amp;lt;/altitudeMode&amp;gt;&lt;br /&gt;
        &amp;lt;coordinates&amp;gt;&amp;quot; . _x($c-&amp;gt;{'lon'}) . &amp;quot;,&amp;quot; . _x($c-&amp;gt;{'lat'}) . &amp;quot;,$height&amp;lt;/coordinates&amp;gt;&lt;br /&gt;
      &amp;lt;/Point&amp;gt;&lt;br /&gt;
    &amp;lt;/Placemark&amp;gt;&lt;br /&gt;
  &amp;quot;;&lt;br /&gt;
  		      });&lt;br /&gt;
&lt;br /&gt;
That was a lot of code just to print out each waypoint description,&lt;br /&gt;
but you'll note a lot of it was deciding whether to print description&lt;br /&gt;
information and formatting the output.&lt;br /&gt;
&lt;br /&gt;
Then we stop the progress update so the progress bar window goes away:&lt;br /&gt;
&lt;br /&gt;
  	$self-&amp;gt;stop_progress();&lt;br /&gt;
&lt;br /&gt;
And close off the waypoint folder: &lt;br /&gt;
&lt;br /&gt;
  	print $fh &amp;quot;&amp;lt;/Folder&amp;gt;\n&amp;quot;;&lt;br /&gt;
      }&lt;br /&gt;
&lt;br /&gt;
=== 528 Foot Circle Creation (&amp;quot;jails&amp;quot;) ===&lt;br /&gt;
&lt;br /&gt;
Next we do the 528 foot circles, but only if requested via the dojail option:&lt;br /&gt;
&lt;br /&gt;
      # create jails around the cache&lt;br /&gt;
      if ($self-&amp;gt;{'options'}{'dojail'}) {&lt;br /&gt;
&lt;br /&gt;
And we place them in their own folder too, just like the waypoints above:&lt;br /&gt;
&lt;br /&gt;
  	print $fh &amp;quot;  &amp;lt;Folder&amp;gt;&lt;br /&gt;
      &amp;lt;name&amp;gt;$self-&amp;gt;{'options'}{'dataname'}: Waypoint .1 Mile Boundaries&amp;lt;/name&amp;gt;\n&amp;quot;;&lt;br /&gt;
&lt;br /&gt;
First, we need to calculate a ring of points.  We basically just store&lt;br /&gt;
a ring of latitude, longitude points inside two arrays (distringx and&lt;br /&gt;
distringy).  The ''cos'' and ''sin'' functions are used to plot the&lt;br /&gt;
circumference of a circle in 16 points.  Then we multiply it by the&lt;br /&gt;
radius distance, which is .001428 between each lat/lon.  This actually&lt;br /&gt;
works for latitude but for the longitude it'll be right at the equator&lt;br /&gt;
but very very wrong at the poles.  This needs to be accounted for in&lt;br /&gt;
the future...&lt;br /&gt;
&lt;br /&gt;
  	# calculate a ring&lt;br /&gt;
  	my (@distringx, @distringy);&lt;br /&gt;
  	my $ringcount = 16;&lt;br /&gt;
  	my $radiusdist = .001428;  # right for lat, wrong for long&lt;br /&gt;
  	for (my $i = 0; $i &amp;lt; $ringcount; $i++) {&lt;br /&gt;
  	    push @distringx, cos(2 * 3.1415 * $i / $ringcount) * $radiusdist;&lt;br /&gt;
  	    push @distringy, sin(2 * 3.1415 * $i / $ringcount) * $radiusdist;&lt;br /&gt;
  	}&lt;br /&gt;
  	push @distringx, cos(0) * $radiusdist;&lt;br /&gt;
  	push @distringy, sin(0) * $radiusdist;&lt;br /&gt;
&lt;br /&gt;
More options to just remember in variables for later:&lt;br /&gt;
&lt;br /&gt;
  	my $altitude = $self-&amp;gt;{'options'}{'jailaltitude'};&lt;br /&gt;
  	my $mode = $self-&amp;gt;{'options'}{'jailmode'};&lt;br /&gt;
&lt;br /&gt;
This color is transparent (80), no blue (00), no green (00) and&lt;br /&gt;
maximum red (ff):&lt;br /&gt;
&lt;br /&gt;
  	my $color = &amp;quot;800000ff&amp;quot;;&lt;br /&gt;
  	my $linewidth = 1;&lt;br /&gt;
  	my $extrude = 1;&lt;br /&gt;
&lt;br /&gt;
Again we start a progress bar (but it's so fast usually you won't see it):&lt;br /&gt;
&lt;br /&gt;
  	my $count = 0;&lt;br /&gt;
  	my $next = 0;&lt;br /&gt;
  	$self-&amp;gt;setup_progress($set-&amp;gt;num(), &amp;quot;Creating Jail Circles&amp;quot;);&lt;br /&gt;
&lt;br /&gt;
Now, we use the same foreach method mentioned above.&lt;br /&gt;
&lt;br /&gt;
  	$set-&amp;gt;foreach(sub {&lt;br /&gt;
&lt;br /&gt;
These update the progress bar:&lt;br /&gt;
&lt;br /&gt;
  			  $count++;&lt;br /&gt;
  			  $next = $self-&amp;gt;set_progress($count++)&lt;br /&gt;
  			    if ($count &amp;gt;= $next);&lt;br /&gt;
&lt;br /&gt;
Now we create a variable reference to the waypoint data in the 'data' hash:&lt;br /&gt;
(not really necessary, but...)&lt;br /&gt;
&lt;br /&gt;
  			  my $c=$_[0]{'data'};&lt;br /&gt;
&lt;br /&gt;
And print a Polygon KML object for each cache:&lt;br /&gt;
&lt;br /&gt;
  			  print $fh &amp;quot;&lt;br /&gt;
     &amp;lt;Placemark id=\&amp;quot;jail$count\&amp;quot;&amp;gt;&lt;br /&gt;
      &amp;lt;name&amp;gt;GeoJail$count&amp;lt;/name&amp;gt;&lt;br /&gt;
      &amp;lt;Style&amp;gt;&lt;br /&gt;
        &amp;lt;PolyStyle&amp;gt;&lt;br /&gt;
          &amp;lt;color&amp;gt;$color&amp;lt;/color&amp;gt;&lt;br /&gt;
        &amp;lt;/PolyStyle&amp;gt;&lt;br /&gt;
        &amp;lt;LineStyle&amp;gt;&lt;br /&gt;
          &amp;lt;width&amp;gt;$linewidth&amp;lt;/width&amp;gt;&lt;br /&gt;
          &amp;lt;color&amp;gt;$color&amp;lt;/color&amp;gt;&lt;br /&gt;
        &amp;lt;/LineStyle&amp;gt;&lt;br /&gt;
      &amp;lt;/Style&amp;gt;&lt;br /&gt;
      &amp;lt;Polygon id=\&amp;quot;poly$count\&amp;quot;&amp;gt;&lt;br /&gt;
        &amp;lt;extrude&amp;gt;$extrude&amp;lt;/extrude&amp;gt;&lt;br /&gt;
        &amp;lt;tessellate&amp;gt;0&amp;lt;/tessellate&amp;gt;&lt;br /&gt;
        &amp;lt;altitudeMode&amp;gt;$mode&amp;lt;/altitudeMode&amp;gt;&lt;br /&gt;
        &amp;lt;outerBoundaryIs&amp;gt;&lt;br /&gt;
          &amp;lt;LinearRing&amp;gt;&lt;br /&gt;
            &amp;lt;coordinates&amp;gt;&lt;br /&gt;
  &amp;quot;;&lt;br /&gt;
&lt;br /&gt;
Here we print coordinates for the ring in the real wold by taking the&lt;br /&gt;
lat/lon of the waypoint and then add in the circle difference at each&lt;br /&gt;
point that we calculated above.  Sometimes the circle point will be&lt;br /&gt;
negative, sometimes positive.  IE, the points this prints out will&lt;br /&gt;
rotate around the waypoint point at a fixed distance (528 feet) at&lt;br /&gt;
each point from the starting lat/lon location of the waypoint.&lt;br /&gt;
&lt;br /&gt;
  			  for (my $i = 0; $i &amp;lt;= $ringcount; $i++) {&lt;br /&gt;
  			      print $fh ($c-&amp;gt;{'lon'}+$distringy[$i]) . &amp;quot;,&amp;quot; .&lt;br /&gt;
  				($c-&amp;gt;{'lat'}+$distringx[$i]) . &amp;quot;,&amp;quot; .&lt;br /&gt;
  				  $altitude, &amp;quot; &amp;quot;;&lt;br /&gt;
  			  }&lt;br /&gt;
&lt;br /&gt;
Then print the closing part of the waypoint circle KML code:&lt;br /&gt;
&lt;br /&gt;
  			  print $fh &amp;quot;&lt;br /&gt;
            &amp;lt;/coordinates&amp;gt;&lt;br /&gt;
          &amp;lt;/LinearRing&amp;gt;&lt;br /&gt;
        &amp;lt;/outerBoundaryIs&amp;gt;&lt;br /&gt;
      &amp;lt;/Polygon&amp;gt;&lt;br /&gt;
    &amp;lt;/Placemark&amp;gt;&lt;br /&gt;
  &amp;quot;;&lt;br /&gt;
  		      });&lt;br /&gt;
&lt;br /&gt;
And stop the progress bar again, and close the circle:&lt;br /&gt;
&lt;br /&gt;
  	$self-&amp;gt;stop_progress();&lt;br /&gt;
  	&lt;br /&gt;
  	print $fh &amp;quot;&amp;lt;/Folder&amp;gt;\n&amp;quot;;&lt;br /&gt;
      }&lt;br /&gt;
&lt;br /&gt;
=== Density Plot Function Invocation ===&lt;br /&gt;
&lt;br /&gt;
Now, we actually print the density plot.  The get_density_map function&lt;br /&gt;
is actually defined inside the GeoDB::Export::Density module instead.&lt;br /&gt;
We'll include it below and explain it as well.  In the meantime, just&lt;br /&gt;
know that it prints out a bunch more KML polygons to represent the&lt;br /&gt;
density clouds:&lt;br /&gt;
&lt;br /&gt;
      # nodensity is historic&lt;br /&gt;
      $self-&amp;gt;get_density_map($set, $fh)&lt;br /&gt;
        if ($self-&amp;gt;{'options'}{'dodensity'} &amp;amp;&amp;amp; !$self-&amp;gt;{'options'}{'nodensity'});&lt;br /&gt;
&lt;br /&gt;
And then we close the whole thing off.&lt;br /&gt;
&lt;br /&gt;
The remaining code in this section are some functions that calculate a&lt;br /&gt;
icon name from the geocache information.  Traditionals are put into&lt;br /&gt;
icons according to size, the rest are put into icons according to&lt;br /&gt;
cache type.  The icon name also has the difficulty level in it, so a&lt;br /&gt;
small icon at difficulty 2 becomes small2.  The decimal is dropped, so&lt;br /&gt;
a small at 2.5 becomes small25.&lt;br /&gt;
&lt;br /&gt;
  print $fh &amp;quot;&amp;lt;/Folder&amp;gt;&lt;br /&gt;
  &amp;lt;/Document&amp;gt;&lt;br /&gt;
  &amp;lt;/kml&amp;gt;&lt;br /&gt;
  &amp;quot;;&lt;br /&gt;
  }&lt;br /&gt;
  &lt;br /&gt;
  my %containers =&lt;br /&gt;
    (&lt;br /&gt;
     'Micro' 	=&amp;gt; 'micro',&lt;br /&gt;
     'Small' 	=&amp;gt; 'small',&lt;br /&gt;
     'Regular'    =&amp;gt; 'regular',&lt;br /&gt;
     'Not chosen' =&amp;gt; 'nosize',&lt;br /&gt;
     'Other'      =&amp;gt; 'nosize',&lt;br /&gt;
     'Large'      =&amp;gt; 'large',&lt;br /&gt;
    );&lt;br /&gt;
  &lt;br /&gt;
  my %types =&lt;br /&gt;
    (&lt;br /&gt;
     'Multi-cache' =&amp;gt; 'multi',&lt;br /&gt;
     'Unknown Cache' =&amp;gt; 'unknown',&lt;br /&gt;
     'Virtual Cache' =&amp;gt; 'virtual',&lt;br /&gt;
     'Webcam Cache' =&amp;gt; 'webcam',&lt;br /&gt;
     'Event Cache' =&amp;gt; 'event',&lt;br /&gt;
     'Earthcache' =&amp;gt; 'earth',&lt;br /&gt;
     # XXX!!!  need letterbox!&lt;br /&gt;
     # 'Letterbox Hybrid' =&amp;gt; 'letter',&lt;br /&gt;
    );&lt;br /&gt;
  &lt;br /&gt;
  sub get_tomtom_style {&lt;br /&gt;
      # this matches the code in scripts/devices/tomtom too&lt;br /&gt;
      my $cache = $_[0];&lt;br /&gt;
  &lt;br /&gt;
      # XXX: infield vs solved...&lt;br /&gt;
  &lt;br /&gt;
      # traditionals break down by size&lt;br /&gt;
      if ($_[0]{'data'}{'subtype'} eq 'Traditional Cache') {&lt;br /&gt;
  	if (exists($containers{$_[0]{data}{groundspeak_container}})) {&lt;br /&gt;
  	    my $diff = $_[0]{data}{groundspeak_difficulty};&lt;br /&gt;
  	    $diff =~ s/\.//;&lt;br /&gt;
  	    return &amp;quot;#$containers{$_[0]{data}{groundspeak_container}}$diff&amp;quot;;&lt;br /&gt;
  	}&lt;br /&gt;
      } else {&lt;br /&gt;
  	if (exists($types{$_[0]{data}{subtype}})) {&lt;br /&gt;
  	    return &amp;quot;#$types{$_[0]{data}{subtype}}$_[0]{data}{groundspeak_difficulty}&amp;quot;;&lt;br /&gt;
  	}&lt;br /&gt;
  	# the rest get icons for the type&lt;br /&gt;
      }&lt;br /&gt;
      return &amp;quot;#khStyle652&amp;quot;;&lt;br /&gt;
  }&lt;br /&gt;
&lt;br /&gt;
=== Density Plot Code ===&lt;br /&gt;
&lt;br /&gt;
This is actually from the GeoDB::Export::Density code file:&lt;br /&gt;
&lt;br /&gt;
.&lt;/div&gt;</summary>
		<author><name>Yamar</name></author>	</entry>

	</feed>