text: """
  Copyright 2011-2015 Kyle Lancaster
  
  This program is free software: you can redistribute it and/or modify
  it under the terms of the GNU General Public License as published by
  the Free Software Foundation, either version 3 of the License, or
  (at your option) any later version.
  
  This program is distributed in the hope that it will be useful,
  but WITHOUT ANY WARRANTY; without even the implied warranty of
  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  GNU General Public License for more details.
  
  You should have received a copy of the GNU General Public License
  along with this program.  If not, see <http://www.gnu.org/licenses/>.
  
  Contact me at kyle.lan@gmail.com
  """
  
  from simplekml.abstractview import Camera, LookAt
  from simplekml.base import Kmlable, Snippet, OverlayXY, ScreenXY, RotationXY, Size, check
  from simplekml.coordinates import Coordinates
  from simplekml.icon import Icon, Link
  from simplekml.model import Location, Orientation, Scale, ResourceMap
  from simplekml.overlay import ViewVolume, ImagePyramid
  from simplekml.region import LatLonBox, GxLatLonQuad, Region
  from simplekml.schema import ExtendedData, Schema
  from simplekml.styleselector import Style, StyleMap
  from simplekml.substyle import IconStyle, LabelStyle, BalloonStyle, LineStyle, ListStyle, PolyStyle
  from simplekml.timeprimitive import TimeSpan, TimeStamp
  from simplekml.tour import GxTour
  
  
  class Feature(Kmlable):
      """Abstract class extended by all features.
  
      The arguments are the same as the properties.
  
      .. note::
        Not to be used directly.
      """
  
      _id = 0
      def __init__(self,
                   name=None,
                   visibility=None,
                   open=None,
                   atomauthor=None,
                   atomlink=None,
                   address=None,
                   xaladdressdetails=None,
                   phonenumber=None,
                   snippet=None,
                   description=None,
                   camera=None,
                   lookat=None,
                   timestamp=None,
                   timespan=None,
                   region=None,
                   extendeddata=None,
                   gxballoonvisibility=None):
          Feature._id += 1
          super(Feature, self).__init__()
          self._kml['name'] = name
          self._kml['visibility'] = visibility
          self._kml['open'] = open
          self._kml['atom:author'] = atomauthor
          self._kml['atom:link'] = atomlink
          self._kml['address'] = address
          self._kml['xal:AddressDetails'] = xaladdressdetails
          self._kml['phoneNumber'] = phonenumber
          self._kml['description'] = description
          self._kml['Camera'] = camera
          self._kml['LookAt'] = lookat
          self._kml['snippet_'] = snippet
          self._kml['TimeStamp_'] = timestamp
          self._kml['TimeSpan_'] = timespan
          self._kml['Region'] = region
          self._kml['styleUrl'] = None
          self._kml['ExtendedData'] = extendeddata
          self._kml['gx:balloonVisibility'] = gxballoonvisibility
          self._id = "feat_{0}".format(Feature._id)
          self._style = None
          self._stylemap = None
          self._features = []
          self._styles = []
          self._stylemaps = []
          self._folders = []
  
      @property
      def id(self):
          """The id string."""
          return self._id
  
      @property
      def name(self):
          """Name of placemark, accepts string."""
          return self._kml['name']
  
      @name.setter
      def name(self, name):
          self._kml['name'] = name
  
      @property
      def visibility(self):
          """Whether the feature is shown, accepts int 0 or 1."""
          return self._kml['visibility']
  
      @visibility.setter
      def visibility(self, visibility):
          self._kml['visibility'] = visibility
  
      @property
      def open(self):
          """Whether open or closed in Places panel, accepts int 0 or 1."""
          return self._kml['open']
  
      @open.setter
      def open(self, open):
          self._kml['open'] = open
  
      @property
      def atomauthor(self):
          """Author of the feature, accepts string."""
          return self._kml['atom:author']
  
      @atomauthor.setter
      def atomauthor(self, atomauthor):
          self._kml['atom:author'] = atomauthor
  
      @property
      def atomlink(self):
          """URL containing this KML, accepts string."""
          return self._kml['atom:link']
  
      @atomlink.setter
      def atomlink(self, atomlink):
          self._kml['atom:link'] = atomlink
  
      @property
      def address(self):
          """Standard address, accepts string."""
          return self._kml['address']
  
      @address.setter
      def address(self, address):
          self._kml['address'] = address
  
      @property
      def xaladdressdetails(self):
          """Address in xAL format, accepts string.
  
          .. note::
              There seems to be a bug in Google Earth where the inclusion of the namespace
              xmlns:xal="urn:oasis:names:tc:ciq:xsdschema:xAL:2.0" seems to break some other elements of the KML such
              as touring (a tour will not play). If xaladdressdetails is used the above namespace will be added to the
              KML and will possibly break other elements. Use with caution.
          """
          return self._kml['xal:AddressDetails']
  
      @xaladdressdetails.setter
      def xaladdressdetails(self, xaladdressdetails):
          self._kml['xal:AddressDetails'] = xaladdressdetails
  
      @property
      def phonenumber(self):
          """Phone number used by Google Maps mobile, accepts string."""
          return self._kml['phoneNumber']
  
      @phonenumber.setter
      def phonenumber(self, phonenumber):
          self._kml['phoneNumber'] = phonenumber
  
      @property
      def description(self):
          """Description shown in the information balloon, accepts string."""
          return self._kml['description']
  
      @description.setter
      def description(self, description):
          self._kml['description'] = description
  
      @property
      def gxballoonvisibility(self):
          """
          Toggles visibility of a description balloon, accepts int 0 or 1
  
          *New in version 1.1.1*
          """
          return self._kml['gx:balloonVisibility']
  
      @gxballoonvisibility.setter
      def gxballoonvisibility(self, gxballoonvisibility):
          self._kml['gx:balloonVisibility'] = gxballoonvisibility
  
      @property
      def camera(self):
          """Camera that views the scene, accepts :class:`simplekml.Camera`"""
          if self._kml['Camera'] is None:
              self._kml['Camera'] = Camera()
              self._kml['LookAt'] = None
          return self._kml['Camera']
  
      @camera.setter
      @check(Camera)
      def camera(self, camera):
          self._kml['Camera'] = camera
          self._kml['LookAt'] = None
  
      @property
      def lookat(self):
          """Camera relative to the feature, accepts :class:`simplekml.LookAt`"""
          if self._kml['LookAt'] is None:
              self._kml['LookAt'] = LookAt()
              self._kml['Camera'] = None
          return self._kml['LookAt']
  
      @lookat.setter
      @check(LookAt)
      def lookat(self, lookat):
          self._kml['Camera'] = None
          self._kml['LookAt'] = lookat
  
      @property
      def snippet(self):
          """Short description of the feature, accepts :class:`simplekml.Snippet`"""
          if self._kml['snippet_'] is None:
              self._kml['snippet_'] = Snippet()
          return self._kml['snippet_']
  
      @snippet.setter
      @check(Snippet)
      def snippet(self, snippet):
          self._kml['snippet_'] = snippet
  
      @property
      def extendeddata(self):
          """Extra data for the feature."""
          if self._kml['ExtendedData'] is None:
              self._kml['ExtendedData'] = ExtendedData()
          return self._kml['ExtendedData']
  
      @extendeddata.setter
      @check(ExtendedData)
      def extendeddata(self, extendeddata):
          self._kml['ExtendedData'] = extendeddata
  
      @property
      def timestamp(self):
          """Single moment in time, accepts :class:`simplekml.TimeStamp`"""
          if self._kml['TimeStamp_'] is None:
              self._kml['TimeStamp_'] = TimeStamp()
          return self._kml['TimeStamp_']
  
      @timestamp.setter
      @check(TimeStamp)
      def timestamp(self, timestamp):
          self._kml['TimeStamp_'] = timestamp
  
      @property
      def timespan(self):
          """Period of time, accepts :class:`simplekml.TimeSpan`"""
          if self._kml['TimeSpan_'] is None:
              self._kml['TimeSpan_'] = TimeSpan()
          return self._kml['TimeSpan_']
  
      @timespan.setter
      @check(TimeSpan)
      def timespan(self, timespan):
          self._kml['TimeSpan_'] = timespan
  
      @property
      def region(self):
          """Bounding box of feature, accepts :class:`simplekml.Region`"""
          if self._kml['Region'] is None:
              self._kml['Region'] = Region()
          return self._kml['Region']
  
      @region.setter
      @check(Region)
      def region(self, region):
          self._kml['Region'] = region
  
      @property
      def id(self):
          """Id number of feature, read-only."""
          return self._id
  
      @property
      def style(self):
          """The current style of the feature, accepts :class:`simplekml.Style`"""
          if self._style is None:
              self._style = Style()
              self._setstyle(self._style)
              self._addstyle(self._style)
          return self._style
  
      @style.setter
      @check(Style)
      def style(self, style):
          self._setstyle(style)
          self._addstyle(style)
          self._style = style
  
      @property
      def stylemap(self):
          """The current StyleMap of the feature, accepts :class:`simplekml.StyleMap`"""
          if self._stylemap is None:
              self._stylemap = StyleMap()
              self._setstyle(self._stylemap)
              self._addstylemap(self._stylemap)
          return self._stylemap
  
      @stylemap.setter
      @check(StyleMap)
      def stylemap(self, stylemap):
          self._setstyle(stylemap)
          self._addstylemap(stylemap)
          self._stylemap = stylemap
  
      @property
      def styleurl(self):
          """Reference to the current styleurl or the feature, accepts string."""
          return self._kml['styleUrl']
  
      @styleurl.setter
      def styleurl(self, styleurl):
          self._kml['styleUrl'] = styleurl
  
      @property
      def iconstyle(self):
          """IconStyle of the feature, accepts :class:`simplekml.IconStyle`"""
          return self.style.iconstyle
  
      @iconstyle.setter
      @check(IconStyle)
      def iconstyle(self, iconstyle):
          self.style.iconstyle = iconstyle
  
      @property
      def labelstyle(self):
          """LabelStyle of the feature, accepts :class:`simplekml.LabelStyle`"""
          return self.style.labelstyle
  
      @labelstyle.setter
      @check(LabelStyle)
      def labelstyle(self, labelstyle):
          self.style.labelstyle = labelstyle
  
      @property
      def linestyle(self):
          """LineStyle of the feature, accepts :class:`simplekml.LineStyle`"""
          return self.style.linestyle
  
      @linestyle.setter
      @check(LineStyle)
      def linestyle(self, linestyle):
          self.style.linestyle = linestyle
  
      @property
      def polystyle(self):
          """PolyStyle of the feature, accepts :class:`simplekml.PolyStyle`"""
          return self.style.polystyle
  
      @polystyle.setter
      @check(PolyStyle)
      def polystyle(self, polystyle):
          self.style.polystyle = polystyle
  
      @property
      def balloonstyle(self):
          """BalloonStyle of the feature, accepts :class:`simplekml.BalloonStyle`"""
          return self.style.balloonstyle
  
      @balloonstyle.setter
      @check(BalloonStyle)
      def balloonstyle(self, balloonstyle):
          self.style.balloonstyle = balloonstyle
  
      @property
      def liststyle(self):
          """ListStyle of the feature, accepts :class:`simplekml.ListStyle`"""
          return self.style.liststyle
  
      @liststyle.setter
      @check(ListStyle)
      def liststyle(self, liststyle):
          self.style.liststyle = liststyle
  
      def _addstyle(self, style):
          """Attaches the given style (style) to this feature."""
          if style not in self._styles:
              self._styles.append(style)
  
      def _addstylemap(self, style):
          """Attaches the given style (style) to this feature."""
          if style not in self._stylemaps:
              self._stylemaps.append(style)
  
      def _setstyle(self, style):
          self._kml['styleUrl'] = "#{0}".format(style.id)
  
      def __str__(self):
          buf = []
          for stylemap in self._stylemaps:
              self._addstyle(stylemap.normalstyle)
              self._addstyle(stylemap.highlightstyle)
          str = '<{0} id="{1}">'.format(self.__class__.__name__, self._id)
          buf.append(str)
          for style in self._styles:
              buf.append(style.__str__())
          for stylemap in self._stylemaps:
              buf.append(stylemap.__str__())
          buf.append(super(Feature, self).__str__())
          for folder in self._folders:
              buf.append(folder.__str__())
          for feat in self._features:
              buf.append(feat.__str__())
          buf.append("</{0}>".format(self.__class__.__name__))
          return "".join(buf)
  
  
  class Container(Feature):
      """Abstract class, extended by :class:`simplekml.Document` and :class:`simplekml.Folder`
  
      Arguments are the same as :class:`simplekml.Feature`
  
      .. note::
         Not to be used directly.
      """
      def __init__(self, **kwargs):
          super(Container, self).__init__(**kwargs)
  
      @property
      def features(self):
          """Returns a list of all the features that have been attached to this container.
  
          *New in version 1.1.0*
          """
          feats = []
          for feat in self._features:
              if isinstance(feat, Placemark):
                  feats.append(feat.geometry)
              else:
                  feats.append(feat)
          return feats
  
      @property
      def allfeatures(self):
          """Returns a list of all the features that have been attached to this container, and all sub features.
  
          *New in version 1.1.0*
          """
          feats = []
          for feat in self.features:
              if isinstance(feat, Container):
                  feats += feat.allfeatures
              feats.append(feat)
          return feats
  
      @property
      def geometries(self):
          """Returns a list of all the geometries that have been attached to this container.
  
          *New in version 1.1.0*
          """
          return [i for i in self.features if isinstance(i, Geometry)]
  
      @property
      def allgeometries(self):
          """Returns a list of all the geometries that have been attached to this container, and all sub geometries.
  
          *New in version 1.1.0*
          """
          return [i for i in self.allfeatures if isinstance(i, Geometry)]
  
      @property
      def containers(self):
          """Returns a list of all the containers that have been attached to this container.
  
          *New in version 1.1.0*
          """
          return [i for i in self.features if isinstance(i, Container)]
  
      @property
      def allcontainers(self):
          """Returns a list of all the containers that have been attached to this container, and all sub containers.
  
          *New in version 1.1.0*
          """
          feats = []
          for feat in self.containers:
              if isinstance(feat, Container):
                  feats += feat.allcontainers
              feats.append(feat)
          return feats
  
      @property
      def styles(self):
          """Returns a list of all the styles that have been attached to this container.
  
          *New in version 1.1.0*
          """
          return self._styles
  
      @property
      def allstyles(self):
          """Returns a list of all the styles that have been attached to this container, and all sub styles.
  
          *New in version 1.1.0*
          """
          return [style for container in self.allcontainers for style in container.styles]
  
      @property
      def stylemaps(self):
          """Returns a list of all the stylemaps that have been attached to this container.
  
          *New in version 1.1.0*
          """
          return self._stylemaps
  
      @property
      def allstylemaps(self):
          """Returns a list of all the stylemaps that have been attached to this container, and all sub stylemaps.
  
          *New in version 1.1.0*
          """
          return [stylemap for container in self.allcontainers for stylemap in container.stylemaps]
  
      def _newfeature(self, cls, **kwargs):
          """Creates a new feature from the given class and attaches it to this
          feature.
          """
          feat = cls(**kwargs)
          feat._parent = self
          if isinstance(feat, Geometry):
              self._features.append(feat._placemark)
              feat._parent = self
              if feat._style is not None:
                  self._addstyle(feat._style)
          else:
              self._features.append(feat)
          return feat
  
      def newpoint(self, **kwargs):
          """Creates a new :class:`simplekml.Point` and attaches it to this KML document.
  
          Arguments are the same as :class:`simplekml.Point`
  
          Returns:
            * an instance of :class:`simplekml.Point` class.
          """
          return self._newfeature(Point, **kwargs)
  
      def newlinestring(self, **kwargs):
          """Creates a new :class:`simplekml.LineString` and attaches it to this KML document.
  
          Arguments are the same as :class:`simplekml.LineString`
  
          Returns:
            * an instance of :class:`simplekml.LineString` class.
          """
          return self._newfeature(LineString, **kwargs)
  
      def newpolygon(self, **kwargs):
          """Creates a new :class:`simplekml.Polygon` and attaches it to this KML document.
  
          Arguments are the same as :class:`simplekml.Polygon`
  
          Returns:
            * an instance of :class:`simplekml.Polygon` class.
          """
          return self._newfeature(Polygon, **kwargs)
  
      def newmultigeometry(self, **kwargs):
          """Creates a new :class:`simplekml.MultiGeometry` and attaches it to this KML document.
  
          Arguments are the same as :class:`simplekml.MultiGeometry`
  
          Returns:
            * an instance of :class:`simplekml.MultiGeometry` class.
          """
          return self._newfeature(MultiGeometry, **kwargs)
  
      def newgroundoverlay(self, **kwargs):
          """Creates a new :class:`simplekml.GroundOverlay` and attaches it to this KML document.
  
          Arguments are the same as :class:`simplekml.GroundOverlay`
  
          Returns:
            * an instance of :class:`simplekml.GroundOverlay` class.
          """
          return self._newfeature(GroundOverlay, **kwargs)
  
      def newscreenoverlay(self, **kwargs):
          """Creates a new :class:`simplekml.ScreenOverlay` and attaches it to this KML document.
  
          Arguments are the same as :class:`simplekml.ScreenOverlay`
  
          Returns:
            * an instance of :class:`simplekml.ScreenOverlay` class.
          """
          return self._newfeature(ScreenOverlay, **kwargs)
  
      def newphotooverlay(self, **kwargs):
          """Creates a new :class:`simplekml.PhotoOverlay` and attaches it to this KML document.
  
          Arguments are the same as :class:`simplekml.PhotoOverlay`
  
          Returns:
            * an instance of :class:`simplekml.PhotoOverlay` class.
          """
          return self._newfeature(PhotoOverlay, **kwargs)
  
      def newmodel(self, **kwargs):
          """Creates a new :class:`simplekml.Model` and attaches it to this KML document.
  
          Arguments are the same as :class:`simplekml.Model`
  
          Returns:
            * an instance of :class:`simplekml.Model` class.
          """
          return self._newfeature(Model, **kwargs)
  
      def newgxtrack(self, **kwargs):
          """Creates a new :class:`simplekml.GxTrack` and attaches it to this KML document.
  
          Arguments are the same as :class:`simplekml.GxTrack`
  
          Returns:
            * an instance of :class:`simplekml.GxTrack` class.
          """
          return self._newfeature(GxTrack, **kwargs)
  
      def newgxmultitrack(self, **kwargs):
          """Creates a new :class:`simplekml.GxMultiTrack` and attaches it to this KML document.
  
          Arguments are the same as :class:`simplekml.GxMultiTrack`
  
          Returns:
            * an instance of :class:`simplekml.GxMultiTrack` class.
          """
          return self._newfeature(GxMultiTrack, **kwargs)
  
      def newfolder(self, **kwargs):
          """Creates a new :class:`simplekml.Folder` and attaches it to this KML document.
  
          Arguments are the same as :class:`simplekml.Folder`
  
          Returns:
            * an instance of :class:`simplekml.Folder` class.
          """
          return self._newfeature(Folder, **kwargs)
  
      def newdocument(self, **kwargs):
          """Creates a new :class:`simplekml.Folder` and attaches it to this KML document.
  
          Arguments are the same as :class:`simplekml.Folder`
  
          Returns:
            * an instance of :class:`simplekml.Folder` class.
          """
          return self._newfeature(Document, **kwargs)
  
      def newnetworklink(self, **kwargs):
          """Creates a new :class:`simplekml.NetworkLink` and attaches it to this KML document.
  
          Arguments are the same as :class:`simplekml.NetworkLink`
  
          Returns:
            * an instance of :class:`simplekml.NetworkLink` class.
          """
          return self._newfeature(NetworkLink, **kwargs)
  
      def newgxtour(self, **kwargs):
          """Creates a new :class:`simplekml.GxTour` and attaches it to this KML document.
  
          Arguments are the same as :class:`simplekml.GxTour`
  
          Returns:
            * an instance of :class:`simplekml.NetworkLink` class.
          """
          return self._newfeature(GxTour, **kwargs)
  
  
  class Document(Container):
      """A container for features and styles.
  
      Arguments are the same as the properties.
  
      Usage::
  
          import simplekml
          kml = simplekml.Kml()
          doc = kml.newdocument(name='A Document')
          pnt = doc.newpoint()
          kml.save("Document.kml")
      """
  
      def __init__(self, **kwargs):
          super(Document, self).__init__(**kwargs)
  
      def newschema(self, **kwargs):
          """Creates a new :class:`simplekml.Schema` and attaches it to this KML document.
  
          Arguments are the same as :class:`simplekml.Schema`
  
          Returns:
            * an instance of :class:`simplekml.Schema` class.
          """
          return self._newfeature(Schema, **kwargs)
  
  
  class Folder(Container):
      """A container for features that act like a folder.
  
      Arguments are the same as the properties.
  
      Usage::
  
          import simplekml
          kml = simplekml.Kml()
          fol = kml.newfolder(name='A Folder')
          pnt = fol.newpoint()
          kml.save("Folder.kml")
      """
  
      def __init__(self, **kwargs):
          super(Folder, self).__init__(**kwargs)
  
  
  class Geometry(Kmlable):
      """Abstract class for all Geometries.
  
      Arguments are the same as :class:`simplekml.Placemark`
      
      .. note::
         Not to be used directly.
      """
      _id = 0
      def __init__(self, **kwargs):
          super(Geometry, self).__init__()
          self._id = "geom_{0}".format(Geometry._id)
          Geometry._id += 1
          self._placemark = Placemark(**kwargs)
          self._placemark.geometry = self
          self._parent = None
          self._style = None
          self._stylemap = None
  
  
      @property
      def id(self):
          """The id string."""
          return self._id
  
      @property
      def name(self):
          """Name of placemark, accepts string."""
          return self._placemark.name
  
      @name.setter
      def name(self, name):
          self._placemark.name = name
  
      @property
      def visibility(self):
          """Whether the feature is shown, accepts int 0 or 1."""
          return self._placemark.visibility
  
      @visibility.setter
      def visibility(self, visibility):
          self._placemark.visibility = visibility
  
      @property
      def atomauthor(self):
          """Author of the feature, accepts string."""
          return self._placemark.atomauthor
  
      @atomauthor.setter
      def atomauthor(self, atomauthor):
          self._placemark.atomauthor = atomauthor
  
      @property
      def atomlink(self):
          """URL containing this KML, accepts string."""
          return self._placemark.atomlink
  
      @atomlink.setter
      def atomlink(self, atomlink):
          self._placemark.atomlink = atomlink
  
      @property
      def address(self):
          """Standard address, accepts string."""
          return self._placemark.address
  
      @address.setter
      def address(self, address):
          self._placemark.address = address
  
      @property
      def xaladdressdetails(self):
          """Address in xAL format, accepts string."""
          return self._placemark.xaladdressdetails
  
      @xaladdressdetails.setter
      def xaladdressdetails(self, xaladdressdetails):
          self._placemark.xaladdressdetails = xaladdressdetails
  
      @property
      def phonenumber(self):
          """Phone number used by Google Maps mobile, accepts string."""
          return self._placemark.phonenumber
  
      @phonenumber.setter
      def phonenumber(self, phonenumber):
          self._placemark.phonenumber = phonenumber
  
      @property
      def description(self):
          """Description shown in the information balloon, accepts string."""
          return self._placemark.description
  
      @description.setter
      def description(self, description):
          self._placemark.description = description
  
      @property
      def gxballoonvisibility(self):
          """
          Toggles visibility of a description balloon, accepts int 0 or 1
  
          *New in version 1.1.1*
          """
          return self._placemark.gxballoonvisibility
  
      @gxballoonvisibility.setter
      def gxballoonvisibility(self, gxballoonvisibility):
          self._placemark.gxballoonvisibility = gxballoonvisibility
  
      @property
      def camera(self):
          """Camera that views the scene, accepts :class:`simplekml.Camera`"""
          if self._placemark.camera is None:
              self._placemark.camera = Camera()
          return self._placemark.camera
  
      @camera.setter
      @check(Camera)
      def camera(self, camera):
          self._placemark.camera = camera
  
      @property
      def lookat(self):
          """Camera relative to the feature, accepts :class:`simplekml.LookAt`"""
          if self._placemark.lookat is None:
              self._placemark.lookat = LookAt()
          return self._placemark.lookat
  
      @lookat.setter
      @check(LookAt)
      def lookat(self, lookat):
          self._placemark.lookat = lookat
  
      @property
      def snippet(self):
          """Short description of the feature, accepts :class:`simplekml.Snippet`"""
          return self._placemark.snippet
  
      @snippet.setter
      @check(Snippet)
      def snippet(self, snippet):
          self._placemark.snippet = snippet
  
      @property
      def extendeddata(self):
          """Short description of the feature, accepts :class:`simplekml.Snippet`"""
          return self._placemark.extendeddata
  
      @extendeddata.setter
      @check(ExtendedData)
      def extendeddata(self, extendeddata):
          self._placemark.extendeddata = extendeddata
  
      @property
      def timespan(self):
          """Period of time, accepts :class:`simplekml.TimeSpan`"""
          return self._placemark.timespan
  
      @timespan.setter
      @check(TimeSpan)
      def timespan(self, timespan):
          self._placemark.timespan = timespan
  
      @property
      def timestamp(self):
          """Single moment in time, accepts :class:`simplekml.TimeStamp`"""
          return self._placemark.timestamp
  
      @timestamp.setter
      @check(TimeStamp)
      def timestamp(self, timestamp):
          self._placemark.timestamp = timestamp
  
      @property
      def region(self):
          """Bounding box of feature, accepts :class:`simplekml.Region`"""
          return self._placemark.region
  
      @region.setter
      @check(Region)
      def region(self, region):
          self._placemark.region = region
  
      @property
      def style(self):
          """The current style of the feature, accepts :class:`simplekml.Style`"""
          if self._style is None:
              self._style = Style()
              self._placemark._setstyle(self._style)
              if self._parent is not None:
                  self._parent._addstyle(self._style)
          return self._style
  
      @style.setter
      @check(Style)
      def style(self, style):
          self._placemark._setstyle(style)
          if self._parent is not None:
              self._parent._addstyle(style)
          self._style = style
  
      @property
      def stylemap(self):
          """The current StyleMap of the feature, accepts :class:`simplekml.StyleMap`"""
          if self._stylemap is None:
              self._stylemap = StyleMap()
              self._placemark._setstyle(self._stylemap)
              if self._parent is not None:
                  self._parent._addstylemap(self._stylemap)
          return self._stylemap
  
      @stylemap.setter
      @check(StyleMap)
      def stylemap(self, stylemap):
          self._placemark._setstyle(stylemap)
          if self._parent is not None:
              self._parent._addstylemap(stylemap)
          self._stylemap = stylemap
  
      @property
      def iconstyle(self):
          """IconStyle of the feature, accepts :class:`simplekml.IconStyle`"""
          return self.style.iconstyle
  
      @iconstyle.setter
      @check(IconStyle)
      def iconstyle(self, iconstyle):
          self.style.iconstyle = iconstyle
  
      @property
      def labelstyle(self):
          """LabelStyle of the feature, accepts :class:`simplekml.LabelStyle`"""
          return self.style.labelstyle
  
      @labelstyle.setter
      @check(LabelStyle)
      def labelstyle(self, labelstyle):
          self.style.labelstyle = labelstyle
  
      @property
      def linestyle(self):
          """LineStyle of the feature, accepts :class:`simplekml.LineStyle`"""
          return self.style.linestyle
  
      @linestyle.setter
      @check(LineStyle)
      def linestyle(self, linestyle):
          self.style.linestyle = linestyle
  
      @property
      def polystyle(self):
          """PolyStyle of the feature, accepts :class:`simplekml.PolyStyle`"""
          return self.style.polystyle
  
      @polystyle.setter
      @check(PolyStyle)
      def polystyle(self, polystyle):
          self.style.polystyle = polystyle
  
      @property
      def balloonstyle(self):
          """BalloonStyle of the feature, accepts :class:`simplekml.BalloonStyle`"""
          return self.style.balloonstyle
  
      @balloonstyle.setter
      @check(BalloonStyle)
      def balloonstyle(self, balloonstyle):
          self.style.balloonstyle = balloonstyle
  
      @property
      def liststyle(self):
          """ListStyle of the feature, accepts :class:`simplekml.ListStyle`"""
          return self.style.liststyle
  
      @liststyle.setter
      @check(ListStyle)
      def liststyle(self, liststyle):
          self.style.liststyle = liststyle
      
      @property
      def placemark(self):
          """The placemark that contains this feature, read-only."""
          return self._placemark
  
  
  class Placemark(Feature):
      """A Placemark is a Feature with associated Geometry.
  
      Args:
        * geometry: any class that inherits from :class:`simplekml.Geometry`
        * *all other args same as* :class:`simplekml.Feature`
  
      .. note::
         Not to be used directly.
      """
  
      def __init__(self, geometry=None, **kwargs):
          super(Placemark, self).__init__(**kwargs)
          self._kml['Geometry_'] = geometry
  
      @property
      def geometry(self):
          """Accepts a class that inherits from :class:`simplekml.Geometry`"""
          return self._kml['Geometry_']
  
      @geometry.setter
      @check(Geometry, True)
      def geometry(self, geom):
          self._kml['Geometry_'] = geom
  
  
  class PointGeometry(Geometry):
      """Abstract class for any geometry requiring coordinates (not :class:`simplekml.Polygon`).
  
      Args:
        * coords: list of tuples (see :func:`simplekml.coords` for examples)
        * *all other args same as* :class:`simplekml.Geometry`
  
      .. note::
         Not to be used directly.
      """
      def __init__(self,
                   coords=(), **kwargs):
          super(PointGeometry, self).__init__(**kwargs)
          self._kml['coordinates'] = Coordinates()
          self._kml['coordinates'].addcoordinates(list(coords))
  
      @property
      def coords(self):
          """The coordinates of the feature, accepts list of tuples.
  
          A tuple represents a coordinate in the order longitude then latitude. The tuple has the option
          of specifying a height. If no height is given, it defaults to zero. A point feature has just one point,
          therefore a list with one tuple is given.
  
          Examples:
            * No height:      `[(1.0, 1.0), (2.0, 1.0)]`
            * Height:         `[(1.0, 1.0, 50.0), (2.0, 1.0, 10.0)]`
            * Point:          `[(1.0, 1.0)]` # longitude, latitude
            * Point + height: `[(1.0, 1.0, 100)]` # longitude, latitude, height of 100m
          """
          return self._kml['coordinates']
  
      @coords.setter
      def coords(self, coords):
          self._kml['coordinates'] = Coordinates()
          self._kml['coordinates'].addcoordinates(coords)
  
  
  class LinearRing(PointGeometry):
      """A closed line string, typically the outer boundary of a :class:`simplekml.Polygon`
  
      Arguments are the same as the properties.
  
      Usage::
  
          import simplekml
          kml = simplekml.Kml()
          pol = kml.newpolygon()
          print pol.outerboundaryis # Shows that the outer boundary of a polygon is a linear ring
          pol.outerboundaryis.coords = [(0.0,0.0), (1.0,1.0), (2.0,2.0)]
          kml.save("LinearRing.kml")
      """
      def __init__(self, coords=(),
                   extrude=None,
                   tessellate=None,
                   altitudemode=None,
                   gxaltitudemode=None,
                   gxaltitudeoffset=None,
                   **kwargs):
          super(LinearRing, self).__init__(list(coords), **kwargs)
          self._kml['extrude'] = extrude
          self._kml['tessellate'] = tessellate
          self._kml['altitudeMode'] = altitudemode
          self._kml['gx:altitudeMode'] = gxaltitudemode
          self._kml['gx:altitudeOffset'] = gxaltitudeoffset
  
      @property
      def extrude(self):
          """Connect the LinearRing to the ground, accepts int (0 or 1)."""
          return self._kml['extrude']
  
      @extrude.setter
      def extrude(self, extrude):
          self._kml['extrude'] = extrude
  
      @property
      def tessellate(self):
          """Allows the LinearRing to follow the terrain, accepts int (0 or 1)."""
          return self._kml['tessellate']
  
      @tessellate.setter
      def tessellate(self, tessellate):
          self._kml['tessellate'] = tessellate
  
      @property
      def altitudemode(self):
          """Specifies how the altitude for the Camera is interpreted.
  
          Accepts :class:`simplekml.AltitudeMode` constants.
          """
          return self._kml['altitudeMode']
  
      @altitudemode.setter
      def altitudemode(self, mode):
          self._kml['altitudeMode'] = mode
  
      @property
      def gxaltitudemode(self):
          """Specifies how the altitude for the Camera is interpreted.
  
          With the addition of being relative to the sea floor.
          Accepts :class:`simplekml.GxAltitudeMode` constants.
          """
          return self._kml['gx:altitudeMode']
  
      @gxaltitudemode.setter
      def gxaltitudemode(self, mode):
          self._kml['gx:altitudeMode'] = mode
  
      @property
      def gxaltitudeoffset(self):
          """How much to offsets the LinearRing vertically, accepts int."""
          return self._kml['gx:altitudeOffset']
  
      @gxaltitudeoffset.setter
      def gxaltitudeoffset(self, offset):
          self._kml['gx:altitudeOffset'] = offset
  
      def __str__(self):
          return '<LinearRing id="{0}">{1}</LinearRing>'.format(self._id, super(LinearRing, self).__str__())
  
  
  class Point(PointGeometry):
      """A geographic location defined by lon, lat, and altitude.
  
      Arguments are the same as the properties.
  
      Usage::
  
          import simplekml
          kml = simplekml.Kml()
          pnt = kml.newpoint(name='A Point')
          pnt.coords = [(1.0, 2.0)]
          kml.save("Point.kml")
  
      Styling a Single Point::
  
          import simplekml
          kml = simplekml.Kml()
          pnt = kml.newpoint(name='A Point')
          pnt.coords = [(1.0, 2.0)]
          pnt.style.labelstyle.color = simplekml.Color.red  # Make the text red
          pnt.style.labelstyle.scale = 2  # Make the text twice as big
          pnt.style.iconstyle.icon.href = 'http://maps.google.com/mapfiles/kml/shapes/placemark_circle.png'
          kml.save("Point Styling.kml")
  
      Sharing a Style with many Points (Shared Style)::
  
          import simplekml
          kml = simplekml.Kml()
          style = simplekml.Style()
          style.labelstyle.color = simplekml.Color.red  # Make the text red
          style.labelstyle.scale = 2  # Make the text twice as big
          style.iconstyle.icon.href = 'http://maps.google.com/mapfiles/kml/shapes/placemark_circle.png'
          for lon in range(2):  # Generate longitude values
              for lat in range(2): # Generate latitude values
                 pnt = kml.newpoint(name='Point: {0}{0}'.format(lon,lat))
                 pnt.style = style
          kml.save("Point Shared Style.kml")
      """
  
      def __init__(self,
                   extrude=None,
                   altitudemode=None,
                   gxaltitudemode=None,
                   **kwargs):
          super(Point, self).__init__(**kwargs)
          self._kml['extrude'] = extrude
          self._kml['altitudeMode'] = altitudemode
          self._kml['gx:altitudeMode'] = gxaltitudemode
  
      @property
      def extrude(self):
          """Connect the Point to the ground, accepts int (0 or 1)."""
          return self._kml['extrude']
  
      @extrude.setter
      def extrude(self, extrude):
          self._kml['extrude'] = extrude
  
      @property
      def altitudemode(self):
          """Specifies how the altitude for the Camera is interpreted.
  
          Accepts :class:`simplekml.AltitudeMode` constants.
          """
          return self._kml['altitudeMode']
  
      @altitudemode.setter
      def altitudemode(self, mode):
          self._kml['altitudeMode'] = mode
  
      @property
      def gxaltitudemode(self):
          """Specifies how the altitude for the Camera is interpreted.
  
          With the addition of being relative to the sea floor.
          Accepts :class:`simplekml.GxAltitudeMode` constants.
          """
          return self._kml['gx:altitudeMode']
  
      @gxaltitudemode.setter
      def gxaltitudemode(self, mode):
          self._kml['gx:altitudeMode'] = mode
  
      def __str__(self):
          return '<Point id="{0}">{1}</Point>'.format(self._id, super(Point, self).__str__())
  
  
  class LineString(PointGeometry):
      """A connected set of line segments.
  
      Arguments are the same as the properties.
  
      Usage::
  
          import simplekml
          kml = simplekml.Kml()
          ls = kml.newlinestring(name='A LineString')
          ls.coords = [(18.333868,-34.038274,10.0), (18.370618,-34.034421,10.0)]
          ls.extrude = 1
          ls.altitudemode = simplekml.AltitudeMode.relativetoground
          kml.save("LineString.kml")
  
      Styling::
  
          import simplekml
          kml = simplekml.Kml()
          ls = kml.newlinestring(name='A LineString')
          ls.coords = [(18.333868,-34.038274,10.0), (18.370618,-34.034421,10.0)]
          ls.extrude = 1
          ls.altitudemode = simplekml.AltitudeMode.relativetoground
          ls.style.linestyle.width = 5
          ls.style.linestyle.color = simplekml.Color.blue
          kml.save("LineString Styling.kml")
      """
      def __init__(self,
                   extrude=None,
                   tessellate=None,
                   altitudemode=None,
                   gxaltitudemode=None,
                   gxaltitudeoffset=None,
                   gxdraworder=None,
                   **kwargs):
          super(LineString, self).__init__(**kwargs)
          self._kml['extrude'] = extrude
          self._kml['tessellate'] = tessellate
          self._kml['altitudeMode'] = altitudemode
          self._kml['gx:altitudeMode'] = gxaltitudemode
          self._kml['gx:altitudeOffset'] = gxaltitudeoffset
          self._kml['gx:drawOrder'] = gxdraworder
  
      @property
      def extrude(self):
          """Connect the LinearRing to the ground, accepts int (0 or 1)."""
          return self._kml['extrude']
  
      @extrude.setter
      def extrude(self, extrude):
          self._kml['extrude'] = extrude
  
      @property
      def tessellate(self):
          """Allowe the LinearRing to follow the terrain, accepts int (0 or 1)."""
          return self._kml['tessellate']
  
      @tessellate.setter
      def tessellate(self, tessellate):
          self._kml['tessellate'] = tessellate
  
      @property
      def altitudemode(self):
          """Specifies how the altitude for the Camera is interpreted.
  
          Accepts :class:`simplekml.AltitudeMode` constants.
          """
          return self._kml['altitudeMode']
  
      @altitudemode.setter
      def altitudemode(self, mode):
          self._kml['altitudeMode'] = mode
  
      @property
      def gxaltitudemode(self):
          """Specifies how the altitude for the Camera is interpreted.
  
          With the addition of being relative to the sea floor.
          Accepts :class:`simplekml.GxAltitudeMode` constants.
          """
          return self._kml['gx:altitudeMode']
  
      @gxaltitudemode.setter
      def gxaltitudemode(self, mode):
          self._kml['gx:altitudeMode'] = mode
  
      @property
      def gxaltitudeoffset(self):
          """How much to offsets the LinearRing vertically, accepts int."""
          return self._kml['gx:altitudeOffset']
  
      @gxaltitudeoffset.setter
      def gxaltitudeoffset(self, offset):
          self._kml['gx:altitudeOffset'] = offset
  
      @property
      def gxdraworder(self):
          """The order to draw the linestring, accepts int."""
          return self._kml['gx:drawOrder']
  
      @gxdraworder.setter
      def gxdraworder(self, gxdraworder):
          self._kml['gx:drawOrder'] = gxdraworder
  
      def __str__(self):
          return '<LineString id="{0}">{1}</LineString>'.format(self._id, super(LineString, self).__str__())
  
  
  class Polygon(Geometry):
      """A Polygon is defined by an outer boundary and/or an inner boundary.
  
      Arguments are the same as the properties.
  
      Usage::
  
          import simplekml
          kml = simplekml.Kml()
          pol = kml.newpolygon(name='A Polygon')
          pol.outerboundaryis = [(18.333868,-34.038274), (18.370618,-34.034421),
                                 (18.350616,-34.051677),(18.333868,-34.038274)]
          pol.innerboundaryis = [(18.347171,-34.040177), (18.355741,-34.039730),
                                 (18.350467,-34.048388),(18.347171,-34.040177)]
          kml.save("Polygon.kml")
          
      Styling::
  
          import simplekml
          kml = simplekml.Kml()
          pol = kml.newpolygon(name='A Polygon')
          pol.outerboundaryis = [(18.333868,-34.038274), (18.370618,-34.034421),
                                 (18.350616,-34.051677),(18.333868,-34.038274)]
          pol.innerboundaryis = [(18.347171,-34.040177), (18.355741,-34.039730),
                                 (18.350467,-34.048388),(18.347171,-34.040177)]
          pol.style.linestyle.color = simplekml.Color.green
          pol.style.linestyle.width = 5
          pol.style.polystyle.color = simplekml.Color.changealphaint(100, simplekml.Color.green)
          kml.save("Polygon Styling.kml")
      """
  
      def __init__(self,
                   extrude=None,
                   tessellate=None,
                   altitudemode=None,
                   gxaltitudemode=None,
                   outerboundaryis=(),
                   innerboundaryis=(), **kwargs):
          super(Polygon, self).__init__(**kwargs)
          self._kml['extrude'] = extrude
          self._kml['tessellate'] = tessellate
          self._kml['altitudeMode'] = altitudemode
          self._kml['gx:altitudeMode'] = gxaltitudemode
          self._kml['outerBoundaryIs'] = LinearRing(list(outerboundaryis))
          self._kml['innerBoundaryIs'] = None
          self.innerboundaryis = list(innerboundaryis)
  
      @property
      def extrude(self):
          """Connect the LinearRing to the ground, accepts int (0 or 1)."""
          return self._kml['extrude']
  
      @extrude.setter
      def extrude(self, extrude):
          self._kml['extrude'] = extrude
  
      @property
      def tessellate(self):
          """Allows the Polygon to follow the terrain, accepts int (0 or 1)."""
          return self._kml['tessellate']
  
      @tessellate.setter
      def tessellate(self, tessellate):
          self._kml['tessellate'] = tessellate
  
      @property
      def altitudemode(self):
          """Specifies how the altitude for the Camera is interpreted.
  
          Accepts :class:`simplekml.AltitudeMode` constants.
          """
          return self._kml['altitudeMode']
  
      @altitudemode.setter
      def altitudemode(self, mode):
          self._kml['altitudeMode'] = mode
  
      @property
      def gxaltitudemode(self):
          """Specifies how the altitude for the Camera is interpreted.
  
          With the addition of being relative to the sea floor.
          Accepts :class:`simplekml.GxAltitudeMode` constants.
          """
          return self._kml['gx:altitudeMode']
  
      @gxaltitudemode.setter
      def gxaltitudemode(self, mode):
          self._kml['gx:altitudeMode'] = mode
  
      @property
      def innerboundaryis(self):
          """The inner boundaries.
  
          Accepts list of list of tuples of floats for multiple boundaries, or a
          list of tuples of floats for a single boundary.
          """
          return self._innerboundaryis
  
      @innerboundaryis.setter
      def innerboundaryis(self, rings):
          self._innerboundaryis = []
          if not len(rings):
              self._kml['innerBoundaryIs'] = None
          else:
              if type(rings[0]) == type(()):
                  rings = [rings]
              self._kml['innerBoundaryIs'] = ''
              for ring in rings:
                  self._kml['innerBoundaryIs'] += LinearRing(ring).__str__()
                  self._innerboundaryis.append(LinearRing(ring))
  
      @property
      def outerboundaryis(self):
          """The outer boundary, accepts a list of tuples of floats."""
          return self._kml['outerBoundaryIs']
  
      @outerboundaryis.setter
      def outerboundaryis(self, coords):
          self._kml['outerBoundaryIs'] = LinearRing(coords)
  
      def __str__(self):
          return '<Polygon id="{0}">{1}</Polygon>'.format(self._id, super(Polygon, self).__str__())
  
  
  class MultiGeometry(Geometry):
      """MultiGeometry is a collection of simple features (Points, LineStrings, etc).
  
      Arguments are the same as the properties.
  
      Usage::
  
          import simplekml
          kml = simplekml.Kml()
          multipnt = kml.newmultigeometry(name="MultiPoint")
          for lon in range(2):  # Generate longitude values
              for lat in range(2): # Generate latitude values
                  multipnt.newpoint(coords=[(lon, lat)])
          kml.save("MultiGeometry.kml")
          
      Styling::
  
          import simplekml
          kml = simplekml.Kml()
          multipnt = kml.newmultigeometry(name="MultiPoint")
          multipnt.style.labelstyle.scale = 0  # Remove the labels from all the points
          multipnt.style.iconstyle.color = simplekml.Color.red
          for lon in range(2):  # Generate longitude values
              for lat in range(2): # Generate latitude values
                  multipnt.newpoint(coords=[(lon, lat)])
          kml.save("MultiGeometry Styling.kml")
      """
  
      def __init__(self,
                   geometries=(), **kwargs):
          super(MultiGeometry, self).__init__(**kwargs)
          self._geometries = list(geometries)
  
      def _newfeature(self, cls, **kwargs):
          feat = cls(**kwargs)
          feat._parent = self._placemark
          self._geometries.append(feat)
          return feat
  
      def newpoint(self, **kwargs):
          """Creates a new :class:`simplekml.Point` and attaches it to this MultiGeometry.
  
          The arguments are the same as :class:`simplekml.Point`
  
          Returns:
            * an instance of :class:`simplekml.Point`
          """
          return self._newfeature(Point, **kwargs)
  
      def newlinestring(self, **kwargs):
          """Creates a new :class:`simplekml.LineString` and attaches it to this MultiGeometry.
  
          The arguments are the same as :class:`simplekml.LineString`
  
          Returns:
            * an instance of :class:`simplekml.LineString`
          """
          return self._newfeature(LineString, **kwargs)
  
      def newpolygon(self, **kwargs):
          """Creates a new :class:`simplekml.Polygon` and attaches it to this MultiGeometry.
  
          The arguments are the same as :class:`simplekml.Polygon`
  
          Returns:
            * an instance of :class:`simplekml.Polygon`
          """
          return self._newfeature(Polygon, **kwargs)
  
      def newgroundoverlay(self, **kwargs):
          """Creates a new :class:`simplekml.GroundOverlay` and attaches it to this MultiGeometry.
  
          The arguments are the same as :class:`simplekml.GroundOverlay`
  
          Returns:
            * an instance of :class:`simplekml.GroundOverlay`
          """
          return self._newfeature(GroundOverlay, **kwargs)
  
      def newscreenoverlay(self, **kwargs):
          """Creates a new :class:`simplekml.ScreenOverlay` and attaches it to this MultiGeometry.
  
          The arguments are the same as :class:`simplekml.ScreenOverlay`
  
          Returns:
            * an instance of :class:`simplekml.ScreenOverlay`
          """
          return self._newfeature(ScreenOverlay, **kwargs)
  
      def newphotooverlay(self, **kwargs):
          """Creates a new :class:`simplekml.PhotoOverlay` and attaches it to this MultiGeometry.
  
          The arguments are the same as :class:`simplekml.PhotoOverlay`
  
          Returns:
            * an instance of :class:`simplekml.PhotoOverlay`
          """
          return self._newfeature(PhotoOverlay, **kwargs)
  
      def newmodel(self, **kwargs):
          """Creates a new :class:`simplekml.Model` and attaches it to this MultiGeometry.
  
          The arguments are the same as :class:`simplekml.Model`
  
          Returns:
            * an instance of :class:`simplekml.Model`
          """
          return self._newfeature(Model, **kwargs)
  
      def __str__(self):
          buf = ['<MultiGeometry id="{0}">'.format(self._id),
                 super(MultiGeometry, self).__str__()]
          for geom in self._geometries:
              buf.append(geom.__str__())
          buf.append("</MultiGeometry>")
          return "".join(buf)
  
  
  class Overlay(Feature):
      """Abstract class for image overlays.
  
      Arguments are the same as the properties.
  
      .. note::
        Not to be used directly.
      """
      def __init__(self, color=None,
                         draworder=None,
                         icon=None,
                         **kwargs):
          super(Overlay, self).__init__(**kwargs)
          self._kml['color'] = color
          self._kml['drawOrder'] = draworder
          self._kml['Icon_'] = icon
  
      @property
      def color(self):
          """The color of the overlay, accepts hex string."""
          return self._kml['color']
  
      @color.setter
      def color(self, color):
          self._kml['color'] = color
  
      @property
      def draworder(self):
          """The order to draw the overlay, accepts int."""
          return self._kml['drawOrder']
  
      @draworder.setter
      def draworder(self, draworder):
          self._kml['drawOrder'] = draworder
  
      @property
      def icon(self):
          """The icon to use for the overlay, accepts :class:`simplekml.Icon`"""
          if self._kml['Icon_'] is None:
              self._kml['Icon_'] = Icon()
          return self._kml['Icon_']
  
      @icon.setter
      @check(Icon)
      def icon(self, icon):
          self._kml['Icon_'] = icon
  
  
  class GroundOverlay(Overlay):
      """Draws an image overlay draped onto the terrain.
  
      Arguments are the same as the properties.
      
      Usage::
  
          import simplekml
          kml = simplekml.Kml()
          ground = kml.newgroundoverlay(name='GroundOverlay')
          ground.icon.href = 'http://simplekml.googlecode.com/hg/samples/resources/smile.png'
          ground.gxlatlonquad.coords = [(18.410524,-33.903972),(18.411429,-33.904171),
                                        (18.411757,-33.902944),(18.410850,-33.902767)]
          # or
          #ground.latlonbox.north = -33.902828
          #ground.latlonbox.south = -33.904104
          #ground.latlonbox.east =  18.410684
          #ground.latlonbox.west =  18.411633
          #ground.latlonbox.rotation = -14
          kml.save("GroundOverlay.kml")
      """
  
      def __init__(self, altitude=None,
                         altitudemode=None,
                         gxaltitudemode=None,
                         latlonbox=None,
                         gxlatlonquad=None,
                         **kwargs):
          super(GroundOverlay, self).__init__(**kwargs)
          self._kml['altitude'] = altitude
          self._kml['altitudeMode'] = altitudemode
          self._kml['gx:altitudeMode'] = gxaltitudemode
          self._kml['LatLonBox'] = latlonbox
          self._kml['gx:LatLonQuad'] = gxlatlonquad
  
      @property
      def altitude(self):
          """Distance above earth surface, accepts float."""
          return self._kml['altitude']
  
      @altitude.setter
      def altitude(self, altitude):
          self._kml['altitude'] = altitude
  
      @property
      def altitudemode(self):
          """Specifies how the altitude for the Camera is interpreted.
  
          Accepts :class:`simplekml.AltitudeMode` constants.
          """
          return self._kml['altitudeMode']
  
      @altitudemode.setter
      def altitudemode(self, altitudemode):
          self._kml['altitudeMode'] = altitudemode
  
      @property
      def gxaltitudemode(self):
          """Specifies how the altitude for the Camera is interpreted.
  
          With the addition of being relative to the sea floor.
          Accepts :class:`simplekml.GxAltitudeMode` constants.
          """
          return self._kml['gx:altitudeMode']
  
      @gxaltitudemode.setter
      def gxaltitudemode(self, gxaltitudemode):
          self._kml['gx:altitudeMode'] = gxaltitudemode
  
      @property
      def latlonbox(self):
          """Specifies where the top, bottom, right, and left sides are.
  
          Accepts :class:`simplekml.LatLonBox`.
          """
          if self._kml['LatLonBox'] is None:
              self._kml['LatLonBox'] = LatLonBox()
          return self._kml['LatLonBox']
  
      @latlonbox.setter
      @check(LatLonBox)
      def latlonbox(self, latlonbox):
          self._kml['LatLonBox'] = latlonbox
  
      @property
      def gxlatlonquad(self):
          """Specifies the coordinates of the four corner points of a quadrilateral
          defining the overlay area. Accepts :class:`simplekml.GxLatLonQuad`
          """
          if self._kml['gx:LatLonQuad'] is None:
              self._kml['gx:LatLonQuad'] = GxLatLonQuad()
          return self._kml['gx:LatLonQuad']
  
      @gxlatlonquad.setter
      @check(GxLatLonQuad)
      def gxlatlonquad(self, gxlatlonquad):
          self._kml['gx:LatLonQuad'] = gxlatlonquad
  
  
  class ScreenOverlay(Overlay):
      """Draws an image overlay fixed to the screen.
  
      Arguments are the same as the properties.
  
      Usage::
  
          import simplekml
          kml = simplekml.Kml()
          screen = kml.newscreenoverlay(name='ScreenOverlay')
          screen.icon.href = 'http://simplekml.googlecode.com/hg/samples/resources/simplekml-logo.png'
          screen.overlayxy = simplekml.OverlayXY(x=0,y=1,xunits=simplekml.Units.fraction,
                                                 yunits=simplekml.Units.fraction)
          screen.screenxy = simplekml.ScreenXY(x=15,y=15,xunits=simplekml.Units.pixel,
                                               yunits=simplekml.Units.insetpixels)
          screen.size.x = -1
          screen.size.y = -1
          screen.size.xunits = simplekml.Units.fraction
          screen.size.yunits = simplekml.Units.fraction
          kml.save("ScreenOverlay.kml")
      """
  
      def __init__(self, overlayxy=None,
                         screenxy=None,
                         rotationxy=None,
                         size=None,
                         rotation=None,
                         **kwargs):
          super(ScreenOverlay, self).__init__(**kwargs)
          self._kml['rotation'] =rotation
          self._kml['overlayXY_'] = overlayxy
          self._kml['screenXY_'] = screenxy
          self._kml['rotationXY_'] = rotationxy
          self._kml['size_'] = size
  
      @property
      def rotation(self):
          """Rotation of the overlay, accepts float."""
          return self._kml['rotation']
  
      @rotation.setter
      def rotation(self, rotation):
          self._kml['rotation'] = rotation
  
      @property
      def overlayxy(self):
          """Point on the overlay image that is mapped to a screen coordinate.
  
          Specifies a point on (or outside of) the overlay image that is mapped
          to the screen coordinate :class:`simplekml.ScreenXY`,
          accepts :class:`simplekml.OverlayXY`
          """
          if self._kml['overlayXY_'] is None:
              self._kml['overlayXY_'] = OverlayXY()
          return self._kml['overlayXY_']
  
      @overlayxy.setter
      @check(OverlayXY)
      def overlayxy(self, overlayxy):
          self._kml['overlayXY_'] = overlayxy
  
      @property
      def screenxy(self):
          """Point relative to screen origin that the image is mapped to.
  
          Specifies a point relative to the screen origin that the overlay image
          is mapped to, accepts :class:`simplekml.ScreenXY`
          """
          if self._kml['screenXY_'] is None:
              self._kml['screenXY_'] = ScreenXY()
          return self._kml['screenXY_']
  
      @screenxy.setter
      @check(ScreenXY)
      def screenxy(self, screenxy):
          self._kml['screenXY_'] = screenxy
  
      @property
      def rotationxy(self):
          """Point relative to the screen about which the overlay is rotated.
  
          Accepts :class:`simplekml.RotationXY`
          """
          if self._kml['rotationXY_'] is None:
              self._kml['rotationXY_'] = RotationXY()
          return self._kml['rotationXY_']
  
      @rotationxy.setter
      @check(RotationXY)
      def rotationxy(self, rotationxy):
          self._kml['rotationXY_'] = rotationxy
  
      @property
      def size(self):
          """The size of the image for the screen overlay, accepts :class:`simplekml.Size`"""
          if self._kml['size_'] is None:
              self._kml['size_'] = Size()
          return self._kml['size_']
  
      @size.setter
      @check(Size)
      def size(self, size):
          self._kml['size_'] = size
  
  
  class PhotoOverlay(Overlay):
      """Geographically locate a photograph in Google Earth.
  
      Arguments are the same as the properties.
  
      Usage::
  
          import simplekml
          kml = simplekml.Kml()
          photo = kml.newphotooverlay(name='PhotoOverlay Test')
          photo.camera = simplekml.Camera(longitude=18.410858, latitude=-33.904446, altitude=50,
                                          altitudemode=simplekml.AltitudeMode.clamptoground)
          photo.point.coords = [(18.410858,-33.90444)]
          photo.style.iconstyle.icon.href = 'http://maps.google.com/mapfiles/kml/shapes/camera.png'
          photo.icon.href = 'http://simplekml.googlecode.com/hg/samples/resources/stadium.jpg'
          photo.viewvolume = simplekml.ViewVolume(-25,25,-15,15,1)
          kml.save("PhotoOverlay.kml")
      """
  
      def __init__(self, rotation=None,
                         viewvolume=None,
                         imagepyramid=None,
                         point=None,
                         shape=None,
                         **kwargs):
          super(PhotoOverlay, self).__init__(**kwargs)
          self._kml['rotation'] = rotation
          self._kml['ViewVolume'] = viewvolume
          self._kml['ImagePyramid'] = imagepyramid
          self._kml['point_'] = point
          self._kml['shape'] = shape
  
      @property
      def rotation(self):
          """Rotation of the overlay, accepts float."""
          return self._kml['rotation']
  
      @rotation.setter
      def rotation(self, rotation):
          self._kml['rotation'] = rotation
  
      @property
      def viewvolume(self):
          """How much of the current scene is visible, accepts :class:`simplekml.ViewVolume`"""
          if self._kml['ViewVolume'] is None:
              self._kml['ViewVolume'] = ViewVolume()
          return self._kml['ViewVolume']
  
      @viewvolume.setter
      @check(ViewVolume)
      def viewvolume(self, viewvolume):
          self._kml['ViewVolume'] = viewvolume
  
      @property
      def imagepyramid(self):
          """Hierarchical set of images, accepts :class:`simplekml.ImagePyramid`"""
          if self._kml['ImagePyramid'] is None:
              self._kml['ImagePyramid'] = ImagePyramid()
          return self._kml['ImagePyramid']
  
      @imagepyramid.setter
      @check(ImagePyramid)
      def imagepyramid(self, imagepyramid):
          self._kml['ImagePyramid'] = imagepyramid
  
      @property
      def point(self):
          """Draws an icon to mark the position of the overlay,accepts :class:`simplekml.Point`"""
          if self._kml['point_'] is None:
              self._kml['point_'] = Point()
          return self._kml['point_']
  
      @point.setter
      @check(Point)
      def point(self, point):
          self._kml['point_'] = point
  
      @property
      def shape(self):
          """Shape the photo is drawn, accepts string from :class:`simplekml.Shape` constants."""
          return self._kml['shape']
  
      @shape.setter
      def shape(self, shape):
          self._kml['shape'] = shape
  
  
  class NetworkLink(Feature):
      """References a KML file or KMZ archive on a local or remote network.
  
      Arguments are the same as the properties.
  
      Usage::
  
          import simplekml
          kml = simplekml.Kml()
          netlink = kml.newnetworklink(name="Network Link")
          netlink.link.href = "http://simplekml.googlecode.com/hg/samples/samples.kml"
          netlink.link.viewrefreshmode = simplekml.ViewRefreshMode.onrequest
          kml.save("NetworkLink.kml")
      """
      
      def __init__(self, refreshvisibility=None,
                         flytoview=None,
                         link=None,
                         **kwargs):
          super(NetworkLink, self).__init__(**kwargs)
          self._kml['refreshVisibility'] = refreshvisibility
          self._kml['flyToView'] = flytoview
          self._kml['Link_'] = link
  
      @property
      def refreshvisibility(self):
          """How the visibility is affected by a refresh
  
          A value of 0 leaves the visibility of features within the control of
          the Google Earth user. Set the value to 1 to reset the visibility of
          features each time the NetworkLink is refreshed, accepts int (0 or 1).
          """
          return self._kml['refreshVisibility']
  
      @refreshvisibility.setter
      def refreshvisibility(self, refreshvisibility):
          self._kml['refreshVisibility'] = refreshvisibility
  
      @property
      def flytoview(self):
          """A value of 1 causes Google Earth to fly to the view of the AbstractView.
  
          Accepts int (0 or 1).
          """
          return self._kml['flyToView']
  
      @flytoview.setter
      def flytoview(self, flytoview):
          self._kml['flyToView'] = flytoview
  
      @property
      def link(self):
          """A :class:`simplekml.Link` class instance, accepts :class:`simplekml.Link`"""
          if self._kml['Link_'] is None:
              self._kml['Link_'] = Link()
          return self._kml['Link_']
  
      @link.setter
      @check(Link)
      def link(self, link):
          self._kml['Link_'] = link
  
  
  class Model(Geometry):
      """A 3D object described in a COLLADA file.
  
      Arguments are the same as the properties.
      """
  
      def __init__(self,
                   altitudemode=None,
                   gxaltitudemode=None,
                   location=None,
                   orientation=None,
                   scale=None,
                   link=None,
                   resourcemap=None,
                   **kwargs):
          super(Model, self).__init__(**kwargs)
          self._kml['altitudeMode'] = altitudemode
          self._kml['gx:altitudeMode'] = gxaltitudemode
          self._kml['Location'] = location
          self._kml['Orientation'] = orientation
          self._kml['Scale'] = scale
          self._kml['Link_'] = link
          self._kml['ResourceMap'] = resourcemap
  
      @property
      def altitudemode(self):
          """Specifies how the altitude for the Camera is interpreted.
  
          Accepts :class:`simplekml.AltitudeMode` constants.
          """
          return self._kml['altitudeMode']
  
      @altitudemode.setter
      def altitudemode(self, altitudemode):
          self._kml['altitudeMode'] = altitudemode
  
      @property
      def gxaltitudemode(self):
          """Specifies how the altitude for the Camera is interpreted.
  
          With the addition of being relative to the sea floor.
          Accepts :class:`simplekml.GxAltitudeMode` constants.
          """
          return self._kml['gx:altitudeMode']
  
      @gxaltitudemode.setter
      def gxaltitudemode(self, gxaltitudemode):
          self._kml['gx:altitudeMode'] = gxaltitudemode
  
      @property
      def location(self):
          """Position of the origin of the model, accepts :class:`simplekml.Location`"""
          if self._kml['Location'] is None:
              self._kml['Location'] = Location()
          return self._kml['Location']
  
      @location.setter
      @check(Location)
      def location(self, location):
          self._kml['Location'] = location
  
      @property
      def orientation(self):
          """The rotation on the model, accepts :class:`simplekml.Orientation`"""
          if self._kml['Orientation'] is None:
              self._kml['Orientation'] = Orientation()
          return self._kml['Orientation']
  
      @orientation.setter
      @check(Orientation)
      def orientation(self, orientation):
          self._kml['Orientation'] = orientation
  
      @property
      def scale(self):
          """"The scale of the model, accepts :class:`simplekml.Scale`"""
          if self._kml['Scale'] is None:
              self._kml['Scale'] = Scale()
          return self._kml['Scale']
  
      @scale.setter
      @check(Scale)
      def scale(self, scale):
          self._kml['Scale'] = scale
  
      @property
      def link(self):
          """"A :class:`simplekml.Link` class instance, accepts :class:`simplekml.Link`"""
          if self._kml['Link_'] is None:
              self._kml['Link_'] = Link()
          return self._kml['Link_']
  
      @link.setter
      @check(Link)
      def link(self, link):
          self._kml['Link_'] = link
  
      @property
      def resourcemap(self):
          """Used for mapping textures, accepts :class:`simplekml.ResourceMap`"""
          if self._kml['ResourceMap'] is None:
              self._kml['ResourceMap'] = ResourceMap()
          return self._kml['ResourceMap']
  
      @resourcemap.setter
      @check(ResourceMap)
      def resourcemap(self, resourcemap):
          self._kml['ResourceMap'] = resourcemap
  
      def __str__(self):
          return '<Model id="{0}">{1}</Model>'.format(self._id, super(Model, self).__str__())
  
  
  class GxTrack(Geometry):
      """A track describes how an object moves through the world over a given time period.
  
      Arguments are the same as the properties.
  
      Usage::
  
          # This is a recreation of the example found in the KML Reference:
          # http://code.google.com/apis/kml/documentation/kmlreference.html#gxtrack
  
          import os
          from simplekml import Kml, Snippet, Types
  
          # Data for the track
          when = ["2010-05-28T02:02:09Z",
              "2010-05-28T02:02:35Z",
              "2010-05-28T02:02:44Z",
              "2010-05-28T02:02:53Z",
              "2010-05-28T02:02:54Z",
              "2010-05-28T02:02:55Z",
              "2010-05-28T02:02:56Z"]
  
          coord = [(-122.207881,37.371915,156.000000),
              (-122.205712,37.373288,152.000000),
              (-122.204678,37.373939,147.000000),
              (-122.203572,37.374630,142.199997),
              (-122.203451,37.374706,141.800003),
              (-122.203329,37.374780,141.199997),
              (-122.203207,37.374857,140.199997)]
  
          cadence = [86, 103, 108, 113, 113, 113, 113]
          heartrate = [181, 177, 175, 173, 173, 173, 173]
          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
          trk.extendeddata.schemadata.newgxsimplearraydata('power', power) # Ditto
  
          # Styling
          trk.stylemap.normalstyle.iconstyle.icon.href = 'http://earth.google.com/images/kml-icons/track-directional/track-0.png'
          trk.stylemap.normalstyle.linestyle.color = '99ffac59'
          trk.stylemap.normalstyle.linestyle.width = 6
          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 = '99ffac59'
          trk.stylemap.highlightstyle.linestyle.width = 8
  
          # Save the kml to file
          kml.save("GxTrack.kml")
      """
  
      def __init__(self,
                   extrude=None,
                   altitudemode=None,
                   gxaltitudemode=None,
                   model=None,
                   **kwargs):
          super(GxTrack, self).__init__(**kwargs)
          self._kml['extrude'] = extrude
          self._kml['altitudeMode'] = altitudemode
          self._kml['gx:altitudeMode'] = gxaltitudemode
          self._kml['ExtendedData'] = None
          self._kml['Model_'] = model
          self.whens = []
          self.gxcoords = []
          self.gxangles = []
  
      @property
      def extrude(self):
          """Connect the GxTrack to the ground, accepts int (0 or 1)."""
          return self._kml['extrude']
  
      @extrude.setter
      def extrude(self, extrude):
          self._kml['extrude'] = extrude
  
      @property
      def altitudemode(self):
          """Specifies how the altitude for the Camera is interpreted.
  
          Accepts :class:`simplekml.AltitudeMode` constants.
  
          """
          return self._kml['altitudeMode']
  
      @altitudemode.setter
      def altitudemode(self, altitudemode):
          self._kml['altitudeMode'] = altitudemode
  
      @property
      def gxaltitudemode(self):
          """Specifies how the altitude for the Camera is interpreted.
  
          With the addition of being relative to the sea floor.
          Accepts :class:`simplekml.GxAltitudeMode` constants.
          """
          return self._kml['gx:altitudeMode']
  
      @gxaltitudemode.setter
      def gxaltitudemode(self, gxaltitudemode):
          self._kml['gx:altitudeMode'] = gxaltitudemode
  
      def newdata(self, gxcoord, when, angle=None):
          """Creates a new gxcoord, when time and angle (if provided).
  
          This is a convenience method for calling newwhen, newgxcoord and
          newangle. when and gxcoord are required, angle is optional.
          """
          self.newgxcoord(gxcoord)
          self.newwhen(when)
          if angle is not None:
              self.newangle(angle)
  
      def newwhen(self, when):
          """Creates a new when time, accepts string or list of string.
  
          If one string is given a single when entry is created, but if a list of
          strings is given, a when entry is created for each string in the list.
          """
          if type(when) == list:
              self.whens += when
          else:
              self.whens.append(when)
  
      def newgxcoord(self, coord):
          """Creates a gx:coord, accepts list of one tuples.
  
          A gxcoord entry is created for every tuple in the list.
          """
          if type(coord) == list:
              for crd in coord:
                  coords = Coordinates()
                  coords.addcoordinates([crd])
                  self.gxcoords.append(coords)
          else:
              coords = Coordinates()
              coords.addcoordinates(list(coord))
              self.gxcoords.append(coords)
  
      def newgxangle(self, angle):
          """Creates a new gx:angle, accepts float or list of floats.
  
          If one float is given a single angle entry is created, but if a list of
          floats is given, a angle entry is created for each float in the list.
          """
          if type(angle) == list:
              self.gxangles += angle
          else:
              self.gxangles.append(angle)
  
      @property
      def extendeddata(self):
          """Extra data for the feature."""
          if self._kml['ExtendedData'] is None:
              self._kml['ExtendedData'] = ExtendedData()
          return self._kml['ExtendedData']
  
      @extendeddata.setter
      @check(ExtendedData)
      def extendeddata(self, extendeddata):
          self._kml['ExtendedData'] = extendeddata
  
      @property
      def model(self):
          """A model to use on the track, accepts :class:`simplekml.Model`
  
          *New in version 1.2.1*
          """
          if self._kml['Model_'] is None:
              self._kml['Model_'] = Model()
          return self._kml['Model_']
  
      @model.setter
      @check(Model)
      def model(self, model):
          self._kml['Model_'] = model
  
      def __str__(self):
          buf = ['<gx:Track>']
          for when in self.whens:
              buf.append("<when>{0}</when>".format(when))
          for angle in self.gxangles:
              buf.append("<gx:angle>{0}</gx:angle>".format(angle))
          for gxcoord in self.gxcoords:
              buf.append("<gx:coord>{0}</gx:coord>".format(gxcoord.__str__().replace(',', ' ')))
          buf.append(super(GxTrack, self).__str__())
          buf.append('</gx:Track>')
          return "".join(buf)
  
  
  class GxMultiTrack(Geometry):
      """A container for grouping gx:tracks.
  
      Arguments are the same as the properties.
  
      Usage::
  
          import simplekml
          kml = simplekml.Kml()
          multitrack = kml.newgxmultitrack()
          track1 = multitrack.newgxtrack(name="track1")
          track2 = multitrack.newgxtrack(name="track2")
          kml.save("GxMultiTrack.kml")
      """
  
      def __init__(self,
                   tracks=(), gxinterpolate=None, **kwargs):
          super(GxMultiTrack, self).__init__(**kwargs)
          self._kml['gx:interpolate'] = gxinterpolate
          self.tracks = list(tracks)
  
      def newgxtrack(self, **kwargs):
          """Creates a new :class:`simplekml.GxTrack` and attaches it to this mutlitrack.
  
          Returns an instance of :class:`simplekml.GxTrack` class.
  
          Args:
            * Same as :class:`simplekml.GxTrack`, except arguments that are not applicable in a multitrack grouping
              will be ignored, such as name, visibility, open, etc.
          """
          self.tracks.append(GxTrack(**kwargs))
          return self.tracks[-1]
  
      def __str__(self):
          buf = ['<gx:MultiTrack id="{0}">'.format(self._id),
                 super(GxMultiTrack, self).__str__()]
          for track in self.tracks:
              buf.append(track.__str__())
          buf.append("</gx:MultiTrack>")
          return "".join(buf)
  