Commit 5f488f37 authored by Christian Ledermann's avatar Christian Ledermann

move geometries out of kml.Placemark int geometry.Geometry, add tests. The...

move geometries out of kml.Placemark int geometry.Geometry, add tests. The Tests for GeometryCollection fail if shapely is installed, waiting for guidance how to handle GeometryCollections with shapely
parent 1951be6b
...@@ -26,9 +26,11 @@ except ImportError: ...@@ -26,9 +26,11 @@ except ImportError:
NS = '{http://www.opengis.net/kml/2.2}' NS = '{http://www.opengis.net/kml/2.2}'
ATOMNS = '{http://www.w3.org/2005/Atom}' ATOMNS = '{http://www.w3.org/2005/Atom}'
GXNS = '{http://www.google.com/kml/ext/2.2}'
if hasattr(etree, 'register_namespace'): if hasattr(etree, 'register_namespace'):
etree.register_namespace('kml', NS[1:-1]) etree.register_namespace('kml', NS[1:-1])
etree.register_namespace('atom', ATOMNS[1:-1]) etree.register_namespace('atom', ATOMNS[1:-1])
etree.register_namespace('gx', GXNS[1:-1])
FORCE3D = False FORCE3D = False
...@@ -37,6 +37,10 @@ from config import etree ...@@ -37,6 +37,10 @@ from config import etree
from base import _BaseObject from base import _BaseObject
import logging
logger = logging.getLogger('fastkml.geometry')
class Geometry(_BaseObject): class Geometry(_BaseObject):
""" """
...@@ -106,6 +110,7 @@ class Geometry(_BaseObject): ...@@ -106,6 +110,7 @@ class Geometry(_BaseObject):
else: else:
self.geometry = asShape(geometry) self.geometry = asShape(geometry)
# write kml
def _set_altitude_mode(self, element): def _set_altitude_mode(self, element):
if self.altitude_mode: if self.altitude_mode:
...@@ -126,17 +131,17 @@ class Geometry(_BaseObject): ...@@ -126,17 +131,17 @@ class Geometry(_BaseObject):
clampToGround = (self.altitude_mode == 'clampToGround') or (self.altitude_mode == None) clampToGround = (self.altitude_mode == 'clampToGround') or (self.altitude_mode == None)
element = etree.Element("%scoordinates" %self.ns) element = etree.Element("%scoordinates" %self.ns)
if len(coordinates[0]) == 2: if len(coordinates[0]) == 2:
if config.FORCE3D and not clampToGround: if config.FORCE3D: # and not clampToGround:
tuples = ('%f,%f,0.000000' % tuple(c) for c in coordinates) tuples = ('%f,%f,0.000000' % tuple(c) for c in coordinates)
else: else:
tuples = ('%f,%f' % tuple(c) for c in coordinates) tuples = ('%f,%f' % tuple(c) for c in coordinates)
elif len(coordinates[0]) == 3: elif len(coordinates[0]) == 3:
if clampToGround: #if clampToGround:
# if the altitude is ignored anyway, we may as well # if the altitude is ignored anyway, we may as well
# ignore the z-value # ignore the z-value
tuples = ('%f,%f' % tuple(c[:2]) for c in coordinates) # tuples = ('%f,%f' % tuple(c[:2]) for c in coordinates)
else: #else:
tuples = ('%f,%f,%f' % tuple(c) for c in coordinates) tuples = ('%f,%f,%f' % tuple(c) for c in coordinates)
else: else:
raise ValueError("Invalid dimensions") raise ValueError("Invalid dimensions")
element.text = ' '.join(tuples) element.text = ' '.join(tuples)
...@@ -238,3 +243,136 @@ class Geometry(_BaseObject): ...@@ -238,3 +243,136 @@ class Geometry(_BaseObject):
else: else:
raise ValueError("Illegal geometry type.") raise ValueError("Illegal geometry type.")
# read kml
def _get_geometry_spec(self, element):
extrude = element.find('%sextrude' % self.ns)
if extrude is not None:
try:
et = bool(int(extrude.text.strip()))
except ValueError:
et = False
self.extrude = et
else:
self.extrude = False
tessellate = element.find('%stessellate' % self.ns)
if tessellate is not None:
try:
te = bool(int(tessellate.text.strip()))
except ValueError:
te = False
self.tessellate = te
else:
self.tessellate = False
altitude_mode = element.find('%saltitudeMode' % self.ns)
if altitude_mode is not None:
am = altitude_mode.text.strip()
if am in ['clampToGround',
#'relativeToSeaFloor', 'clampToSeaFloor',
'relativeToGround', 'absolute']:
self.altitude_mode = am
else:
self.altitude_mode = None
else:
self.altitude_mode = None
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 in polygon
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, LinearRing
if element.tag == ('%sPoint' % self.ns):
coords = self._get_coordinates(element)
self._get_geometry_spec(element)
return Point(coords[0])
if element.tag == ('%sLineString' % self.ns):
coords = self._get_coordinates(element)
self._get_geometry_spec(element)
return LineString(coords)
if element.tag == ('%sPolygon' % self.ns):
self._get_geometry_spec(element)
outer_boundary = element.find('%souterBoundaryIs' %self.ns)
ob = self._get_linear_ring(outer_boundary)
inner_boundaries = element.findall('%sinnerBoundaryIs' %self.ns)
ibs = []
for inner_boundary in inner_boundaries:
ibs.append(self._get_linear_ring(inner_boundary))
return Polygon(ob, ibs)
if element.tag == ('%sLinearRing' % self.ns):
coords = self._get_coordinates(element)
self._get_geometry_spec(element)
return LinearRing(coords)
def _get_multigeometry(self, element):
# MultiGeometry
geoms = []
if element.tag == ('%sMultiGeometry' % self.ns):
points = element.findall('%sPoint' % self.ns)
if points:
for point in points:
self._get_geometry_spec(point)
geoms.append(Point(self._get_coordinates(point)[0]))
linestrings = element.findall('%sLineString' % self.ns)
if linestrings:
for ls in linestrings:
self._get_geometry_spec(ls)
geoms.append(LineString(self._get_coordinates(ls)))
polygons = element.findall('%sPolygon' % self.ns)
if polygons:
for polygon in polygons:
self._get_geometry_spec(polygon)
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))
linearings = element.findall('%sLinearRing' % self.ns)
if linearings:
for lr in linearings:
self._get_geometry_spec(lr)
geoms.append(LinearRing(self._get_coordinates(ls)))
if len(geoms) > 0:
geom_types = []
for geom in geoms:
geom_types.append(geom.geom_type)
geom_types = list(set(geom_types))
if len(geom_types) > 1:
return GeometryCollection(geoms)
if geom_types[0] == 'Point':
return MultiPoint(geoms)
elif geom_types[0] == 'LineString':
return MultiLineString(geoms)
elif geom_types[0] == 'Polygon':
return MultiPolygon(geoms)
elif geom_types[0] == 'LinearRing':
return GeometryCollection(geoms)
def from_element(self, element):
geom = self._get_geometry(element)
if geom is not None:
self.geometry = geom
else:
mgeom = self._get_multigeometry(element)
if mgeom is not None:
self.geometry = mgeom
else:
logger.warn('No geometries found')
...@@ -72,3 +72,13 @@ gx:y ...@@ -72,3 +72,13 @@ gx:y
The complete XML schema for elements in this extension namespace is The complete XML schema for elements in this extension namespace is
located at http://developers.google.com/kml/schema/kml22gx.xsd. located at http://developers.google.com/kml/schema/kml22gx.xsd.
""" """
import logging
logger = logging.getLogger('fastkml.gx')
from config import etree
from config import GXNS as NS
from config import LXML
...@@ -29,6 +29,7 @@ http://schemas.opengis.net/kml/. ...@@ -29,6 +29,7 @@ http://schemas.opengis.net/kml/.
from geometry import Point, LineString, Polygon from geometry import Point, LineString, Polygon
from geometry import MultiPoint, MultiLineString, MultiPolygon from geometry import MultiPoint, MultiLineString, MultiPolygon
from geometry import LinearRing from geometry import LinearRing
from geometry import Geometry
from datetime import datetime, date from datetime import datetime, date
...@@ -555,172 +556,57 @@ class Placemark(_Feature): ...@@ -555,172 +556,57 @@ class Placemark(_Feature):
""" """
__name__ = "Placemark" __name__ = "Placemark"
geometry = None _geometry = None
@property
def geometry(self):
return self._geometry.geometry
@geometry.setter
def geometry(self, geometry):
if isinstance(geometry, Geometry):
self._geometry = geometry
else:
self._geometry = Geometry(ns=self.ns, geometry=geometry)
def _get_coordinates(self, element): def from_element(self, element):
coordinates = element.find('%scoordinates' % self.ns) super(Placemark, self).from_element(element)
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) point = element.find('%sPoint' % self.ns)
if point is not None: if point is not None:
coords = self._get_coordinates(point) geom = Geometry(ns=self.ns)
return Point(coords[0]) geom.from_element(point)
self._geometry = geom
return
line = element.find('%sLineString' % self.ns) line = element.find('%sLineString' % self.ns)
if line is not None: if line is not None:
coords = self._get_coordinates(line) geom = Geometry(ns=self.ns)
return LineString(coords) geom.from_element(line)
self._geometry = geom
return
polygon = element.find('%sPolygon' % self.ns) polygon = element.find('%sPolygon' % self.ns)
if polygon is not None: if polygon is not None:
outer_boundary = polygon.find('%souterBoundaryIs' %self.ns) geom = Geometry(ns=self.ns)
ob = self._get_linear_ring(outer_boundary) geom.from_element(polygon)
inner_boundaries = polygon.findall('%sinnerBoundaryIs' %self.ns) self._geometry = geom
ibs = [] return
for inner_boundary in inner_boundaries: linearring = element.find('%sLinearRing' % self.ns)
ibs.append(self._get_linear_ring(inner_boundary)) if linearring is not None:
return Polygon(ob, ibs) geom = Geometry(ns=self.ns)
return self._get_linear_ring(element) geom.from_element(linearring)
self._geometry = geom
return
def _get_multigeometry(self, element):
# MultiGeometry
multigeometry = element.find('%sMultiGeometry' % self.ns) multigeometry = element.find('%sMultiGeometry' % self.ns)
geoms = []
if multigeometry is not None: if multigeometry is not None:
points = multigeometry.findall('%sPoint' % self.ns) geom = Geometry(ns=self.ns)
if points: geom.from_element(multigeometry)
for point in points: self._geometry = geom
geoms.append(Point(self._get_coordinates(point)[0])) return
return MultiPoint(geoms) logger.warn('No geometries found')
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)
#XXX GeometryCollection
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')
#XXX move to geometry.Geometry
def _etree_coordinates(self, coordinates):
element = etree.Element("%scoordinates" %self.ns)
if len(coordinates[0]) == 2:
if config.FORCE3D:
tuples = ('%f,%f,0.000000' % tuple(c) for c in coordinates)
else:
tuples = ('%f,%f' % 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("%sPoint" %self.ns)
coords = list(point.coords)
element.append(self._etree_coordinates(coords))
return element
def _etree_linestring(self, linestring):
element = etree.Element("%sLineString" %self.ns)
coords = list(linestring.coords)
element.append(self._etree_coordinates(coords))
return element
def _etree_linearring(self, linearring):
element = etree.Element("%sLinearRing" %self.ns)
coords = list(linearring.coords)
element.append(self._etree_coordinates(coords))
return element
def _etree_polygon(self, polygon):
element = etree.Element("%sPolygon" %self.ns)
outer_boundary = etree.SubElement(element, "%souterBoundaryIs" %self.ns)
outer_boundary.append(self._etree_linearring(polygon.exterior))
for ib in polygon.interiors:
inner_boundary = etree.SubElement(element, "%sinnerBoundaryIs" %self.ns)
inner_boundary.append(self._etree_linearring(ib))
return element
def _etree_multipoint(self, points):
element = etree.Element("%sMultiGeometry" %self.ns)
for point in points.geoms:
element.append(self._etree_point(point))
return element
def _etree_multilinestring(self, linestrings):
element = etree.Element("%sMultiGeometry" %self.ns)
for linestring in linestrings.geoms:
element.append(self._etree_linestring(linestring))
return element
def _etree_multipolygon(self, polygons):
element = etree.Element("%sMultiGeometry" %self.ns)
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): def etree_element(self):
element = super(Placemark, self).etree_element() element = super(Placemark, self).etree_element()
if self.geometry is not None: if self._geometry is not None:
element.append(self._etree_geometry()) element.append(self._geometry.etree_element())
else: else:
logger.error('Object does not have a geometry') logger.error('Object does not have a geometry')
return element return element
......
...@@ -41,11 +41,13 @@ try: ...@@ -41,11 +41,13 @@ try:
from fastkml.geometry import MultiPoint, MultiLineString, MultiPolygon from fastkml.geometry import MultiPoint, MultiLineString, MultiPolygon
from fastkml.geometry import LinearRing, GeometryCollection from fastkml.geometry import LinearRing, GeometryCollection
from fastkml.geometry import Geometry from fastkml.geometry import Geometry
from fastkml.geometry import asShape
except ImportError: except ImportError:
from geometry import Point, LineString, Polygon from geometry import Point, LineString, Polygon
from geometry import MultiPoint, MultiLineString, MultiPolygon from geometry import MultiPoint, MultiLineString, MultiPolygon
from geometry import LinearRing, GeometryCollection from geometry import LinearRing, GeometryCollection
from geometry import Geometry from geometry import Geometry
from geometry import asShape
class BaseClassesTestCase(unittest.TestCase): class BaseClassesTestCase(unittest.TestCase):
""" BaseClasses must raise a NotImplementedError on etree_element """ BaseClasses must raise a NotImplementedError on etree_element
...@@ -871,7 +873,6 @@ class AtomTestCase( unittest.TestCase ): ...@@ -871,7 +873,6 @@ class AtomTestCase( unittest.TestCase ):
a.email = 'christian' a.email = 'christian'
self.assertFalse('email>' in str(a.to_string())) self.assertFalse('email>' in str(a.to_string()))
def test_link(self): def test_link(self):
l = atom.Link(href="http://localhost/", rel="alternate") l = atom.Link(href="http://localhost/", rel="alternate")
self.assertEqual(l.href, "http://localhost/") self.assertEqual(l.href, "http://localhost/")
...@@ -948,6 +949,8 @@ class SetGeometryTestCase( unittest.TestCase ): ...@@ -948,6 +949,8 @@ class SetGeometryTestCase( unittest.TestCase ):
#for geometries != LineString tesselate is ignored #for geometries != LineString tesselate is ignored
geom.geometry = Point(0,1) geom.geometry = Point(0,1)
self.assertFalse('tessellate' in geom.to_string()) self.assertFalse('tessellate' in geom.to_string())
geom.geometry = Polygon([(0,0), (1,0), (1,1), (0,0)])
self.assertFalse('tessellate' in geom.to_string())
def testPoint(self): def testPoint(self):
p = Point(0,1) p = Point(0,1)
...@@ -1002,38 +1005,240 @@ class SetGeometryTestCase( unittest.TestCase ): ...@@ -1002,38 +1005,240 @@ class SetGeometryTestCase( unittest.TestCase ):
in g.to_string()) in g.to_string())
def testMultiPoint(self): def testMultiPoint(self):
pass p0 = Point(0,1)
p1 = Point(1,1)
g = Geometry(geometry=MultiPoint([p0,p1]))
self.assertTrue('MultiGeometry' in g.to_string())
self.assertTrue('Point' in g.to_string())
self.assertTrue('coordinates>0.000000,1.000000</' in g.to_string())
self.assertTrue('coordinates>1.000000,1.000000</' in g.to_string())
def testMultiLineString(self): def testMultiLineString(self):
pass l0 = LineString([(0,0), (1,0)])
l1 = LineString([(0,1), (1,1)])
g = Geometry(geometry=MultiLineString([l0,l1]))
self.assertTrue('MultiGeometry' in g.to_string())
self.assertTrue('LineString' in g.to_string())
self.assertTrue('coordinates>0.000000,0.000000 1.000000,0.000000</' in g.to_string())
self.assertTrue('coordinates>0.000000,1.000000 1.000000,1.000000</' in g.to_string())
def testMultiPolygon(self): def testMultiPolygon(self):
pass #with holes
p0 = Polygon([(-1,-1), (2,-1), (2,2), (-1,-1)],[[(0,0), (1,0), (1,1), (0,0)]])
#without holes
p1 = Polygon([(3,0), (4,0), (4,1), (3,0)])
g = Geometry(geometry=MultiPolygon([p0,p1]))
self.assertTrue('MultiGeometry' in g.to_string())
self.assertTrue('Polygon' in g.to_string())
self.assertTrue('outerBoundaryIs' in g.to_string())
self.assertTrue('innerBoundaryIs' in g.to_string())
self.assertTrue('LinearRing' in g.to_string())
self.assertTrue(
'coordinates>0.000000,0.000000 1.000000,0.000000 1.000000,1.000000 0.000000,0.000000</'
in g.to_string())
self.assertTrue(
'coordinates>-1.000000,-1.000000 2.000000,-1.000000 2.000000,2.000000 -1.000000,-1.000000</'
in g.to_string())
self.assertTrue(
'coordinates>3.000000,0.000000 4.000000,0.000000 4.000000,1.000000 3.000000,0.000000</'
in g.to_string())
def testGeometryCollection(self): def testGeometryCollection(self):
pass po = Polygon([(3,0), (4,0), (4,1), (3,0)])
l = LineString([(0,0), (1,1)])
p = Point(0,1)
geo_if = {'type': 'GeometryCollection', 'geometries': [
po.__geo_interface__, l.__geo_interface__,
p.__geo_interface__ ]}
g = Geometry(geometry=GeometryCollection([po,p,l]))
#g = Geometry(geometry=asShape(geo_if))
self.assertTrue('MultiGeometry' in g.to_string())
self.assertTrue('Polygon' in g.to_string())
self.assertTrue('outerBoundaryIs' in g.to_string())
self.assertFalse('innerBoundaryIs' in g.to_string())
self.assertTrue('LinearRing' in g.to_string())
self.assertTrue(
'coordinates>3.000000,0.000000 4.000000,0.000000 4.000000,1.000000 3.000000,0.000000</'
in g.to_string())
self.assertTrue('LineString' in g.to_string())
self.assertTrue('coordinates>0.000000,0.000000 1.000000,1.000000</' in g.to_string())
self.assertTrue('Point' in g.to_string())
self.assertTrue('coordinates>0.000000,1.000000</' in g.to_string())
class GetGeometryTestCase( unittest.TestCase ): class GetGeometryTestCase( unittest.TestCase ):
def test_altitude_mode(self):
doc = """<kml:Point xmlns:kml="http://www.opengis.net/kml/2.2">
<kml:coordinates>0.000000,1.000000</kml:coordinates>
<kml:altitudeMode>clampToGround</kml:altitudeMode>
</kml:Point>"""
g = Geometry()
self.assertEqual(g.altitude_mode, None)
g.from_string(doc)
self.assertEqual(g.altitude_mode, 'clampToGround')
def test_extrude(self):
doc = """<kml:Point xmlns:kml="http://www.opengis.net/kml/2.2">
<kml:coordinates>0.000000,1.000000</kml:coordinates>
<kml:extrude>1</kml:extrude>
</kml:Point>"""
g = Geometry()
self.assertEqual(g.extrude, False)
g.from_string(doc)
self.assertEqual(g.extrude, True)
def test_tesselate(self):
doc = """<kml:Point xmlns:kml="http://www.opengis.net/kml/2.2">
<kml:coordinates>0.000000,1.000000</kml:coordinates>
<kml:tessellate>1</kml:tessellate>
</kml:Point>"""
g = Geometry()
self.assertEqual(g.tessellate, False)
g.from_string(doc)
self.assertEqual(g.tessellate, True)
def testPoint(self): def testPoint(self):
pass doc = """<kml:Point xmlns:kml="http://www.opengis.net/kml/2.2">
<kml:coordinates>0.000000,1.000000</kml:coordinates>
</kml:Point>"""
g = Geometry()
g.from_string(doc)
self.assertEqual(g.geometry.__geo_interface__,
{'type': 'Point', 'coordinates': (0.0, 1.0)})
def testLineString(self): def testLineString(self):
pass doc = """<kml:LineString xmlns:kml="http://www.opengis.net/kml/2.2">
<kml:coordinates>0.000000,0.000000 1.000000,1.000000</kml:coordinates>
</kml:LineString>"""
g = Geometry()
g.from_string(doc)
self.assertEqual(g.geometry.__geo_interface__,
{'type': 'LineString', 'coordinates': ((0.0, 0.0), (1.0, 1.0))})
def testLinearRing(self): def testLinearRing(self):
pass doc = """<kml:LinearRing xmlns:kml="http://www.opengis.net/kml/2.2">
<kml:coordinates>0.000000,0.000000 1.000000,0.000000 1.000000,1.000000 0.000000,0.000000</kml:coordinates>
</kml:LinearRing>
"""
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 testPolygon(self): def testPolygon(self):
pass doc = """<kml:Polygon xmlns:kml="http://www.opengis.net/kml/2.2">
<kml:outerBoundaryIs>
<kml:LinearRing>
<kml:coordinates>0.000000,0.000000 1.000000,0.000000 1.000000,1.000000 0.000000,0.000000</kml:coordinates>
</kml:LinearRing>
</kml:outerBoundaryIs>
</kml:Polygon>
"""
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 ="""<kml:Polygon xmlns:kml="http://www.opengis.net/kml/2.2">
<kml:outerBoundaryIs>
<kml:LinearRing>
<kml:coordinates>-1.000000,-1.000000 2.000000,-1.000000 2.000000,2.000000 -1.000000,-1.000000</kml:coordinates>
</kml:LinearRing>
</kml:outerBoundaryIs>
<kml:innerBoundaryIs>
<kml:LinearRing>
<kml:coordinates>0.000000,0.000000 1.000000,0.000000 1.000000,1.000000 0.000000,0.000000</kml:coordinates>
</kml:LinearRing>
</kml:innerBoundaryIs>
</kml:Polygon>
"""
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 testMultiPoint(self): def testMultiPoint(self):
pass doc = """
<kml:MultiGeometry xmlns:kml="http://www.opengis.net/kml/2.2">
<kml:Point>
<kml:coordinates>0.000000,1.000000</kml:coordinates>
</kml:Point>
<kml:Point>
<kml:coordinates>1.000000,1.000000</kml:coordinates>
</kml:Point>
</kml:MultiGeometry>
"""
g = Geometry()
g.from_string(doc)
self.assertEqual(len(g.geometry), 2)
def testMultiLineString(self): def testMultiLineString(self):
pass doc = """
def testMultiPolygon(self): <kml:MultiGeometry xmlns:kml="http://www.opengis.net/kml/2.2">
pass <kml:LineString>
def testGeometryCollection(self): <kml:coordinates>0.000000,0.000000 1.000000,0.000000</kml:coordinates>
pass </kml:LineString>
<kml:LineString>
<kml:coordinates>0.000000,1.000000 1.000000,1.000000</kml:coordinates>
</kml:LineString>
</kml:MultiGeometry>
"""
g = Geometry()
g.from_string(doc)
self.assertEqual(len(g.geometry), 2)
def testMultiPolygon(self):
doc = """
<kml:MultiGeometry xmlns:kml="http://www.opengis.net/kml/2.2">
<kml:Polygon>
<kml:outerBoundaryIs>
<kml:LinearRing>
<kml:coordinates>-1.000000,-1.000000 2.000000,-1.000000 2.000000,2.000000 -1.000000,-1.000000</kml:coordinates>
</kml:LinearRing>
</kml:outerBoundaryIs>
<kml:innerBoundaryIs>
<kml:LinearRing>
<kml:coordinates>0.000000,0.000000 1.000000,0.000000 1.000000,1.000000 0.000000,0.000000</kml:coordinates>
</kml:LinearRing>
</kml:innerBoundaryIs>
</kml:Polygon>
<kml:Polygon>
<kml:outerBoundaryIs>
<kml:LinearRing>
<kml:coordinates>3.000000,0.000000 4.000000,0.000000 4.000000,1.000000 3.000000,0.000000</kml:coordinates>
</kml:LinearRing>
</kml:outerBoundaryIs>
</kml:Polygon>
</kml:MultiGeometry>
"""
g = Geometry()
g.from_string(doc)
self.assertEqual(len(g.geometry), 2)
def testGeometryCollection(self):
doc = """
<kml:MultiGeometry xmlns:kml="http://www.opengis.net/kml/2.2">
<kml:Polygon>
<kml:outerBoundaryIs>
<kml:LinearRing>
<kml:coordinates>3.000000,0.000000 4.000000,0.000000 4.000000,1.000000 3.000000,0.000000</kml:coordinates>
</kml:LinearRing>
</kml:outerBoundaryIs>
</kml:Polygon>
<kml:Point>
<kml:coordinates>0.000000,1.000000</kml:coordinates>
</kml:Point>
<kml:LineString>
<kml:coordinates>0.000000,0.000000 1.000000,1.000000</kml:coordinates>
</kml:LineString>
</kml:MultiGeometry>
"""
g = Geometry()
g.from_string(doc)
self.assertEqual(len(g.geometry), 3)
class Force3DTestCase( unittest.TestCase ): class Force3DTestCase( unittest.TestCase ):
...@@ -1044,15 +1249,18 @@ class Force3DTestCase( unittest.TestCase ): ...@@ -1044,15 +1249,18 @@ class Force3DTestCase( unittest.TestCase ):
p3 = kml.Placemark(ns, 'id', 'name', 'description') p3 = kml.Placemark(ns, 'id', 'name', 'description')
p3.geometry = Polygon([(0, 0, 0), (1, 1, 0), (1, 0, 0)]) p3.geometry = Polygon([(0, 0, 0), (1, 1, 0), (1, 0, 0)])
config.FORCE3D = False config.FORCE3D = False
#p3.altitudeMode = 'absolute'
self.assertNotEqual(p2.to_string(), p3.to_string()) self.assertNotEqual(p2.to_string(), p3.to_string())
config.FORCE3D = True config.FORCE3D = True
self.assertEqual(p2.to_string(), p3.to_string()) self.assertEqual(p2.to_string(), p3.to_string())
#XXX
#altitudeMode clampToGround indicates to ignore an altitude specification. #altitudeMode clampToGround indicates to ignore an altitude specification.
#p3.altitudeMode = 'clampToGround' #p3.altitudeMode = 'clampToGround'
#self.assertEqual(p2.to_string(), p3.to_string()) #self.assertEqual(p2.to_string(), p3.to_string())
#config.FORCE3D = False #config.FORCE3D = False
#self.assertEqual(p2.to_string(), p3.to_string()) #self.assertNotEqual(p2.to_string(), p3.to_string())
#Important: Set FORCE3D back to False!
config.FORCE3D = False
def test_suite(): def test_suite():
suite = unittest.TestSuite() suite = unittest.TestSuite()
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment