diff --git a/sites/all/modules/kml/gml.inc b/sites/all/modules/kml/gml.inc
new file mode 100644
index 0000000..a9bf9c7
--- /dev/null
+++ b/gml.inc
@@ -0,0 +1,124 @@
+<?php
+// $Id: gml.inc,v 1.1.2.4 2010/05/19 14:29:42 tmcw Exp $
+
+/**
+ * @file WKT to GML converter
+ * Adapted from OpenLayers
+ */
+
+//TODO: namespace or encapsulate into a class
+
+define('NS_GML', 'http://www.opengis.net/gml');
+
+/**
+ * @param $wkt string of WKT data
+ * @return $geometry array of parsed geometry
+ *
+ * This function is not intended to be tested:
+ * it is parsing geometries into an internal format.
+ */
+function parse_wkt($wkt) {
+  $type_string = '/^\s*(\w+)\s*\(\s*(.*)\s*\)\s*$/';
+  $paren_comma = '/\)\s*,\s*\(/';
+  $trim_parens = '/^\s*\(?(.*?)\)?\s*$/';
+
+  $geometry = array();
+  if (preg_match($type_string, $wkt, $matches)) {
+    $type = strtolower($matches[1]);
+
+    if ($type == 'polygon' ||
+        $type == 'geometrycollection' ||
+        $type == 'point') {
+      $content = $matches[2];
+      $rings = preg_split($paren_comma, $content);
+      $rings = preg_replace($trim_parens, '$1', $rings);
+
+      foreach ($rings as $ring) {
+        $r = array();
+        $points = explode(',', $ring);
+
+        foreach ($points as $point) {
+          $r[] = trim($point);
+        }
+        $geometry[] = $r;
+      }
+    }
+  }
+
+  return $geometry;
+}
+
+/**
+ * @param $geometry array of parsed geometry
+ * @return $gml string of GML XML
+ */
+function geometry_to_gml($geometry) {
+  $doc = new SimpleXMLElement(
+    "<gml:polygon xmlns:gml='http://www.opengis.net/gml'></gml:polygon>");
+  $gml = $doc->addChild('Polygon', '', NS_GML);
+  $outer = TRUE;
+
+  foreach ($geometry as $ring) {
+    if ($outer) {
+      $boundary = $gml->addChild('exterior', '', NS_GML);
+      $outer = FALSE;
+    } else {
+      $boundary = $gml->addChild('interior', '', NS_GML);
+    }
+
+    $linear_ring = $boundary->addChild('gml:LinearRing', '', NS_GML);
+    $pos = $linear_ring->addChild('gml:posList', implode(' ', $ring), NS_GML);
+    $pos->addAttribute('decimal', '.');
+  }
+
+  // this workaround required by the fact that 
+  // ->asXML() on root elements will produce XML opening and 
+  // closing tags
+  return $doc->children(NS_GML)->asXML();
+}
+
+
+/**
+ * @param $geometry array of parsed geometry
+ * @return $kml string of KML XML
+ */
+function geometry_to_multigeometry_kml($geometry) {
+  $doc = new SimpleXMLElement("<MultiGeometry></MultiGeometry>");
+  $kml = $doc->addChild('MultiGeometry');
+  foreach ($geometry as $ring) {
+    foreach ($ring as $point) {
+      // Extract coordinates from POINT element
+      $coordinates = check_plain(str_replace(array('POINT(', ')', ' '), array('', '', ','), $point)).',0';
+      $root_point = $kml->addChild('Point');
+      $coordinates = $root_point->addChild('coordinates', $coordinates);
+    }
+  }
+  return $doc->children()->asXML();
+}
+
+/**
+ * Convert WKT to GML
+ * @param $wkt a string of wkt
+ * @return $gml a string of gml (or FALSE if no features)
+ *
+ * This is a convenience function for converting wkt to gml
+ */
+function wkt_to_gml($wkt) {
+  $geometry = parse_wkt($wkt);
+  return empty($geometry) ? FALSE : geometry_to_gml($geometry);
+}
+
+
+/**
+ * Convert WKT to GML
+ * @param $wkt a string of wkt
+ * @return $gml a string of gml (or FALSE if no features)
+ *
+ * This is a convenience function for converting wkt to MultiGeometry element collection
+ */
+function wkt_to_kml($wkt) {
+  $geometry = parse_wkt($wkt);
+  return empty($geometry) ? FALSE : geometry_to_multigeometry_kml($geometry);
+}
+
+
diff --git a/sites/all/modules/kml/kml.module b/sites/all/modules/kml/kml.module
index b982f00..b660dd8 100644
--- a/kml.module
+++ b/kml.module
@@ -27,6 +27,12 @@ function kml_theme() {
       'template' => 'kml-placemark',
       'path' => $path . "/views",
     ),
+    'kml_placemark_wkt' => array(
+      'arguments' => array('point' => array(), 'points' => array()),
+      'file' => 'kml_views.theme.inc',
+      'template' => 'kml-placemark-wkt',
+      'path' => $path . "/views",
+    ),
     'kml_feed_icon' => array(
       'arguments' => array(),
       'file' => 'kml_views.theme.inc',
diff --git a/sites/all/modules/kml/views/kml-placemark-wkt.tpl.php b/sites/all/modules/kml/views/kml-placemark-wkt.tpl.php
new file mode 100644
index 0000000..828d77f
--- /dev/null
+++ b/views/kml-placemark-wkt.tpl.php
@@ -0,0 +1,12 @@
+<Placemark>
+  <name>
+    <![CDATA[<?php print strip_tags($name) ?>]]>
+  </name>
+  <description>
+    <![CDATA[<?php print $description ?>]]>
+  </description>
+  <?php if ($styleURL): ?>
+    <styleUrl><?php echo $styleURL; ?></styleUrl>
+  <?php endif; ?>
+  <?php print $geometry ?>
+</Placemark>
diff --git a/sites/all/modules/kml/views/kml_views.theme.inc b/sites/all/modules/kml/views/kml_views.theme.inc
index 0ff8486..89e4755 100644
--- a/views/kml_views.theme.inc
+++ b/views/kml_views.theme.inc
@@ -13,7 +13,12 @@ function template_preprocess_views_view_kml(&$vars) {
   $style = theme('kml_style', $points);
 
   foreach ($points as $point) {
-    $rows .= theme('kml_placemark', $point, $points);
+    if ($vars['options']['data_source']['provider'] == 'openlayers_wkt' && $point['wkt']) {
+      $rows .= theme('kml_placemark_wkt', $point, $points);
+    }
+    elseif ($vars['options']['data_source']['provider'] == 'lat_lon' && $point['point']) {
+      $rows .= theme('kml_placemark', $point, $points);
+    }
   }
      
   $vars['rows'] = $rows;
@@ -51,9 +56,26 @@ function template_preprocess_kml_placemark(&$vars) {
 }
 
 /**
+ * Preprocess for theme('kml_placemark_wkt').
+ */
+function template_preprocess_kml_placemark_wkt(&$vars) {
+  $vars['name'] = filter_xss_admin($vars['point']['name']);
+  $vars['description'] = filter_xss_admin($vars['point']['description']);
+  $vars['geometry'] = $vars['point']['wkt'];
+  $vars['styleURL'] = check_plain($vars['point']['styleURL']);
+
+  // Create a variable for every field that is unassigned, (is not Name, Desc,
+  // Lat, or Lon.) These can be used in custom kml-placemark-wkt.tpl.php theme
+  // implementations, each as $content['VARNAME'].
+  foreach($vars['point']['content'] as $key => $value) {
+    $vars['content'][$key] = filter_xss_admin($value);
+  }
+}
+
+/**
  * Theme function for feed icon.
  */
 function theme_kml_feed_icon() {
   $icon = drupal_get_path('module', 'kml').'/images/kml.png';
   return theme('image', $icon, t('KML icon'), t('Download KML Feed'));
-}
\ No newline at end of file
+}
diff --git a/sites/all/modules/kml/views/views_plugin_style_kml.inc b/sites/all/modules/kml/views/views_plugin_style_kml.inc
index 7a10856..f9670ef 100644
--- a/views/views_plugin_style_kml.inc
+++ b/views/views_plugin_style_kml.inc
@@ -38,8 +38,6 @@ class views_plugin_style_kml extends views_plugin_style {
     $field_options = array(
       'name' => t('Name'),
       'description' => t('Description'),
-      'longitude' => t('Longitude'),
-      'latitude' => t('Latitude'),
     );
     
     foreach ($field_options as $k => $v) {
@@ -90,8 +88,6 @@ class views_plugin_style_kml extends views_plugin_style {
       $field_options = array(
         'name' => t('Name'),
         'description' => t('Description'),
-        'longitude' => t('Longitude'),
-        'latitude' => t('Latitude'),
       );
       $form['filename'] = array(
         '#type' => 'textfield',
@@ -104,11 +100,62 @@ class views_plugin_style_kml extends views_plugin_style {
       $form['fields'] = array(
         '#type' => 'fieldset',
         '#title' => 'Field usage',
-        '#description' => t('Select the fields that contain the latitude,
-        longitude and title of each point. Remaining fields will be available
-        as <em>$content[\'VARNAME\']</em> in <em>kml-placemark.tpl.php</em>.'),
+        '#description' => t('Select the fields that contain the title of each
+        point. Remaining fields will be available as <em>$content[\'VARNAME\']
+        </em> in <em>kml-placemark.tpl.php</em>.'),
         '#weight' => -10,
       );
+      $form['data_source'] = array(
+       '#type' => 'fieldset',
+       '#title' => t('Lat/Long source'),
+       '#description' => t('Select the fields that contain latitude and longitude of each point.'),
+       '#tree' => TRUE,
+       '#collapsible' => FALSE,
+      );
+      $form['data_source']['provider'] = array(
+        '#type' => 'select',
+        '#title' => t('Map Data Sources'),
+        '#description' => t('Choose which sources of data to provide latitude and langitude values.'),
+        '#options' => array(
+          'lat_lon' => t('Lat/Lon Points'),
+          'openlayers_wkt' => t('OpenLayers WKT')
+        ),
+        '#default_value' => ($this->options['data_source']['provider'] ? $this->options['data_source']['provider'] : ''),
+        '#required' => TRUE,
+      );
+      if (count($field_names > 0)) {
+        $form['data_source']['lat'] = array(
+          '#type' => 'select',
+          '#title' => t('Latitude Field'),
+          '#description' => t('Choose a field for Latitude.  This should be a field that is a decimal or float value.'),
+          '#options' => $field_names,
+          '#default_value' => $this->options['data_source']['lat'],
+          '#process' => array('views_process_dependency'),
+          '#dependency' => array('edit-style-options-data-source-provider' => array('lat_lon')),
+       //   '#required' => TRUE
+        );
+        $form['data_source']['lon'] = array(
+         '#type' => 'select',
+          '#title' => t('Longitude Field'),
+           '#description' => t('Choose a field for Longitude.  This should be a field that is a decimal or float value.'),
+          '#options' => $field_names,
+          '#default_value' => $this->options['data_source']['lon'],
+          '#process' => array('views_process_dependency'),
+          '#dependency' => array('edit-style-options-data-source-provider' => array('lat_lon')),
+        //  '#required' => TRUE
+        );
+        // Other: WKT
+        $form['data_source']['openlayers_wkt'] = array(
+          '#type' => 'select',
+          '#title' => t('WKT Field'),
+          '#description' => t('Choose the OpenLayers WKT field.'),
+          '#options' => $field_names,
+          '#default_value' => $this->options['data_source']['openlayers_wkt'],
+          '#process' => array('views_process_dependency'),
+          '#dependency' => array('edit-style-options-data-source-provider' => array('openlayers_wkt')),
+         // '#required' => TRUE
+        );
+      }
       foreach ($field_options as $k => $v) {
         $form['fields'][$k] = array(
           '#type' => 'select',
@@ -121,6 +168,29 @@ class views_plugin_style_kml extends views_plugin_style {
     }
   }
 
+
+  function kml_points_prerender($options, $field, &$point) {
+    static $data_source;
+    /* Select correct data source to get lat/long values */
+    if (!$data_source) {
+      $data_source = $options['provider'];
+    }
+    switch ($data_source) {
+      case 'openlayers_wkt':
+        include_once(drupal_get_path('module', 'kml').'/gml.inc');
+        $point['wkt'] = wkt_to_kml($field[$options['openlayers_wkt']]);
+        error_log(print_r($point['wkt'],1),0);
+      break;
+      case 'lat_lon':
+        $lat = $field[$options['lat']];
+        $lon = $field[$options['lon']];
+        $point['point'] = $lon . ',' . $lat . ',0';
+        unset($point['lat']);
+        unset($point['lon']);
+      break;
+    }
+  }
+
   function map_rows($rows) {
     // Fields must be rendered in order as of Views 2.3, 
     // so we will pre-render everything.
@@ -143,20 +213,13 @@ class views_plugin_style_kml extends views_plugin_style {
         elseif ($key == $this->options['fields']['description']) {
           $point['description'] = $row[$key];
         }
-        elseif ($key == $this->options['fields']['longitude']) {
-          $point['lon'] = $row[$key];
-        }
-        elseif ($key == $this->options['fields']['latitude']) {
-          $point['lat'] = $row[$key];
-        }
         else{
           $point['content'][$key] = $row[$key];
         }
       }
 
-      $point['point'] = $point['lon'] . ',' . $point['lat'] . ',0';
-      unset($point['lat']);
-      unset($point['lon']);
+      /* Lat/Long pre render */
+      $this->kml_points_prerender($this->options['data_source'], $row, $point);
 
       if ($this->options['linestring']['enable']) {
         $points[$point['group']][] = $point;
