Example #1
0
# Data Example---------------------------------------------------------------------------------------------------------
# Create and style a point
pnt = kml.newpoint(name='1. World of Birds (Data)',
                   coords=[(18.361960, -34.016543)])
pnt.iconstyle.icon.href = 'http://maps.google.com/mapfiles/kml/paddle/1.png'

# Add the Data to the point
pnt.extendeddata.newdata(name='birds', value=400, displayname="Bird Species")
pnt.extendeddata.newdata(name='aviaries', value=100, displayname="Aviaries")
pnt.extendeddata.newdata(name='visitors',
                         value=10000,
                         displayname="Annual Visitors")

# Simple Data Example -------------------------------------------------------------------------------------------------
# Create a schema
schema = kml.newschema(name='WOW')

schema.newsimplefield(name='birds', type='int', displayname='Bird Species')
schema.newsimplefield(name='aviaries', type='int', displayname='Aviaries')
schema.newsimplefield(name='visitors',
                      type='int',
                      displayname='Annual Visitors')

# Create and style a point
pnt = kml.newpoint(name='2. World of Birds (Simple Data)',
                   coords=[(18.361960, -34.017224)])
pnt.iconstyle.icon.href = 'http://maps.google.com/mapfiles/kml/paddle/2.png'
# Uncomment the following line to display the data in a prettier format than the default table
#pnt.balloonstyle.text = """$[WOW/visitors] <b>$[WOW/visitors/displayName]</b> come to the World of Birds to walk through $[WOW/aviaries] <b>$[WOW/aviaries/displayName]</b> to see $[WOW/birds] <b>$[WOW/birds/displayName]</b>."""

# Add extended data to the point
Example #2
0
# Create the KML document
kml = Kml(name="Tracks", open=1)
doc = kml.newdocument(name='GPS device',
                      snippet=Snippet('Created Wed Jun 2 15:33:39 2010'))
doc.lookat.gxtimespan.begin = '2010-05-28T02:02:09Z'
doc.lookat.gxtimespan.end = '2010-05-28T02:02:56Z'
doc.lookat.longitude = -122.205544
doc.lookat.latitude = 37.373386
doc.lookat.range = 1300.000000

# Create a folder
fol = doc.newfolder(name='Tracks')

# Create a schema for extended data: heart rate, cadence and power
schema = kml.newschema()
schema.newgxsimplearrayfield(name='heartrate',
                             type=Types.int,
                             displayname='Heart Rate')
schema.newgxsimplearrayfield(name='cadence',
                             type=Types.int,
                             displayname='Cadence')
schema.newgxsimplearrayfield(name='power',
                             type=Types.float,
                             displayname='Power')

# Create a new track in the folder
trk = fol.newgxtrack(name='2010-05-28T01:16:35.000Z')

# Apply the above schema to this track
trk.extendeddata.schemadata.schemaurl = schema.id
def write_track_kml(csvreader):
    """
    Inputs: csv contains lon/lat
    Output:	glider track kml file
    """
    coord = []
    timerange = []

    lat_f = int(cfg.get(section1, "LAT_COLUMN"))
    lon_f = int(cfg.get(section1, "LON_COLUMN"))
    date_f = int(cfg.get(section1, "DATE_COLUMN"))
    date_fmt = cfg.get(section1, "DATE_FORMAT")
    kml_dir = cfg.get(section1, "KML_DIR")
    mission_date = cfg.get(section1, "MISSION_START_DATE")
    organization = cfg.get(section1, "ORGANIZATION")
    vehicle_name = cfg.get(section1, "VEHICLE_NAME")
    kml_title = cfg.get(section1, "KML_DOC_TITLE")
    kml_lookat_lon = float(cfg.get(section1, "KML_LOOKAT_LON"))
    kml_lookat_lat = float(cfg.get(section1, "KML_LOOKAT_LAT"))
    kml_lookat_range = float(cfg.get(section1, "KML_LOOKAT_RANGE"))
    kml_cdata_title = cfg.get(section1, "KML_CDATA_TITLE")
    plot_url = cfg.get(section1, "PLOT_URL")
    plot_width = int(cfg.get(section1, "PLOT_WIDTH"))
    plot_height = int(cfg.get(section1, "PLOT_HEIGHT"))
    plot_temp = cfg.get(section1, "PLOT_TEMP")
    plot_oxyg = cfg.get(section1, "PLOT_OXYG")
    plot_sali = cfg.get(section1, "PLOT_SALI")
    plot_chlo = cfg.get(section1, "PLOT_CHLO")
    plot_cdom = cfg.get(section1, "PLOT_CDOM")
    icon_url = cfg.get(section1, "ICON_URL")
    icon_normal_scale = cfg.get(section1, "ICON_NORMAL_SCALE")
    icon_normal_color = cfg.get(section1, "ICON_NORMAL_COLOR")
    icon_normal_width = cfg.get(section1, "ICON_NORMAL_WIDTH")
    icon_highlight_url = cfg.get(section1, "ICON_HIGHLIGHT_URL")
    icon_highlight_scale = cfg.get(section1, "ICON_HIGHLIGHT_SCALE")
    icon_highlight_color = cfg.get(section1, "ICON_HIGHLIGHT_COLOR")
    icon_highlight_width = cfg.get(section1, "ICON_HIGHLIGHT_WIDTH")
    path_line_color = cfg.get(section1, "PATH_LINE_COLOR")
    path_line_width = int(cfg.get(section1, "PATH_LINE_WIDTH"))

    csvheader = cfg.get(section1, "CSV_HEADER")
    if csvheader == "YES":
        csvreader.next()
    else:
        pass

    for row in csvreader:
        coord.append((row[lon_f - 1], row[lat_f - 1], 0.0))  # -1 for python order
        timestamp = time.strptime(row[date_f - 1], date_fmt)
        kmltime = time.strftime("%Y-%m-%dT%H:%M:%SZ", timestamp)  # KML requires specific time format
        timerange.append(kmltime)  # time stamp

    # This constructs the KML document from the CSV file.
    kml = Kml(name="%s %s" % (organization, vehicle_name))
    doc = kml.newdocument(name="%s" % kml_title, snippet=Snippet(timerange[0]))
    doc.lookat.gxtimespan.begin = timerange[0]
    doc.lookat.gxtimespan.end = timerange[-1]
    doc.lookat.longitude = kml_lookat_lon
    doc.lookat.latitude = kml_lookat_lat
    doc.lookat.range = kml_lookat_range
    # Create a folder
    ge_dir = doc.newfolder(name="Tracks")
    # Create a schema for extended data: heart rate, cadence and power
    schema = kml.newschema()

    # Create a new track in the folder
    trk = ge_dir.newgxtrack(name="%s %s" % (organization, vehicle_name))
    desc1 = "<![CDATA[\n%s<br />\n<br />\n" % kml_cdata_title
    desc2 = "<a href='%s/glider.html' target='_blank'>Link to Plot</a><br />\n" % plot_url
    desc_temp = "<img src='%s/%s' height='%d' width='%d' /><br />\n" % (plot_url, plot_temp, plot_height, plot_width)
    desc_oxyg = "<img src='%s/%s' height='%d' width='%d' /><br />\n" % (plot_url, plot_oxyg, plot_height, plot_width)
    desc_sali = "<img src='%s/%s' height='%d' width='%d' /><br />\n" % (plot_url, plot_sali, plot_height, plot_width)
    desc_chlo = "<img src='%s/%s' height='%d' width='%d' /><br />\n" % (plot_url, plot_chlo, plot_height, plot_width)
    desc_cdom = "<img src='%s/%s' height='%d' width='%d' /><br />\n" % (plot_url, plot_cdom, plot_height, plot_width)
    desc3 = "]]>\n"
    trk.description = desc1 + desc2 + desc_temp + desc_oxyg + desc_sali + desc_chlo + desc_cdom + desc3
    # Apply the above schema to this track
    trk.extendeddata.schemadata.schemaurl = schema.id
    # Add all information to the track
    trk.newwhen(timerange)  # Each item in the give nlist will become a new <when> tag
    trk.newgxcoord(coord)  # Ditto

    # Style
    trk.stylemap.normalstyle.iconstyle.icon.href = icon_url
    trk.stylemap.normalstyle.iconstyle.scale = icon_normal_scale
    trk.stylemap.normalstyle.linestyle.color = icon_normal_color
    trk.stylemap.normalstyle.linestyle.width = icon_normal_width
    trk.stylemap.highlightstyle.iconstyle.icon.href = icon_highlight_url
    trk.stylemap.highlightstyle.iconstyle.scale = icon_highlight_scale
    trk.stylemap.highlightstyle.linestyle.color = icon_highlight_color
    trk.stylemap.highlightstyle.linestyle.width = icon_highlight_width

    # Create a path line
    gpath = kml.newlinestring(name="%s %s" % (organization, vehicle_name))
    gpath.description = trk.description
    gpath.timespan.begin = timerange[0]
    gpath.timespan.end = ""
    gpath.coords = coord
    gpath.style.linestyle.color = path_line_color
    gpath.style.linestyle.width = path_line_width

    # Check if KML Directory exists
    if not os.path.exists(kml_dir):
        os.makedirs(kml_dir)

    # Save the KML
    kml.save("%s/Glider_%s_%s_%s.kml" % (kml_dir, organization, vehicle_name, mission_date))
    print("Glider_%s_%s_%s.kml created in '%s' folder" % (organization, vehicle_name, mission_date, kml_dir))
    def plot_the_files(self, results, issi, google, gps, firstplot):
        """
        Receives the results and an issi's to plot
        :param firstplot:
        :param gps:
        :param google:
        :param results:
        :param issi:
        :return:
        """

        when = []
        coord = []
        speeds = []
        headings = []
        times = []
        year = results[issi][0][1][6:10]
        month = results[issi][0][1][3:5]
        day = results[issi][0][1][0:2]

        kml = Kml(name="{}_{}-{}-{}".format(issi, year, month, day), open=1)
        doc = kml.newdocument(name="{}".format(issi),
                              snippet=Snippet('Created {}-{}-{}'.format(
                                  year, month, day)))

        for x in range(0, len(results[issi])):
            tup = (results[issi][x][3], results[issi][x][2])
            theTime = results[issi][x][1][11:]
            when.append("{}-{}-{}T{}Z".format(year, month, day, theTime))
            coord.append(tup)
            speeds.append(int(results[issi][x][4]))
            headings.append(int(results[issi][x][5]))
            times.append(results[issi][x][1])

        # Create circle track
        if gps[0] != 0 and firstplot:

            R = 6378.1
            d = float(gps[2])  # distance
            circle_coords = []

            lat1 = radians(float(gps[0]))
            lon1 = radians(float(gps[1]))

            for b in range(1, 360):
                brng = radians(b)
                lat2 = asin(
                    sin(lat1) * cos(d / R) +
                    cos(lat1) * sin(d / R) * cos(brng))
                lon2 = lon1 + atan2(
                    sin(brng) * sin(d / R) * cos(lat1),
                    cos(d / R) - sin(lat1) * sin(lat2))
                lat2 = degrees(lat2)
                lon2 = degrees(lon2)
                circle_coords.append((lon2, lat2))

            doc2 = kml.newdocument(name="Search Area",
                                   snippet=Snippet('{}-{}-{}'.format(
                                       gps[0], gps[1], gps[2])))
            fol2 = doc2.newfolder(name='Search Area')
            trk2 = fol2.newgxtrack(name='search area')
            trk2.newgxcoord(circle_coords)
            trk2.stylemap.normalstyle.linestyle.color = '641400FF'
            trk2.stylemap.normalstyle.linestyle.width = 6

        # Folder
        fol = doc.newfolder(name='Tracks')

        # schema for extra data
        schema = kml.newschema()
        schema.newgxsimplearrayfield(name='speed',
                                     type=Types.int,
                                     displayname='Speed')
        schema.newgxsimplearrayfield(name='heading',
                                     type=Types.int,
                                     displayname='Heading')
        schema.newgxsimplearrayfield(name='time',
                                     type=Types.string,
                                     displayname='Time')

        # New Track
        trk = fol.newgxtrack(name=issi)

        # Apply Schema
        trk.extendeddata.schemadata.schemaurl = schema.id

        # add all info to track
        trk.newwhen(when)
        trk.newgxcoord(coord)
        trk.extendeddata.schemadata.newgxsimplearraydata('time', times)
        trk.extendeddata.schemadata.newgxsimplearraydata('speed', speeds)
        trk.extendeddata.schemadata.newgxsimplearraydata('heading', headings)

        # Styling
        trk.stylemap.normalstyle.iconstyle.icon.href = 'http://maps.google.com/mapfiles/kml/shapes/track.png'
        trk.stylemap.normalstyle.linestyle.color = '99ffac59'
        trk.stylemap.normalstyle.linestyle.width = 6
        trk.stylemap.highlightstyle.iconstyle.icon.href = 'http://maps.google.com/mapfiles/kml/shapes/track.png'
        trk.stylemap.highlightstyle.iconstyle.scale = 1.2
        trk.stylemap.highlightstyle.linestyle.color = '99ffac59'
        trk.stylemap.highlightstyle.linestyle.width = 8
        kml.save("results/{}_{}-{}-{}.kml".format(issi, year, month, day))

        if google:
            try:
                os.system(
                    "start " +
                    "results/{}_{}-{}-{}.kml".format(issi, year, month, day))
            except:
                pass
Example #5
0
power = [327.0, 177.0, 179.0, 162.0, 166.0, 177.0, 183.0]

# Create the KML document
kml = Kml(name="Tracks", open=1)
doc = kml.newdocument(name='GPS device', snippet=Snippet('Created Wed Jun 2 15:33:39 2010'))
doc.lookat.gxtimespan.begin = '2010-05-28T02:02:09Z'
doc.lookat.gxtimespan.end = '2010-05-28T02:02:56Z'
doc.lookat.longitude = -122.205544
doc.lookat.latitude = 37.373386
doc.lookat.range = 1300.000000

# Create a folder
fol = doc.newfolder(name='Tracks')

# Create a schema for extended data: heart rate, cadence and power
schema = kml.newschema()
schema.newgxsimplearrayfield(name='heartrate', type=Types.int, displayname='Heart Rate')
schema.newgxsimplearrayfield(name='cadence', type=Types.int, displayname='Cadence')
schema.newgxsimplearrayfield(name='power', type=Types.float, displayname='Power')

# Create a new track in the folder
trk = fol.newgxtrack(name='2010-05-28T01:16:35.000Z')

# Apply the above schema to this track
trk.extendeddata.schemadata.schemaurl = schema.id

# Add all the information to the track
trk.newwhen(when) # Each item in the give nlist will become a new <when> tag
trk.newgxcoord(coord) # Ditto
trk.extendeddata.schemadata.newgxsimplearraydata('heartrate', heartrate) # Ditto
trk.extendeddata.schemadata.newgxsimplearraydata('cadence', cadence) # Ditto
Example #6
0
kml = Kml(name="ExtendedData", open=1)

