Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
F
fastkml
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Issues
0
Issues
0
List
Boards
Labels
Milestones
Merge Requests
0
Merge Requests
0
Analytics
Analytics
Repository
Value Stream
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Commits
Issue Boards
Open sidebar
Aurélien Vermylen
fastkml
Commits
a2b94a48
Commit
a2b94a48
authored
Jun 22, 2012
by
Christian Ledermann
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
add geometry processing
parent
c9ef8d55
Changes
3
Hide whitespace changes
Inline
Side-by-side
Showing
3 changed files
with
295 additions
and
17 deletions
+295
-17
fastkml/kml.py
fastkml/kml.py
+202
-9
fastkml/tests.py
fastkml/tests.py
+92
-8
setup.py
setup.py
+1
-0
No files found.
fastkml/kml.py
View file @
a2b94a48
# -*- coding: utf-8 -*-
# -*- coding: utf-8 -*-
from
shapely.geometry
import
Point
,
LineString
,
Polygon
from
shapely.geometry
import
MultiPoint
,
MultiLineString
,
MultiPolygon
from
shapely.geometry.polygon
import
LinearRing
import
logging
logger
=
logging
.
getLogger
(
'fastkml'
)
try
:
try
:
from
lxml
import
etree
from
lxml
import
etree
LXML
=
True
except
ImportError
:
except
ImportError
:
import
xml.etree.ElementTree
as
etree
import
xml.etree.ElementTree
as
etree
LXML
=
False
class
KML
(
object
):
class
KML
(
object
):
""" represents a KML File """
""" represents a KML File """
...
@@ -19,7 +29,9 @@ class KML(object):
...
@@ -19,7 +29,9 @@ class KML(object):
self
.
from_string
(
f
.
read
())
self
.
from_string
(
f
.
read
())
f
.
close
()
f
.
close
()
def
from_string
(
self
,
xml_string
):
def
from_string
(
self
,
xml_string
):
""" create a KML object from a xml string"""
element
=
etree
.
XML
(
xml_string
)
element
=
etree
.
XML
(
xml_string
)
if
element
.
tag
.
endswith
(
'kml'
):
if
element
.
tag
.
endswith
(
'kml'
):
ns
=
element
.
tag
.
rstrip
(
'kml'
)
ns
=
element
.
tag
.
rstrip
(
'kml'
)
...
@@ -68,20 +80,36 @@ class _Feature(object):
...
@@ -68,20 +80,36 @@ class _Feature(object):
subclasses are:
subclasses are:
Container (Document, Folder),
Container (Document, Folder),
Placemark,
Placemark,
NetworkLink,
#
NetworkLink,
GroundOverlay,
#
GroundOverlay,
PhotoOverlay,
#
PhotoOverlay,
ScreenOverlay
#
ScreenOverlay
"""
"""
id
=
None
id
=
None
name
=
None
name
=
None
#User-defined text displayed in the 3D viewer as the label for the
#object (for example, for a Placemark, Folder, or NetworkLink).
description
=
None
description
=
None
#User-supplied content that appears in the description balloon.
visibility
=
1
visibility
=
1
#Boolean value. Specifies whether the feature is drawn in the 3D
#viewer when it is initially loaded. In order for a feature to be
#visible, the <visibility> tag of all its ancestors must also be
#set to 1.
isopen
=
0
isopen
=
0
#Boolean value. Specifies whether a Document or Folder appears
#closed or open when first loaded into the Places panel.
#0=collapsed (the default), 1=expanded.
styleUrl
=
None
#URL of a <Style> or <StyleMap> defined in a Document.
#If the style is in the same file, use a # reference.
#If the style is defined in an external file, use a full URL
#along with # referencing.
#atom_author = None
#atom_author = None
#atom_link = None
#atom_link = None
#styleUrl = None
def
__init__
(
self
,
ns
,
id
=
None
,
name
=
None
,
description
=
None
):
def
__init__
(
self
,
ns
,
id
=
None
,
name
=
None
,
description
=
None
):
...
@@ -155,7 +183,6 @@ class _Container(_Feature):
...
@@ -155,7 +183,6 @@ class _Container(_Feature):
def
etree_element
(
self
):
def
etree_element
(
self
):
element
=
super
(
_Container
,
self
).
etree_element
()
element
=
super
(
_Container
,
self
).
etree_element
()
for
feature
in
self
.
features
():
for
feature
in
self
.
features
():
assert
(
feature
!=
self
)
element
.
append
(
feature
.
etree_element
())
element
.
append
(
feature
.
etree_element
())
return
element
return
element
...
@@ -192,7 +219,7 @@ class Document(_Container):
...
@@ -192,7 +219,7 @@ class Document(_Container):
class
Folder
(
_Container
):
class
Folder
(
_Container
):
"""
"""
A Folder is used to arrange other Features hierarchically
A Folder is used to arrange other Features hierarchically
(Folders, Placemarks,
NetworkLinks, or
Overlays).
(Folders, Placemarks,
#NetworkLinks, or #
Overlays).
"""
"""
__name__
=
"Folder"
__name__
=
"Folder"
...
@@ -210,9 +237,175 @@ class Folder(_Container):
...
@@ -210,9 +237,175 @@ class Folder(_Container):
self
.
append
(
feature
)
self
.
append
(
feature
)
class
Placemark
(
_Feature
):
class
Placemark
(
_Feature
):
__name__
=
"Placemark"
__name__
=
"Placemark"
styleUrl
=
None
geometry
=
None
geometry
=
None
pass
def
_get_coordinates
(
self
,
element
):
coordinates
=
element
.
find
(
'%scoordinates'
%
self
.
ns
)
if
coordinates
is
not
None
:
latlons
=
coordinates
.
text
.
strip
().
split
()
coords
=
[]
for
latlon
in
latlons
:
coords
.
append
([
float
(
c
)
for
c
in
latlon
.
split
(
','
)])
return
coords
def
_get_linear_ring
(
self
,
element
):
# LinearRing
lr
=
element
.
find
(
'%sLinearRing'
%
self
.
ns
)
if
lr
is
not
None
:
coords
=
self
.
_get_coordinates
(
lr
)
return
LinearRing
(
coords
)
def
_get_geometry
(
self
,
element
):
# Point, LineString,
# Polygon,
point
=
element
.
find
(
'%sPoint'
%
self
.
ns
)
if
point
is
not
None
:
coords
=
self
.
_get_coordinates
(
point
)
return
Point
(
coords
[
0
])
line
=
element
.
find
(
'%sLineString'
%
self
.
ns
)
if
line
is
not
None
:
coords
=
self
.
_get_coordinates
(
line
)
return
LineString
(
coords
)
polygon
=
element
.
find
(
'%sPolygon'
%
self
.
ns
)
if
polygon
is
not
None
:
outer_boundary
=
polygon
.
find
(
'%souterBoundaryIs'
%
self
.
ns
)
ob
=
self
.
_get_linear_ring
(
outer_boundary
)
inner_boundaries
=
polygon
.
findall
(
'%sinnerBoundaryIs'
%
self
.
ns
)
ibs
=
[]
for
inner_boundary
in
inner_boundaries
:
ibs
.
append
(
self
.
_get_linear_ring
(
inner_boundary
))
return
Polygon
(
ob
,
ibs
)
return
self
.
_get_linear_ring
(
element
)
def
_get_multigeometry
(
self
,
element
):
# MultiGeometry
multigeometry
=
element
.
find
(
'%sMultiGeometry'
%
self
.
ns
)
geoms
=
[]
if
multigeometry
is
not
None
:
points
=
multigeometry
.
findall
(
'%sPoint'
%
self
.
ns
)
if
points
:
for
point
in
points
:
geoms
.
append
(
Point
(
self
.
_get_coordinates
(
point
)))
return
MultiPoint
(
geoms
)
linestrings
=
multigeometry
.
findall
(
'%sLineString'
%
self
.
ns
)
if
linestrings
:
for
ls
in
linestrings
:
geoms
.
append
(
LineString
(
self
.
_get_coordinates
(
ls
)))
return
MultiLineString
(
geoms
)
polygons
=
multigeometry
.
findall
(
'%sPolygon'
%
self
.
ns
)
if
polygons
:
for
polygon
in
polygons
:
outer_boundary
=
polygon
.
find
(
'%souterBoundaryIs'
%
self
.
ns
)
ob
=
self
.
_get_linear_ring
(
outer_boundary
)
inner_boundaries
=
polygon
.
findall
(
'%sinnerBoundaryIs'
%
self
.
ns
)
ibs
=
[]
for
inner_boundary
in
inner_boundaries
:
ibs
.
append
(
self
.
_get_linear_ring
(
inner_boundary
))
geoms
.
append
(
Polygon
(
ob
,
ibs
))
return
MultiPolygon
(
geoms
)
def
from_element
(
self
,
element
):
super
(
Placemark
,
self
).
from_element
(
element
)
mgeom
=
self
.
_get_multigeometry
(
element
)
geom
=
self
.
_get_geometry
(
element
)
if
mgeom
is
not
None
:
self
.
geometry
=
mgeom
elif
geom
is
not
None
:
self
.
geometry
=
geom
else
:
logger
.
warn
(
'No geometries found'
)
def
_etree_coordinates
(
self
,
coordinates
):
element
=
etree
.
Element
(
"coordinates"
)
if
len
(
coordinates
[
0
])
==
2
:
tuples
=
(
'%f,%f,0.0'
%
tuple
(
c
)
for
c
in
coordinates
)
elif
len
(
coordinates
[
0
])
==
3
:
tuples
=
(
'%f,%f,%f'
%
tuple
(
c
)
for
c
in
coordinates
)
else
:
raise
ValueError
(
"Invalid dimensions"
)
element
.
text
=
' '
.
join
(
tuples
)
return
element
def
_etree_point
(
self
,
point
):
element
=
etree
.
Element
(
"Point"
)
coords
=
list
(
point
.
coords
)
element
.
append
(
self
.
_etree_coordinates
(
coords
))
return
element
def
_etree_linestring
(
self
,
linestring
):
element
=
etree
.
Element
(
"LineString"
)
coords
=
list
(
linestring
.
coords
)
element
.
append
(
self
.
_etree_coordinates
(
coords
))
return
element
def
_etree_linearring
(
self
,
linearring
):
element
=
etree
.
Element
(
"LinearRing"
)
coords
=
list
(
linearring
.
coords
)
element
.
append
(
self
.
_etree_coordinates
(
coords
))
return
element
def
_etree_polygon
(
self
,
polygon
):
element
=
etree
.
Element
(
"Polygon"
)
outer_boundary
=
etree
.
SubElement
(
element
,
"outerBoundaryIs"
)
outer_boundary
.
append
(
self
.
_etree_linearring
(
polygon
.
exterior
))
for
ib
in
polygon
.
interiors
:
inner_boundary
=
etree
.
SubElement
(
element
,
"innerBoundaryIs"
)
inner_boundary
.
append
(
self
.
_etree_linearring
(
ib
))
return
element
def
_etree_multipoint
(
self
,
points
):
element
=
etree
.
Element
(
"MultiGeometry"
)
for
point
in
points
.
geoms
:
element
.
append
(
self
.
_etree_point
(
point
))
return
element
def
_etree_multilinestring
(
self
,
linestrings
):
element
=
etree
.
Element
(
"MultiGeometry"
)
for
linestring
in
linestrings
.
geoms
:
element
.
append
(
self
.
_etree_linestring
(
linestring
))
return
element
def
_etree_multipolygon
(
self
,
polygons
):
element
=
etree
.
Element
(
"MultiGeometry"
)
for
polygon
in
polygons
.
geoms
:
element
.
append
(
self
.
_etree_polygon
(
polygon
))
return
element
def
_etree_geometry
(
self
):
if
isinstance
(
self
.
geometry
,
Point
):
return
self
.
_etree_point
(
self
.
geometry
)
elif
isinstance
(
self
.
geometry
,
LineString
):
return
self
.
_etree_linestring
(
self
.
geometry
)
elif
isinstance
(
self
.
geometry
,
LinearRing
):
return
self
.
_etree_linearring
(
self
.
geometry
)
elif
isinstance
(
self
.
geometry
,
Polygon
):
return
self
.
_etree_polygon
(
self
.
geometry
)
elif
isinstance
(
self
.
geometry
,
MultiPoint
):
return
self
.
_etree_multipoint
(
self
.
geometry
)
elif
isinstance
(
self
.
geometry
,
MultiLineString
):
return
self
.
_etree_multilinestring
(
self
.
geometry
)
elif
isinstance
(
self
.
geometry
,
MultiPolygon
):
return
self
.
_etree_multipolygon
(
self
.
geometry
)
def
etree_element
(
self
):
element
=
super
(
Placemark
,
self
).
etree_element
()
if
self
.
geometry
is
not
None
:
element
.
append
(
self
.
_etree_geometry
())
else
:
logger
.
warn
(
'Object does not have a geometry'
)
return
element
fastkml/tests.py
View file @
a2b94a48
# -*- coding: utf-8 -*-
# -*- coding: utf-8 -*-
import
unittest
import
unittest
import
kml
from
fastkml
import
kml
import
xml.etree.ElementTree
as
etree
import
xml.etree.ElementTree
as
etree
from
shapely.geometry
import
Point
,
LineString
,
Polygon
from
shapely.geometry
import
MultiPoint
,
MultiLineString
,
MultiPolygon
from
shapely.geometry.polygon
import
LinearRing
class
BuildKmlTestCase
(
unittest
.
TestCase
):
class
BuildKmlTestCase
(
unittest
.
TestCase
):
""" Build a simple KML File """
""" Build a simple KML File """
def
test_kml
(
self
):
def
test_kml
(
self
):
""" kml file without contents """
""" kml file without contents """
k
=
None
k
=
kml
.
KML
()
k
=
kml
.
KML
()
self
.
assertEqual
(
len
(
k
.
features
()),
0
)
self
.
assertEqual
(
len
(
k
.
features
()),
0
)
self
.
assertEqual
(
k
.
to_string
(),
self
.
assertEqual
(
k
.
to_string
(),
'<ns0:kml xmlns:ns0="http://www.opengis.net/kml/2.2" />'
)
'<ns0:kml xmlns:ns0="http://www.opengis.net/kml/2.2"/>'
)
k2
=
kml
.
KML
()
k2
.
from_string
(
k
.
to_string
())
self
.
assertEqual
(
k
.
to_string
(),
k2
.
to_string
())
print
k
.
to_string
()
def
test_folder
(
self
):
def
test_folder
(
self
):
""" KML file with folders """
""" KML file with folders """
...
@@ -26,15 +31,25 @@ class BuildKmlTestCase( unittest.TestCase ):
...
@@ -26,15 +31,25 @@ class BuildKmlTestCase( unittest.TestCase ):
k
.
append
(
f2
)
k
.
append
(
f2
)
self
.
assertEqual
(
len
(
k
.
features
()),
2
)
self
.
assertEqual
(
len
(
k
.
features
()),
2
)
self
.
assertEqual
(
len
(
k
.
features
()[
0
].
features
()),
1
)
self
.
assertEqual
(
len
(
k
.
features
()[
0
].
features
()),
1
)
print
k
.
to_string
()
k2
=
kml
.
KML
()
s
=
k
.
to_string
()
k2
.
from_string
(
s
)
self
.
assertEqual
(
s
,
k2
.
to_string
())
print
s
def
test_placemark
(
self
):
def
test_placemark
(
self
):
k
=
kml
.
KML
()
k
=
kml
.
KML
()
p
=
kml
.
Placemark
(
''
,
'id'
,
'name'
,
'description'
)
p
=
kml
.
Placemark
(
''
,
'id'
,
'name'
,
'description'
)
p
.
geometry
=
Point
(
0.0
,
0.0
)
p2
=
kml
.
Placemark
(
''
,
'id2'
,
'name2'
,
'description2'
)
p2
=
kml
.
Placemark
(
''
,
'id2'
,
'name2'
,
'description2'
)
p2
.
geometry
=
LineString
([(
0
,
0
),
(
1
,
1
)])
k
.
append
(
p
)
k
.
append
(
p
)
k
.
append
(
p2
)
k
.
append
(
p2
)
self
.
assertEqual
(
len
(
k
.
features
()),
2
)
self
.
assertEqual
(
len
(
k
.
features
()),
2
)
k2
=
kml
.
KML
()
k2
.
from_string
(
k
.
to_string
())
#self.assertEqual(k.to_string(), k2.to_string())
print
k
.
to_string
()
def
test_document
(
self
):
def
test_document
(
self
):
k
=
kml
.
KML
()
k
=
kml
.
KML
()
...
@@ -47,11 +62,19 @@ class BuildKmlTestCase( unittest.TestCase ):
...
@@ -47,11 +62,19 @@ class BuildKmlTestCase( unittest.TestCase ):
f2
=
kml
.
Folder
(
''
,
'id2'
,
'name2'
,
'description2'
)
f2
=
kml
.
Folder
(
''
,
'id2'
,
'name2'
,
'description2'
)
d
.
append
(
f2
)
d
.
append
(
f2
)
p
=
kml
.
Placemark
(
''
,
'id'
,
'name'
,
'description'
)
p
=
kml
.
Placemark
(
''
,
'id'
,
'name'
,
'description'
)
p
.
geometry
=
Polygon
([(
0
,
0
),
(
1
,
1
),
(
1
,
0
)])
p2
=
kml
.
Placemark
(
''
,
'id2'
,
'name2'
,
'description2'
)
p2
=
kml
.
Placemark
(
''
,
'id2'
,
'name2'
,
'description2'
)
#p2 does not have a geometry!
f2
.
append
(
p
)
f2
.
append
(
p
)
nf
.
append
(
p2
)
nf
.
append
(
p2
)
self
.
assertEqual
(
len
(
k
.
features
()),
1
)
self
.
assertEqual
(
len
(
k
.
features
()),
1
)
self
.
assertEqual
(
len
(
k
.
features
()[
0
].
features
()),
2
)
self
.
assertEqual
(
len
(
k
.
features
()[
0
].
features
()),
2
)
k2
=
kml
.
KML
()
k2
.
from_string
(
k
.
to_string
())
#self.assertEqual(k.to_string(), k2.to_string())
print
k
.
to_string
()
class
KmlFromStringTestCase
(
unittest
.
TestCase
):
class
KmlFromStringTestCase
(
unittest
.
TestCase
):
...
@@ -86,6 +109,9 @@ class KmlFromStringTestCase( unittest.TestCase ):
...
@@ -86,6 +109,9 @@ class KmlFromStringTestCase( unittest.TestCase ):
k
.
from_string
(
doc
)
k
.
from_string
(
doc
)
self
.
assertEqual
(
len
(
k
.
features
()),
1
)
self
.
assertEqual
(
len
(
k
.
features
()),
1
)
self
.
assertEqual
(
len
(
k
.
features
()[
0
].
features
()),
2
)
self
.
assertEqual
(
len
(
k
.
features
()[
0
].
features
()),
2
)
k2
=
kml
.
KML
()
k2
.
from_string
(
k
.
to_string
())
#self.assertEqual(k.to_string(), k2.to_string())
print
k
.
to_string
()
print
k
.
to_string
()
...
@@ -134,6 +160,9 @@ class KmlFromStringTestCase( unittest.TestCase ):
...
@@ -134,6 +160,9 @@ class KmlFromStringTestCase( unittest.TestCase ):
k
.
from_string
(
doc
)
k
.
from_string
(
doc
)
self
.
assertEqual
(
len
(
k
.
features
()),
1
)
self
.
assertEqual
(
len
(
k
.
features
()),
1
)
self
.
assertEqual
(
len
(
k
.
features
()[
0
].
features
()),
3
)
self
.
assertEqual
(
len
(
k
.
features
()[
0
].
features
()),
3
)
k2
=
kml
.
KML
()
k2
.
from_string
(
k
.
to_string
())
#self.assertEqual(k.to_string(), k2.to_string())
print
k
.
to_string
()
print
k
.
to_string
()
def
test_placemark
(
self
):
def
test_placemark
(
self
):
...
@@ -152,16 +181,71 @@ class KmlFromStringTestCase( unittest.TestCase ):
...
@@ -152,16 +181,71 @@ class KmlFromStringTestCase( unittest.TestCase ):
k
.
from_string
(
doc
)
k
.
from_string
(
doc
)
self
.
assertEqual
(
len
(
k
.
features
()),
1
)
self
.
assertEqual
(
len
(
k
.
features
()),
1
)
self
.
assertEqual
(
k
.
features
()[
0
].
name
,
"Simple placemark"
)
self
.
assertEqual
(
k
.
features
()[
0
].
name
,
"Simple placemark"
)
k2
=
kml
.
KML
()
k2
.
from_string
(
k
.
to_string
())
#self.assertEqual(k.to_string(), k2.to_string())
print
k
.
to_string
()
print
k
.
to_string
()
def
test_polygon
(
self
):
doc
=
"""<?xml version="1.0" encoding="UTF-8"?>
<kml xmlns="http://www.opengis.net/kml/2.2">
<Placemark>
<name>South Africa</name>
<Polygon><outerBoundaryIs><LinearRing><coordinates>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 </coordinates></LinearRing></outerBoundaryIs><innerBoundaryIs><LinearRing><coordinates>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 </coordinates></LinearRing></innerBoundaryIs></Polygon>
</Placemark> </kml>"""
k
=
kml
.
KML
()
k
.
from_string
(
doc
)
self
.
assertEqual
(
len
(
k
.
features
()),
1
)
self
.
assertTrue
(
isinstance
(
k
.
features
()[
0
].
geometry
,
Polygon
))
k2
=
kml
.
KML
()
k2
.
from_string
(
k
.
to_string
())
#self.assertEqual(k.to_string(), k2.to_string())
print
k
.
to_string
()
def
test_multipoints
(
self
):
pass
def
test_multilinestrings
(
self
):
doc
=
"""<?xml version="1.0" encoding="UTF-8"?>
<kml xmlns="http://www.opengis.net/kml/2.2">
<Placemark>
<name>Dnipro (Dnieper)</name>
<MultiGeometry><LineString><coordinates>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 </coordinates></LineString><LineString><coordinates>33.194,49.094,0 32.884,49.225,0 32.603,49.302,0 31.886,49.555,0 </coordinates></LineString><LineString><coordinates>31.44,50,0 31.48,49.933,0 31.486,49.871,0 31.467,49.754,0 </coordinates></LineString><LineString><coordinates>30.508,51.217,0 30.478,50.904,0 30.479,50.749,0 30.515,50.597,0 </coordinates></LineString></MultiGeometry>
</Placemark> </kml>"""
k
=
kml
.
KML
()
k
.
from_string
(
doc
)
self
.
assertEqual
(
len
(
k
.
features
()),
1
)
self
.
assertTrue
(
isinstance
(
k
.
features
()[
0
].
geometry
,
MultiLineString
))
k2
=
kml
.
KML
()
k2
.
from_string
(
k
.
to_string
())
#self.assertEqual(k.to_string(), k2.to_string())
print
k
.
to_string
()
def
test_multipolygon
(
self
):
doc
=
"""<?xml version="1.0" encoding="UTF-8"?>
<kml xmlns="http://www.opengis.net/kml/2.2">
<Placemark>
<name>Antartica</name>
<MultiGeometry><Polygon><outerBoundaryIs><LinearRing><coordinates>-59.572,-80.04,0 -59.866,-80.55,0 -60.16,-81,0 -62.255,-80.863,0 -64.488,-80.922,0 -65.742,-80.589,0 -65.742,-80.55,0 -66.29,-80.256,0 -64.038,-80.295,0 -61.883,-80.393,0 -61.139,-79.981,0 -60.61,-79.629,0 -59.572,-80.04,0 </coordinates></LinearRing></outerBoundaryIs></Polygon><Polygon><outerBoundaryIs><LinearRing><coordinates>-159.208,-79.497,0 -161.128,-79.634,0 -162.44,-79.281,0 -163.027,-78.929,0 -163.067,-78.87,0 -163.713,-78.596,0 -163.713,-78.596,0 -163.106,-78.223,0 -161.245,-78.38,0 -160.246,-78.694,0 -159.482,-79.046,0 -159.208,-79.497,0 </coordinates></LinearRing></outerBoundaryIs></Polygon><Polygon><outerBoundaryIs><LinearRing><coordinates>-45.155,-78.047,0 -43.921,-78.478,0 -43.49,-79.086,0 -43.372,-79.517,0 -43.333,-80.026,0 -44.881,-80.34,0 -46.506,-80.594,0 -48.386,-80.829,0 -50.482,-81.025,0 -52.852,-80.967,0 -54.164,-80.634,0 -53.988,-80.222,0 -51.853,-79.948,0 -50.991,-79.615,0 -50.365,-79.183,0 -49.914,-78.811,0 -49.307,-78.459,0 -48.661,-78.047,0 -48.661,-78.047,0 -48.151,-78.047,0 -46.663,-77.831,0 -45.155,-78.047,0 </coordinates></LinearRing></outerBoundaryIs></Polygon><Polygon><outerBoundaryIs><LinearRing><coordinates>-121.212,-73.501,0 -119.919,-73.658,0 -118.724,-73.481,0 -119.292,-73.834,0 -120.232,-74.089,0 -121.623,-74.01,0 -122.622,-73.658,0 -122.622,-73.658,0 -122.406,-73.325,0 -121.212,-73.501,0 </coordinates></LinearRing></outerBoundaryIs></Polygon><Polygon><outerBoundaryIs><LinearRing><coordinates>-125.56,-73.481,0 -124.032,-73.873,0 -124.619,-73.834,0 -125.912,-73.736,0 -127.283,-73.462,0 -127.283,-73.462,0 -126.558,-73.246,0 -125.56,-73.481,0 </coordinates></LinearRing></outerBoundaryIs></Polygon><Polygon><outerBoundaryIs><LinearRing><coordinates>-98.982,-71.933,0 -97.885,-72.071,0 -96.788,-71.953,0 -96.2,-72.521,0 -96.984,-72.443,0 -98.198,-72.482,0 -99.432,-72.443,0 -100.783,-72.502,0 -101.802,-72.306,0 -102.331,-71.894,0 -102.331,-71.894,0 -101.704,-71.718,0 -100.431,-71.855,0 -98.982,-71.933,0 </coordinates></LinearRing></outerBoundaryIs></Polygon><Polygon><outerBoundaryIs><LinearRing><coordinates>-68.451,-70.956,0 -68.334,-71.406,0 -68.51,-71.798,0 -68.784,-72.171,0 -69.959,-72.308,0 -71.076,-72.504,0 -72.388,-72.484,0 -71.898,-72.092,0 -73.074,-72.229,0 -74.19,-72.367,0 -74.954,-72.073,0 -75.013,-71.661,0 -73.916,-71.269,0 -73.916,-71.269,0 -73.23,-71.152,0 -72.075,-71.191,0 -71.781,-70.681,0 -71.722,-70.309,0 -71.742,-69.506,0 -71.174,-69.035,0 -70.253,-68.879,0 -69.724,-69.251,0 -69.489,-69.623,0 -69.059,-70.074,0 -68.726,-70.505,0 -68.451,-70.956,0 </coordinates></LinearRing></outerBoundaryIs></Polygon><Polygon><outerBoundaryIs><LinearRing><coordinates>-58.614,-64.152,0 -59.045,-64.368,0 -59.789,-64.211,0 -60.612,-64.309,0 -61.297,-64.544,0 -62.022,-64.799,0 -62.512,-65.093,0 -62.649,-65.485,0 -62.59,-65.857,0 -62.12,-66.19,0 -62.806,-66.426,0 -63.746,-66.504,0 -64.294,-66.837,0 -64.882,-67.15,0 -65.508,-67.582,0 -65.665,-67.954,0 -65.313,-68.365,0 -64.784,-68.679,0 -63.961,-68.914,0 -63.197,-69.228,0 -62.786,-69.619,0 -62.571,-69.992,0 -62.277,-70.384,0 -61.807,-70.717,0 -61.513,-71.089,0 -61.376,-72.01,0 -61.082,-72.382,0 -61.004,-72.774,0 -60.69,-73.166,0 -60.827,-73.695,0 -61.376,-74.107,0 -61.963,-74.44,0 -63.295,-74.577,0 -63.746,-74.93,0 -64.353,-75.263,0 -65.861,-75.635,0 -67.193,-75.792,0 -68.446,-76.007,0 -69.798,-76.223,0 -70.601,-76.634,0 -72.207,-76.674,0 -73.97,-76.634,0 -75.556,-76.713,0 -77.24,-76.713,0 -76.927,-77.105,0 -75.399,-77.281,0 -74.283,-77.555,0 -73.656,-77.908,0 -74.773,-78.222,0 -76.496,-78.124,0 -77.926,-78.378,0 -77.985,-78.79,0 -78.024,-79.182,0 -76.849,-79.515,0 -76.633,-79.887,0 -75.36,-80.26,0 -73.245,-80.416,0 -71.443,-80.691,0 -70.013,-81.004,0 -68.192,-81.318,0 -65.704,-81.474,0 -63.256,-81.749,0 -61.552,-82.043,0 -59.691,-82.376,0 -58.712,-82.846,0 -58.222,-83.218,0 -57.008,-82.866,0 -55.363,-82.572,0 -53.62,-82.258,0 -51.544,-82.004,0 -49.761,-81.729,0 -47.274,-81.71,0 -44.826,-81.847,0 -42.808,-82.082,0 -42.162,-81.651,0 -40.771,-81.357,0 -38.245,-81.337,0 -36.267,-81.122,0 -34.386,-80.906,0 -32.31,-80.769,0 -30.097,-80.593,0 -28.55,-80.338,0 -29.255,-79.985,0 -29.686,-79.633,0 -29.686,-79.26,0 -31.625,-79.299,0 -33.681,-79.456,0 -35.64,-79.456,0 -35.914,-79.084,0 -35.777,-78.339,0 -35.327,-78.124,0 -33.897,-77.889,0 -32.212,-77.653,0 -30.998,-77.36,0 -29.784,-77.066,0 -28.883,-76.674,0 -27.512,-76.497,0 -26.16,-76.36,0 -25.475,-76.282,0 -23.928,-76.243,0 -22.459,-76.105,0 -21.225,-75.909,0 -20.01,-75.674,0 -18.914,-75.439,0 -17.523,-75.126,0 -16.642,-74.793,0 -15.701,-74.499,0 -15.408,-74.107,0 -16.465,-73.872,0 -16.113,-73.46,0 -15.447,-73.147,0 -14.409,-72.951,0 -13.312,-72.715,0 -12.294,-72.402,0 -11.51,-72.01,0 -11.02,-71.54,0 -10.296,-71.265,0 -9.101,-71.324,0 -8.611,-71.657,0 -7.417,-71.697,0 -7.377,-71.324,0 -6.868,-70.932,0 -5.791,-71.03,0 -5.536,-71.403,0 -4.342,-71.461,0 -3.049,-71.285,0 -1.795,-71.167,0 -0.659,-71.226,0 -0.229,-71.638,0 0.868,-71.305,0 1.887,-71.128,0 3.023,-70.991,0 4.139,-70.854,0 5.158,-70.619,0 6.274,-70.462,0 7.136,-70.247,0 7.743,-69.894,0 8.487,-70.149,0 9.525,-70.011,0 10.25,-70.482,0 10.818,-70.834,0 11.954,-70.638,0 12.404,-70.247,0 13.423,-69.972,0 14.735,-70.031,0 15.127,-70.403,0 15.949,-70.031,0 17.027,-69.913,0 18.202,-69.874,0 19.259,-69.894,0 20.376,-70.011,0 21.453,-70.07,0 21.923,-70.403,0 22.569,-70.697,0 23.666,-70.521,0 24.841,-70.482,0 25.977,-70.482,0 27.094,-70.462,0 28.093,-70.325,0 29.15,-70.207,0 30.032,-69.933,0 30.972,-69.757,0 31.99,-69.659,0 32.754,-69.384,0 33.302,-68.836,0 33.87,-68.503,0 34.908,-68.659,0 35.3,-69.012,0 36.162,-69.247,0 37.2,-69.169,0 37.905,-69.521,0 38.649,-69.776,0 39.668,-69.541,0 40.02,-69.11,0 40.921,-68.934,0 41.959,-68.601,0 42.939,-68.463,0 44.114,-68.267,0 44.897,-68.052,0 45.72,-67.817,0 46.503,-67.601,0 47.443,-67.719,0 48.344,-67.366,0 48.991,-67.092,0 49.931,-67.111,0 50.753,-66.876,0 50.949,-66.523,0 51.792,-66.249,0 52.614,-66.053,0 53.613,-65.896,0 54.534,-65.818,0 55.415,-65.877,0 56.355,-65.975,0 57.158,-66.249,0 57.256,-66.68,0 58.137,-67.013,0 58.745,-67.288,0 59.939,-67.405,0 60.605,-67.68,0 61.428,-67.954,0 62.387,-68.013,0 63.19,-67.817,0 64.052,-67.405,0 64.992,-67.621,0 65.972,-67.738,0 66.912,-67.856,0 67.891,-67.934,0 68.89,-67.934,0 69.713,-68.973,0 69.673,-69.228,0 69.556,-69.678,0 68.596,-69.933,0 67.813,-70.305,0 67.95,-70.697,0 69.066,-70.678,0 68.929,-71.069,0 68.42,-71.442,0 67.95,-71.853,0 68.714,-72.167,0 69.869,-72.265,0 71.025,-72.088,0 71.573,-71.697,0 71.906,-71.324,0 72.455,-71.011,0 73.081,-70.717,0 73.336,-70.364,0 73.865,-69.874,0 74.492,-69.776,0 75.628,-69.737,0 76.626,-69.619,0 77.645,-69.463,0 78.135,-69.071,0 78.428,-68.698,0 79.114,-68.326,0 80.093,-68.072,0 80.935,-67.876,0 81.484,-67.542,0 82.052,-67.366,0 82.776,-67.209,0 83.775,-67.307,0 84.676,-67.209,0 85.656,-67.092,0 86.752,-67.15,0 87.477,-66.876,0 87.986,-66.21,0 88.358,-66.484,0 88.828,-66.955,0 89.671,-67.15,0 90.63,-67.229,0 91.59,-67.111,0 92.609,-67.19,0 93.549,-67.209,0 94.175,-67.111,0 95.018,-67.17,0 95.781,-67.386,0 96.682,-67.249,0 97.76,-67.249,0 98.68,-67.111,0 99.718,-67.249,0 100.384,-66.915,0 100.893,-66.582,0 101.579,-66.308,0 102.832,-65.563,0 103.479,-65.7,0 104.243,-65.975,0 104.908,-66.328,0 106.182,-66.935,0 107.161,-66.955,0 108.081,-66.955,0 109.159,-66.837,0 110.236,-66.7,0 111.058,-66.426,0 111.744,-66.132,0 112.86,-66.092,0 113.605,-65.877,0 114.388,-66.073,0 114.897,-66.386,0 115.602,-66.7,0 116.699,-66.661,0 117.385,-66.915,0 118.579,-67.17,0 119.833,-67.268,0 120.871,-67.19,0 121.654,-66.876,0 122.32,-66.563,0 123.221,-66.484,0 124.122,-66.621,0 125.16,-66.719,0 126.1,-66.563,0 127.001,-66.563,0 127.883,-66.661,0 128.803,-66.759,0 129.704,-66.582,0 130.781,-66.426,0 131.8,-66.386,0 132.936,-66.386,0 133.856,-66.288,0 134.757,-66.21,0 135.032,-65.72,0 135.071,-65.309,0 135.697,-65.583,0 135.874,-66.034,0 136.207,-66.445,0 136.618,-66.778,0 137.46,-66.955,0 138.596,-66.896,0 139.908,-66.876,0 140.809,-66.817,0 142.122,-66.817,0 143.062,-66.798,0 144.374,-66.837,0 145.49,-66.915,0 146.196,-67.229,0 146,-67.601,0 146.646,-67.895,0 147.723,-68.13,0 148.84,-68.385,0 150.132,-68.561,0 151.484,-68.718,0 152.502,-68.875,0 153.638,-68.895,0 154.285,-68.561,0 155.166,-68.836,0 155.93,-69.149,0 156.811,-69.384,0 158.026,-69.482,0 159.181,-69.6,0 159.671,-69.992,0 160.807,-70.227,0 161.57,-70.58,0 162.687,-70.736,0 163.842,-70.717,0 164.92,-70.776,0 166.114,-70.756,0 167.309,-70.834,0 168.426,-70.971,0 169.464,-71.207,0 170.502,-71.403,0 171.207,-71.697,0 171.089,-72.088,0 170.56,-72.441,0 170.11,-72.892,0 169.757,-73.245,0 169.287,-73.656,0 167.975,-73.813,0 167.387,-74.165,0 166.095,-74.381,0 165.644,-74.773,0 164.959,-75.145,0 164.234,-75.459,0 163.823,-75.87,0 163.568,-76.243,0 163.47,-76.693,0 163.49,-77.066,0 164.058,-77.457,0 164.273,-77.83,0 164.743,-78.183,0 166.604,-78.32,0 166.996,-78.751,0 165.194,-78.907,0 163.666,-79.123,0 161.766,-79.162,0 160.924,-79.73,0 160.748,-80.201,0 160.317,-80.573,0 159.788,-80.945,0 161.12,-81.279,0 161.629,-81.69,0 162.491,-82.062,0 163.705,-82.395,0 165.096,-82.709,0 166.604,-83.022,0 168.896,-83.336,0 169.405,-83.826,0 172.284,-84.041,0 172.477,-84.118,0 173.224,-84.414,0 175.986,-84.159,0 178.277,-84.473,0 180,-84.713,0 180,-90,0 -180,-90,0 -180,-84.713,0 -179.942,-84.721,0 -179.059,-84.139,0 -177.257,-84.453,0 -177.141,-84.418,0 -176.085,-84.099,0 -175.947,-84.11,0 -175.83,-84.118,0 -174.383,-84.534,0 -173.117,-84.118,0 -172.889,-84.061,0 -169.951,-83.885,0 -169,-84.118,0 -168.53,-84.237,0 -167.022,-84.57,0 -164.182,-84.825,0 -161.93,-85.139,0 -158.071,-85.374,0 -155.192,-85.1,0 -150.942,-85.296,0 -148.533,-85.609,0 -145.889,-85.315,0 -143.108,-85.041,0 -142.892,-84.57,0 -146.829,-84.531,0 -150.061,-84.296,0 -150.903,-83.904,0 -153.586,-83.689,0 -153.41,-83.238,0 -153.038,-82.827,0 -152.666,-82.454,0 -152.862,-82.043,0 -154.526,-81.768,0 -155.29,-81.416,0 -156.837,-81.102,0 -154.409,-81.161,0 -152.098,-81.004,0 -150.648,-81.337,0 -148.866,-81.043,0 -147.221,-80.671,0 -146.418,-80.338,0 -146.77,-79.926,0 -148.063,-79.652,0 -149.532,-79.358,0 -151.588,-79.299,0 -153.39,-79.162,0 -155.329,-79.064,0 -155.976,-78.692,0 -157.268,-78.378,0 -158.052,-78.026,0 -158.365,-76.889,0 -157.875,-76.987,0 -156.975,-77.301,0 -155.329,-77.203,0 -153.743,-77.066,0 -152.92,-77.497,0 -151.334,-77.399,0 -150.002,-77.183,0 -148.748,-76.909,0 -147.612,-76.576,0 -146.104,-76.478,0 -146.144,-76.105,0 -146.496,-75.733,0 -146.202,-75.38,0 -144.91,-75.204,0 -144.322,-75.537,0 -142.794,-75.341,0 -141.639,-75.086,0 -140.209,-75.067,0 -138.858,-74.969,0 -137.506,-74.734,0 -136.429,-74.518,0 -135.215,-74.303,0 -134.431,-74.361,0 -133.746,-74.44,0 -132.257,-74.303,0 -130.925,-74.479,0 -129.554,-74.459,0 -128.242,-74.322,0 -126.891,-74.42,0 -125.402,-74.518,0 -124.011,-74.479,0 -122.562,-74.499,0 -121.074,-74.518,0 -119.703,-74.479,0 -118.684,-74.185,0 -117.47,-74.028,0 -116.216,-74.244,0 -115.022,-74.068,0 -113.944,-73.715,0 -113.298,-74.028,0 -112.945,-74.381,0 -112.299,-74.714,0 -111.261,-74.42,0 -110.066,-74.793,0 -108.715,-74.91,0 -107.559,-75.184,0 -106.149,-75.126,0 -104.876,-74.949,0 -103.368,-74.988,0 -102.017,-75.126,0 -100.646,-75.302,0 -100.117,-74.871,0 -100.763,-74.538,0 -101.253,-74.185,0 -102.545,-74.107,0 -103.113,-73.734,0 -103.329,-73.362,0 -103.681,-72.618,0 -102.917,-72.755,0 -101.605,-72.813,0 -100.313,-72.755,0 -99.137,-72.911,0 -98.119,-73.205,0 -97.688,-73.558,0 -96.337,-73.617,0 -95.044,-73.48,0 -93.673,-73.284,0 -92.439,-73.166,0 -91.421,-73.401,0 -90.089,-73.323,0 -89.227,-72.559,0 -88.424,-73.009,0 -87.268,-73.186,0 -86.015,-73.088,0 -85.192,-73.48,0 -83.88,-73.519,0 -82.666,-73.636,0 -81.471,-73.852,0 -80.687,-73.48,0 -80.296,-73.127,0 -79.297,-73.519,0 -77.926,-73.421,0 -76.907,-73.636,0 -76.222,-73.97,0 -74.89,-73.872,0 -73.852,-73.656,0 -72.834,-73.401,0 -71.619,-73.264,0 -70.209,-73.147,0 -68.936,-73.009,0 -67.957,-72.794,0 -67.369,-72.48,0 -67.134,-72.049,0 -67.252,-71.638,0 -67.565,-71.246,0 -67.917,-70.854,0 -68.231,-70.462,0 -68.485,-70.109,0 -68.544,-69.717,0 -68.446,-69.326,0 -67.976,-68.953,0 -67.584,-68.542,0 -67.428,-68.15,0 -67.624,-67.719,0 -67.741,-67.327,0 -67.252,-66.876,0 -66.703,-66.582,0 -66.057,-66.21,0 -65.371,-65.896,0 -64.568,-65.603,0 -64.177,-65.171,0 -63.628,-64.897,0 -63.001,-64.642,0 -62.042,-64.584,0 -61.415,-64.27,0 -60.71,-64.074,0 -59.887,-63.957,0 -59.163,-63.702,0 -58.595,-63.388,0 -57.811,-63.271,0 -57.224,-63.525,0 -57.596,-63.859,0 -58.614,-64.152,0 </coordinates></LinearRing></outerBoundaryIs></Polygon></MultiGeometry>
</Placemark> </kml>"""
k
=
kml
.
KML
()
k
.
from_string
(
doc
)
self
.
assertEqual
(
len
(
k
.
features
()),
1
)
self
.
assertTrue
(
isinstance
(
k
.
features
()[
0
].
geometry
,
MultiPolygon
))
k2
=
kml
.
KML
()
k2
.
from_string
(
k
.
to_string
())
#self.assertEqual(k.to_string(), k2.to_string())
print
k
.
to_string
()
print
def
test_suite
():
def
test_suite
():
suite
=
unittest
.
TestSuite
()
suite
=
unittest
.
TestSuite
()
suite
.
addTest
(
unittest
.
makeSuite
(
KmlFromStringTestCase
))
suite
.
addTest
(
unittest
.
makeSuite
(
KmlFromStringTestCase
))
suite
.
addTest
(
unittest
.
makeSuite
(
BuildKmlTestCase
))
suite
.
addTest
(
unittest
.
makeSuite
(
BuildKmlTestCase
))
return
suite
return
suite
if
__name__
==
'__main__'
:
if
__name__
==
'__main__'
:
...
...
setup.py
View file @
a2b94a48
...
@@ -19,6 +19,7 @@ Create and read KML Files""",
...
@@ -19,6 +19,7 @@ Create and read KML Files""",
zip_safe
=
False
,
zip_safe
=
False
,
install_requires
=
[
install_requires
=
[
# -*- Extra requirements: -*-
# -*- Extra requirements: -*-
'shapely'
,
],
],
entry_points
=
"""
entry_points
=
"""
# -*- Entry points: -*-
# -*- Entry points: -*-
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment