Skip to content
Permalink
Browse files

Add geo_interface to shape and geometry classes with tests

  • Loading branch information...
geographika committed Mar 12, 2019
1 parent 3ed8857 commit 0abe369fb1e9250caa589f48272479afb27a0045
Showing with 121 additions and 55 deletions.
  1. +81 −54 mapscript/python/pyextend.i
  2. +1 −1 mapscript/python/tests/cases/line_test.py
  3. +39 −0 mapscript/python/tests/cases/shape_test.py
@@ -134,62 +134,71 @@ def fromstring(data, mappath=None):

%pythoncode %{

@property
def __geo_interface__(self):

bounds = self.bounds
geom_type = self.type

# see https://tools.ietf.org/html/rfc7946 for GeoJSON types

if ms_geom_type == MS_SHAPE_POINT or ms_geom_type == MS_SHP_POINTZ or ms_geom_type == MS_SHP_POINTM:
geom_type = "Point"
elif ms_geom_type == MS_SHP_MULTIPOINTZ or ms_geom_type == MS_SHP_MULTIPOINTM:
geom_type = "MultiPoint"
elif ms_geom_type == MS_SHAPE_LINE or ms_geom_type == MS_SHP_ARCZ or ms_geom_type == MS_SHP_ARCM:
if self.numlines == 1:
geom_type = "LineString"
else:
geom_type = "MultiLineString"
elif ms_geom_type == MS_SHAPE_POLYGON or ms_geom_type == MS_SHP_POLYGONZ or ms_geom_type == MS_SHP_POLYGONM:
if self.numlines == 1:
geom_type = "Polygon"
else:
geom_type = "MultiPolygon"
elif ms_geom_type == MS_SHAPE_NULL:
return None
else:
raise TypeError("Shape type {} not supported".format(geom_type))

properties = {}



coords = []

# property names are stored at the layer level
# https://github.com/mapserver/mapserver/issues/130
property_names = [for self.getValue(idx) in range(0, self.numvalues)]


property_values = [for self.getValue(idx) in range(0, self.numvalues)]

properties = zip(property_names, property_values)
@property
def __geo_interface__(self):

bounds = self.bounds
ms_geom_type = self.type

# see https://tools.ietf.org/html/rfc7946 for GeoJSON types

if ms_geom_type == MS_SHAPE_POINT or ms_geom_type == MS_SHP_POINTZ or ms_geom_type == MS_SHP_POINTM:
geom_type = "Point"
elif ms_geom_type == MS_SHP_MULTIPOINTZ or ms_geom_type == MS_SHP_MULTIPOINTM:
geom_type = "MultiPoint"
elif ms_geom_type == MS_SHAPE_LINE or ms_geom_type == MS_SHP_ARCZ or ms_geom_type == MS_SHP_ARCM:
if self.numlines == 1:
geom_type = "LineString"
else:
geom_type = "MultiLineString"
elif ms_geom_type == MS_SHAPE_POLYGON or ms_geom_type == MS_SHP_POLYGONZ or ms_geom_type == MS_SHP_POLYGONM:
if self.numlines == 1:
geom_type = "Polygon"
else:
geom_type = "MultiPolygon"
elif ms_geom_type == MS_SHAPE_NULL:
return None
else:
raise TypeError("Shape type {} not supported".format(geom_type))

properties = {}
coords = []

# property names are stored at the layer level
# https://github.com/mapserver/mapserver/issues/130

if hasattr(self, "_attributes"):
property_names = self._attributes
else:
property_names = [str(idx) for idx in range(0, self.numvalues)]

property_values = [self.getValue(idx) for idx in range(0, self.numvalues)]

properties = dict(zip(property_names, property_values))

for idx in range(0, self.numlines):
line = self.get(idx)
geom = line.__geo_interface__
coords.append(geom["coordinates"])

return {
"type": "Feature",
"bbox": (bounds.minx, bounds.miny, bounds.maxx, bounds.maxy),
"properties": properties,
"geometry": {
"type": geom_type,
"coordinates": coords
}
}

for idx in range(0, self.numlines):
line = self.get(idx)
geom = line.__geo_interface__
coords.append(geom["coordinates"])
def getAttributes(self):
return self._attributes

def setAttributes(self, attributes):
self._attributes = attributes

return {
"type": "Feature",
"bbox": (bounds.minx, bounds.miny, bounds.maxx, bounds.maxxy),
"properties": properties
"geometry": {
"type": geom_type,
"coordinates": coords
}
}
__swig_getmethods__["attributes"] = getAttributes
__swig_setmethods__["attributes"] = setAttributes

%}
}
@@ -231,6 +240,7 @@ def fromstring(data, mappath=None):
PyTuple_SetItem(output,1,PyInt_FromLong((long)self->height));
return output;
}

%pythoncode %{

def get_height(self):
@@ -251,6 +261,23 @@ def fromstring(data, mappath=None):
%}
}

/******************************************************************************
* Extensions to layerObj
*****************************************************************************/

%extend layerObj {

%pythoncode %{

def getAttributes(self):
self.open()
attributes = [self.getItem(idx) for idx in range(0, self.numitems)]
self.close()
return attributes

%}
}

/******************************************************************************
* Extensions to imageObj
*****************************************************************************/
@@ -75,7 +75,7 @@ def xtestAlterNumPoints(self):
assert error_thrown is True

def testLineGeoInterface(self):
"""return point using the __geo_interface__ protocol"""
"""return line using the __geo_interface__ protocol"""
assert self.line.__geo_interface__ == {"type": "LineString", "coordinates": [(0.0, 1.0), (2.0, 3.0)]}


@@ -86,6 +86,45 @@ def testGetNumFeatures(self):
inline_layer = self.map.getLayerByName('INLINE')
assert inline_layer.getNumFeatures() == 1

def testShapeGeoInterface(self):
"""return the shape using the __geo_interface__ protocol with no attribute names"""
inline_layer = self.map.getLayerByName('POLYGON')
inline_layer.open()
inline_layer.template = "FAKE"
inline_layer.queryByIndex(self.map, -1, 0)
res = inline_layer.getResult(0)
s = inline_layer.getShape(res)
assert s.__geo_interface__ == {
'geometry': {
'type': 'Polygon',
'coordinates': [[(-0.25, 51.227222), (-0.25, 51.727222), (0.25, 51.727222),
(0.25, 51.227222), (-0.25, 51.227222)]]
},
'type': 'Feature',
'bbox': (-0.25, 51.227222, 0.25, 51.727222),
'properties': {'1': 'A Polygon', '0': '1'}
}

def testShapeGeoInterfaceWithFields(self):
"""return the shape using the __geo_interface__ protocol with attribute names"""
inline_layer = self.map.getLayerByName('POLYGON')
inline_layer.open()
inline_layer.template = "FAKE"
inline_layer.queryByIndex(self.map, -1, 0)
res = inline_layer.getResult(0)
s = inline_layer.getShape(res)
s.attributes = inline_layer.getAttributes()
assert s.__geo_interface__ == {
'geometry': {
'type': 'Polygon',
'coordinates': [[(-0.25, 51.227222), (-0.25, 51.727222), (0.25, 51.727222),
(0.25, 51.227222), (-0.25, 51.227222)]]
},
'type': 'Feature',
'bbox': (-0.25, 51.227222, 0.25, 51.727222),
'properties': {'FNAME': 'A Polygon', 'FID': '1'}
}


class ShapeValuesTestCase(unittest.TestCase):

0 comments on commit 0abe369

Please sign in to comment.
You can’t perform that action at this time.