# Data Example---------------------------------------------------------------------------------------------------------
# Create and style a point
pnt = kml.newpoint(name='1. World of Birds (Data)', coords =[(18.361960,-34.016543)])
pnt.iconstyle.icon.href = 'http://maps.google.com/mapfiles/kml/paddle/1.png'

# Add the Data to the point
pnt.extendeddata.newdata(name='birds', value=400, displayname="Bird Species")
pnt.extendeddata.newdata(name='aviaries', value=100, displayname="Aviaries")
pnt.extendeddata.newdata(name='visitors', value=10000, displayname="Annual Visitors")


# Simple Data Example -------------------------------------------------------------------------------------------------
# Create a schema
schema = kml.newschema(name='WOW')

schema.newsimplefield(name='birds', type='int', displayname='Bird Species')
schema.newsimplefield(name='aviaries', type='int', displayname='Aviaries')
schema.newsimplefield(name='visitors', type='int', displayname='Annual Visitors')

# Create and style a point
pnt = kml.newpoint(name='2. World of Birds (Simple Data)', coords =[(18.361960,-34.017224)])
pnt.iconstyle.icon.href = 'http://maps.google.com/mapfiles/kml/paddle/2.png'
# Uncomment the following line to display the data in a prettier format than the default table
#pnt.balloonstyle.text = """$[WOW/visitors] <b>$[WOW/visitors/displayName]</b> come to the World of Birds to walk through $[WOW/aviaries] <b>$[WOW/aviaries/displayName]</b> to see $[WOW/birds] <b>$[WOW/birds/displayName]</b>."""

# Add extended data to the point
pnt.extendeddata.schemadata.schemaurl = schema.id
pnt.extendeddata.schemadata.newsimpledata('birds', 400)
pnt.extendeddata.schemadata.newsimpledata('aviaries', 100)
Example #7
0
    def kml_convert(self, base_name):
        """Function to read and convert a DBI3 log file to KML format

        If called with base_name=None, parse the log file but return a SummaryList with
        parse status and skip the actual KML creation.

        Args:
            base_name: Base path and filename for output - add extension

        Returns: int, str
            int - 0=success, 1=warning, -1=error
            str - Success info or warning/error message
        """
        # TODO handle optional GPS altitude completely
        #
        # Determine unit conversion for additional data fields
        # Allow additional data fields to be english or metric
        if not self.kml_cfg.kml_use_metric:
            temp_is_f = True  # False=centegrade
            alt_is_ft = True  # False=meters
            spd_is_mph = True  # False=kph
            roc_is_fps = True  # False=meters per second
        else:
            temp_is_f = False
            roc_is_fps = False
            spd_is_mph = False
            alt_is_ft = False

        # check the status of the log_parse()
        if self.dbi3_log.data_recs == 0:
            return 1, "No GPS data records, skip KML file generations"
        elif self.dbi3_log.data_recs < 0:
            return -1, "No END record, skip KML file generation"

        # fw ver 1.3 added GPS altitude.  If we have both we use the preferred (pressure/GPS)
        # altitude in the track points and add the other as an additional data field.
        add_pressure_alt = False
        add_gps_alt = False
        if len(self.dbi3_log.kml_gps_msl) > 0:
            if self.dbi3_log.kml_coord_alt_gps:
                add_pressure_alt = True
            else:
                add_gps_alt = True

        # Establish unit of measure strings depending on Metric vs English measures
        tempStr = "F" if temp_is_f else "C"
        sogStr = "MPH" if spd_is_mph else "mps"
        distStr = "mi" if spd_is_mph else "m"
        rocStr = "FPM" if roc_is_fps else "mps"
        altStr = "ft" if alt_is_ft else "m"

        # avg_sog in meters/second
        avg_sog = (self.dbi3_log.elapsed_dist /
                   (self.dbi3_log.kml_end_time -
                    self.dbi3_log.kml_start_time).total_seconds())

        e_hr, remainder = divmod(
            int((self.dbi3_log.kml_end_time -
                 self.dbi3_log.kml_start_time).total_seconds()), 3600)
        e_min, e_sec = divmod(remainder, 60)

        if self.kml_cfg.track_note:
            t_note = "<b>{}</b>\n".format(self.kml_cfg.track_note)
        else:
            t_note = ""

        # Our 'trip computer' values are formatted into a KML description string to be included in
        # the track object.
        property_table = """<![CDATA[{}\
<table>
<tr><td><b>Distance </b>{:.2f} {}</td><tr>
<tr><td><b>Min Alt </b>{:.2f} {}</td><tr>
<tr><td><b>Max Alt </b>{:.2f} {}</td><tr>
<tr><td><b>Avg Speed </b>{:.2f} {}</td><tr>
<tr><td><b>Max Speed </b>{:.2f}(SOG {:.2f}) {}</td><tr>
<tr><td><b>Start Time </b>{}</td><tr>
<tr><td><b>End Time </b>{}</td><tr>
<tr><td><b>Elapsed </b>{:02d}:{:02d}:{:02d}</td><tr>
<tr><td>DBI3  {}  FWVER {}</td><tr>
<tr><td>Formatted {}</td><tr>
</table>]]>""".format(
            t_note,
            conv_M_to_mi(self.dbi3_log.elapsed_dist)
            if spd_is_mph else self.dbi3_log.elapsed_dist,
            distStr,
            conv_M_to_ft(self.dbi3_log.min_altitude)
            if alt_is_ft else self.dbi3_log.min_altitude,
            altStr,
            conv_M_to_ft(self.dbi3_log.max_altitude)
            if alt_is_ft else self.dbi3_log.max_altitude,
            altStr,
            conv_M_to_mi(avg_sog * 60 * 60) if spd_is_mph else avg_sog,
            sogStr,
            conv_M_to_mi(self.dbi3_log.max_computed_sog * 60 *
                         60) if spd_is_mph else self.dbi3_log.max_computed_sog,
            conv_M_to_mi(self.dbi3_log.max_sog * 60 *
                         60) if spd_is_mph else self.dbi3_log.max_sog,
            sogStr,
            self.dbi3_log.kml_start_time.strftime("%Y-%m-%d %H:%M:%S"),
            self.dbi3_log.kml_end_time.strftime("%Y-%m-%d %H:%M:%S"),
            e_hr,
            e_min,
            e_sec,
            self.app_config.sn,
            self.dbi3_log.dbi3_fwver,
            datetime.now().strftime("%Y-%m-%d %H:%M:%S"),
        )

        #
        # Moving on to KML generation

        # Create the KML document
        kml = Kml(
            open=1,
            name=self.dbi3_log.kml_start_time.strftime("%Y%m%d_%H%MZ_DBI3"),
            description=property_table,
        )
        # doc = kml.newdocument(name=kml_start.strftime('%Y%m%d_%H%MZ_Track'), description=property_table)
        # snippet=Snippet('DBI3LogConversion run ' + datetime.now().isoformat(' ')))
        doc = kml
        # kml timespan is based on the first and last valid data record, not DBI3 log start/end.
        # doc.lookat.gxtimespan.begin = kml_start.isoformat('T')
        # doc.lookat.gxtimespan.end = kml_end.isoformat('T')
        # doc.lookat.longitude = max_lon - ((max_lon - min_lon) / 2)
        # doc.lookat.latitude = max_lat - ((max_lat - min_lat) / 2)
        # doc.lookat.range = calc_distance((min_lat, min_lon), (max_lat, max_lon)) * 1.5

        # Create a folder
        # fol = doc.newfolder(name='Tracks')
        fol = doc

        # Create a schema for extended data
        schema = kml.newschema()
        if add_gps_alt:
            schema.newgxsimplearrayfield(name="g_alt",
                                         type=Types.float,
                                         displayname="GPS ALT " + altStr)
        if add_pressure_alt:
            schema.newgxsimplearrayfield(name="p_alt",
                                         type=Types.float,
                                         displayname="PRES ALT " + altStr)
        if "AMBT" in self.kml_cfg.kml_fields:
            schema.newgxsimplearrayfield(name="a_temp",
                                         type=Types.float,
                                         displayname="Ambient " + tempStr)
        if "TOPT" in self.kml_cfg.kml_fields:
            schema.newgxsimplearrayfield(name="t_temp",
                                         type=Types.float,
                                         displayname="Top " + tempStr)
        if "DIFF" in self.kml_cfg.kml_fields:
            schema.newgxsimplearrayfield(name="d_temp",
                                         type=Types.float,
                                         displayname="Diff " + tempStr)
        if "COG" in self.kml_cfg.kml_fields:
            schema.newgxsimplearrayfield(name="cog",
                                         type=Types.float,
                                         displayname="COG")
        if "SOG" in self.kml_cfg.kml_fields:
            schema.newgxsimplearrayfield(name="sog",
                                         type=Types.float,
                                         displayname="SOG " + sogStr)
        if "ROC" in self.kml_cfg.kml_fields:
            schema.newgxsimplearrayfield(name="roc",
                                         type=Types.float,
                                         displayname="ROC " + rocStr)
        if "BATM" in self.kml_cfg.kml_fields:
            schema.newgxsimplearrayfield(name="batm",
                                         type=Types.float,
                                         displayname="BAT V")
        if "BRDT" in self.kml_cfg.kml_fields:
            schema.newgxsimplearrayfield(name="brdt",
                                         type=Types.float,
                                         displayname="BRD " + tempStr)

        # Create a new track in the folder
        trk = fol.newgxtrack(
            name=self.dbi3_log.kml_start_time.strftime("%Y%m%d_%H%MZ Track"),
            altitudemode=self.kml_cfg.
            altitudemode,  # absolute, clampToGround, relativeToGround
            extrude=self.kml_cfg.extend_to_ground,
            description=property_table,
        )
        trk.lookat.gxtimespan.begin = self.dbi3_log.kml_start_time.isoformat(
            "T")
        trk.lookat.gxtimespan.end = self.dbi3_log.kml_end_time.isoformat("T")
        trk.lookat.longitude = self.dbi3_log.max_lon - (
            (self.dbi3_log.max_lon - self.dbi3_log.min_lon) / 2)
        trk.lookat.latitude = self.dbi3_log.max_lat - (
            (self.dbi3_log.max_lat - self.dbi3_log.min_lat) / 2)
        trk.lookat.range = (calc_distance(
            (self.dbi3_log.min_lat, self.dbi3_log.min_lon),
            (self.dbi3_log.max_lat, self.dbi3_log.max_lon),
        ) * 1.5)

        # Apply the above schema to this track
        trk.extendeddata.schemadata.schemaurl = schema.id

        #
        # Add all the information to the track
        #
        # Each item in the give nlist will become a new <when> tag
        trk.newwhen(self.dbi3_log.kml_when)
        trk.newgxcoord(self.dbi3_log.kml_coord)

        # Add points to the start and end of the track
        pnt = fol.newpoint(name="Start",
                           coords=[(self.dbi3_log.kml_start_lon,
                                    self.dbi3_log.kml_start_lat)])
        pnt.description = self.dbi3_log.kml_start_time.isoformat("T")
        pnt.style.labelstyle.color = KML_START_COLOR
        pnt.style.iconstyle.icon.href = (
            "http://maps.google.com/mapfiles/kml/shapes/placemark_circle.png")
        pnt = fol.newpoint(name="Finish",
                           coords=[(self.dbi3_log.kml_end_lon,
                                    self.dbi3_log.kml_end_lat)])
        pnt.description = self.dbi3_log.kml_end_time.isoformat("T")
        pnt.style.labelstyle.color = KML_END_COLOR
        pnt.style.iconstyle.icon.href = (
            "http://maps.google.com/mapfiles/kml/shapes/placemark_circle.png")

        # Add any additional data fields that are requested
        if add_gps_alt:
            trk.extendeddata.schemadata.newgxsimplearraydata(
                "g_alt", self.dbi3_log.kml_gps_msl)
        if add_pressure_alt:
            trk.extendeddata.schemadata.newgxsimplearraydata(
                "p_alt", self.dbi3_log.kml_alt)
        if "AMBT" in self.kml_cfg.kml_fields:
            trk.extendeddata.schemadata.newgxsimplearraydata(
                "a_temp", self.dbi3_log.kml_a_temp)
        if "TOPT" in self.kml_cfg.kml_fields:
            trk.extendeddata.schemadata.newgxsimplearraydata(
                "t_temp", self.dbi3_log.kml_t_temp)
        if "DIFF" in self.kml_cfg.kml_fields:
            trk.extendeddata.schemadata.newgxsimplearraydata(
                "d_temp", self.dbi3_log.kml_diff_t)
        if "COG" in self.kml_cfg.kml_fields:
            trk.extendeddata.schemadata.newgxsimplearraydata(
                "cog", self.dbi3_log.kml_cog)
        if "SOG" in self.kml_cfg.kml_fields:
            trk.extendeddata.schemadata.newgxsimplearraydata(
                "sog", self.dbi3_log.kml_sog)
        if "ROC" in self.kml_cfg.kml_fields:
            trk.extendeddata.schemadata.newgxsimplearraydata(
                "roc", self.dbi3_log.kml_roc)
        if "BATM" in self.kml_cfg.kml_fields:
            trk.extendeddata.schemadata.newgxsimplearraydata(
                "batm", self.dbi3_log.kml_batm)
        if "BRDT" in self.kml_cfg.kml_fields:
            trk.extendeddata.schemadata.newgxsimplearraydata(
                "brdt", self.dbi3_log.kml_brdt)

        # Styling
        trk.stylemap.normalstyle.iconstyle.icon.href = (
            "http://earth.google.com/images/kml-icons/track-directional/track-0.png"
        )
        trk.stylemap.normalstyle.linestyle.color = KML_LINE_COLOR
        trk.stylemap.normalstyle.linestyle.width = 3
        trk.stylemap.highlightstyle.iconstyle.icon.href = (
            "http://earth.google.com/images/kml-icons/track-directional/track-0.png"
        )
        trk.stylemap.highlightstyle.iconstyle.scale = 1.2
        trk.stylemap.highlightstyle.linestyle.color = KML_LINE_COLOR
        trk.stylemap.highlightstyle.linestyle.width = 8

        # Save the kml to file
        kml.save(base_name + ".kml")

        return 0, self.dbi3_log.proc_log