fastkml-0.11/0000775000175000017500000000000012550665156013753 5ustar travistravis00000000000000fastkml-0.11/setup.cfg0000664000175000017500000000007312550665156015574 0ustar travistravis00000000000000[egg_info] tag_build = tag_date = 0 tag_svn_revision = 0 fastkml-0.11/PKG-INFO0000664000175000017500000002007612550665156015055 0ustar travistravis00000000000000Metadata-Version: 1.1 Name: fastkml Version: 0.11 Summary: Fast KML processing in python Home-page: https://github.com/cleder/fastkml Author: Christian Ledermann Author-email: christian.ledermann@gmail.com License: LGPL Description: Introduction ============ Fastkml is a library to read, write and manipulate KML files. It aims to keep it simple and fast (using lxml_ if available). Fast refers to the time you spend to write and read KML files as well as the time you spend to get aquainted to the library or to create KML objects. It aims to provide all of the functionality that KML clients such as `OpenLayers `_, `Google Maps `_, and `Google Earth `_ provides. Geometries are handled as pygeoif_ or, if installed, shapely_ objects. .. _pygeoif: http://pypi.python.org/pypi/pygeoif/ .. _shapely: http://pypi.python.org/pypi/Shapely .. _lxml: https://pypi.python.org/pypi/lxml .. _dateutils: https://pypi.python.org/pypi/dateutils .. _pip: https://pypi.python.org/pypi/pip Fastkml is continually tested with *Travis CI*: .. image:: https://api.travis-ci.org/cleder/fastkml.png :target: https://travis-ci.org/cleder/fastkml :alt: Tests .. image:: https://coveralls.io/repos/cleder/fastkml/badge.png?branch=master :target: https://coveralls.io/r/cleder/fastkml?branch=master :alt: coveralls.io .. image:: http://codecov.io/github/cleder/fastkml/coverage.svg?branch=master :target: http://codecov.io/github/cleder/fastkml?branch=master :alt: codecov.io Is Maintained and documented: .. image:: https://pypip.in/v/fastkml/badge.png :target: https://pypi.python.org/pypi/fastkml :alt: Latest PyPI version .. image:: https://pypip.in/status/fastkml/badge.svg :target: https://pypi.python.org/pypi/fastkml/ :alt: Development Status .. image:: https://readthedocs.org/projects/fastkml/badge/ :target: https://fastkml.readthedocs.org/ :alt: Documentation .. image:: https://badge.waffle.io/cleder/fastkml.png?label=ready&title=Ready :target: https://waffle.io/cleder/fastkml :alt: 'Stories in Ready' .. image:: https://www.openhub.net/p/fastkml/widgets/project_thin_badge.gif :target: https://www.openhub.net/p/fastkml :alt: Statistics from OpenHub Supports python 2 and 3: .. image:: https://pypip.in/py_versions/fastkml/badge.svg :target: https://pypi.python.org/pypi/fastkml/ :alt: Supported Python versions .. image:: https://pypip.in/implementation/fastkml/badge.svg :target: https://pypi.python.org/pypi/fastkml/ :alt: Supported Python implementations Documentation ============= You can find all of the documentation for FastKML at `fastkml.readthedocs.org `_. If you find something that is missing, please submit a pull request on `GitHub `_ with the improvement. Install ======== You can install the package with ``pip install fastkml`` or ``easy_install fastkml`` which should also pull in all requirements. Requirements ------------- * pygeoif_ * dateutils_ Optional --------- * lxml_ * shapely_ You can install all of the requirements for working with FastKML by using pip_:: pip install -r requirements.txt .. note:: Shapely_ requires that libgeos be installed on your system. ``apt-get install libgeos-dev`` will install these requirements for you on Debian- based systems. Limitations =========== *Tesselate*, *Extrude* and *Altitude Mode* are assigned to a Geometry or Geometry collection (MultiGeometry). You cannot assign different values of *Tesselate*, *Extrude* or *Altitude Mode* on parts of a MultiGeometry. Currently, the only major feature missing for the full Google Earth experience is the `gx extension `_. This will most likely be added after the 1.0 version release. You can find the complete list of current issues on `GitHub `_. Changelog ========= 0.11.1 (2015/07/13) - add travis deploy to travis.yml 0.11 (2015/07/10) ----------------- - handle coordinates tuples which contain spaces 0.10 (2015/06/09) ----------------- - Fix bug when the fill or outline attributes of a PolyStyle are float strings 0.9 (2014/10/17) ----------------- - Add tox.ini for running tests using tox [Ian Lee] - Add documentation, hosted at https://fastkml.readthedocs.org [Ian Lee] 0.8 (2014/09/18) ----------------- - Add support for address and phoneNumber [Ian Lee] - Add support for Ground Overlay kml [Ian Lee] 0.7 (2014/08/01) ---------------- - Handle case where Document booleans (visibility,isopen) are 'true' or 'false' [jwhelland] - test case additions and lxml warning [Ian Lee] - pep8-ify source code (except test_main.py) [Ian Lee] - pyflakes-ify source code (except __init__.py) [Ian Lee] 0.6 (2014/05/29) ---------------- - add Schema - add SchemaData - make use of lxmls default namespace 0.5 (2013/10/23) ----------------- - handle big files with huge_tree for lxml [Egil Moeller] - bugfixes 0.4 (2013/09/05) ----------------- - adds the ability to add untyped extended data / named value pairs [Denis Krienbuehl] 0.3 (2012/11/15) ----------------- - specify minor python versions tested with Travis CI - add support for tesselation, altitudeMode and extrude to Geometries - move implementation of geometry from kml.Placemark to geometry.Geometry - add support for heterogenous GeometryCollection - python 3 compatible - fix test for python 3 - change license to LGPL - register namespaces for a more pleasant, human readable xml output 0.2 (2012/07/27) ----------------- - remove dependency on shapely - add more functionality 0.1.1 (2012/06/29) ------------------ - add MANIFEST.in 0.1 (2012/06/27) ---------------- - initial release Keywords: GIS KML Google Maps OpenLayers Platform: UNKNOWN Classifier: Topic :: Scientific/Engineering :: GIS Classifier: Programming Language :: Python Classifier: Programming Language :: Python :: 2 Classifier: Programming Language :: Python :: 2.6 Classifier: Programming Language :: Python :: 2.7 Classifier: Programming Language :: Python :: 3 Classifier: Programming Language :: Python :: 3.2 Classifier: Programming Language :: Python :: 3.3 Classifier: Programming Language :: Python :: 3.4 Classifier: Intended Audience :: Developers Classifier: License :: OSI Approved :: GNU Library or Lesser General Public License (LGPL) Classifier: Development Status :: 5 - Production/Stable Classifier: Operating System :: OS Independent fastkml-0.11/setup.py0000664000175000017500000000372612550664775015503 0ustar travistravis00000000000000from setuptools import setup, find_packages from setuptools.command.test import test as TestCommand import sys import os class PyTest(TestCommand): def finalize_options(self): TestCommand.finalize_options(self) self.test_args = [] self.test_suite = True def run_tests(self): # import here, cause outside the eggs aren't loaded import pytest errno = pytest.main(self.test_args) sys.exit(errno) setup( name='fastkml', version='0.11', description="Fast KML processing in python", long_description=( open("README.rst").read() + "\n" + open(os.path.join("docs", "HISTORY.txt")).read() ), classifiers=[ "Topic :: Scientific/Engineering :: GIS", "Programming Language :: Python", 'Programming Language :: Python :: 2', 'Programming Language :: Python :: 2.6', 'Programming Language :: Python :: 2.7', 'Programming Language :: Python :: 3', 'Programming Language :: Python :: 3.2', 'Programming Language :: Python :: 3.3', 'Programming Language :: Python :: 3.4', 'Intended Audience :: Developers', 'License :: OSI Approved :: GNU Library or Lesser General Public License (LGPL)', 'Development Status :: 5 - Production/Stable', 'Operating System :: OS Independent', ], # Get strings from http://pypi.python.org/pypi?%3Aaction=list_classifiers keywords='GIS KML Google Maps OpenLayers', author='Christian Ledermann', author_email='christian.ledermann@gmail.com', url='https://github.com/cleder/fastkml', license='LGPL', packages=find_packages(exclude=['ez_setup', 'examples', 'tests']), include_package_data=True, zip_safe=False, tests_require=['pytest'], cmdclass={'test': PyTest}, install_requires=[ # -*- Extra requirements: -*- 'pygeoif', 'python-dateutil', ], entry_points=""" # -*- Entry points: -*- """, ) fastkml-0.11/README.rst0000664000175000017500000000734712550664775015463 0ustar travistravis00000000000000Introduction ============ Fastkml is a library to read, write and manipulate KML files. It aims to keep it simple and fast (using lxml_ if available). Fast refers to the time you spend to write and read KML files as well as the time you spend to get aquainted to the library or to create KML objects. It aims to provide all of the functionality that KML clients such as `OpenLayers `_, `Google Maps `_, and `Google Earth `_ provides. Geometries are handled as pygeoif_ or, if installed, shapely_ objects. .. _pygeoif: http://pypi.python.org/pypi/pygeoif/ .. _shapely: http://pypi.python.org/pypi/Shapely .. _lxml: https://pypi.python.org/pypi/lxml .. _dateutils: https://pypi.python.org/pypi/dateutils .. _pip: https://pypi.python.org/pypi/pip Fastkml is continually tested with *Travis CI*: .. image:: https://api.travis-ci.org/cleder/fastkml.png :target: https://travis-ci.org/cleder/fastkml :alt: Tests .. image:: https://coveralls.io/repos/cleder/fastkml/badge.png?branch=master :target: https://coveralls.io/r/cleder/fastkml?branch=master :alt: coveralls.io .. image:: http://codecov.io/github/cleder/fastkml/coverage.svg?branch=master :target: http://codecov.io/github/cleder/fastkml?branch=master :alt: codecov.io Is Maintained and documented: .. image:: https://pypip.in/v/fastkml/badge.png :target: https://pypi.python.org/pypi/fastkml :alt: Latest PyPI version .. image:: https://pypip.in/status/fastkml/badge.svg :target: https://pypi.python.org/pypi/fastkml/ :alt: Development Status .. image:: https://readthedocs.org/projects/fastkml/badge/ :target: https://fastkml.readthedocs.org/ :alt: Documentation .. image:: https://badge.waffle.io/cleder/fastkml.png?label=ready&title=Ready :target: https://waffle.io/cleder/fastkml :alt: 'Stories in Ready' .. image:: https://www.openhub.net/p/fastkml/widgets/project_thin_badge.gif :target: https://www.openhub.net/p/fastkml :alt: Statistics from OpenHub Supports python 2 and 3: .. image:: https://pypip.in/py_versions/fastkml/badge.svg :target: https://pypi.python.org/pypi/fastkml/ :alt: Supported Python versions .. image:: https://pypip.in/implementation/fastkml/badge.svg :target: https://pypi.python.org/pypi/fastkml/ :alt: Supported Python implementations Documentation ============= You can find all of the documentation for FastKML at `fastkml.readthedocs.org `_. If you find something that is missing, please submit a pull request on `GitHub `_ with the improvement. Install ======== You can install the package with ``pip install fastkml`` or ``easy_install fastkml`` which should also pull in all requirements. Requirements ------------- * pygeoif_ * dateutils_ Optional --------- * lxml_ * shapely_ You can install all of the requirements for working with FastKML by using pip_:: pip install -r requirements.txt .. note:: Shapely_ requires that libgeos be installed on your system. ``apt-get install libgeos-dev`` will install these requirements for you on Debian- based systems. Limitations =========== *Tesselate*, *Extrude* and *Altitude Mode* are assigned to a Geometry or Geometry collection (MultiGeometry). You cannot assign different values of *Tesselate*, *Extrude* or *Altitude Mode* on parts of a MultiGeometry. Currently, the only major feature missing for the full Google Earth experience is the `gx extension `_. This will most likely be added after the 1.0 version release. You can find the complete list of current issues on `GitHub `_. fastkml-0.11/MANIFEST.in0000664000175000017500000000016512550664775015521 0ustar travistravis00000000000000include *.rst recursive-include docs *.txt recursive-exclude *.pyc *.pyo include docs/LICENSE.GPL exclude fastkml/.* fastkml-0.11/fastkml.egg-info/0000775000175000017500000000000012550665156017106 5ustar travistravis00000000000000fastkml-0.11/fastkml.egg-info/top_level.txt0000664000175000017500000000001012550665156021627 0ustar travistravis00000000000000fastkml fastkml-0.11/fastkml.egg-info/requires.txt0000664000175000017500000000003012550665156021477 0ustar travistravis00000000000000pygeoif python-dateutil fastkml-0.11/fastkml.egg-info/not-zip-safe0000664000175000017500000000000112550665140021325 0ustar travistravis00000000000000 fastkml-0.11/fastkml.egg-info/entry_points.txt0000664000175000017500000000004112550665156022377 0ustar travistravis00000000000000 # -*- Entry points: -*- fastkml-0.11/fastkml.egg-info/dependency_links.txt0000664000175000017500000000000112550665156023154 0ustar travistravis00000000000000 fastkml-0.11/fastkml.egg-info/SOURCES.txt0000664000175000017500000000074012550665156020773 0ustar travistravis00000000000000MANIFEST.in README.rst setup.py docs/CONTRIBUTORS.txt docs/HISTORY.txt docs/LICENSE.GPL docs/LICENSE.txt fastkml/__init__.py fastkml/atom.py fastkml/base.py fastkml/config.py fastkml/geometry.py fastkml/gx.py fastkml/kml.py fastkml/styles.py fastkml/test_main.py fastkml.egg-info/PKG-INFO fastkml.egg-info/SOURCES.txt fastkml.egg-info/dependency_links.txt fastkml.egg-info/entry_points.txt fastkml.egg-info/not-zip-safe fastkml.egg-info/requires.txt fastkml.egg-info/top_level.txtfastkml-0.11/fastkml.egg-info/PKG-INFO0000664000175000017500000002007612550665156020210 0ustar travistravis00000000000000Metadata-Version: 1.1 Name: fastkml Version: 0.11 Summary: Fast KML processing in python Home-page: https://github.com/cleder/fastkml Author: Christian Ledermann Author-email: christian.ledermann@gmail.com License: LGPL Description: Introduction ============ Fastkml is a library to read, write and manipulate KML files. It aims to keep it simple and fast (using lxml_ if available). Fast refers to the time you spend to write and read KML files as well as the time you spend to get aquainted to the library or to create KML objects. It aims to provide all of the functionality that KML clients such as `OpenLayers `_, `Google Maps `_, and `Google Earth `_ provides. Geometries are handled as pygeoif_ or, if installed, shapely_ objects. .. _pygeoif: http://pypi.python.org/pypi/pygeoif/ .. _shapely: http://pypi.python.org/pypi/Shapely .. _lxml: https://pypi.python.org/pypi/lxml .. _dateutils: https://pypi.python.org/pypi/dateutils .. _pip: https://pypi.python.org/pypi/pip Fastkml is continually tested with *Travis CI*: .. image:: https://api.travis-ci.org/cleder/fastkml.png :target: https://travis-ci.org/cleder/fastkml :alt: Tests .. image:: https://coveralls.io/repos/cleder/fastkml/badge.png?branch=master :target: https://coveralls.io/r/cleder/fastkml?branch=master :alt: coveralls.io .. image:: http://codecov.io/github/cleder/fastkml/coverage.svg?branch=master :target: http://codecov.io/github/cleder/fastkml?branch=master :alt: codecov.io Is Maintained and documented: .. image:: https://pypip.in/v/fastkml/badge.png :target: https://pypi.python.org/pypi/fastkml :alt: Latest PyPI version .. image:: https://pypip.in/status/fastkml/badge.svg :target: https://pypi.python.org/pypi/fastkml/ :alt: Development Status .. image:: https://readthedocs.org/projects/fastkml/badge/ :target: https://fastkml.readthedocs.org/ :alt: Documentation .. image:: https://badge.waffle.io/cleder/fastkml.png?label=ready&title=Ready :target: https://waffle.io/cleder/fastkml :alt: 'Stories in Ready' .. image:: https://www.openhub.net/p/fastkml/widgets/project_thin_badge.gif :target: https://www.openhub.net/p/fastkml :alt: Statistics from OpenHub Supports python 2 and 3: .. image:: https://pypip.in/py_versions/fastkml/badge.svg :target: https://pypi.python.org/pypi/fastkml/ :alt: Supported Python versions .. image:: https://pypip.in/implementation/fastkml/badge.svg :target: https://pypi.python.org/pypi/fastkml/ :alt: Supported Python implementations Documentation ============= You can find all of the documentation for FastKML at `fastkml.readthedocs.org `_. If you find something that is missing, please submit a pull request on `GitHub `_ with the improvement. Install ======== You can install the package with ``pip install fastkml`` or ``easy_install fastkml`` which should also pull in all requirements. Requirements ------------- * pygeoif_ * dateutils_ Optional --------- * lxml_ * shapely_ You can install all of the requirements for working with FastKML by using pip_:: pip install -r requirements.txt .. note:: Shapely_ requires that libgeos be installed on your system. ``apt-get install libgeos-dev`` will install these requirements for you on Debian- based systems. Limitations =========== *Tesselate*, *Extrude* and *Altitude Mode* are assigned to a Geometry or Geometry collection (MultiGeometry). You cannot assign different values of *Tesselate*, *Extrude* or *Altitude Mode* on parts of a MultiGeometry. Currently, the only major feature missing for the full Google Earth experience is the `gx extension `_. This will most likely be added after the 1.0 version release. You can find the complete list of current issues on `GitHub `_. Changelog ========= 0.11.1 (2015/07/13) - add travis deploy to travis.yml 0.11 (2015/07/10) ----------------- - handle coordinates tuples which contain spaces 0.10 (2015/06/09) ----------------- - Fix bug when the fill or outline attributes of a PolyStyle are float strings 0.9 (2014/10/17) ----------------- - Add tox.ini for running tests using tox [Ian Lee] - Add documentation, hosted at https://fastkml.readthedocs.org [Ian Lee] 0.8 (2014/09/18) ----------------- - Add support for address and phoneNumber [Ian Lee] - Add support for Ground Overlay kml [Ian Lee] 0.7 (2014/08/01) ---------------- - Handle case where Document booleans (visibility,isopen) are 'true' or 'false' [jwhelland] - test case additions and lxml warning [Ian Lee] - pep8-ify source code (except test_main.py) [Ian Lee] - pyflakes-ify source code (except __init__.py) [Ian Lee] 0.6 (2014/05/29) ---------------- - add Schema - add SchemaData - make use of lxmls default namespace 0.5 (2013/10/23) ----------------- - handle big files with huge_tree for lxml [Egil Moeller] - bugfixes 0.4 (2013/09/05) ----------------- - adds the ability to add untyped extended data / named value pairs [Denis Krienbuehl] 0.3 (2012/11/15) ----------------- - specify minor python versions tested with Travis CI - add support for tesselation, altitudeMode and extrude to Geometries - move implementation of geometry from kml.Placemark to geometry.Geometry - add support for heterogenous GeometryCollection - python 3 compatible - fix test for python 3 - change license to LGPL - register namespaces for a more pleasant, human readable xml output 0.2 (2012/07/27) ----------------- - remove dependency on shapely - add more functionality 0.1.1 (2012/06/29) ------------------ - add MANIFEST.in 0.1 (2012/06/27) ---------------- - initial release Keywords: GIS KML Google Maps OpenLayers Platform: UNKNOWN Classifier: Topic :: Scientific/Engineering :: GIS Classifier: Programming Language :: Python Classifier: Programming Language :: Python :: 2 Classifier: Programming Language :: Python :: 2.6 Classifier: Programming Language :: Python :: 2.7 Classifier: Programming Language :: Python :: 3 Classifier: Programming Language :: Python :: 3.2 Classifier: Programming Language :: Python :: 3.3 Classifier: Programming Language :: Python :: 3.4 Classifier: Intended Audience :: Developers Classifier: License :: OSI Approved :: GNU Library or Lesser General Public License (LGPL) Classifier: Development Status :: 5 - Production/Stable Classifier: Operating System :: OS Independent fastkml-0.11/fastkml/0000775000175000017500000000000012550665156015414 5ustar travistravis00000000000000fastkml-0.11/fastkml/test_main.py0000664000175000017500000044672512550664775020001 0ustar travistravis00000000000000# -*- coding: utf-8 -*- # Copyright (C) 2012 Christian Ledermann # # This library is free software; you can redistribute it and/or modify it under # the terms of the GNU Lesser General Public License as published by the Free # Software Foundation; either version 2.1 of the License, or (at your option) # any later version. # # This library 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 Lesser General Public License for more # details. # # You should have received a copy of the GNU Lesser General Public License # along with this library; if not, write to the Free Software Foundation, Inc., # 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA try: import unittest2 as unittest # Needed in Python 2.6 except: import unittest from fastkml import kml from fastkml import styles from fastkml import base from fastkml import atom from fastkml import config from fastkml import gx # NOQA import datetime from dateutil.tz import tzutc, tzoffset from fastkml.config import etree from fastkml.geometry import Point, LineString, Polygon from fastkml.geometry import MultiPoint, MultiLineString, MultiPolygon from fastkml.geometry import LinearRing, GeometryCollection from fastkml.geometry import Geometry class BaseClassesTestCase(unittest.TestCase): """ BaseClasses must raise a NotImplementedError on etree_element and a TypeError on from_element """ def test_base_object(self): bo = base._BaseObject(id='id0') self.assertEqual(bo.id, 'id0') self.assertEqual(bo.ns, config.NS) self.assertEqual(bo.targetId, None) self.assertEqual(bo.__name__, None) bo.targetId = 'target' self.assertEqual(bo.targetId, 'target') bo.ns = '' bo.id = None self.assertEqual(bo.id, None) self.assertEqual(bo.ns, '') self.assertRaises(NotImplementedError, bo.etree_element) element = etree.Element(config.NS + 'Base') self.assertRaises(TypeError, bo.from_element) self.assertRaises(TypeError, bo.from_element, element) bo.__name__ = 'NotABaseObject' self.assertRaises(TypeError, bo.from_element, element) # Note that we can coax baseclasses not to throw errors bo.__name__ = 'Base' bo.ns = config.NS bo.from_element(element) self.assertEqual(bo.id, None) self.assertEqual(bo.ns, config.NS) self.assertFalse(bo.etree_element(), None) self.assertTrue(len(bo.to_string()) > 1) def test_feature(self): f = kml._Feature(name='A Feature') self.assertRaises(NotImplementedError, f.etree_element) self.assertEqual(f.name, 'A Feature') self.assertEqual(f.visibility, 1) self.assertEqual(f.isopen, 0) self.assertEqual(f._atom_author, None) self.assertEqual(f._atom_link, None) self.assertEqual(f.address, None) # self.assertEqual(f.phoneNumber, None) self.assertEqual(f._snippet, None) self.assertEqual(f.description, None) self.assertEqual(f._styleUrl, None) self.assertEqual(f._styles, []) self.assertEqual(f._time_span, None) self.assertEqual(f._time_stamp, None) # self.assertEqual(f.region, None) # self.assertEqual(f.extended_data, None) f.__name__ = 'Feature' f.styleUrl = '#default' self.assertTrue('Feature>' in str(f.to_string())) self.assertTrue('#default' in str(f.to_string())) def test_container(self): f = kml._Container(name='A Container') # apparently you can add documents to containes # d = kml.Document() # self.assertRaises(TypeError, f.append, d) p = kml.Placemark() f.append(p) self.assertRaises(NotImplementedError, f.etree_element) def test_overlay(self): o = kml._Overlay(name='An Overlay') self.assertEqual(o._color, None) self.assertEqual(o._drawOrder, None) self.assertEqual(o._icon, None) self.assertRaises(NotImplementedError, o.etree_element) def test_atom_link(self): ns = '{http://www.opengis.net/kml/2.2}' l = atom.Link(ns=ns) self.assertEqual(l.ns, ns) def test_atom_person(self): ns = '{http://www.opengis.net/kml/2.2}' p = atom._Person(ns=ns) self.assertEqual(p.ns, ns) class BuildKmlTestCase(unittest.TestCase): """ Build a simple KML File """ def test_kml(self): """ kml file without contents """ k = kml.KML() self.assertEqual(len(list(k.features())), 0) if config.LXML: self.assertEqual( str(k.to_string())[:43], '' [:43]) else: if hasattr(etree, 'register_namespace'): self.assertEqual(str(k.to_string())[:51], ''[:51]) else: self.assertEqual(str(k.to_string())[:51], ''[:51]) k2 = kml.KML() k2.from_string(k.to_string()) self.assertEqual(k.to_string(), k2.to_string()) def test_folder(self): """ KML file with folders """ ns = '{http://www.opengis.net/kml/2.2}' k = kml.KML() f = kml.Folder(ns, 'id', 'name', 'description') nf = kml.Folder(ns, 'nested-id', 'nested-name', 'nested-description') f.append(nf) k.append(f) f2 = kml.Folder(ns, 'id2', 'name2', 'description2') k.append(f2) self.assertEqual(len(list(k.features())), 2) self.assertEqual(len(list(list(k.features())[0].features())), 1) k2 = kml.KML() s = k.to_string() k2.from_string(s) self.assertEqual(s, k2.to_string()) def test_placemark(self): ns = '{http://www.opengis.net/kml/2.2}' k = kml.KML(ns=ns) p = kml.Placemark(ns, 'id', 'name', 'description') p.geometry = Point(0.0, 0.0, 0.0) p2 = kml.Placemark(ns, 'id2', 'name2', 'description2') p2.geometry = LineString([(0, 0, 0), (1, 1, 1)]) k.append(p) k.append(p2) self.assertEqual(len(list(k.features())), 2) k2 = kml.KML() k2.from_string(k.to_string(prettyprint=True)) self.assertEqual(k.to_string(), k2.to_string()) def test_schema(self): ns = '{http://www.opengis.net/kml/2.2}' self.assertRaises(ValueError, kml.Schema, ns) s = kml.Schema(ns, 'some_id') self.assertEqual(len(list(s.simple_fields)), 0) s.append('int', 'Integer', 'An Integer') self.assertEqual(list(s.simple_fields)[0]['type'], 'int') self.assertEqual(list(s.simple_fields)[0]['name'], 'Integer') self.assertEqual(list(s.simple_fields)[0]['displayName'], 'An Integer') s.simple_fields = None self.assertEqual(len(list(s.simple_fields)), 0) self.assertRaises( TypeError, s.append, ('none', 'Integer', 'An Integer')) self.assertRaises( TypeError, s.simple_fields, [('none', 'Integer', 'An Integer')]) self.assertRaises( TypeError, s.simple_fields, ('int', 'Integer', 'An Integer')) fields = { 'type': 'int', 'name': 'Integer', 'displayName': 'An Integer' } s.simple_fields = fields self.assertEqual(list(s.simple_fields)[0]['type'], 'int') self.assertEqual(list(s.simple_fields)[0]['name'], 'Integer') self.assertEqual(list(s.simple_fields)[0]['displayName'], 'An Integer') s.simple_fields = [['float', 'Float'], fields] self.assertEqual(list(s.simple_fields)[0]['type'], 'float') self.assertEqual(list(s.simple_fields)[0]['name'], 'Float') self.assertEqual(list(s.simple_fields)[0]['displayName'], None) self.assertEqual(list(s.simple_fields)[1]['type'], 'int') self.assertEqual(list(s.simple_fields)[1]['name'], 'Integer') self.assertEqual(list(s.simple_fields)[1]['displayName'], 'An Integer') def test_schema_data(self): ns = '{http://www.opengis.net/kml/2.2}' self.assertRaises(ValueError, kml.SchemaData, ns) self.assertRaises(ValueError, kml.SchemaData, ns, '') sd = kml.SchemaData(ns, '#default') sd.append_data('text', 'Some Text') self.assertEqual(len(sd.data), 1) sd.append_data(value=1, name='Integer') self.assertEqual(len(sd.data), 2) self.assertEqual(sd.data[0], {'value': 'Some Text', 'name': 'text'}) self.assertEqual(sd.data[1], {'value': 1, 'name': 'Integer'}) data = (('text', 'Some new Text'), {'value': 2, 'name': 'Integer'}) sd.data = data self.assertEqual(len(sd.data), 2) self.assertEqual( sd.data[0], {'value': 'Some new Text', 'name': 'text'}) self.assertEqual(sd.data[1], {'value': 2, 'name': 'Integer'}) def test_untyped_extended_data(self): ns = '{http://www.opengis.net/kml/2.2}' k = kml.KML(ns=ns) p = kml.Placemark(ns, 'id', 'name', 'description') p.geometry = Point(0.0, 0.0, 0.0) p.extended_data = kml.UntypedExtendedData(elements=[ kml.UntypedExtendedDataElement( name='info', value='so much to see'), kml.UntypedExtendedDataElement( name='weather', display_name='Weather', value='blue skies') ]) self.assertEqual(len(p.extended_data.elements), 2) k.append(p) k2 = kml.KML() k2.from_string(k.to_string(prettyprint=True)) k.to_string() extended_data = list(k2.features())[0].extended_data self.assertTrue(extended_data is not None) self.assertTrue(len(extended_data.elements), 2) self.assertEqual(extended_data.elements[0].name, 'info') self.assertEqual(extended_data.elements[0].value, 'so much to see') self.assertEqual(extended_data.elements[0].display_name, None) self.assertEqual(extended_data.elements[1].name, 'weather') self.assertEqual(extended_data.elements[1].value, 'blue skies') self.assertEqual(extended_data.elements[1].display_name, 'Weather') def test_untyped_extended_data_nested(self): ns = '{http://www.opengis.net/kml/2.2}' k = kml.KML(ns=ns) d = kml.Document(ns, 'docid', 'doc name', 'doc description') d.extended_data = kml.UntypedExtendedData(elements=[ kml.UntypedExtendedDataElement(name='type', value='Document') ]) f = kml.Folder(ns, 'fid', 'f name', 'f description') f.extended_data = kml.UntypedExtendedData(elements=[ kml.UntypedExtendedDataElement(name='type', value='Folder') ]) k.append(d) d.append(f) k2 = kml.KML() k2.from_string(k.to_string()) document_data = list(k2.features())[0].extended_data folder_data = list(list(k2.features())[0].features())[0].extended_data self.assertEqual(document_data.elements[0].name, 'type') self.assertEqual(document_data.elements[0].value, 'Document') self.assertEqual(folder_data.elements[0].name, 'type') self.assertEqual(folder_data.elements[0].value, 'Folder') def test_document(self): k = kml.KML() ns = '{http://www.opengis.net/kml/2.2}' d = kml.Document(ns, 'docid', 'doc name', 'doc description') f = kml.Folder(ns, 'fid', 'f name', 'f description') k.append(d) d.append(f) nf = kml.Folder( ns, 'nested-fid', 'nested f name', 'nested f description') f.append(nf) f2 = kml.Folder(ns, 'id2', 'name2', 'description2') d.append(f2) p = kml.Placemark(ns, 'id', 'name', 'description') p.geometry = Polygon([(0, 0, 0), (1, 1, 0), (1, 0, 1)]) p2 = kml.Placemark(ns, 'id2', 'name2', 'description2') # p2 does not have a geometry! f2.append(p) nf.append(p2) self.assertEqual(len(list(k.features())), 1) self.assertEqual(len(list((list(k.features())[0].features()))), 2) k2 = kml.KML() k2.from_string(k.to_string()) self.assertEqual(k.to_string(), k2.to_string()) def test_author(self): d = kml.Document() d.author = 'Christian Ledermann' self.assertTrue('Christian Ledermann' in str(d.to_string())) a = atom.Author( name='Nobody', uri='http://localhost', email='cl@donotreply.com') d.author = a self.assertEqual(d.author, 'Nobody') self.assertFalse('Christian Ledermann' in str(d.to_string())) self.assertTrue('Nobody' in str(d.to_string())) self.assertTrue('http://localhost' in str(d.to_string())) self.assertTrue('cl@donotreply.com' in str(d.to_string())) d2 = kml.Document() d2.from_string(d.to_string()) self.assertEqual(d.to_string(), d2.to_string()) d.author = None def test_link(self): d = kml.Document() d.link = 'http://localhost' self.assertTrue('http://localhost' in str(d.to_string())) l = atom.Link(href='#here') d.link = l self.assertTrue('#here' in str(d.to_string())) self.assertRaises(TypeError, d.link, object) d2 = kml.Document() d2.from_string(d.to_string()) self.assertEqual(d.to_string(), d2.to_string()) d.link = None def test_address(self): address = '1600 Amphitheatre Parkway, Mountain View, CA 94043, USA' d = kml.Document() d.address = address self.assertTrue(address in str(d.to_string())) self.assertTrue('address>' in str(d.to_string())) def test_phone_number(self): phone = '+1 234 567 8901' d = kml.Document() d.phoneNumber = phone self.assertTrue(phone in str(d.to_string())) self.assertTrue('phoneNumber>' in str(d.to_string())) class KmlFromStringTestCase(unittest.TestCase): def test_document(self): doc = """ Document.kml 1 Document Feature 1 #exampleStyleDocument -122.371,37.816,0 Document Feature 2 #exampleStyleDocument -122.370,37.817,0 """ k = kml.KML() k.from_string(doc) self.assertEqual(len(list(k.features())), 1) self.assertEqual(len(list(list(k.features())[0].features())), 2) k2 = kml.KML() k2.from_string(k.to_string()) self.assertEqual(k.to_string(), k2.to_string()) def test_document_booleans(self): doc = """ Document.kml true 1 """ k = kml.KML() k.from_string(doc) self.assertEqual(list(k.features())[0].visibility, 1) self.assertEqual(list(k.features())[0].isopen, 1) doc = """ Document.kml 0 false """ k = kml.KML() k.from_string(doc) self.assertEqual(list(k.features())[0].visibility, 0) self.assertEqual(list(k.features())[0].isopen, 0) def test_folders(self): doc = """ Folder.kml 1 A folder is a container that can hold multiple other objects Folder object 1 (Placemark) -122.377588,37.830266,0 Folder object 2 (Polygon) -122.377830,37.830445,0 -122.377576,37.830631,0 -122.377840,37.830642,0 -122.377830,37.830445,0 Folder object 3 (Path) 1 -122.378009,37.830128,0 -122.377885,37.830379,0 """ k = kml.KML() k.from_string(doc) self.assertEqual(len(list(k.features())), 1) self.assertEqual(len(list(list(k.features())[0].features())), 3) k2 = kml.KML() k2.from_string(k.to_string()) self.assertEqual(k.to_string(), k2.to_string()) def test_placemark(self): doc = """ Simple placemark Attached to the ground. Intelligently places itself at the height of the underlying terrain. -122.0822035425683,37.42228990140251,0 """ k = kml.KML() k.from_string(doc) self.assertEqual(len(list(k.features())), 1) self.assertEqual(list(k.features())[0].name, "Simple placemark") k2 = kml.KML() k2.from_string(k.to_string()) self.assertEqual(k.to_string(), k2.to_string()) def test_extended_data(self): doc = """ Simple placemark -122.0822035425683,37.42228990140251,0 This is hole ]]> 1 The par for this hole is ]]> 4 Mount Everest 347.45 10000 """ k = kml.KML() k.from_string(doc) extended_data = list(k.features())[0].extended_data self.assertEqual(extended_data.elements[0].name, 'holeNumber') self.assertEqual(extended_data.elements[0].value, '1') self.assertTrue( 'This is hole ' in extended_data.elements[0].display_name) self.assertEqual(extended_data.elements[1].name, 'holePar') self.assertEqual(extended_data.elements[1].value, '4') self.assertTrue( 'The par for this hole is ' in extended_data.elements[1].display_name) sd = extended_data.elements[2] self.assertEqual(sd.data[0]['name'], 'TrailHeadName') self.assertEqual(sd.data[1]['value'], '347.45') def test_polygon(self): doc = """ South Africa 31.521,-29.257,0 31.326,-29.402,0 30.902,-29.91,0 30.623,-30.424,0 30.056,-31.14,0 28.926,-32.172,0 28.22,-32.772,0 27.465,-33.227,0 26.419,-33.615,0 25.91,-33.667,0 25.781,-33.945,0 25.173,-33.797,0 24.678,-33.987,0 23.594,-33.794,0 22.988,-33.916,0 22.574,-33.864,0 21.543,-34.259,0 20.689,-34.417,0 20.071,-34.795,0 19.616,-34.819,0 19.193,-34.463,0 18.855,-34.444,0 18.425,-33.998,0 18.377,-34.137,0 18.244,-33.868,0 18.25,-33.281,0 17.925,-32.611,0 18.248,-32.429,0 18.222,-31.662,0 17.567,-30.726,0 17.064,-29.879,0 17.063,-29.876,0 16.345,-28.577,0 16.824,-28.082,0 17.219,-28.356,0 17.387,-28.784,0 17.836,-28.856,0 18.465,-29.045,0 19.002,-28.972,0 19.895,-28.461,0 19.896,-24.768,0 20.166,-24.918,0 20.759,-25.868,0 20.666,-26.477,0 20.89,-26.829,0 21.606,-26.727,0 22.106,-26.28,0 22.58,-25.979,0 22.824,-25.5,0 23.312,-25.269,0 23.734,-25.39,0 24.211,-25.67,0 25.025,-25.72,0 25.665,-25.487,0 25.766,-25.175,0 25.942,-24.696,0 26.486,-24.616,0 26.786,-24.241,0 27.119,-23.574,0 28.017,-22.828,0 29.432,-22.091,0 29.839,-22.102,0 30.323,-22.272,0 30.66,-22.152,0 31.191,-22.252,0 31.67,-23.659,0 31.931,-24.369,0 31.752,-25.484,0 31.838,-25.843,0 31.333,-25.66,0 31.044,-25.731,0 30.95,-26.023,0 30.677,-26.398,0 30.686,-26.744,0 31.283,-27.286,0 31.868,-27.178,0 32.072,-26.734,0 32.83,-26.742,0 32.58,-27.47,0 32.462,-28.301,0 32.203,-28.752,0 31.521,-29.257,0 28.978,-28.956,0 28.542,-28.648,0 28.074,-28.851,0 27.533,-29.243,0 26.999,-29.876,0 27.749,-30.645,0 28.107,-30.546,0 28.291,-30.226,0 28.848,-30.07,0 29.018,-29.744,0 29.325,-29.257,0 28.978,-28.956,0 """ k = kml.KML() k.from_string(doc) self.assertEqual(len(list(k.features())), 1) self.assertTrue(isinstance(list(k.features())[0].geometry, Polygon)) k2 = kml.KML() k2.from_string(k.to_string()) self.assertEqual(k.to_string(), k2.to_string()) def test_multipoints(self): doc = """ MultiPoint #stylesel_9 16,-35,0.0 16,-33,0.0 16,-31,0.0 16,-29,0.0 16,-27,0.0 16,-25,0.0 16,-23,0.0 16,-21,0.0 18,-35,0.0 18,-33,0.0 18,-31,0.0 18,-29,0.0 """ k = kml.KML() k.from_string(doc) self.assertEqual(len(list(k.features())), 1) self.assertTrue(isinstance(list(k.features())[0].geometry, MultiPoint)) self.assertEqual(len(list(k.features())[0].geometry.geoms), 12) k2 = kml.KML() k2.from_string(k.to_string()) self.assertEqual(k.to_string(), k2.to_string()) def test_multilinestrings(self): doc = """ Dnipro (Dnieper) 33.54,46.831,0 33.606,46.869,0 33.662,46.957,0 33.739,47.05,0 33.859,47.149,0 33.976,47.307,0 33.998,47.411,0 34.155,47.49,0 34.448,47.542,0 34.712,47.553,0 34.946,47.521,0 35.088,47.528,0 35.138,47.573,0 35.149,47.657,0 35.106,47.842,0 33.194,49.094,0 32.884,49.225,0 32.603,49.302,0 31.886,49.555,0 31.44,50,0 31.48,49.933,0 31.486,49.871,0 31.467,49.754,0 30.508,51.217,0 30.478,50.904,0 30.479,50.749,0 30.515,50.597,0 """ k = kml.KML() k.from_string(doc) self.assertEqual(len(list(k.features())), 1) self.assertTrue( isinstance(list(k.features())[0].geometry, MultiLineString)) self.assertEqual(len(list(k.features())[0].geometry.geoms), 4) k2 = kml.KML() k2.from_string(k.to_string()) self.assertEqual(k.to_string(), k2.to_string()) def test_multipolygon(self): doc = """ Italy 12.621,35.492,0 12.611,35.489,0 12.603,35.491,0 12.598,35.494,0 12.594,35.494,0 12.556,35.508,0 12.536,35.513,0 12.526,35.517,0 12.534,35.522,0 12.556,35.521,0 12.567,35.519,0 12.613,35.515,0 12.621,35.513,0 12.624,35.512,0 12.622,35.51,0 12.621,35.508,0 12.624,35.502,0 12.621,35.492,0 12.873,35.852,0 12.857,35.852,0 12.851,35.856,0 12.846,35.863,0 12.847,35.868,0 12.854,35.871,0 12.86,35.872,0 12.867,35.872,0 12.874,35.866,0 12.877,35.856,0 12.873,35.852,0 11.981,36.827,0 11.988,36.824,0 11.994,36.825,0 12,36.836,0 12.038,36.806,0 12.052,36.79,0 12.054,36.767,0 12.031,36.741,0 11.997,36.745,0 11.962,36.765,0 11.938,36.789,0 11.934,36.795,0 11.926,36.812,0 11.923,36.828,0 11.935,36.836,0 11.939,36.837,0 11.947,36.841,0 11.952,36.843,0 11.958,36.84,0 11.968,36.831,0 11.972,36.829,0 11.981,36.827,0 12.322,37.94,0 12.337,37.933,0 12.355,37.927,0 12.369,37.925,0 12.358,37.914,0 12.343,37.913,0 12.327,37.918,0 12.315,37.925,0 12.3,37.919,0 12.288,37.921,0 12.279,37.929,0 12.274,37.939,0 12.288,37.938,0 12.298,37.941,0 12.306,37.945,0 12.315,37.946,0 12.322,37.94,0 12.078,37.96,0 12.079,37.95,0 12.065,37.951,0 12.048,37.961,0 12.037,37.974,0 12.03,37.984,0 12.036,37.991,0 12.054,37.992,0 12.065,37.986,0 12.072,37.968,0 12.078,37.96,0 15.643,38.262,0 15.635,38.261,0 15.625,38.261,0 15.584,38.24,0 15.57,38.227,0 15.564,38.214,0 15.56,38.2,0 15.576,38.2,0 15.527,38.137,0 15.501,38.085,0 15.393,37.976,0 15.303,37.864,0 15.284,37.833,0 15.267,37.812,0 15.242,37.795,0 15.214,37.761,0 15.207,37.747,0 15.209,37.737,0 15.219,37.718,0 15.221,37.706,0 15.217,37.696,0 15.203,37.685,0 15.2,37.675,0 15.197,37.655,0 15.185,37.626,0 15.179,37.604,0 15.164,37.567,0 15.117,37.522,0 15.097,37.494,0 15.092,37.477,0 15.09,37.459,0 15.093,37.36,0 15.097,37.343,0 15.104,37.33,0 15.111,37.322,0 15.181,37.291,0 15.218,37.285,0 15.237,37.275,0 15.253,37.257,0 15.262,37.234,0 15.245,37.246,0 15.236,37.242,0 15.229,37.23,0 15.221,37.22,0 15.222,37.237,0 15.216,37.244,0 15.206,37.244,0 15.193,37.24,0 15.2,37.227,0 15.184,37.207,0 15.195,37.176,0 15.217,37.155,0 15.234,37.165,0 15.248,37.158,0 15.248,37.152,0 15.23,37.149,0 15.232,37.135,0 15.247,37.118,0 15.265,37.11,0 15.289,37.108,0 15.304,37.101,0 15.309,37.086,0 15.303,37.062,0 15.289,37.069,0 15.283,37.061,0 15.284,37.048,0 15.292,37.042,0 15.313,37.044,0 15.322,37.04,0 15.33,37.027,0 15.333,37.011,0 15.325,37.008,0 15.315,37.012,0 15.309,37.018,0 15.304,37.016,0 15.269,37,0 15.275,36.993,0 15.267,36.989,0 15.264,36.987,0 15.269,36.98,0 15.269,36.973,0 15.245,36.972,0 15.227,36.965,0 15.212,36.956,0 15.197,36.952,0 15.175,36.944,0 15.159,36.924,0 15.108,36.82,0 15.107,36.808,0 15.095,36.799,0 15.099,36.779,0 15.118,36.747,0 15.135,36.687,0 15.135,36.675,0 15.115,36.66,0 15.094,36.655,0 15.074,36.659,0 15.056,36.671,0 15.041,36.687,0 15.034,36.694,0 15.021,36.699,0 15.008,36.703,0 14.998,36.702,0 14.994,36.696,0 14.983,36.689,0 14.958,36.698,0 14.919,36.72,0 14.883,36.73,0 14.847,36.726,0 14.781,36.699,0 14.777,36.707,0 14.774,36.71,0 14.761,36.706,0 14.745,36.719,0 14.685,36.726,0 14.672,36.744,0 14.659,36.754,0 14.601,36.772,0 14.583,36.781,0 14.566,36.778,0 14.488,36.793,0 14.476,36.805,0 14.395,36.945,0 14.37,36.973,0 14.279,37.044,0 14.209,37.081,0 14.127,37.112,0 14.089,37.117,0 13.977,37.11,0 13.968,37.108,0 13.949,37.099,0 13.939,37.096,0 13.895,37.101,0 13.833,37.139,0 13.795,37.152,0 13.752,37.159,0 13.716,37.171,0 13.684,37.189,0 13.599,37.256,0 13.57,37.273,0 13.535,37.282,0 13.489,37.288,0 13.453,37.299,0 13.422,37.314,0 13.373,37.346,0 13.33,37.366,0 13.312,37.381,0 13.303,37.386,0 13.29,37.389,0 13.279,37.393,0 13.254,37.432,0 13.248,37.436,0 13.226,37.446,0 13.215,37.458,0 13.207,37.464,0 13.195,37.466,0 13.19,37.469,0 13.18,37.484,0 13.175,37.487,0 13.052,37.5,0 13.037,37.495,0 13.027,37.493,0 13.017,37.497,0 13.011,37.507,0 13.005,37.527,0 13.001,37.535,0 12.975,37.557,0 12.943,37.568,0 12.863,37.576,0 12.781,37.574,0 12.698,37.563,0 12.66,37.565,0 12.637,37.582,0 12.595,37.638,0 12.578,37.652,0 12.564,37.658,0 12.524,37.658,0 12.507,37.665,0 12.49,37.682,0 12.475,37.703,0 12.466,37.72,0 12.461,37.734,0 12.46,37.748,0 12.457,37.76,0 12.449,37.771,0 12.437,37.783,0 12.428,37.797,0 12.428,37.809,0 12.445,37.816,0 12.447,37.812,0 12.461,37.819,0 12.466,37.823,0 12.464,37.825,0 12.471,37.853,0 12.473,37.854,0 12.478,37.872,0 12.479,37.881,0 12.477,37.886,0 12.468,37.897,0 12.466,37.906,0 12.465,37.913,0 12.465,37.914,0 12.468,37.916,0 12.491,37.954,0 12.497,37.98,0 12.503,37.997,0 12.505,38.011,0 12.493,38.021,0 12.524,38.031,0 12.55,38.055,0 12.577,38.072,0 12.609,38.062,0 12.639,38.079,0 12.652,38.091,0 12.657,38.107,0 12.663,38.116,0 12.677,38.116,0 12.692,38.112,0 12.705,38.111,0 12.726,38.126,0 12.725,38.15,0 12.72,38.175,0 12.732,38.193,0 12.738,38.181,0 12.75,38.182,0 12.761,38.181,0 12.767,38.162,0 12.791,38.117,0 12.819,38.078,0 12.829,38.07,0 12.858,38.058,0 12.869,38.051,0 12.87,38.042,0 12.902,38.028,0 12.945,38.033,0 13.028,38.062,0 13.062,38.083,0 13.07,38.091,0 13.072,38.095,0 13.07,38.101,0 13.069,38.114,0 13.067,38.123,0 13.057,38.133,0 13.055,38.142,0 13.09,38.166,0 13.084,38.174,0 13.09,38.183,0 13.102,38.19,0 13.113,38.193,0 13.123,38.191,0 13.158,38.179,0 13.18,38.176,0 13.208,38.176,0 13.231,38.184,0 13.239,38.207,0 13.255,38.202,0 13.267,38.205,0 13.278,38.21,0 13.297,38.214,0 13.311,38.219,0 13.319,38.22,0 13.324,38.218,0 13.326,38.211,0 13.327,38.205,0 13.329,38.2,0 13.367,38.179,0 13.372,38.173,0 13.374,38.14,0 13.377,38.131,0 13.392,38.103,0 13.514,38.11,0 13.542,38.094,0 13.54,38.077,0 13.542,38.067,0 13.548,38.056,0 13.558,38.049,0 13.588,38.039,0 13.623,38.015,0 13.652,38.001,0 13.698,37.993,0 13.712,37.988,0 13.708,37.985,0 13.708,37.984,0 13.706,37.98,0 13.727,37.981,0 13.791,37.973,0 13.813,37.978,0 13.858,37.996,0 13.899,38.004,0 13.913,38.012,0 13.925,38.022,0 13.939,38.029,0 14.008,38.038,0 14.021,38.049,0 14.063,38.03,0 14.084,38.024,0 14.107,38.021,0 14.122,38.022,0 14.152,38.029,0 14.274,38.015,0 14.332,38.018,0 14.385,38.029,0 14.433,38.049,0 14.465,38.037,0 14.512,38.044,0 14.635,38.081,0 14.668,38.099,0 14.696,38.121,0 14.734,38.157,0 14.745,38.161,0 14.778,38.159,0 14.799,38.16,0 14.875,38.175,0 14.889,38.182,0 14.898,38.186,0 14.908,38.187,0 14.936,38.186,0 14.945,38.182,0 14.963,38.163,0 14.97,38.159,0 14.982,38.158,0 15.008,38.152,0 15.04,38.153,0 15.049,38.152,0 15.054,38.148,0 15.064,38.135,0 15.069,38.131,0 15.088,38.128,0 15.106,38.133,0 15.123,38.141,0 15.178,38.156,0 15.204,38.183,0 15.241,38.241,0 15.238,38.249,0 15.237,38.251,0 15.237,38.253,0 15.241,38.261,0 15.238,38.265,0 15.244,38.265,0 15.247,38.254,0 15.241,38.23,0 15.246,38.217,0 15.258,38.21,0 15.275,38.207,0 15.292,38.207,0 15.322,38.211,0 15.4,38.232,0 15.423,38.244,0 15.434,38.253,0 15.473,38.268,0 15.513,38.297,0 15.529,38.302,0 15.56,38.3,0 15.616,38.28,0 15.652,38.275,0 15.649,38.266,0 15.643,38.262,0 14.999,38.371,0 14.987,38.364,0 14.964,38.381,0 14.949,38.396,0 14.946,38.412,0 14.96,38.433,0 14.967,38.433,0 14.967,38.418,0 14.983,38.412,0 14.994,38.403,0 15.002,38.391,0 15.008,38.378,0 14.999,38.371,0 14.967,38.453,0 14.949,38.451,0 14.935,38.458,0 14.922,38.469,0 14.908,38.474,0 14.9,38.481,0 14.901,38.498,0 14.91,38.515,0 14.925,38.522,0 14.958,38.522,0 14.967,38.516,0 14.96,38.502,0 14.966,38.497,0 14.975,38.49,0 14.98,38.487,0 14.98,38.481,0 14.953,38.481,0 14.958,38.469,0 14.962,38.465,0 14.967,38.461,0 14.967,38.453,0 14.361,38.539,0 14.346,38.535,0 14.343,38.547,0 14.357,38.551,0 14.361,38.539,0 14.864,38.549,0 14.862,38.539,0 14.824,38.552,0 14.794,38.571,0 14.815,38.584,0 14.852,38.585,0 14.867,38.581,0 14.877,38.569,0 14.873,38.565,0 14.869,38.56,0 14.864,38.549,0 14.585,38.557,0 14.574,38.557,0 14.552,38.562,0 14.544,38.575,0 14.543,38.587,0 14.546,38.588,0 14.564,38.585,0 14.576,38.577,0 14.58,38.566,0 14.585,38.561,0 14.585,38.557,0 13.177,38.693,0 13.165,38.691,0 13.153,38.695,0 13.153,38.702,0 13.158,38.71,0 13.169,38.717,0 13.186,38.718,0 13.196,38.711,0 13.197,38.708,0 13.177,38.693,0 15.225,38.777,0 15.217,38.773,0 15.206,38.775,0 15.187,38.789,0 15.187,38.793,0 15.194,38.798,0 15.204,38.802,0 15.209,38.806,0 15.212,38.81,0 15.219,38.812,0 15.228,38.81,0 15.235,38.808,0 15.239,38.804,0 15.237,38.796,0 15.232,38.789,0 15.23,38.783,0 15.225,38.777,0 8.361,39.118,0 8.386,39.105,0 8.418,39.106,0 8.445,39.102,0 8.457,39.073,0 8.459,39.068,0 8.464,39.065,0 8.47,39.065,0 8.477,39.07,0 8.478,39.07,0 8.48,39.072,0 8.484,39.07,0 8.465,39.056,0 8.46,39.05,0 8.464,39.042,0 8.455,39.028,0 8.447,38.994,0 8.438,38.967,0 8.433,38.963,0 8.422,38.96,0 8.41,38.962,0 8.407,38.967,0 8.406,38.974,0 8.402,38.981,0 8.365,39.029,0 8.35,39.062,0 8.354,39.083,0 8.354,39.091,0 8.347,39.091,0 8.347,39.097,0 8.361,39.118,0 8.306,39.104,0 8.291,39.099,0 8.27,39.1,0 8.255,39.107,0 8.258,39.118,0 8.258,39.124,0 8.233,39.144,0 8.225,39.157,0 8.231,39.173,0 8.246,39.181,0 8.291,39.188,0 8.306,39.193,0 8.307,39.161,0 8.313,39.12,0 8.306,39.104,0 13.959,40.712,0 13.945,40.701,0 13.935,40.705,0 13.92,40.704,0 13.904,40.7,0 13.891,40.694,0 13.882,40.699,0 13.86,40.707,0 13.85,40.715,0 13.857,40.735,0 13.862,40.744,0 13.871,40.749,0 13.868,40.752,0 13.863,40.762,0 13.884,40.762,0 13.947,40.745,0 13.966,40.735,0 13.963,40.729,0 13.963,40.723,0 13.966,40.715,0 13.959,40.712,0 13.427,40.791,0 13.415,40.786,0 13.419,40.796,0 13.424,40.8,0 13.432,40.801,0 13.427,40.791,0 8.333,41.105,0 8.343,41.098,0 8.345,41.086,0 8.342,41.074,0 8.333,41.064,0 8.275,41.057,0 8.252,41.043,0 8.252,41.016,0 8.247,40.993,0 8.21,40.996,0 8.218,41.005,0 8.222,41.014,0 8.224,41.024,0 8.224,41.033,0 8.229,41.042,0 8.242,41.052,0 8.261,41.064,0 8.276,41.07,0 8.278,41.081,0 8.276,41.095,0 8.278,41.105,0 8.285,41.107,0 8.303,41.105,0 8.306,41.109,0 8.309,41.114,0 8.314,41.118,0 8.327,41.126,0 8.326,41.118,0 8.328,41.112,0 8.333,41.105,0 9.471,41.19,0 9.474,41.184,0 9.475,41.179,0 9.47,41.172,0 9.464,41.173,0 9.456,41.181,0 9.449,41.186,0 9.442,41.183,0 9.437,41.186,0 9.448,41.205,0 9.443,41.211,0 9.446,41.22,0 9.454,41.234,0 9.46,41.242,0 9.468,41.241,0 9.475,41.236,0 9.478,41.228,0 9.48,41.224,0 9.479,41.217,0 9.471,41.19,0 9.239,41.249,0 9.247,41.248,0 9.258,41.249,0 9.269,41.236,0 9.268,41.202,0 9.279,41.195,0 9.275,41.199,0 9.274,41.205,0 9.275,41.212,0 9.279,41.221,0 9.286,41.221,0 9.29,41.209,0 9.289,41.205,0 9.286,41.201,0 9.286,41.195,0 9.3,41.196,0 9.306,41.198,0 9.313,41.201,0 9.317,41.196,0 9.334,41.187,0 9.336,41.211,0 9.353,41.207,0 9.389,41.181,0 9.389,41.187,0 9.397,41.184,0 9.405,41.181,0 9.413,41.181,0 9.423,41.181,0 9.423,41.174,0 9.417,41.171,0 9.415,41.168,0 9.413,41.164,0 9.409,41.16,0 9.421,41.156,0 9.427,41.149,0 9.433,41.14,0 9.443,41.133,0 9.438,41.125,0 9.437,41.115,0 9.443,41.092,0 9.455,41.112,0 9.461,41.12,0 9.471,41.126,0 9.467,41.13,0 9.466,41.134,0 9.463,41.137,0 9.457,41.14,0 9.47,41.146,0 9.482,41.145,0 9.495,41.142,0 9.509,41.14,0 9.514,41.143,0 9.519,41.148,0 9.524,41.15,0 9.533,41.14,0 9.525,41.133,0 9.535,41.128,0 9.541,41.123,0 9.547,41.121,0 9.553,41.126,0 9.56,41.126,0 9.562,41.122,0 9.562,41.121,0 9.564,41.121,0 9.567,41.119,0 9.566,41.107,0 9.563,41.097,0 9.557,41.088,0 9.546,41.077,0 9.544,41.082,0 9.541,41.087,0 9.54,41.092,0 9.522,41.031,0 9.512,41.016,0 9.533,41.016,0 9.525,41.03,0 9.544,41.037,0 9.555,41.034,0 9.558,41.025,0 9.553,41.009,0 9.558,41.009,0 9.559,41.011,0 9.559,41.013,0 9.56,41.016,0 9.566,41.011,0 9.569,41.009,0 9.574,41.009,0 9.589,41.02,0 9.616,41.019,0 9.645,41.011,0 9.663,41.002,0 9.652,40.991,0 9.637,40.992,0 9.62,40.999,0 9.605,41.002,0 9.588,40.996,0 9.583,40.98,0 9.579,40.962,0 9.567,40.948,0 9.572,40.935,0 9.558,40.931,0 9.512,40.934,0 9.512,40.929,0 9.513,40.928,0 9.505,40.927,0 9.512,40.915,0 9.521,40.915,0 9.53,40.919,0 9.54,40.92,0 9.55,40.917,0 9.568,40.908,0 9.574,40.906,0 9.593,40.91,0 9.608,40.918,0 9.623,40.924,0 9.643,40.92,0 9.638,40.911,0 9.632,40.905,0 9.624,40.9,0 9.615,40.899,0 9.615,40.893,0 9.651,40.879,0 9.656,40.876,0 9.658,40.864,0 9.664,40.858,0 9.672,40.859,0 9.684,40.865,0 9.69,40.856,0 9.7,40.85,0 9.712,40.847,0 9.725,40.845,0 9.691,40.836,0 9.682,40.829,0 9.69,40.817,0 9.69,40.811,0 9.675,40.814,0 9.662,40.809,0 9.658,40.8,0 9.669,40.79,0 9.67,40.801,0 9.676,40.788,0 9.705,40.759,0 9.711,40.745,0 9.715,40.727,0 9.745,40.68,0 9.749,40.667,0 9.754,40.605,0 9.757,40.595,0 9.762,40.587,0 9.769,40.584,0 9.782,40.582,0 9.786,40.576,0 9.787,40.567,0 9.793,40.557,0 9.821,40.536,0 9.827,40.529,0 9.827,40.519,0 9.816,40.502,0 9.813,40.492,0 9.809,40.471,0 9.801,40.455,0 9.779,40.427,0 9.762,40.39,0 9.75,40.377,0 9.728,40.372,0 9.713,40.366,0 9.701,40.353,0 9.684,40.324,0 9.671,40.312,0 9.646,40.296,0 9.635,40.282,0 9.627,40.263,0 9.625,40.248,0 9.629,40.205,0 9.632,40.196,0 9.655,40.144,0 9.666,40.131,0 9.68,40.126,0 9.688,40.12,0 9.711,40.096,0 9.733,40.084,0 9.731,40.068,0 9.694,39.993,0 9.688,39.961,0 9.697,39.934,0 9.703,39.937,0 9.71,39.94,0 9.716,39.94,0 9.718,39.934,0 9.715,39.924,0 9.709,39.922,0 9.702,39.922,0 9.697,39.919,0 9.69,39.906,0 9.685,39.894,0 9.684,39.882,0 9.69,39.871,0 9.684,39.871,0 9.684,39.865,0 9.688,39.863,0 9.693,39.86,0 9.697,39.858,0 9.697,39.852,0 9.685,39.84,0 9.676,39.819,0 9.671,39.793,0 9.669,39.769,0 9.67,39.756,0 9.676,39.732,0 9.677,39.718,0 9.675,39.708,0 9.665,39.691,0 9.663,39.677,0 9.661,39.67,0 9.656,39.663,0 9.652,39.652,0 9.65,39.639,0 9.656,39.594,0 9.654,39.567,0 9.629,39.502,0 9.645,39.484,0 9.64,39.452,0 9.615,39.399,0 9.603,39.355,0 9.601,39.341,0 9.604,39.326,0 9.612,39.316,0 9.635,39.303,0 9.635,39.297,0 9.608,39.289,0 9.582,39.266,0 9.568,39.238,0 9.574,39.214,0 9.566,39.205,0 9.569,39.199,0 9.577,39.194,0 9.581,39.187,0 9.578,39.179,0 9.569,39.159,0 9.567,39.149,0 9.558,39.139,0 9.54,39.134,0 9.523,39.125,0 9.519,39.104,0 9.511,39.108,0 9.508,39.111,0 9.508,39.116,0 9.512,39.124,0 9.497,39.133,0 9.481,39.135,0 9.466,39.132,0 9.451,39.124,0 9.443,39.124,0 9.439,39.133,0 9.429,39.138,0 9.409,39.146,0 9.384,39.169,0 9.378,39.173,0 9.368,39.177,0 9.346,39.196,0 9.337,39.201,0 9.327,39.203,0 9.313,39.208,0 9.3,39.214,0 9.293,39.221,0 9.286,39.214,0 9.272,39.22,0 9.253,39.225,0 9.217,39.228,0 9.198,39.221,0 9.182,39.207,0 9.17,39.193,0 9.167,39.187,0 9.137,39.194,0 9.114,39.211,0 9.073,39.248,0 9.064,39.243,0 9.056,39.247,0 9.048,39.256,0 9.039,39.262,0 9.025,39.265,0 9.015,39.264,0 9.013,39.26,0 9.026,39.256,0 9.026,39.248,0 9.022,39.24,0 9.027,39.236,0 9.036,39.232,0 9.038,39.227,0 9.039,39.228,0 9.051,39.225,0 9.075,39.23,0 9.08,39.224,0 9.08,39.216,0 9.08,39.212,0 9.039,39.179,0 9.027,39.165,0 9.019,39.146,0 9.017,39.124,0 9.019,39.104,0 9.025,39.086,0 9.033,39.07,0 9.038,39.063,0 9.044,39.058,0 9.046,39.051,0 9.03,39.03,0 9.019,38.995,0 9.026,38.995,0 9.016,38.989,0 9.013,38.99,0 9.005,38.995,0 8.997,38.983,0 8.895,38.902,0 8.889,38.9,0 8.878,38.899,0 8.873,38.896,0 8.862,38.882,0 8.854,38.878,0 8.842,38.88,0 8.828,38.889,0 8.806,38.906,0 8.806,38.885,0 8.791,38.904,0 8.767,38.92,0 8.74,38.93,0 8.717,38.932,0 8.695,38.925,0 8.669,38.91,0 8.652,38.891,0 8.656,38.871,0 8.641,38.864,0 8.635,38.871,0 8.643,38.89,0 8.634,38.895,0 8.616,38.896,0 8.6,38.899,0 8.6,38.906,0 8.616,38.923,0 8.616,38.947,0 8.604,38.965,0 8.581,38.96,0 8.573,39.013,0 8.56,39.057,0 8.553,39.057,0 8.545,39.051,0 8.521,39.061,0 8.505,39.063,0 8.51,39.068,0 8.519,39.083,0 8.505,39.091,0 8.483,39.08,0 8.483,39.084,0 8.478,39.09,0 8.474,39.107,0 8.466,39.119,0 8.455,39.125,0 8.443,39.118,0 8.439,39.128,0 8.439,39.153,0 8.436,39.166,0 8.429,39.173,0 8.419,39.177,0 8.413,39.175,0 8.416,39.166,0 8.41,39.169,0 8.406,39.174,0 8.403,39.181,0 8.402,39.19,0 8.399,39.201,0 8.393,39.204,0 8.386,39.204,0 8.381,39.207,0 8.373,39.222,0 8.372,39.23,0 8.377,39.238,0 8.427,39.283,0 8.433,39.302,0 8.416,39.323,0 8.418,39.339,0 8.383,39.359,0 8.375,39.379,0 8.379,39.388,0 8.396,39.404,0 8.402,39.412,0 8.406,39.427,0 8.404,39.436,0 8.39,39.462,0 8.387,39.465,0 8.387,39.47,0 8.395,39.481,0 8.422,39.508,0 8.436,39.525,0 8.452,39.558,0 8.464,39.577,0 8.457,39.584,0 8.465,39.598,0 8.463,39.617,0 8.45,39.659,0 8.447,39.704,0 8.443,39.714,0 8.443,39.721,0 8.447,39.731,0 8.445,39.757,0 8.447,39.762,0 8.46,39.76,0 8.469,39.755,0 8.5,39.716,0 8.518,39.702,0 8.539,39.696,0 8.566,39.701,0 8.515,39.713,0 8.505,39.721,0 8.507,39.738,0 8.521,39.755,0 8.536,39.771,0 8.546,39.783,0 8.539,39.783,0 8.536,39.776,0 8.531,39.77,0 8.525,39.766,0 8.519,39.762,0 8.53,39.772,0 8.541,39.789,0 8.549,39.807,0 8.553,39.821,0 8.556,39.852,0 8.554,39.864,0 8.546,39.878,0 8.524,39.899,0 8.495,39.912,0 8.464,39.914,0 8.436,39.899,0 8.443,39.893,0 8.446,39.898,0 8.45,39.899,0 8.456,39.898,0 8.464,39.899,0 8.452,39.893,0 8.445,39.883,0 8.436,39.858,0 8.429,39.865,0 8.438,39.877,0 8.432,39.885,0 8.419,39.892,0 8.404,39.903,0 8.401,39.903,0 8.399,39.905,0 8.395,39.912,0 8.394,39.92,0 8.397,39.927,0 8.4,39.933,0 8.402,39.94,0 8.394,39.977,0 8.395,39.988,0 8.407,40.01,0 8.408,40.022,0 8.395,40.036,0 8.381,40.03,0 8.378,40.033,0 8.385,40.042,0 8.402,40.05,0 8.405,40.049,0 8.435,40.051,0 8.453,40.056,0 8.46,40.057,0 8.469,40.062,0 8.48,40.074,0 8.488,40.089,0 8.491,40.104,0 8.486,40.118,0 8.468,40.144,0 8.464,40.163,0 8.46,40.216,0 8.477,40.262,0 8.477,40.292,0 8.463,40.314,0 8.442,40.331,0 8.416,40.345,0 8.409,40.338,0 8.387,40.352,0 8.384,40.372,0 8.395,40.424,0 8.391,40.442,0 8.38,40.468,0 8.366,40.492,0 8.35,40.502,0 8.332,40.51,0 8.324,40.531,0 8.32,40.555,0 8.313,40.578,0 8.292,40.595,0 8.268,40.594,0 8.217,40.57,0 8.196,40.578,0 8.206,40.598,0 8.217,40.612,0 8.194,40.617,0 8.177,40.606,0 8.167,40.586,0 8.162,40.564,0 8.154,40.578,0 8.148,40.593,0 8.141,40.619,0 8.141,40.625,0 8.158,40.632,0 8.174,40.641,0 8.186,40.656,0 8.189,40.68,0 8.192,40.68,0 8.196,40.685,0 8.198,40.691,0 8.193,40.694,0 8.18,40.695,0 8.174,40.697,0 8.168,40.701,0 8.154,40.719,0 8.146,40.726,0 8.134,40.729,0 8.21,40.865,0 8.216,40.881,0 8.217,40.899,0 8.21,40.914,0 8.193,40.92,0 8.179,40.928,0 8.183,40.945,0 8.194,40.963,0 8.203,40.975,0 8.21,40.975,0 8.213,40.963,0 8.221,40.962,0 8.229,40.962,0 8.237,40.955,0 8.236,40.946,0 8.232,40.934,0 8.23,40.921,0 8.234,40.91,0 8.278,40.865,0 8.311,40.85,0 8.422,40.839,0 8.478,40.826,0 8.501,40.824,0 8.521,40.827,0 8.599,40.853,0 8.619,40.866,0 8.635,40.881,0 8.641,40.896,0 8.71,40.92,0 8.734,40.921,0 8.752,40.919,0 8.765,40.914,0 8.823,40.947,0 8.84,40.961,0 8.876,41.008,0 8.889,41.016,0 8.887,41.02,0 8.887,41.021,0 8.886,41.022,0 8.882,41.023,0 8.914,41.032,0 8.923,41.037,0 8.93,41.043,0 8.941,41.061,0 8.947,41.064,0 8.959,41.07,0 8.976,41.082,0 8.991,41.097,0 9.006,41.122,0 9.025,41.129,0 9.094,41.135,0 9.108,41.139,0 9.136,41.16,0 9.142,41.153,0 9.158,41.169,0 9.164,41.184,0 9.163,41.225,0 9.172,41.243,0 9.191,41.251,0 9.213,41.256,0 9.231,41.262,0 9.233,41.253,0 9.239,41.249,0 9.435,41.217,0 9.395,41.211,0 9.377,41.213,0 9.373,41.222,0 9.373,41.23,0 9.378,41.234,0 9.385,41.237,0 9.392,41.241,0 9.396,41.248,0 9.398,41.256,0 9.402,41.258,0 9.408,41.258,0 9.414,41.262,0 9.422,41.261,0 9.427,41.254,0 9.431,41.246,0 9.43,41.238,0 9.429,41.229,0 9.431,41.225,0 9.434,41.221,0 9.435,41.217,0 10.316,42.341,0 10.313,42.324,0 10.294,42.328,0 10.297,42.345,0 10.306,42.352,0 10.316,42.341,0 10.922,42.334,0 10.909,42.325,0 10.874,42.36,0 10.862,42.366,0 10.871,42.376,0 10.877,42.387,0 10.884,42.392,0 10.896,42.386,0 10.907,42.378,0 10.919,42.356,0 10.931,42.346,0 10.926,42.339,0 10.922,42.334,0 10.095,42.577,0 10.086,42.572,0 10.072,42.573,0 10.059,42.576,0 10.05,42.582,0 10.053,42.589,0 10.063,42.592,0 10.073,42.6,0 10.08,42.614,0 10.084,42.615,0 10.088,42.604,0 10.092,42.596,0 10.096,42.591,0 10.098,42.588,0 10.098,42.584,0 10.095,42.577,0 10.431,42.816,0 10.437,42.804,0 10.431,42.787,0 10.421,42.776,0 10.407,42.769,0 10.389,42.763,0 10.408,42.757,0 10.426,42.741,0 10.431,42.722,0 10.416,42.709,0 10.411,42.718,0 10.404,42.719,0 10.394,42.718,0 10.382,42.722,0 10.378,42.728,0 10.368,42.746,0 10.365,42.75,0 10.352,42.755,0 10.338,42.765,0 10.326,42.765,0 10.314,42.743,0 10.305,42.76,0 10.266,42.744,0 10.246,42.757,0 10.241,42.742,0 10.236,42.736,0 10.23,42.735,0 10.148,42.737,0 10.125,42.743,0 10.107,42.757,0 10.102,42.784,0 10.112,42.801,0 10.134,42.812,0 10.159,42.817,0 10.18,42.819,0 10.19,42.817,0 10.213,42.808,0 10.225,42.804,0 10.243,42.803,0 10.266,42.804,0 10.266,42.809,0 10.265,42.81,0 10.263,42.81,0 10.26,42.812,0 10.273,42.819,0 10.273,42.826,0 10.273,42.827,0 10.29,42.825,0 10.327,42.826,0 10.323,42.811,0 10.333,42.806,0 10.348,42.806,0 10.355,42.808,0 10.359,42.817,0 10.366,42.823,0 10.375,42.827,0 10.382,42.832,0 10.393,42.858,0 10.401,42.869,0 10.413,42.873,0 10.422,42.871,0 10.432,42.864,0 10.439,42.855,0 10.444,42.845,0 10.437,42.838,0 10.432,42.828,0 10.431,42.816,0 9.844,43.06,0 9.848,43.058,0 9.854,43.059,0 9.843,43.035,0 9.828,43.019,0 9.81,43.017,0 9.793,43.037,0 9.812,43.071,0 9.827,43.081,0 9.841,43.065,0 9.842,43.063,0 9.844,43.06,0 12.122,46.972,0 12.128,46.949,0 12.135,46.937,0 12.142,46.928,0 12.142,46.919,0 12.127,46.909,0 12.137,46.906,0 12.161,46.903,0 12.172,46.899,0 12.184,46.891,0 12.189,46.885,0 12.195,46.88,0 12.209,46.877,0 12.251,46.876,0 12.267,46.868,0 12.276,46.846,0 12.276,46.834,0 12.273,46.827,0 12.27,46.82,0 12.267,46.808,0 12.267,46.795,0 12.269,46.789,0 12.275,46.785,0 12.284,46.78,0 12.305,46.774,0 12.326,46.772,0 12.343,46.765,0 12.351,46.743,0 12.37,46.711,0 12.405,46.69,0 12.446,46.679,0 12.5,46.672,0 12.531,46.658,0 12.547,46.652,0 12.562,46.651,0 12.62,46.656,0 12.67,46.653,0 12.679,46.65,0 12.697,46.641,0 12.707,46.638,0 12.716,46.638,0 12.732,46.642,0 12.74,46.643,0 12.774,46.635,0 12.83,46.61,0 13.065,46.598,0 13.146,46.585,0 13.21,46.558,0 13.231,46.552,0 13.271,46.551,0 13.373,46.566,0 13.417,46.56,0 13.478,46.564,0 13.485,46.562,0 13.499,46.551,0 13.507,46.547,0 13.549,46.546,0 13.67,46.519,0 13.685,46.518,0 13.701,46.52,0 13.701,46.512,0 13.699,46.505,0 13.695,46.499,0 13.69,46.493,0 13.688,46.468,0 13.677,46.452,0 13.659,46.445,0 13.634,46.446,0 13.6,46.443,0 13.576,46.427,0 13.554,46.406,0 13.53,46.388,0 13.484,46.371,0 13.46,46.359,0 13.447,46.355,0 13.434,46.354,0 13.423,46.345,0 13.41,46.324,0 13.391,46.302,0 13.365,46.29,0 13.373,46.28,0 13.379,46.268,0 13.385,46.243,0 13.385,46.243,0 13.385,46.243,0 13.398,46.231,0 13.402,46.217,0 13.41,46.208,0 13.437,46.211,0 13.423,46.229,0 13.438,46.225,0 13.468,46.223,0 13.482,46.218,0 13.51,46.214,0 13.529,46.205,0 13.559,46.184,0 13.584,46.181,0 13.614,46.184,0 13.637,46.18,0 13.645,46.162,0 13.616,46.125,0 13.505,46.066,0 13.482,46.045,0 13.49,46.039,0 13.493,46.032,0 13.49,46.026,0 13.482,46.018,0 13.477,46.016,0 13.462,46.006,0 13.475,45.996,0 13.479,45.993,0 13.48,45.992,0 13.481,45.991,0 13.482,45.99,0 13.482,45.989,0 13.509,45.967,0 13.539,45.969,0 13.572,45.98,0 13.606,45.985,0 13.623,45.966,0 13.608,45.927,0 13.569,45.865,0 13.566,45.83,0 13.581,45.809,0 13.609,45.799,0 13.644,45.796,0 13.66,45.792,0 13.709,45.765,0 13.779,45.743,0 13.858,45.649,0 13.869,45.641,0 13.884,45.635,0 13.893,45.635,0 13.895,45.632,0 13.887,45.619,0 13.848,45.585,0 13.801,45.581,0 13.761,45.596,0 13.712,45.593,0 13.719,45.6,0 13.731,45.613,0 13.757,45.613,0 13.787,45.611,0 13.809,45.614,0 13.796,45.617,0 13.787,45.624,0 13.778,45.635,0 13.74,45.649,0 13.758,45.655,0 13.754,45.672,0 13.74,45.691,0 13.727,45.703,0 13.648,45.762,0 13.63,45.772,0 13.575,45.789,0 13.552,45.792,0 13.535,45.782,0 13.525,45.76,0 13.529,45.74,0 13.555,45.737,0 13.519,45.725,0 13.514,45.721,0 13.508,45.714,0 13.481,45.71,0 13.47,45.707,0 13.452,45.694,0 13.429,45.681,0 13.402,45.675,0 13.377,45.683,0 13.392,45.686,0 13.41,45.691,0 13.425,45.698,0 13.432,45.707,0 13.423,45.724,0 13.382,45.73,0 13.37,45.744,0 13.352,45.74,0 13.255,45.756,0 13.246,45.759,0 13.222,45.776,0 13.216,45.779,0 13.206,45.778,0 13.17,45.768,0 13.158,45.754,0 13.15,45.751,0 13.14,45.755,0 13.132,45.769,0 13.12,45.772,0 13.111,45.767,0 13.109,45.758,0 13.112,45.749,0 13.124,45.744,0 13.124,45.737,0 13.101,45.736,0 13.081,45.727,0 13.07,45.713,0 13.076,45.697,0 13.092,45.689,0 13.112,45.691,0 13.15,45.703,0 13.139,45.689,0 13.104,45.669,0 13.096,45.652,0 13.086,45.642,0 13.061,45.636,0 12.982,45.635,0 12.944,45.628,0 12.781,45.553,0 12.612,45.496,0 12.513,45.47,0 12.497,45.46,0 12.488,45.456,0 12.452,45.45,0 12.424,45.438,0 12.411,45.436,0 12.419,45.451,0 12.43,45.464,0 12.436,45.475,0 12.431,45.484,0 12.441,45.483,0 12.448,45.484,0 12.452,45.489,0 12.452,45.498,0 12.459,45.498,0 12.463,45.489,0 12.468,45.485,0 12.472,45.486,0 12.479,45.491,0 12.466,45.504,0 12.477,45.503,0 12.488,45.504,0 12.498,45.506,0 12.5,45.504,0 12.501,45.506,0 12.504,45.503,0 12.507,45.499,0 12.507,45.498,0 12.504,45.498,0 12.493,45.498,0 12.493,45.491,0 12.516,45.492,0 12.521,45.505,0 12.522,45.519,0 12.531,45.525,0 12.549,45.527,0 12.563,45.531,0 12.574,45.54,0 12.582,45.553,0 12.57,45.549,0 12.545,45.536,0 12.538,45.536,0 12.519,45.55,0 12.511,45.559,0 12.507,45.573,0 12.486,45.565,0 12.459,45.548,0 12.443,45.53,0 12.452,45.518,0 12.452,45.512,0 12.435,45.512,0 12.418,45.523,0 12.411,45.518,0 12.404,45.518,0 12.397,45.539,0 12.385,45.523,0 12.391,45.514,0 12.425,45.504,0 12.425,45.498,0 12.412,45.493,0 12.394,45.491,0 12.381,45.494,0 12.384,45.504,0 12.351,45.505,0 12.31,45.489,0 12.273,45.463,0 12.253,45.436,0 12.253,45.43,0 12.259,45.43,0 12.251,45.42,0 12.247,45.411,0 12.249,45.402,0 12.259,45.395,0 12.25,45.385,0 12.248,45.378,0 12.249,45.371,0 12.246,45.361,0 12.238,45.358,0 12.229,45.357,0 12.224,45.354,0 12.233,45.34,0 12.221,45.327,0 12.217,45.316,0 12.209,45.309,0 12.188,45.306,0 12.175,45.31,0 12.164,45.316,0 12.155,45.313,0 12.15,45.292,0 12.16,45.283,0 12.169,45.262,0 12.181,45.258,0 12.192,45.263,0 12.2,45.274,0 12.203,45.288,0 12.198,45.299,0 12.218,45.294,0 12.222,45.283,0 12.221,45.269,0 12.225,45.251,0 12.214,45.248,0 12.212,45.243,0 12.216,45.237,0 12.225,45.23,0 12.222,45.216,0 12.231,45.204,0 12.248,45.197,0 12.267,45.196,0 12.264,45.2,0 12.263,45.201,0 12.259,45.203,0 12.274,45.211,0 12.296,45.226,0 12.308,45.23,0 12.299,45.215,0 12.305,45.201,0 12.316,45.186,0 12.322,45.172,0 12.322,45.139,0 12.329,45.101,0 12.319,45.103,0 12.308,45.108,0 12.309,45.114,0 12.308,45.124,0 12.308,45.128,0 12.298,45.106,0 12.297,45.088,0 12.307,45.078,0 12.329,45.08,0 12.326,45.083,0 12.324,45.086,0 12.322,45.093,0 12.341,45.081,0 12.354,45.067,0 12.364,45.052,0 12.377,45.039,0 12.377,45.032,0 12.369,45.031,0 12.365,45.029,0 12.361,45.027,0 12.356,45.024,0 12.369,45.011,0 12.384,45.026,0 12.387,45.039,0 12.381,45.051,0 12.369,45.065,0 12.384,45.056,0 12.402,45.05,0 12.414,45.043,0 12.411,45.032,0 12.427,45.02,0 12.435,45.015,0 12.445,45.011,0 12.465,44.992,0 12.487,44.976,0 12.5,44.983,0 12.497,44.984,0 12.49,44.983,0 12.487,44.983,0 12.487,44.991,0 12.503,44.991,0 12.517,44.987,0 12.528,44.98,0 12.535,44.97,0 12.534,44.961,0 12.524,44.95,0 12.528,44.943,0 12.519,44.934,0 12.516,44.928,0 12.513,44.922,0 12.507,44.922,0 12.5,44.921,0 12.495,44.91,0 12.493,44.878,0 12.488,44.862,0 12.475,44.845,0 12.445,44.82,0 12.444,44.825,0 12.439,44.835,0 12.433,44.846,0 12.425,44.854,0 12.44,44.877,0 12.444,44.89,0 12.439,44.901,0 12.427,44.905,0 12.416,44.9,0 12.407,44.891,0 12.404,44.884,0 12.393,44.868,0 12.392,44.859,0 12.417,44.851,0 12.416,44.843,0 12.409,44.836,0 12.397,44.833,0 12.397,44.826,0 12.404,44.825,0 12.417,44.821,0 12.425,44.82,0 12.417,44.803,0 12.398,44.794,0 12.376,44.792,0 12.358,44.804,0 12.347,44.815,0 12.322,44.833,0 12.304,44.843,0 12.293,44.843,0 12.267,44.826,0 12.267,44.82,0 12.281,44.82,0 12.254,44.751,0 12.247,44.711,0 12.253,44.668,0 12.266,44.636,0 12.276,44.62,0 12.284,44.614,0 12.286,44.602,0 12.281,44.532,0 12.284,44.487,0 12.315,44.387,0 12.319,44.361,0 12.322,44.353,0 12.326,44.348,0 12.34,44.334,0 12.343,44.329,0 12.345,44.308,0 12.351,44.288,0 12.369,44.25,0 12.391,44.222,0 12.418,44.195,0 12.459,44.166,0 12.479,44.139,0 12.511,44.114,0 12.548,44.093,0 12.575,44.085,0 12.632,44.03,0 12.662,44.008,0 12.692,43.99,0 12.711,43.983,0 12.757,43.972,0 12.804,43.967,0 12.823,43.958,0 12.863,43.935,0 12.929,43.916,0 12.939,43.904,0 12.948,43.897,0 13.254,43.703,0 13.371,43.65,0 13.39,43.644,0 13.4,43.635,0 13.447,43.623,0 13.474,43.612,0 13.484,43.616,0 13.491,43.623,0 13.497,43.627,0 13.5,43.628,0 13.502,43.63,0 13.505,43.633,0 13.511,43.633,0 13.517,43.631,0 13.52,43.627,0 13.522,43.622,0 13.525,43.62,0 13.544,43.613,0 13.558,43.596,0 13.57,43.58,0 13.579,43.573,0 13.599,43.569,0 13.616,43.56,0 13.625,43.547,0 13.618,43.531,0 13.761,43.264,0 13.777,43.243,0 13.781,43.236,0 13.787,43.2,0 13.791,43.192,0 13.803,43.178,0 13.835,43.127,0 13.849,43.092,0 13.866,43.007,0 13.945,42.798,0 13.981,42.73,0 14.002,42.698,0 14.064,42.625,0 14.069,42.609,0 14.076,42.599,0 14.221,42.47,0 14.285,42.428,0 14.357,42.393,0 14.388,42.373,0 14.43,42.321,0 14.561,42.225,0 14.596,42.208,0 14.654,42.191,0 14.694,42.185,0 14.71,42.175,0 14.718,42.16,0 14.723,42.119,0 14.73,42.099,0 14.741,42.084,0 14.758,42.079,0 14.781,42.075,0 14.8,42.066,0 14.836,42.044,0 14.871,42.032,0 14.953,42.021,0 14.994,42.01,0 15.008,42.001,0 15.035,41.974,0 15.046,41.969,0 15.064,41.964,0 15.105,41.942,0 15.124,41.934,0 15.166,41.927,0 15.282,41.928,0 15.401,41.908,0 15.447,41.907,0 15.612,41.928,0 15.775,41.921,0 16.028,41.944,0 16.112,41.928,0 16.112,41.926,0 16.141,41.92,0 16.161,41.892,0 16.18,41.893,0 16.177,41.877,0 16.184,41.858,0 16.193,41.821,0 16.194,41.808,0 16.193,41.791,0 16.185,41.779,0 16.167,41.763,0 16.146,41.749,0 16.128,41.742,0 16.108,41.737,0 16.09,41.726,0 16.064,41.701,0 16.028,41.68,0 15.926,41.64,0 15.901,41.614,0 15.892,41.577,0 15.897,41.536,0 15.912,41.503,0 15.934,41.479,0 15.962,41.459,0 16.022,41.428,0 16.086,41.412,0 16.101,41.403,0 16.115,41.393,0 16.302,41.328,0 16.461,41.262,0 16.521,41.25,0 16.539,41.239,0 16.555,41.227,0 16.594,41.207,0 16.831,41.146,0 16.852,41.133,0 16.859,41.133,0 16.859,41.14,0 16.865,41.14,0 16.886,41.124,0 17.058,41.082,0 17.204,41.021,0 17.277,40.98,0 17.311,40.955,0 17.348,40.912,0 17.362,40.906,0 17.378,40.902,0 17.414,40.881,0 17.476,40.83,0 17.493,40.824,0 17.513,40.82,0 17.549,40.802,0 17.635,40.785,0 17.646,40.78,0 17.749,40.747,0 17.844,40.694,0 17.922,40.683,0 17.956,40.67,0 17.956,40.647,0 17.967,40.647,0 17.993,40.653,0 18.008,40.65,0 18.012,40.644,0 18.012,40.635,0 18.016,40.625,0 18.04,40.608,0 18.044,40.602,0 18.038,40.557,0 18.12,40.504,0 18.212,40.464,0 18.232,40.461,0 18.239,40.457,0 18.259,40.43,0 18.271,40.421,0 18.304,40.4,0 18.33,40.366,0 18.344,40.351,0 18.362,40.345,0 18.371,40.338,0 18.438,40.268,0 18.501,40.152,0 18.505,40.146,0 18.51,40.142,0 18.517,40.139,0 18.512,40.127,0 18.514,40.12,0 18.518,40.114,0 18.517,40.104,0 18.509,40.094,0 18.492,40.084,0 18.484,40.055,0 18.471,40.043,0 18.435,40.022,0 18.412,39.979,0 18.408,39.968,0 18.405,39.947,0 18.395,39.925,0 18.393,39.916,0 18.4,39.89,0 18.401,39.878,0 18.387,39.825,0 18.39,39.817,0 18.384,39.814,0 18.374,39.8,0 18.369,39.796,0 18.347,39.798,0 18.339,39.8,0 18.331,39.803,0 18.283,39.833,0 18.266,39.837,0 18.225,39.837,0 18.212,39.839,0 18.187,39.852,0 18.162,39.86,0 18.131,39.883,0 18.095,39.903,0 18.082,39.906,0 18.072,39.911,0 18.008,39.986,0 17.996,39.995,0 17.996,40.002,0 18.012,40.003,0 18.021,40.01,0 18.023,40.021,0 18.016,40.036,0 18.006,40.045,0 17.979,40.051,0 17.968,40.057,0 18.003,40.074,0 18.012,40.096,0 17.998,40.12,0 17.968,40.146,0 17.941,40.163,0 17.927,40.176,0 17.92,40.191,0 17.92,40.21,0 17.917,40.227,0 17.912,40.24,0 17.9,40.249,0 17.913,40.249,0 17.913,40.255,0 17.864,40.285,0 17.848,40.29,0 17.513,40.303,0 17.494,40.307,0 17.441,40.331,0 17.431,40.331,0 17.41,40.33,0 17.4,40.331,0 17.393,40.335,0 17.375,40.348,0 17.369,40.351,0 17.352,40.355,0 17.297,40.379,0 17.241,40.395,0 17.213,40.406,0 17.201,40.42,0 17.224,40.428,0 17.244,40.441,0 17.248,40.457,0 17.228,40.474,0 17.248,40.48,0 17.296,40.473,0 17.317,40.482,0 17.324,40.498,0 17.305,40.499,0 17.262,40.488,0 17.264,40.491,0 17.269,40.496,0 17.248,40.503,0 17.23,40.497,0 17.211,40.487,0 17.191,40.482,0 17.182,40.485,0 17.177,40.493,0 17.172,40.502,0 17.167,40.509,0 17.157,40.512,0 17.134,40.512,0 17.125,40.515,0 17.05,40.519,0 16.977,40.492,0 16.913,40.445,0 16.783,40.301,0 16.762,40.269,0 16.738,40.211,0 16.731,40.2,0 16.716,40.193,0 16.68,40.146,0 16.625,40.108,0 16.605,40.084,0 16.597,40.046,0 16.6,40.034,0 16.614,39.996,0 16.632,39.966,0 16.622,39.953,0 16.606,39.943,0 16.59,39.92,0 16.543,39.885,0 16.509,39.837,0 16.492,39.805,0 16.49,39.775,0 16.503,39.747,0 16.529,39.721,0 16.529,39.714,0 16.516,39.689,0 16.546,39.661,0 16.592,39.636,0 16.625,39.625,0 16.75,39.62,0 16.783,39.611,0 16.799,39.603,0 16.817,39.591,0 16.831,39.576,0 16.838,39.56,0 16.847,39.552,0 16.906,39.529,0 16.954,39.499,0 16.971,39.495,0 16.996,39.492,0 17.012,39.486,0 17.024,39.475,0 17.036,39.461,0 17.058,39.441,0 17.089,39.422,0 17.125,39.409,0 17.159,39.406,0 17.123,39.338,0 17.115,39.283,0 17.115,39.269,0 17.118,39.256,0 17.125,39.244,0 17.143,39.222,0 17.146,39.21,0 17.141,39.179,0 17.123,39.121,0 17.125,39.091,0 17.148,39.054,0 17.152,39.046,0 17.159,39.04,0 17.193,39.031,0 17.207,39.029,0 17.187,39.019,0 17.177,39.012,0 17.173,39.005,0 17.172,38.966,0 17.173,38.96,0 17.139,38.936,0 17.136,38.932,0 17.128,38.929,0 17.119,38.919,0 17.105,38.899,0 17.096,38.919,0 17.071,38.923,0 17.043,38.916,0 17.023,38.906,0 16.997,38.929,0 16.982,38.937,0 16.958,38.94,0 16.936,38.938,0 16.839,38.918,0 16.728,38.879,0 16.688,38.856,0 16.68,38.847,0 16.671,38.84,0 16.611,38.816,0 16.586,38.798,0 16.575,38.785,0 16.564,38.756,0 16.551,38.741,0 16.539,38.723,0 16.535,38.7,0 16.547,38.693,0 16.55,38.69,0 16.549,38.672,0 16.559,38.596,0 16.578,38.528,0 16.578,38.503,0 16.57,38.429,0 16.562,38.416,0 16.523,38.387,0 16.509,38.371,0 16.498,38.369,0 16.468,38.348,0 16.436,38.34,0 16.34,38.301,0 16.307,38.277,0 16.17,38.143,0 16.152,38.111,0 16.126,38.005,0 16.112,37.973,0 16.102,37.96,0 16.091,37.949,0 16.078,37.94,0 16.064,37.932,0 16.016,37.924,0 16.002,37.919,0 15.943,37.933,0 15.762,37.925,0 15.736,37.931,0 15.709,37.941,0 15.685,37.953,0 15.666,37.967,0 15.646,37.988,0 15.636,38.009,0 15.639,38.027,0 15.659,38.042,0 15.633,38.074,0 15.625,38.092,0 15.628,38.107,0 15.642,38.126,0 15.648,38.143,0 15.647,38.162,0 15.639,38.186,0 15.633,38.22,0 15.651,38.241,0 15.685,38.253,0 15.787,38.278,0 15.796,38.285,0 15.799,38.291,0 15.813,38.3,0 15.817,38.306,0 15.83,38.351,0 15.905,38.474,0 15.918,38.517,0 15.916,38.55,0 15.901,38.578,0 15.871,38.604,0 15.864,38.608,0 15.851,38.613,0 15.845,38.618,0 15.836,38.628,0 15.834,38.634,0 15.836,38.639,0 15.837,38.649,0 15.845,38.66,0 15.864,38.668,0 15.905,38.679,0 15.969,38.712,0 16.003,38.725,0 16.049,38.728,0 16.121,38.721,0 16.137,38.724,0 16.153,38.731,0 16.18,38.748,0 16.201,38.776,0 16.216,38.814,0 16.222,38.856,0 16.221,38.899,0 16.215,38.919,0 16.205,38.934,0 16.19,38.943,0 16.169,38.947,0 16.155,38.955,0 16.14,38.974,0 16.084,39.075,0 16.043,39.31,0 16.032,39.345,0 15.955,39.489,0 15.934,39.513,0 15.905,39.536,0 15.877,39.551,0 15.868,39.564,0 15.865,39.588,0 15.851,39.615,0 15.837,39.652,0 15.816,39.679,0 15.807,39.695,0 15.789,39.796,0 15.789,39.79,0 15.784,39.81,0 15.779,39.82,0 15.772,39.824,0 15.77,39.83,0 15.783,39.868,0 15.775,39.891,0 15.742,39.929,0 15.735,39.943,0 15.729,39.964,0 15.714,39.981,0 15.679,40.009,0 15.652,40.043,0 15.631,40.057,0 15.625,40.065,0 15.625,40.078,0 15.611,40.073,0 15.536,40.078,0 15.51,40.07,0 15.493,40.059,0 15.46,40.029,0 15.425,40.004,0 15.405,39.999,0 15.377,40.002,0 15.354,40.012,0 15.315,40.034,0 15.303,40.036,0 15.294,40.032,0 15.284,40.03,0 15.273,40.028,0 15.262,40.029,0 15.262,40.036,0 15.28,40.047,0 15.264,40.074,0 15.234,40.1,0 15.21,40.112,0 15.191,40.119,0 15.128,40.169,0 15.113,40.175,0 15.096,40.173,0 15.066,40.166,0 15.048,40.169,0 15.035,40.175,0 15.015,40.194,0 14.974,40.223,0 14.967,40.224,0 14.959,40.231,0 14.923,40.238,0 14.912,40.241,0 14.907,40.258,0 14.932,40.285,0 14.94,40.307,0 14.933,40.324,0 14.933,40.334,0 14.943,40.338,0 14.954,40.34,0 14.965,40.345,0 14.973,40.352,0 14.98,40.359,0 14.99,40.394,0 14.976,40.431,0 14.889,40.573,0 14.862,40.607,0 14.836,40.632,0 14.81,40.653,0 14.783,40.67,0 14.753,40.676,0 14.72,40.667,0 14.691,40.649,0 14.679,40.646,0 14.626,40.649,0 14.614,40.646,0 14.572,40.617,0 14.545,40.613,0 14.517,40.62,0 14.487,40.632,0 14.472,40.624,0 14.423,40.615,0 14.402,40.602,0 14.356,40.583,0 14.343,40.57,0 14.331,40.584,0 14.329,40.605,0 14.338,40.624,0 14.36,40.632,0 14.38,40.634,0 14.388,40.637,0 14.395,40.65,0 14.403,40.657,0 14.471,40.699,0 14.48,40.711,0 14.475,40.729,0 14.461,40.744,0 14.443,40.755,0 14.426,40.762,0 14.415,40.765,0 14.399,40.767,0 14.391,40.77,0 14.385,40.774,0 14.372,40.787,0 14.367,40.79,0 14.349,40.797,0 14.313,40.828,0 14.295,40.839,0 14.276,40.84,0 14.249,40.837,0 14.224,40.831,0 14.213,40.821,0 14.204,40.801,0 14.182,40.8,0 14.112,40.829,0 14.096,40.834,0 14.083,40.831,0 14.077,40.822,0 14.078,40.81,0 14.082,40.797,0 14.083,40.783,0 14.075,40.788,0 14.041,40.798,0 14.053,40.837,0 14.044,40.875,0 13.966,40.996,0 13.931,41.014,0 13.918,41.023,0 13.915,41.033,0 13.913,41.054,0 13.911,41.064,0 13.885,41.104,0 13.786,41.203,0 13.722,41.252,0 13.709,41.256,0 13.679,41.25,0 13.664,41.25,0 13.657,41.259,0 13.595,41.253,0 13.564,41.238,0 13.576,41.208,0 13.544,41.206,0 13.535,41.208,0 13.526,41.215,0 13.52,41.225,0 13.515,41.229,0 13.508,41.221,0 13.5,41.221,0 13.481,41.239,0 13.325,41.295,0 13.286,41.295,0 13.205,41.284,0 13.187,41.278,0 13.152,41.26,0 13.115,41.251,0 13.091,41.226,0 13.069,41.221,0 13.045,41.227,0 13.037,41.24,0 13.034,41.257,0 13.024,41.273,0 13.013,41.286,0 12.993,41.315,0 12.98,41.331,0 12.924,41.379,0 12.894,41.399,0 12.863,41.413,0 12.842,41.418,0 12.764,41.421,0 12.749,41.423,0 12.679,41.458,0 12.655,41.465,0 12.643,41.458,0 12.636,41.447,0 12.62,41.459,0 12.546,41.544,0 12.449,41.63,0 12.343,41.702,0 12.328,41.711,0 12.301,41.717,0 12.286,41.727,0 12.277,41.729,0 12.247,41.733,0 12.24,41.736,0 12.224,41.75,0 12.216,41.768,0 12.212,41.787,0 12.212,41.808,0 12.207,41.827,0 12.195,41.847,0 12.171,41.879,0 12.148,41.903,0 12.05,41.96,0 12.039,41.965,0 12.03,41.973,0 12.027,41.986,0 12.021,41.993,0 11.993,41.996,0 11.983,42,0 11.97,42.011,0 11.953,42.022,0 11.935,42.031,0 11.917,42.038,0 11.84,42.036,0 11.828,42.034,0 11.823,42.047,0 11.81,42.066,0 11.794,42.084,0 11.78,42.092,0 11.772,42.106,0 11.751,42.128,0 11.746,42.136,0 11.744,42.152,0 11.737,42.169,0 11.683,42.252,0 11.659,42.279,0 11.54,42.349,0 11.49,42.359,0 11.421,42.386,0 11.397,42.393,0 11.397,42.4,0 11.387,42.404,0 11.377,42.407,0 11.366,42.408,0 11.355,42.407,0 11.363,42.4,0 11.334,42.4,0 11.26,42.421,0 11.246,42.422,0 11.228,42.422,0 11.212,42.419,0 11.205,42.411,0 11.201,42.395,0 11.187,42.379,0 11.185,42.366,0 11.175,42.369,0 11.165,42.369,0 11.158,42.368,0 11.157,42.366,0 11.148,42.371,0 11.135,42.384,0 11.107,42.391,0 11.095,42.402,0 11.087,42.418,0 11.081,42.435,0 11.1,42.443,0 11.123,42.446,0 11.167,42.448,0 11.175,42.458,0 11.184,42.48,0 11.19,42.504,0 11.188,42.521,0 11.167,42.546,0 11.159,42.564,0 11.149,42.563,0 11.138,42.559,0 11.129,42.558,0 11.117,42.572,0 11.108,42.591,0 11.098,42.607,0 11.081,42.612,0 11.078,42.632,0 11.054,42.647,0 11.006,42.668,0 11.001,42.68,0 10.996,42.696,0 10.99,42.71,0 10.982,42.716,0 10.973,42.72,0 10.944,42.743,0 10.891,42.764,0 10.732,42.804,0 10.756,42.819,0 10.766,42.835,0 10.767,42.854,0 10.766,42.877,0 10.769,42.884,0 10.775,42.888,0 10.778,42.894,0 10.774,42.908,0 10.764,42.918,0 10.751,42.925,0 10.682,42.949,0 10.633,42.958,0 10.584,42.959,0 10.54,42.949,0 10.544,42.939,0 10.547,42.935,0 10.519,42.925,0 10.5,42.94,0 10.478,42.99,0 10.503,43.005,0 10.518,43.024,0 10.54,43.079,0 10.536,43.091,0 10.536,43.112,0 10.54,43.134,0 10.547,43.147,0 10.539,43.164,0 10.535,43.185,0 10.533,43.226,0 10.529,43.246,0 10.517,43.267,0 10.438,43.388,0 10.374,43.453,0 10.36,43.465,0 10.327,43.477,0 10.318,43.492,0 10.295,43.568,0 10.265,43.809,0 10.252,43.846,0 10.211,43.92,0 10.181,43.955,0 10.137,43.978,0 10.106,44.016,0 10.091,44.025,0 10.073,44.029,0 10.036,44.048,0 10.015,44.052,0 9.999,44.058,0 9.989,44.06,0 9.985,44.055,0 9.981,44.05,0 9.973,44.045,0 9.963,44.044,0 9.954,44.048,0 9.938,44.06,0 9.905,44.08,0 9.888,44.093,0 9.877,44.088,0 9.845,44.108,0 9.827,44.107,0 9.834,44.1,0 9.829,44.098,0 9.825,44.095,0 9.82,44.093,0 9.825,44.085,0 9.831,44.079,0 9.839,44.075,0 9.848,44.072,0 9.848,44.066,0 9.842,44.063,0 9.839,44.06,0 9.834,44.052,0 9.847,44.046,0 9.843,44.041,0 9.833,44.042,0 9.827,44.055,0 9.82,44.063,0 9.772,44.079,0 9.722,44.113,0 9.71,44.118,0 9.683,44.136,0 9.673,44.141,0 9.644,44.142,0 9.632,44.144,0 9.622,44.148,0 9.587,44.178,0 9.581,44.179,0 9.573,44.191,0 9.557,44.2,0 9.512,44.215,0 9.5,44.222,0 9.49,44.231,0 9.485,44.244,0 9.473,44.24,0 9.454,44.237,0 9.437,44.239,0 9.43,44.247,0 9.423,44.257,0 9.375,44.272,0 9.368,44.294,0 9.263,44.336,0 9.231,44.353,0 9.222,44.344,0 9.214,44.333,0 9.21,44.321,0 9.211,44.305,0 9.166,44.318,0 9.147,44.328,0 9.149,44.34,0 9.131,44.363,0 9.103,44.374,0 9.002,44.387,0 8.953,44.4,0 8.924,44.411,0 8.915,44.409,0 8.869,44.409,0 8.846,44.413,0 8.838,44.417,0 8.828,44.428,0 8.763,44.432,0 8.738,44.429,0 8.725,44.424,0 8.696,44.406,0 8.686,44.398,0 8.679,44.394,0 8.671,44.394,0 8.663,44.395,0 8.656,44.394,0 8.594,44.363,0 8.577,44.36,0 8.565,44.357,0 8.541,44.34,0 8.467,44.304,0 8.445,44.284,0 8.45,44.264,0 8.44,44.253,0 8.437,44.247,0 8.436,44.24,0 8.433,44.238,0 8.418,44.23,0 8.412,44.227,0 8.407,44.215,0 8.409,44.204,0 8.409,44.193,0 8.395,44.182,0 8.37,44.173,0 8.314,44.16,0 8.285,44.148,0 8.27,44.138,0 8.257,44.128,0 8.234,44.103,0 8.231,44.096,0 8.232,44.08,0 8.231,44.072,0 8.224,44.057,0 8.217,44.045,0 8.17,44.006,0 8.153,43.983,0 8.168,43.962,0 8.168,43.956,0 8.145,43.952,0 8.116,43.927,0 8.09,43.92,0 8.082,43.915,0 8.076,43.909,0 8.073,43.904,0 8.068,43.896,0 8.056,43.892,0 8.032,43.887,0 7.96,43.853,0 7.786,43.822,0 7.737,43.798,0 7.695,43.791,0 7.573,43.791,0 7.545,43.784,0 7.532,43.784,0 7.524,43.789,0 7.513,43.792,0 7.503,43.792,0 7.483,43.84,0 7.478,43.866,0 7.493,43.886,0 7.537,43.921,0 7.557,43.944,0 7.609,43.976,0 7.631,43.994,0 7.639,44.005,0 7.647,44.027,0 7.653,44.04,0 7.664,44.049,0 7.679,44.057,0 7.69,44.067,0 7.692,44.085,0 7.676,44.109,0 7.654,44.125,0 7.642,44.144,0 7.656,44.176,0 7.625,44.18,0 7.584,44.161,0 7.555,44.159,0 7.381,44.123,0 7.341,44.124,0 7.331,44.125,0 7.322,44.132,0 7.316,44.14,0 7.309,44.147,0 7.296,44.151,0 7.27,44.154,0 7.251,44.16,0 7.145,44.207,0 7.105,44.218,0 7.046,44.24,0 7.033,44.243,0 7.02,44.242,0 7.008,44.239,0 6.996,44.238,0 6.983,44.242,0 6.973,44.249,0 6.969,44.258,0 6.966,44.268,0 6.959,44.277,0 6.95,44.285,0 6.93,44.295,0 6.921,44.302,0 6.916,44.31,0 6.904,44.33,0 6.896,44.34,0 6.874,44.358,0 6.87,44.363,0 6.866,44.372,0 6.866,44.377,0 6.869,44.383,0 6.877,44.414,0 6.884,44.423,0 6.918,44.436,0 6.892,44.452,0 6.861,44.475,0 6.839,44.503,0 6.836,44.534,0 6.846,44.547,0 6.897,44.575,0 6.932,44.618,0 6.946,44.625,0 6.934,44.647,0 6.941,44.667,0 6.96,44.683,0 6.983,44.692,0 7.001,44.692,0 7.037,44.685,0 7.055,44.685,0 7.049,44.698,0 7.019,44.739,0 7.015,44.747,0 7.01,44.772,0 6.998,44.794,0 6.999,44.795,0 7.004,44.811,0 7.006,44.812,0 7.006,44.816,0 7.007,44.819,0 7.007,44.822,0 7.005,44.828,0 7.001,44.833,0 6.983,44.847,0 6.933,44.862,0 6.915,44.863,0 6.866,44.856,0 6.847,44.859,0 6.778,44.888,0 6.745,44.908,0 6.728,44.929,0 6.73,44.985,0 6.723,45.013,0 6.697,45.027,0 6.662,45.029,0 6.652,45.036,0 6.64,45.05,0 6.637,45.059,0 6.638,45.067,0 6.637,45.074,0 6.62,45.084,0 6.603,45.103,0 6.615,45.115,0 6.633,45.126,0 6.667,45.14,0 6.676,45.141,0 6.694,45.14,0 6.702,45.141,0 6.711,45.145,0 6.729,45.155,0 6.736,45.157,0 6.771,45.153,0 6.808,45.139,0 6.844,45.13,0 6.877,45.141,0 6.879,45.147,0 6.873,45.152,0 6.868,45.157,0 6.873,45.166,0 6.881,45.168,0 6.905,45.169,0 6.914,45.17,0 6.928,45.18,0 6.946,45.201,0 6.959,45.21,0 6.994,45.221,0 7.03,45.228,0 7.038,45.226,0 7.05,45.215,0 7.055,45.214,0 7.062,45.219,0 7.081,45.243,0 7.108,45.259,0 7.108,45.275,0 7.098,45.295,0 7.093,45.324,0 7.098,45.33,0 7.13,45.357,0 7.151,45.383,0 7.16,45.398,0 7.161,45.411,0 7.153,45.415,0 7.11,45.428,0 7.097,45.435,0 7.089,45.447,0 7.082,45.459,0 7.072,45.47,0 7.028,45.493,0 6.983,45.511,0 6.975,45.526,0 6.97,45.567,0 6.966,45.574,0 6.955,45.586,0 6.953,45.594,0 6.956,45.603,0 6.967,45.62,0 6.969,45.626,0 6.963,45.641,0 6.951,45.647,0 6.919,45.653,0 6.905,45.66,0 6.883,45.676,0 6.869,45.679,0 6.843,45.683,0 6.816,45.697,0 6.796,45.718,0 6.785,45.76,0 6.782,45.777,0 6.783,45.795,0 6.788,45.812,0 6.801,45.826,0 6.816,45.833,0 6.846,45.836,0 6.846,45.838,0 6.849,45.842,0 6.853,45.847,0 6.858,45.849,0 6.862,45.849,0 6.87,45.845,0 6.873,45.845,0 6.88,45.846,0 6.905,45.845,0 6.926,45.85,0 6.949,45.858,0 6.969,45.87,0 6.983,45.886,0 6.989,45.899,0 6.997,45.911,0 7.008,45.921,0 7.022,45.925,0 7.067,45.89,0 7.09,45.881,0 7.121,45.876,0 7.154,45.877,0 7.184,45.88,0 7.245,45.898,0 7.274,45.91,0 7.287,45.913,0 7.362,45.908,0 7.394,45.916,0 7.453,45.946,0 7.483,45.955,0 7.504,45.957,0 7.515,45.967,0 7.524,45.978,0 7.541,45.984,0 7.643,45.966,0 7.659,45.96,0 7.674,45.95,0 7.693,45.931,0 7.694,45.929,0 7.706,45.926,0 7.715,45.927,0 7.722,45.93,0 7.732,45.93,0 7.78,45.918,0 7.808,45.918,0 7.825,45.915,0 7.831,45.914,0 7.844,45.919,0 7.846,45.923,0 7.845,45.928,0 7.848,45.938,0 7.872,45.969,0 7.898,45.982,0 7.969,45.993,0 7.979,45.995,0 7.986,45.999,0 7.998,46.011,0 7.999,46.013,0 8.009,46.028,0 8.011,46.03,0 8.016,46.058,0 8.016,46.069,0 8.018,46.081,0 8.025,46.091,0 8.035,46.097,0 8.056,46.098,0 8.067,46.101,0 8.111,46.127,0 8.132,46.159,0 8.13,46.196,0 8.1,46.236,0 8.077,46.25,0 8.073,46.254,0 8.077,46.262,0 8.087,46.272,0 8.107,46.286,0 8.128,46.292,0 8.172,46.299,0 8.193,46.309,0 8.242,46.354,0 8.27,46.364,0 8.282,46.37,0 8.291,46.378,0 8.297,46.388,0 8.297,46.398,0 8.29,46.401,0 8.287,46.405,0 8.295,46.418,0 8.316,46.434,0 8.343,46.444,0 8.399,46.452,0 8.428,46.449,0 8.442,46.435,0 8.446,46.412,0 8.446,46.382,0 8.443,46.353,0 8.427,46.302,0 8.423,46.276,0 8.427,46.251,0 8.438,46.235,0 8.457,46.225,0 8.483,46.218,0 8.51,46.208,0 8.539,46.188,0 8.602,46.123,0 8.612,46.119,0 8.631,46.115,0 8.677,46.096,0 8.695,46.095,0 8.702,46.098,0 8.718,46.108,0 8.724,46.11,0 8.732,46.107,0 8.739,46.098,0 8.747,46.094,0 8.763,46.093,0 8.794,46.093,0 8.809,46.09,0 8.834,46.066,0 8.82,46.043,0 8.791,46.019,0 8.773,45.991,0 8.77,45.986,0 8.768,45.983,0 8.785,45.982,0 8.8,45.979,0 8.858,45.957,0 8.864,45.953,0 8.871,45.947,0 8.881,45.931,0 8.898,45.91,0 8.907,45.896,0 8.912,45.883,0 8.914,45.866,0 8.91,45.854,0 8.904,45.842,0 8.9,45.826,0 8.94,45.835,0 8.972,45.825,0 9.002,45.821,0 9.034,45.848,0 9.059,45.882,0 9.063,45.899,0 9.052,45.916,0 9.042,45.92,0 9.021,45.923,0 9.011,45.927,0 9.002,45.936,0 8.993,45.954,0 8.983,45.962,0 8.981,45.964,0 8.98,45.967,0 8.981,45.969,0 8.983,45.972,0 9.016,45.993,0 8.998,46.028,0 9.002,46.039,0 9.028,46.053,0 9.05,46.058,0 9.059,46.062,0 9.067,46.071,0 9.07,46.083,0 9.068,46.106,0 9.072,46.119,0 9.091,46.138,0 9.163,46.172,0 9.171,46.183,0 9.176,46.194,0 9.181,46.204,0 9.192,46.21,0 9.204,46.214,0 9.216,46.221,0 9.225,46.231,0 9.24,46.267,0 9.269,46.309,0 9.275,46.331,0 9.274,46.344,0 9.26,46.38,0 9.26,46.394,0 9.263,46.407,0 9.261,46.417,0 9.248,46.423,0 9.238,46.437,0 9.246,46.461,0 9.263,46.485,0 9.282,46.497,0 9.331,46.502,0 9.351,46.498,0 9.352,46.485,0 9.377,46.469,0 9.385,46.466,0 9.395,46.469,0 9.4,46.475,0 9.404,46.483,0 9.411,46.489,0 9.427,46.497,0 9.435,46.498,0 9.438,46.492,0 9.444,46.396,0 9.442,46.381,0 9.444,46.375,0 9.452,46.37,0 9.474,46.362,0 9.483,46.357,0 9.503,46.321,0 9.515,46.309,0 9.536,46.299,0 9.56,46.293,0 9.674,46.292,0 9.693,46.297,0 9.708,46.312,0 9.709,46.32,0 9.707,46.331,0 9.709,46.342,0 9.72,46.351,0 9.731,46.351,0 9.755,46.341,0 9.768,46.339,0 9.789,46.343,0 9.855,46.367,0 9.899,46.372,0 9.918,46.371,0 9.939,46.367,0 9.964,46.356,0 9.971,46.34,0 9.971,46.32,0 9.978,46.298,0 9.992,46.284,0 10.032,46.26,0 10.042,46.243,0 10.043,46.22,0 10.076,46.22,0 10.118,46.231,0 10.146,46.243,0 10.159,46.262,0 10.146,46.28,0 10.105,46.309,0 10.096,46.321,0 10.092,46.329,0 10.092,46.338,0 10.097,46.352,0 10.105,46.361,0 10.126,46.374,0 10.133,46.381,0 10.141,46.403,0 10.133,46.414,0 10.116,46.419,0 10.071,46.425,0 10.042,46.433,0 10.026,46.446,0 10.044,46.467,0 10.035,46.471,0 10.03,46.477,0 10.028,46.484,0 10.027,46.493,0 10.031,46.504,0 10.031,46.526,0 10.033,46.533,0 10.041,46.542,0 10.063,46.557,0 10.071,46.564,0 10.083,46.597,0 10.088,46.604,0 10.097,46.608,0 10.192,46.627,0 10.218,46.627,0 10.234,46.618,0 10.236,46.607,0 10.23,46.586,0 10.235,46.575,0 10.276,46.566,0 10.284,46.561,0 10.289,46.556,0 10.295,46.551,0 10.307,46.547,0 10.319,46.546,0 10.354,46.548,0 10.426,46.535,0 10.444,46.538,0 10.458,46.554,0 10.466,46.578,0 10.467,46.604,0 10.459,46.624,0 10.438,46.636,0 10.396,46.639,0 10.378,46.653,0 10.369,46.672,0 10.374,46.682,0 10.385,46.689,0 10.394,46.701,0 10.397,46.715,0 10.396,46.726,0 10.4,46.736,0 10.417,46.743,0 10.429,46.756,0 10.426,46.769,0 10.419,46.784,0 10.417,46.799,0 10.439,46.817,0 10.445,46.823,0 10.449,46.832,0 10.454,46.864,0 10.486,46.846,0 10.528,46.843,0 10.629,46.862,0 10.647,46.864,0 10.662,46.861,0 10.739,46.83,0 10.749,46.819,0 10.744,46.813,0 10.722,46.8,0 10.717,46.795,0 10.723,46.786,0 10.734,46.786,0 10.755,46.791,0 10.766,46.788,0 10.795,46.777,0 10.805,46.777,0 10.824,46.78,0 10.834,46.78,0 10.843,46.777,0 10.86,46.767,0 10.87,46.764,0 10.88,46.765,0 10.914,46.772,0 10.931,46.774,0 10.966,46.772,0 10.983,46.768,0 10.997,46.769,0 11.011,46.779,0 11.033,46.806,0 11.037,46.808,0 11.049,46.812,0 11.053,46.815,0 11.055,46.82,0 11.053,46.83,0 11.054,46.834,0 11.073,46.865,0 11.084,46.9,0 11.092,46.912,0 11.157,46.957,0 11.174,46.964,0 11.244,46.979,0 11.314,46.987,0 11.349,46.982,0 11.381,46.972,0 11.411,46.97,0 11.445,46.993,0 11.445,46.993,0 11.453,47.001,0 11.462,47.006,0 11.472,47.007,0 11.489,47.004,0 11.496,47.002,0 11.502,46.998,0 11.507,46.993,0 11.515,46.989,0 11.524,46.988,0 11.534,46.99,0 11.543,46.993,0 11.543,46.993,0 11.544,46.993,0 11.544,46.993,0 11.573,46.999,0 11.596,47,0 11.648,46.993,0 11.648,46.993,0 11.65,46.993,0 11.657,46.993,0 11.665,46.993,0 11.684,46.992,0 11.716,46.975,0 11.735,46.971,0 11.746,46.972,0 11.766,46.983,0 11.777,46.988,0 11.823,46.993,0 11.857,47.012,0 11.9,47.028,0 11.944,47.038,0 12.015,47.04,0 12.116,47.077,0 12.181,47.085,0 12.204,47.08,0 12.204,47.053,0 12.182,47.034,0 12.122,47.011,0 12.111,46.993,0 12.118,46.983,0 12.122,46.972,0 12.4,43.903,0 12.429,43.892,0 12.461,43.895,0 12.479,43.917,0 12.478,43.92,0 12.478,43.923,0 12.48,43.926,0 12.483,43.929,0 12.49,43.939,0 12.492,43.956,0 12.489,43.973,0 12.482,43.983,0 12.453,43.979,0 12.421,43.967,0 12.396,43.948,0 12.386,43.925,0 12.4,43.903,0 12.444,41.902,0 12.449,41.9,0 12.455,41.9,0 12.458,41.902,0 12.455,41.908,0 12.447,41.907,0 12.444,41.902,0 """ k = kml.KML() k.from_string(doc) self.assertEqual(len(list(k.features())), 1) self.assertTrue( isinstance(list(k.features())[0].geometry, MultiPolygon)) k2 = kml.KML() k2.from_string(k.to_string()) self.assertEqual(k.to_string(), k2.to_string()) def test_atom(self): pass def test_schema(self): doc = """ Trail Head Name]]> The length in miles]]> change in altitude]]> """ s = kml.Schema(ns='', id='default') s.from_string(doc) self.assertEqual(len(list(s.simple_fields)), 3) self.assertEqual(list(s.simple_fields)[0]['type'], 'string') self.assertEqual(list(s.simple_fields)[1]['type'], 'double') self.assertEqual(list(s.simple_fields)[2]['type'], 'int') self.assertEqual(list(s.simple_fields)[0]['name'], 'TrailHeadName') self.assertEqual(list(s.simple_fields)[1]['name'], 'TrailLength') self.assertEqual(list(s.simple_fields)[2]['name'], 'ElevationGain') self.assertEqual(list(s.simple_fields)[0][ 'displayName' ], 'Trail Head Name') self.assertEqual(list(s.simple_fields)[1][ 'displayName' ], 'The length in miles') self.assertEqual(list(s.simple_fields)[2][ 'displayName' ], 'change in altitude') s1 = kml.Schema(ns='', id='default') s1.from_string(s.to_string()) self.assertEqual(len(list(s1.simple_fields)), 3) self.assertEqual(list(s1.simple_fields)[0]['type'], 'string') self.assertEqual(list(s1.simple_fields)[1]['name'], 'TrailLength') self.assertEqual(list(s1.simple_fields)[2][ 'displayName' ], 'change in altitude') self.assertEqual(s.to_string(), s1.to_string()) doc1 = """ %s """ % doc k = kml.KML() k.from_string(doc1) d = list(k.features())[0] s2 = list(d.schemata())[0] s.ns = config.NS self.assertEqual(s.to_string(), s2.to_string()) k1 = kml.KML() k1.from_string(k.to_string()) self.assertTrue('Schema' in k1.to_string()) self.assertTrue('SimpleField' in k1.to_string()) self.assertEqual(k1.to_string(), k.to_string()) def test_schema_data(self): doc = """ Pi in the sky 3.14159 10 """ sd = kml.SchemaData(ns='', schema_url='#default') sd.from_string(doc) self.assertEqual(sd.schema_url, '#TrailHeadTypeId') self.assertEqual( sd.data[0], {'name': 'TrailHeadName', 'value': 'Pi in the sky'}) self.assertEqual( sd.data[1], {'name': 'TrailLength', 'value': '3.14159'}) self.assertEqual(sd.data[2], {'name': 'ElevationGain', 'value': '10'}) sd1 = kml.SchemaData(ns='', schema_url='#default') sd1.from_string(sd.to_string()) self.assertEqual(sd1.schema_url, '#TrailHeadTypeId') self.assertEqual(sd.to_string(), sd1.to_string()) def test_snippet(self): doc = """ Short Desc """ k = kml.KML() k.from_string(doc) self.assertEqual(list(k.features())[0].snippet['text'], 'Short Desc') self.assertEqual(list(k.features())[0].snippet['maxLines'], 2) list(k.features())[0]._snippet['maxLines'] = 3 self.assertEqual(list(k.features())[0].snippet['maxLines'], 3) self.assertTrue('maxLines="3"' in k.to_string()) list(k.features())[0].snippet = {'text': 'Annother Snippet'} self.assertFalse('maxLines' in k.to_string()) self.assertTrue('Annother Snippet' in k.to_string()) list(k.features())[0].snippet = 'Diffrent Snippet' self.assertFalse('maxLines' in k.to_string()) self.assertTrue('Diffrent Snippet' in k.to_string()) def test_from_wrong_string(self): doc = kml.KML() self.assertRaises(TypeError, doc.from_string, '') def test_address(self): doc = kml.Document() doc.from_string(""" pm-name pm-description 1 1600 Amphitheatre Parkway, Mountain View, CA 94043, USA """) doc2 = kml.Document() doc2.from_string(doc.to_string()) self.assertEqual(doc.to_string(), doc2.to_string()) def test_phone_number(self): doc = kml.Document() doc.from_string(""" pm-name pm-description 1 +1 234 567 8901 """) doc2 = kml.Document() doc2.from_string(doc.to_string()) self.assertEqual(doc.to_string(), doc2.to_string()) def test_groundoverlay(self): doc = kml.KML() doc.from_string( """ Ground Overlays Examples of ground overlays Large-scale overlay on terrain Overlay shows Mount Etna erupting on July 13th, 2001. http://developers.google.com/kml/documentation/images/etna.jpg 37.91904192681665 37.46543388598137 15.35832653742206 14.60128369746704 -0.1556640799496235 """) doc2 = kml.KML() doc2.from_string(doc.to_string()) self.assertEqual(doc.to_string(), doc2.to_string()) def test_linarring_placemark(self): doc = kml.KML() doc.from_string( """ 0.0,0.0 1.0,0.0 1.0,1.0 0.0,0.0 """) doc2 = kml.KML() doc2.from_string(doc.to_string()) self.assertTrue( isinstance(list(doc.features())[0].geometry, LinearRing)) self.assertEqual(doc.to_string(), doc2.to_string()) class StyleTestCase(unittest.TestCase): def test_styleurl(self): f = kml.Document() f.styleUrl = '#somestyle' self.assertEqual(f.styleUrl, '#somestyle') self.assertTrue(isinstance(f._styleUrl, styles.StyleUrl)) s = styles.StyleUrl(config.NS, url='#otherstyle') f.styleUrl = s self.assertTrue(isinstance(f._styleUrl, styles.StyleUrl)) self.assertEqual(f.styleUrl, '#otherstyle') f2 = kml.Document() f2.from_string(f.to_string()) self.assertEqual(f.to_string(), f2.to_string()) def test_style(self): lstyle = styles.LineStyle(color='red', width=2.0) style = styles.Style(styles=[lstyle]) f = kml.Document(styles=[style]) f2 = kml.Document() f2.from_string(f.to_string(prettyprint=True)) self.assertEqual(f.to_string(), f2.to_string()) def test_polystyle_fill(self): style = styles.PolyStyle() def test_polystyle_outline(self): style = styles.PolyStyle() class StyleUsageTestCase(unittest.TestCase): def test_create_document_style(self): style = styles.Style(styles=[styles.PolyStyle(color='7f000000')]) doc = kml.Document(styles=[style]) doc2 = kml.Document() doc2.append_style(style) expected = """ 1 7f000000 1 1 """ doc3 = kml.Document() doc3.from_string(expected) self.assertEqual(doc.to_string(), doc2.to_string()) self.assertEqual(doc2.to_string(), doc3.to_string()) self.assertEqual(doc.to_string(), doc3.to_string()) def test_create_placemark_style(self): style = styles.Style(styles=[styles.PolyStyle(color='7f000000')]) place = kml.Placemark(styles=[style]) place2 = kml.Placemark() place2.append_style(style) expected = """ 1 7f000000 1 1 """ place3 = kml.Placemark() place3.from_string(expected) self.assertEqual(place.to_string(), place2.to_string()) self.assertEqual(place2.to_string(), place3.to_string()) self.assertEqual(place.to_string(), place3.to_string()) class StyleFromStringTestCase(unittest.TestCase): def test_styleurl(self): doc = """ Document.kml 1 #default """ k = kml.KML() k.from_string(doc) self.assertEqual(len(list(k.features())), 1) self.assertEqual(list(k.features())[0].styleUrl, '#default') k2 = kml.KML() k2.from_string(k.to_string()) self.assertEqual(k.to_string(), k2.to_string()) def test_balloonstyle(self): doc = """ Document.kml """ k = kml.KML() k.from_string(doc) self.assertEqual(len(list(k.features())), 1) self.assertTrue( isinstance(list(list(k.features())[0].styles())[0], styles.Style)) style = list(list(list(k.features())[0].styles())[0].styles())[0] self.assertTrue(isinstance(style, styles.BalloonStyle)) self.assertEqual(style.bgColor, 'ffffffbb') self.assertEqual(style.textColor, 'ff000000') self.assertEqual(style.displayMode, 'default') self.assertTrue('$[geDirections]' in style.text) self.assertTrue('$[description]' in style.text) k2 = kml.KML() k2.from_string(k.to_string()) self.assertEqual(k2.to_string(), k.to_string()) def test_balloonstyle_old_color(self): doc = """ Document.kml """ k = kml.KML() k.from_string(doc) self.assertEqual(len(list(k.features())), 1) self.assertTrue( isinstance(list(list(k.features())[0].styles())[0], styles.Style)) style = list(list(list(k.features())[0].styles())[0].styles())[0] self.assertTrue(isinstance(style, styles.BalloonStyle)) self.assertEqual(style.bgColor, 'ffffffbb') k2 = kml.KML() k2.from_string(k.to_string()) self.assertEqual(k2.to_string(), k.to_string()) def test_labelstyle(self): doc = """ Document.kml 1 """ k = kml.KML() k.from_string(doc) self.assertEqual(len(list(k.features())), 1) self.assertTrue( isinstance(list(list(k.features())[0].styles())[0], styles.Style)) style = list(list(list(k.features())[0].styles())[0].styles())[0] self.assertTrue(isinstance(style, styles.LabelStyle)) self.assertEqual(style.color, 'ff0000cc') self.assertEqual(style.colorMode, None) k2 = kml.KML() k2.from_string(k.to_string()) self.assertEqual(k.to_string(), k2.to_string()) def test_iconstyle(self): doc = """ """ k = kml.KML() k.from_string(doc) self.assertEqual(len(list((k.features()))), 1) self.assertTrue( isinstance(list(list(k.features())[0].styles())[0], styles.Style)) style = list(list(list(k.features())[0].styles())[0].styles())[0] self.assertTrue(isinstance(style, styles.IconStyle)) self.assertEqual(style.color, 'ff00ff00') self.assertEqual(style.scale, 1.1) self.assertEqual(style.colorMode, 'random') self.assertEqual(style.heading, 0.0) self.assertEqual(style.icon_href, 'http://maps.google.com/icon21.png') k2 = kml.KML() k2.from_string(k.to_string()) self.assertEqual(k.to_string(), k2.to_string()) def test_linestyle(self): doc = """ LineStyle.kml 1 """ k = kml.KML() k.from_string(doc) self.assertEqual(len(list(k.features())), 1) self.assertTrue( isinstance(list(list(k.features())[0].styles())[0], styles.Style)) style = list(list(list(k.features())[0].styles())[0].styles())[0] self.assertTrue(isinstance(style, styles.LineStyle)) self.assertEqual(style.color, '7f0000ff') self.assertEqual(style.width, 4) k2 = kml.KML() k2.from_string(k.to_string()) self.assertEqual(k.to_string(), k2.to_string()) def test_polystyle(self): doc = """ PolygonStyle.kml 1 """ # XXX fill and outline k = kml.KML() k.from_string(doc) self.assertEqual(len(list(k.features())), 1) self.assertTrue( isinstance(list(list(k.features())[0].styles())[0], styles.Style)) style = list(list(list(k.features())[0].styles())[0].styles())[0] self.assertTrue(isinstance(style, styles.PolyStyle)) self.assertEqual(style.color, 'ff0000cc') self.assertEqual(style.colorMode, 'random') k2 = kml.KML() k2.from_string(k.to_string()) self.assertEqual(k.to_string(), k2.to_string()) def test_polystyle_float_fill(self): doc = """ PolygonStyle.kml 1 """ k = kml.KML() k.from_string(doc) style = list(list(list(k.features())[0].styles())[0].styles())[0] self.assertTrue(isinstance(style, styles.PolyStyle)) self.assertEqual(style.fill, 0) k2 = kml.KML() k2.from_string(k.to_string()) self.assertEqual(k.to_string(), k2.to_string()) def test_polystyle_float_outline(self): doc = """ PolygonStyle.kml 1 """ k = kml.KML() k.from_string(doc) style = list(list(list(k.features())[0].styles())[0].styles())[0] self.assertTrue(isinstance(style, styles.PolyStyle)) self.assertEqual(style.outline, 0) k2 = kml.KML() k2.from_string(k.to_string()) self.assertEqual(k.to_string(), k2.to_string()) def test_styles(self): doc = """ """ k = kml.KML() k.from_string(doc) self.assertEqual(len(list(k.features())), 1) self.assertTrue( isinstance(list(list(k.features())[0].styles())[0], styles.Style)) style = list(list(list(k.features())[0].styles())[0].styles()) self.assertEqual(len(style), 4) k2 = kml.KML() k2.from_string(k.to_string()) self.assertEqual(k.to_string(), k2.to_string()) def test_stylemapurl(self): doc = """ normal #normalState highlight #highlightState """ k = kml.KML() k.from_string(doc) self.assertEqual(len(list(k.features())), 1) self.assertTrue( isinstance( list(list(k.features())[0].styles())[0], styles.StyleMap)) sm = list(list(list(k.features())[0].styles()))[0] self.assertTrue(isinstance(sm.normal, styles.StyleUrl)) self.assertEqual(sm.normal.url, '#normalState') self.assertTrue(isinstance(sm.highlight, styles.StyleUrl)) self.assertEqual(sm.highlight.url, '#highlightState') k2 = kml.KML() k2.from_string(k.to_string()) self.assertEqual(k.to_string(), k2.to_string()) def test_stylemapstyles(self): doc = """ normal highlight """ k = kml.KML() k.from_string(doc) self.assertEqual(len(list(k.features())), 1) self.assertTrue( isinstance( list(list(k.features())[0].styles())[0], styles.StyleMap)) sm = list(list(list(k.features())[0].styles()))[0] self.assertTrue(isinstance(sm.normal, styles.Style)) self.assertEqual(len(list(sm.normal.styles())), 1) self.assertTrue( isinstance(list(sm.normal.styles())[0], styles.LabelStyle)) self.assertTrue(isinstance(sm.highlight, styles.Style)) self.assertTrue(isinstance(sm.highlight, styles.Style)) self.assertEqual(len(list(sm.highlight.styles())), 2) self.assertTrue( isinstance(list(sm.highlight.styles())[0], styles.LineStyle)) self.assertTrue( isinstance(list(sm.highlight.styles())[1], styles.PolyStyle)) k2 = kml.KML() k2.from_string(k.to_string()) self.assertEqual(k.to_string(), k2.to_string()) def test_get_style_by_url(self): doc = """ Document.kml 1 normal #normalState highlight #highlightState """ k = kml.KML() k.from_string(doc) self.assertEqual(len(list(k.features())), 1) document = list(k.features())[0] style = document.get_style_by_url( 'http://localhost:8080/somepath#exampleStyleDocument') self.assertTrue(isinstance(list(style.styles())[0], styles.LabelStyle)) style = document.get_style_by_url('somepath#linestyleExample') self.assertTrue(isinstance(list(style.styles())[0], styles.LineStyle)) style = document.get_style_by_url('#styleMapExample') self.assertTrue(isinstance(style, styles.StyleMap)) class DateTimeTestCase(unittest.TestCase): def test_timestamp(self): now = datetime.datetime.now() ts = kml.TimeStamp(timestamp=now) self.assertEqual(ts.timestamp, [now, 'dateTime']) self.assertTrue('TimeStamp>' in str(ts.to_string())) self.assertTrue('when>' in str(ts.to_string())) self.assertTrue(now.isoformat() in str(ts.to_string())) y2k = datetime.date(2000, 1, 1) ts = kml.TimeStamp(timestamp=y2k) self.assertEqual(ts.timestamp, [y2k, 'date']) self.assertTrue('2000-01-01' in str(ts.to_string())) def test_timestamp_resolution(self): now = datetime.datetime.now() ts = kml.TimeStamp(timestamp=now) self.assertTrue(now.isoformat() in str(ts.to_string())) ts.timestamp[1] = 'date' self.assertTrue(now.date().isoformat() in str(ts.to_string())) self.assertFalse(now.isoformat() in str(ts.to_string())) year = str(now.year) ym = now.strftime('%Y-%m') ts.timestamp[1] = 'gYearMonth' self.assertTrue(ym in str(ts.to_string())) self.assertFalse(now.date().isoformat() in str(ts.to_string())) ts.timestamp[1] = 'gYear' self.assertTrue(year in str(ts.to_string())) self.assertFalse(ym in str(ts.to_string())) ts.timestamp = None self.assertRaises(TypeError, ts.to_string) def test_timespan(self): now = datetime.datetime.now() y2k = datetime.datetime(2000, 1, 1) ts = kml.TimeSpan(end=now, begin=y2k) self.assertEqual(ts.end, [now, 'dateTime']) self.assertEqual(ts.begin, [y2k, 'dateTime']) self.assertTrue('TimeSpan>' in str(ts.to_string())) self.assertTrue('begin>' in str(ts.to_string())) self.assertTrue('end>' in str(ts.to_string())) self.assertTrue(now.isoformat() in str(ts.to_string())) self.assertTrue(y2k.isoformat() in str(ts.to_string())) ts.end = None self.assertFalse(now.isoformat() in str(ts.to_string())) self.assertTrue(y2k.isoformat() in str(ts.to_string())) ts.begin = None self.assertRaises(ValueError, ts.to_string) def test_feature_timestamp(self): now = datetime.datetime.now() f = kml.Document() f.timeStamp = now self.assertEqual(f.timeStamp, now) self.assertTrue(now.isoformat() in str(f.to_string())) self.assertTrue('TimeStamp>' in str(f.to_string())) self.assertTrue('when>' in str(f.to_string())) f.timeStamp = now.date() self.assertTrue(now.date().isoformat() in str(f.to_string())) self.assertFalse(now.isoformat() in str(f.to_string())) f.timeStamp = None self.assertFalse('TimeStamp>' in str(f.to_string())) def test_feature_timespan(self): now = datetime.datetime.now() y2k = datetime.date(2000, 1, 1) f = kml.Document() f.begin = y2k f.end = now self.assertEqual(f.begin, y2k) self.assertEqual(f.end, now) self.assertTrue(now.isoformat() in str(f.to_string())) self.assertTrue('2000-01-01' in str(f.to_string())) self.assertTrue('TimeSpan>' in str(f.to_string())) self.assertTrue('begin>' in str(f.to_string())) self.assertTrue('end>' in str(f.to_string())) f.end = None self.assertFalse(now.isoformat() in str(f.to_string())) self.assertTrue('2000-01-01' in str(f.to_string())) self.assertTrue('TimeSpan>' in str(f.to_string())) self.assertTrue('begin>' in str(f.to_string())) self.assertFalse('end>' in str(f.to_string())) f.begin = None self.assertFalse('TimeSpan>' in str(f.to_string())) def test_feature_timespan_stamp(self): now = datetime.datetime.now() y2k = datetime.date(2000, 1, 1) f = kml.Document() f.begin = y2k f.end = now self.assertTrue(now.isoformat() in str(f.to_string())) self.assertTrue('2000-01-01' in str(f.to_string())) self.assertTrue('TimeSpan>' in str(f.to_string())) self.assertTrue('begin>' in str(f.to_string())) self.assertTrue('end>' in str(f.to_string())) self.assertFalse('TimeStamp>' in str(f.to_string())) self.assertFalse('when>' in str(f.to_string())) # when we set a timestamp an existing timespan will be deleted f.timeStamp = now self.assertTrue(now.isoformat() in str(f.to_string())) self.assertTrue('TimeStamp>' in str(f.to_string())) self.assertTrue('when>' in str(f.to_string())) self.assertFalse('2000-01-01' in str(f.to_string())) self.assertFalse('TimeSpan>' in str(f.to_string())) self.assertFalse('begin>' in str(f.to_string())) self.assertFalse('end>' in str(f.to_string())) # when we set a timespan an existing timestamp will be deleted f.end = y2k self.assertFalse(now.isoformat() in str(f.to_string())) self.assertTrue('2000-01-01' in str(f.to_string())) self.assertTrue('TimeSpan>' in str(f.to_string())) self.assertFalse('begin>' in str(f.to_string())) self.assertTrue('end>' in str(f.to_string())) self.assertFalse('TimeStamp>' in str(f.to_string())) self.assertFalse('when>' in str(f.to_string())) # We manipulate our Feature so it has timespan and stamp ts = kml.TimeStamp(timestamp=now) f._time_stamp = ts # this raises an exception as only either timespan or timestamp # are allowed not both self.assertRaises(ValueError, f.to_string) def test_read_timestamp(self): ts = kml.TimeStamp(ns='') doc = """ 1997 """ ts.from_string(doc) self.assertEqual(ts.timestamp[1], 'gYear') self.assertEqual(ts.timestamp[0], datetime.datetime(1997, 1, 1, 0, 0)) doc = """ 1997-07 """ ts.from_string(doc) self.assertEqual(ts.timestamp[1], 'gYearMonth') self.assertEqual(ts.timestamp[0], datetime.datetime(1997, 7, 1, 0, 0)) doc = """ 199808 """ ts.from_string(doc) self.assertEqual(ts.timestamp[1], 'gYearMonth') self.assertEqual(ts.timestamp[0], datetime.datetime(1998, 8, 1, 0, 0)) doc = """ 1997-07-16 """ ts.from_string(doc) self.assertEqual(ts.timestamp[1], 'date') self.assertEqual(ts.timestamp[0], datetime.datetime(1997, 7, 16, 0, 0)) # dateTime (YYYY-MM-DDThh:mm:ssZ) # Here, T is the separator between the calendar and the hourly notation # of time, and Z indicates UTC. (Seconds are required.) doc = """ 1997-07-16T07:30:15Z """ ts.from_string(doc) self.assertEqual(ts.timestamp[1], 'dateTime') self.assertEqual(ts.timestamp[0], datetime.datetime( 1997, 7, 16, 7, 30, 15, tzinfo=tzutc())) doc = """ 1997-07-16T10:30:15+03:00 """ ts.from_string(doc) self.assertEqual(ts.timestamp[1], 'dateTime') self.assertEqual(ts.timestamp[0], datetime.datetime( 1997, 7, 16, 10, 30, 15, tzinfo=tzoffset(None, 10800))) def test_read_timespan(self): ts = kml.TimeSpan(ns='') doc = """ 1876-08-01 1997-07-16T07:30:15Z """ ts.from_string(doc) self.assertEqual(ts.begin[1], 'date') self.assertEqual(ts.begin[0], datetime.datetime(1876, 8, 1, 0, 0)) self.assertEqual(ts.end[1], 'dateTime') self.assertEqual(ts.end[0], datetime.datetime( 1997, 7, 16, 7, 30, 15, tzinfo=tzutc())) def test_featurefromstring(self): d = kml.Document(ns='') doc = """ Document.kml 1 1997-07-16T10:30:15+03:00 1876-08-01 1997-07-16T07:30:15Z """ d.from_string(doc) class AtomTestCase(unittest.TestCase): def test_author(self): a = atom.Author(name="Christian Ledermann") self.assertEqual(a.name, "Christian Ledermann") a.uri = 'http://iwlearn.net' a.email = 'christian@gmail.com' self.assertTrue("Christian Ledermann" in str(a.to_string())) self.assertTrue('http://iwlearn.net' in str(a.to_string())) self.assertTrue('christian@gmail.com' in str(a.to_string())) self.assertTrue('name>' in str(a.to_string())) self.assertTrue('uri>' in str(a.to_string())) self.assertTrue('email>' in str(a.to_string())) # print (a.to_string()) a.email = 'christian' self.assertFalse('email>' in str(a.to_string())) a2 = atom.Author() a2.from_string(a.to_string()) self.assertEqual(a.to_string(), a2.to_string()) def test_link(self): l = atom.Link(href="http://localhost/", rel="alternate") self.assertEqual(l.href, "http://localhost/") self.assertEqual(l.rel, "alternate") l.title = "Title" l.type = "text/html" l.hreflang = 'en' l.length = "4096" self.assertTrue('href="http://localhost/"' in str(l.to_string())) self.assertTrue('rel="alternate"' in str(l.to_string())) self.assertTrue('title="Title"' in str(l.to_string())) self.assertTrue('hreflang="en"' in str(l.to_string())) self.assertTrue('type="text/html"' in str(l.to_string())) self.assertTrue('length="4096"' in str(l.to_string())) self.assertTrue('link' in str(l.to_string())) self.assertTrue('="http://www.w3.org/2005/Atom"' in str(l.to_string())) l2 = atom.Link() l2.from_string(l.to_string()) self.assertEqual(l.to_string(), l2.to_string()) l.href = None self.assertRaises(ValueError, l.to_string) class SetGeometryTestCase(unittest.TestCase): def test_altitude_mode(self): geom = Geometry() geom.geometry = Point(0, 1) self.assertEqual(geom.altitude_mode, None) self.assertFalse('altitudeMode' in str(geom.to_string())) geom.altitude_mode = 'unknown' self.assertRaises(AssertionError, geom.to_string) geom.altitude_mode = 'clampToSeaFloor' self.assertRaises(AssertionError, geom.to_string) geom.altitude_mode = 'relativeToSeaFloor' self.assertRaises(AssertionError, geom.to_string) geom.altitude_mode = 'clampToGround' self.assertFalse('altitudeMode' in str(geom.to_string())) geom.altitude_mode = 'relativeToGround' self.assertTrue( 'altitudeMode>relativeToGroundabsolute1110.000000,1.0000000.000000,0.000000 1.000000,1.0000000.000000,0.000000 1.000000,0.000000 1.000000,1.000000 0.000000,0.0000000.000000,0.000000 1.000000,0.000000 1.000000,1.000000 0.000000,0.0000000.000000,0.000000 1.000000,0.000000 1.000000,1.000000 0.000000,0.000000-1.000000,-1.000000 2.000000,-1.000000 2.000000,2.000000 -1.000000,-1.0000000.000000,1.0000001.000000,1.0000000.000000,0.000000 1.000000,0.0000000.000000,1.000000 1.000000,1.0000000.000000,0.000000 1.000000,0.000000 1.000000,1.000000 0.000000,0.000000-1.000000,-1.000000 2.000000,-1.000000 2.000000,2.000000 -1.000000,-1.0000003.000000,0.000000 4.000000,0.000000 4.000000,1.000000 3.000000,0.0000003.000000,0.000000 4.000000,0.000000 4.000000,1.000000 3.000000,0.0000000.000000,0.000000 1.000000,1.0000000.000000,1.000000 0.000000,1.000000 clampToGround """ g = Geometry() self.assertEqual(g.altitude_mode, None) g.from_string(doc) self.assertEqual(g.altitude_mode, 'clampToGround') def test_extrude(self): doc = """ 0.000000,1.000000 1 """ g = Geometry() self.assertEqual(g.extrude, False) g.from_string(doc) self.assertEqual(g.extrude, True) def test_tesselate(self): doc = """ 0.000000,1.000000 1 """ g = Geometry() self.assertEqual(g.tessellate, False) g.from_string(doc) self.assertEqual(g.tessellate, True) def test_point(self): doc = """ 0.000000,1.000000 """ g = Geometry() g.from_string(doc) self.assertEqual( g.geometry.__geo_interface__, {'type': 'Point', 'coordinates': (0.0, 1.0)}) def test_linestring(self): doc = """ 0.000000,0.000000 1.000000,1.000000 """ g = Geometry() g.from_string(doc) self.assertEqual( g.geometry.__geo_interface__, {'type': 'LineString', 'coordinates': ((0.0, 0.0), (1.0, 1.0))}) def test_linearring(self): doc = """ 0.000000,0.000000 1.000000,0.000000 1.000000,1.000000 0.000000,0.000000 """ g = Geometry() g.from_string(doc) self.assertEqual( g.geometry.__geo_interface__, { 'type': 'LinearRing', 'coordinates': ((0.0, 0.0), (1.0, 0.0), (1.0, 1.0), (0.0, 0.0)) }) def test_polygon(self): doc = """ 0.000000,0.000000 1.000000,0.000000 1.000000,1.000000 0.000000,0.000000 """ g = Geometry() g.from_string(doc) self.assertEqual( g.geometry.__geo_interface__, { 'type': 'Polygon', 'coordinates': (( (0.0, 0.0), (1.0, 0.0), (1.0, 1.0), (0.0, 0.0) ), ) }) doc = """ -1.000000,-1.000000 2.000000,-1.000000 2.000000,2.000000 -1.000000,-1.000000 0.000000,0.000000 1.000000,0.000000 1.000000,1.000000 0.000000,0.000000 """ g.from_string(doc) self.assertEqual( g.geometry.__geo_interface__, { 'type': 'Polygon', 'coordinates': ( ((-1.0, -1.0), (2.0, -1.0), (2.0, 2.0), (-1.0, -1.0)), ((0.0, 0.0), (1.0, 0.0), (1.0, 1.0), (0.0, 0.0)), ) }) def test_multipoint(self): doc = """ 0.000000,1.000000 1.000000,1.000000 """ g = Geometry() g.from_string(doc) self.assertEqual(len(g.geometry), 2) def test_multilinestring(self): doc = """ 0.000000,0.000000 1.000000,0.000000 0.000000,1.000000 1.000000,1.000000 """ g = Geometry() g.from_string(doc) self.assertEqual(len(g.geometry), 2) def test_multipolygon(self): doc = """ -1.000000,-1.000000 2.000000,-1.000000 2.000000,2.000000 -1.000000,-1.000000 0.000000,0.000000 1.000000,0.000000 1.000000,1.000000 0.000000,0.000000 3.000000,0.000000 4.000000,0.000000 4.000000,1.000000 3.000000,0.000000 """ g = Geometry() g.from_string(doc) self.assertEqual(len(g.geometry), 2) def test_geometrycollection(self): doc = """ 3,0 4,0 4,1 3,0 0.000000,1.000000 0.000000,0.000000 1.000000,1.000000 0.0,0.0 1.0,0.0 1.0,1.0 0.0,1.0 0.0,0.0 """ g = Geometry() g.from_string(doc) self.assertEqual(len(g.geometry), 4) doc = """ 3.0,0.0 4.0,0.0 4.0,1.0 3.0,0.0 0.0,0.0 1.0,0.0 1.0,1.0 0.0,0.0 """ g = Geometry() g.from_string(doc) self.assertEqual(len(g.geometry), 2) self.assertEqual(g.geometry.geom_type, 'GeometryCollection') class Force3DTestCase(unittest.TestCase): def setUp(self): config.FORCE3D = False def tearDown(self): # Important: Set FORCE3D back to False! config.FORCE3D = False def test3d(self): config.FORCE3D = True ns = '' p2 = kml.Placemark(ns, 'id', 'name', 'description') p2.geometry = Polygon([(0, 0), (1, 1), (1, 0)]) p3 = kml.Placemark(ns, 'id', 'name', 'description') p3.geometry = Polygon([(0, 0, 0), (1, 1, 0), (1, 0, 0)]) self.assertEqual(p2.to_string(), p3.to_string()) def testno3d(self): config.FORCE3D = False ns = '' p2 = kml.Placemark(ns, 'id', 'name', 'description') p2.geometry = Polygon([(0, 0), (1, 1), (1, 0)]) p3 = kml.Placemark(ns, 'id', 'name', 'description') p3.geometry = Polygon([(0, 0, 0), (1, 1, 0), (1, 0, 0)]) self.assertNotEqual(p2.to_string(), p3.to_string()) class BaseFeatureTestCase(unittest.TestCase): def test_address_string(self): f = kml._Feature() address = '1600 Amphitheatre Parkway, Mountain View, CA 94043, USA' f.address = address self.assertEqual(f.address, address) def test_address_none(self): f = kml._Feature() f.address = None self.assertEqual(f.address, None) def test_address_value_error(self): f = kml._Feature() with self.assertRaises(ValueError): f.address = 123 def test_phone_number_string(self): f = kml._Feature() f.phoneNumber = '+1-234-567-8901' self.assertEqual(f.phoneNumber, '+1-234-567-8901') def test_phone_number_none(self): f = kml._Feature() f.phoneNumber = None self.assertEqual(f.phoneNumber, None) def test_phone_number_value_error(self): f = kml._Feature() with self.assertRaises(ValueError): f.phoneNumber = 123 class BaseOverlayTestCase(unittest.TestCase): def test_color_string(self): o = kml._Overlay(name='An Overlay') o.color = '00010203' self.assertEqual(o.color, '00010203') def test_color_none(self): o = kml._Overlay(name='An Overlay') o.color = '00010203' self.assertEqual(o.color, '00010203') o.color = None self.assertEqual(o.color, None) def test_color_value_error(self): o = kml._Overlay(name='An Overlay') with self.assertRaises(ValueError): o.color = object() def test_draw_order_string(self): o = kml._Overlay(name='An Overlay') o.drawOrder = '1' self.assertEqual(o.drawOrder, '1') def test_draw_order_int(self): o = kml._Overlay(name='An Overlay') o.drawOrder = 1 self.assertEqual(o.drawOrder, '1') def test_draw_order_none(self): o = kml._Overlay(name='An Overlay') o.drawOrder = '1' self.assertEqual(o.drawOrder, '1') o.drawOrder = None self.assertEqual(o.drawOrder, None) def test_draw_order_value_error(self): o = kml._Overlay(name='An Overlay') with self.assertRaises(ValueError): o.drawOrder = object() def test_icon_without_tag(self): o = kml._Overlay(name='An Overlay') o.icon = 'http://example.com/' self.assertEqual(o.icon, 'http://example.com/') def test_icon_with_open_tag(self): o = kml._Overlay(name='An Overlay') o.icon = 'http://example.com/' self.assertEqual(o.icon, 'http://example.com/') def test_icon_with_close_tag(self): o = kml._Overlay(name='An Overlay') o.icon = 'http://example.com/' self.assertEqual(o.icon, 'http://example.com/') def test_icon_with_tag(self): o = kml._Overlay(name='An Overlay') o.icon = 'http://example.com/' self.assertEqual(o.icon, 'http://example.com/') def test_icon_to_none(self): o = kml._Overlay(name='An Overlay') o.icon = 'http://example.com/' self.assertEqual(o.icon, 'http://example.com/') o.icon = None self.assertEqual(o.icon, None) def test_icon_raise_exception(self): o = kml._Overlay(name='An Overlay') with self.assertRaises(ValueError): o.icon = 12345 class GroundOverlayTestCase(unittest.TestCase): def setUp(self): self.g = kml.GroundOverlay() def test_altitude_int(self): self.g.altitude = 123 self.assertEqual(self.g.altitude, '123') def test_altitude_float(self): self.g.altitude = 123.4 self.assertEqual(self.g.altitude, '123.4') def test_altitude_string(self): self.g.altitude = '123' self.assertEqual(self.g.altitude, '123') def test_altitude_value_error(self): with self.assertRaises(ValueError): self.g.altitude = object() def test_altitude_none(self): self.g.altitude = '123' self.assertEqual(self.g.altitude, '123') self.g.altitude = None self.assertEqual(self.g.altitude, None) def test_altitude_mode_default(self): self.assertEqual(self.g.altitudeMode, 'clampToGround') def test_altitude_mode_error(self): self.g.altitudeMode = '' self.assertEqual(self.g.altitudeMode, 'clampToGround') def test_altitude_mode_clamp(self): self.g.altitudeMode = 'clampToGround' self.assertEqual(self.g.altitudeMode, 'clampToGround') def test_altitude_mode_absolute(self): self.g.altitudeMode = 'absolute' self.assertEqual(self.g.altitudeMode, 'absolute') def test_latlonbox_function(self): self.g.latLonBox(10, 20, 30, 40, 50) self.assertEqual(self.g.north, '10') self.assertEqual(self.g.south, '20') self.assertEqual(self.g.east, '30') self.assertEqual(self.g.west, '40') self.assertEqual(self.g.rotation, '50') def test_latlonbox_string(self): self.g.north = '10' self.g.south = '20' self.g.east = '30' self.g.west = '40' self.g.rotation = '50' self.assertEqual(self.g.north, '10') self.assertEqual(self.g.south, '20') self.assertEqual(self.g.east, '30') self.assertEqual(self.g.west, '40') self.assertEqual(self.g.rotation, '50') def test_latlonbox_int(self): self.g.north = 10 self.g.south = 20 self.g.east = 30 self.g.west = 40 self.g.rotation = 50 self.assertEqual(self.g.north, '10') self.assertEqual(self.g.south, '20') self.assertEqual(self.g.east, '30') self.assertEqual(self.g.west, '40') self.assertEqual(self.g.rotation, '50') def test_latlonbox_float(self): self.g.north = 10.0 self.g.south = 20.0 self.g.east = 30.0 self.g.west = 40.0 self.g.rotation = 50.0 self.assertEqual(self.g.north, '10.0') self.assertEqual(self.g.south, '20.0') self.assertEqual(self.g.east, '30.0') self.assertEqual(self.g.west, '40.0') self.assertEqual(self.g.rotation, '50.0') def test_latlonbox_value_error(self): with self.assertRaises(ValueError): self.g.north = object() with self.assertRaises(ValueError): self.g.south = object() with self.assertRaises(ValueError): self.g.east = object() with self.assertRaises(ValueError): self.g.west = object() with self.assertRaises(ValueError): self.g.rotation = object() self.assertEqual(self.g.north, None) self.assertEqual(self.g.south, None) self.assertEqual(self.g.east, None) self.assertEqual(self.g.west, None) self.assertEqual(self.g.rotation, None) def test_latlonbox_empty_string(self): self.g.north = '' self.g.south = '' self.g.east = '' self.g.west = '' self.g.rotation = '' self.assertEqual(self.g.north, '') self.assertEqual(self.g.south, '') self.assertEqual(self.g.east, '') self.assertEqual(self.g.west, '') self.assertEqual(self.g.rotation, '') def test_latlonbox_none(self): self.g.north = None self.g.south = None self.g.east = None self.g.west = None self.g.rotation = None self.assertEqual(self.g.north, None) self.assertEqual(self.g.south, None) self.assertEqual(self.g.east, None) self.assertEqual(self.g.west, None) self.assertEqual(self.g.rotation, None) class GroundOverlayStringTestCase(unittest.TestCase): def test_default_to_string(self): g = kml.GroundOverlay() expected = kml.GroundOverlay() expected.from_string( '' '1' '') self.assertEqual(g.to_string(), expected.to_string()) def test_to_string(self): g = kml.GroundOverlay() g.icon = 'http://example.com' g.drawOrder = 1 g.color = '00010203' expected = kml.GroundOverlay() expected.from_string( '' '1' '00010203' '1' '<href>http://example.com</href>' '') self.assertEqual(g.to_string(), expected.to_string()) def test_altitude_from_int(self): g = kml.GroundOverlay() g.altitude = 123 expected = kml.GroundOverlay() expected.from_string( '' '1' '123' 'clampToGround' '') self.assertEqual(g.to_string(), expected.to_string()) def test_altitude_from_float(self): g = kml.GroundOverlay() g.altitude = 123.4 expected = kml.GroundOverlay() expected.from_string( '' '1' '123.4' 'clampToGround' '') self.assertEqual(g.to_string(), expected.to_string()) def test_altitude_from_string(self): g = kml.GroundOverlay() g.altitude = '123.4' expected = kml.GroundOverlay() expected.from_string( '' '1' '123.4' 'clampToGround' '') self.assertEqual(g.to_string(), expected.to_string()) def test_altitude_mode_absolute(self): g = kml.GroundOverlay() g.altitude = '123.4' g.altitudeMode = 'absolute' expected = kml.GroundOverlay() expected.from_string( '' '1' '123.4' 'absolute' '') self.assertEqual(g.to_string(), expected.to_string()) def test_altitude_mode_unknown_string(self): g = kml.GroundOverlay() g.altitude = '123.4' g.altitudeMode = 'unknown string' expected = kml.GroundOverlay() expected.from_string( '' '1' '123.4' 'clampToGround' '') self.assertEqual(g.to_string(), expected.to_string()) def test_altitude_mode_value(self): g = kml.GroundOverlay() g.altitude = '123.4' g.altitudeMode = 1234 expected = kml.GroundOverlay() expected.from_string( '' '1' '123.4' 'clampToGround' '') self.assertEqual(g.to_string(), expected.to_string()) def test_latlonbox_no_rotation(self): g = kml.GroundOverlay() g.latLonBox(10, 20, 30, 40) expected = kml.GroundOverlay() expected.from_string( '' '1' '' '10' '20' '30' '40' '0' '' '') self.assertEqual(g.to_string(), expected.to_string()) def test_latlonbox_rotation(self): g = kml.GroundOverlay() g.latLonBox(10, 20, 30, 40, 50) expected = kml.GroundOverlay() expected.from_string( '' '1' '' '10' '20' '30' '40' '50' '' '') self.assertEqual(g.to_string(), expected.to_string()) def test_latlonbox_nswer(self): g = kml.GroundOverlay() g.north = 10 g.south = 20 g.east = 30 g.west = 40 g.rotation = 50 expected = kml.GroundOverlay() expected.from_string( '' '1' '' '10' '20' '30' '40' '50' '' '') self.assertEqual(g.to_string(), expected.to_string()) def test_suite(): suite = unittest.TestSuite() suite.addTest(unittest.makeSuite(BaseClassesTestCase)) suite.addTest(unittest.makeSuite(BuildKmlTestCase)) suite.addTest(unittest.makeSuite(KmlFromStringTestCase)) suite.addTest(unittest.makeSuite(StyleTestCase)) suite.addTest(unittest.makeSuite(StyleFromStringTestCase)) suite.addTest(unittest.makeSuite(DateTimeTestCase)) suite.addTest(unittest.makeSuite(AtomTestCase)) suite.addTest(unittest.makeSuite(SetGeometryTestCase)) suite.addTest(unittest.makeSuite(GetGeometryTestCase)) suite.addTest(unittest.makeSuite(Force3DTestCase)) suite.addTest(unittest.makeSuite(BaseOverlayTestCase)) suite.addTest(unittest.makeSuite(GroundOverlayTestCase)) return suite if __name__ == '__main__': unittest.main() fastkml-0.11/fastkml/styles.py0000664000175000017500000004416312550664775017327 0ustar travistravis00000000000000# -*- coding: utf-8 -*- # Copyright (C) 2012 Christian Ledermann # # This library is free software; you can redistribute it and/or modify it under # the terms of the GNU Lesser General Public License as published by the Free # Software Foundation; either version 2.1 of the License, or (at your option) # any later version. # # This library 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 Lesser General Public License for more # details. # # You should have received a copy of the GNU Lesser General Public License # along with this library; if not, write to the Free Software Foundation, Inc., # 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA """ Once you've created features within Google Earth and examined the KML code Google Earth generates, you'll notice how styles are an important part of how your data is displayed. """ import logging logger = logging.getLogger('fastkml.styles') from fastkml.config import etree from fastkml.base import _BaseObject class StyleUrl(_BaseObject): """ URL of a