Further to relet's answer on how to get individual polygons, you can then run an intersection on all the polygons to create the holes. If your dataset contains overlapping polygons though you're out of luck.
Explain again what is wrong with existing shapefile readers?
Would it not be easier to export feature IDs and M values from the shapefile and then join them back to the polygons after using an existing shapefile reader?
For multipatches you can use the same technique of assigning polygon IDs to a "patch ID" and then adding this attribute back to the features.
Edit: Whilst you say you don't want to use OGR, just in case you change your mind..
import ogr
# Get the driver
driver = ogr.GetDriverByName('ESRI Shapefile')
# Open a shapefile
shapefileName = "D:/temp/myshapefile.shp"
dataset = driver.Open(shapefileName, 0)
layer = dataset.GetLayer()
for index in xrange(layer.GetFeatureCount()):
feature = layer.GetFeature(index)
geometry = feature.GetGeometryRef()
#geometry for polygon as WKT, inner rings, outer rings etc.
print geometry
The geometry should be output as follows:
POLYGON ((79285 57742,78741 54273...),(76087 55694,78511 55088,..))
The first bracket contains the coords of the exterior ring, subsequent brackets the coords of interior rings.
If you have Z values points should be in the format 79285 57742 10 (where the last coord is a height).
Otherwise you could use the Shapely Contains and Within functions to assess every polygon with each other and apply a spatial index beforehand - http://pypi.python.org/pypi/Rtree/ to speed up processing.
I followed the second approach now and this seems to work, comments welcome:
def sortlayer(l, fd):
# fids are unique, fids may be sorted or unsorted, fids may be consecutive or have gaps
# don't care about semantics, don't touch fids and their order, reuse fids
fids = []
vals = []
l.ResetReading()
for f in l:
fid = f.GetFID()
fids.append(fid)
vals.append((f.GetField(fd), fid))
vals.sort()
# index as dict: {newfid: oldfid, ...}
ix = {fids[i]: vals[i][1] for i in xrange(len(fids))}
# swap features around in groups/rings
for fidstart in ix.keys():
if fidstart not in ix: continue
ftmp = l.GetFeature(fidstart)
fiddst = fidstart
while True:
fidsrc = ix.pop(fiddst)
if fidsrc == fidstart: break
f = l.GetFeature(fidsrc)
f.SetFID(fiddst)
l.SetFeature(f)
fiddst = fidsrc
ftmp.SetFID(fiddst)
l.SetFeature(ftmp)
Best Answer
use the
dir()
functionAnd you have all the class/function of the module. You may find what you are looking for with a little function adapted from a script Script de Python para filtrar por patrón de texto los métodos de Clases en PyQGIS de José Guerrero (already used in Iterating over selected features in QGIS Processing)
so
are correct
Rather than using ogr, use the Shapely module, it is easier.
And if you need to work with shapefiles, use the Fiona module (easier and also based on GDAL/OGR, with many examples in GIS stackexchange)
If you want to continue with osgeo/ogr, look at the Python GDAL/OGR Cookbook