- 积分
- 17109
- 贡献
-
- 精华
- 在线时间
- 小时
- 注册时间
- 2012-8-25
- 最后登录
- 1970-1-1
|
登录后查看更多精彩内容~
您需要 登录 才可以下载或查看,没有帐号?立即注册
x
本帖最后由 非对称 于 2018-2-13 18:14 编辑
- # -*- coding: utf-8 -*-
- """
- 特此申明,以下源代码改写自basemap的readshapefile
- 适合在无投影下的经纬度坐标中绘制。
- 需要在投影坐标系绘制,请自行用basemap的readshapefile绘制
- -------------------------------------------------
- File Name: readshp
- Description :
- Author : Xy Liu
- date: 2018/2/13
- -------------------------------------------------
- Change Activity:
- 2018/2/13
- -------------------------------------------------
- """
- import os
- from matplotlib import dedent
- from matplotlib.collections import LineCollection
- __author__ = 'Xy Liu'
- def readshapefile(shapefile, name, drawbounds=True, zorder=None,
- linewidth=0.5, color='k', antialiased=1, ax=None,
- default_encoding='utf-8'):
- """
- Read in shape file, optionally draw boundaries on map.
- .. note::
- - Assumes shapes are 2D
- - only works for Point, MultiPoint, Polyline and Polygon shapes.
- - vertices/points must be in geographic (lat/lon) coordinates.
- Mandatory Arguments:
- .. tabularcolumns:: |l|L|
- ============== ====================================================
- Argument Description
- ============== ====================================================
- shapefile path to shapefile components. Example:
- shapefile='/home/jeff/esri/world_borders' assumes
- that world_borders.shp, world_borders.shx and
- world_borders.dbf live in /home/jeff/esri.
- name name for Basemap attribute to hold the shapefile
- vertices or points in map projection
- coordinates. Class attribute name+'_info' is a list
- of dictionaries, one for each shape, containing
- attributes of each shape from dbf file, For
- example, if name='counties', self.counties
- will be a list of x,y vertices for each shape in
- map projection coordinates and self.counties_info
- will be a list of dictionaries with shape
- attributes. Rings in individual Polygon
- shapes are split out into separate polygons, and
- additional keys 'RINGNUM' and 'SHAPENUM' are added
- to the shape attribute dictionary.
- ============== ====================================================
- The following optional keyword arguments are only relevant for Polyline
- and Polygon shape types, for Point and MultiPoint shapes they are
- ignored.
- .. tabularcolumns:: |l|L|
- ============== ====================================================
- Keyword Description
- ============== ====================================================
- drawbounds draw boundaries of shapes (default True).
- zorder shape boundary zorder (if not specified,
- default for mathplotlib.lines.LineCollection
- is used).
- linewidth shape boundary line width (default 0.5)
- color shape boundary line color (default black)
- antialiased antialiasing switch for shape boundaries
- (default True).
- ax axes instance (overrides default axes instance)
- ============== ====================================================
- A tuple (num_shapes, type, min, max) containing shape file info
- is returned.
- num_shapes is the number of shapes, type is the type code (one of
- the SHPT* constants defined in the shapelib module, see
- http://shapelib.maptools.org/shp_api.html) and min and
- max are 4-element lists with the minimum and maximum values of the
- vertices. If ``drawbounds=True`` a
- matplotlib.patches.LineCollection object is appended to the tuple.
- """
- import shapefile as shp
- from shapefile import Reader
- shp.default_encoding = default_encoding
- if not os.path.exists('%s.shp' % shapefile):
- raise IOError('cannot locate %s.shp' % shapefile)
- if not os.path.exists('%s.shx' % shapefile):
- raise IOError('cannot locate %s.shx' % shapefile)
- if not os.path.exists('%s.dbf' % shapefile):
- raise IOError('cannot locate %s.dbf' % shapefile)
- # open shapefile, read vertices for each object, convert
- # to map projection coordinates (only works for 2D shape types).
- try:
- shf = Reader(shapefile)
- except:
- raise IOError('error reading shapefile %s.shp' % shapefile)
- fields = shf.fields
- coords = []
- attributes = []
- msg = dedent("""
- shapefile must have lat/lon vertices - it looks like this one has vertices
- in map projection coordinates. You can convert the shapefile to geographic
- coordinates using the shpproj utility from the shapelib tools
- (http://shapelib.maptools.org/shapelib-tools.html)""")
- shptype = shf.shapes()[0].shapeType
- bbox = shf.bbox.tolist()
- info = dict()
- info['info'] = (shf.numRecords, shptype, bbox[0:2] + [0., 0.], bbox[2:] + [0., 0.])
- npoly = 0
- for shprec in shf.shapeRecords():
- shp = shprec.shape
- rec = shprec.record
- npoly = npoly + 1
- if shptype != shp.shapeType:
- raise ValueError('readshapefile can only handle a single shape type per file')
- if shptype not in [1, 3, 5, 8]:
- raise ValueError('readshapefile can only handle 2D shape types')
- verts = shp.points
- if shptype in [1, 8]: # a Point or MultiPoint shape.
- lons, lats = list(zip(*verts))
- if max(lons) > 721. or min(lons) < -721. or max(lats) > 90.01 or min(lats) < -90.01:
- raise ValueError(msg)
- # if latitude is slightly greater than 90, truncate to 90
- lats = [max(min(lat, 90.0), -90.0) for lat in lats]
- if len(verts) > 1: # MultiPoint
- x, y = lons, lats
- coords.append(list(zip(x, y)))
- else: # single Point
- x, y = lons[0], lats[0]
- coords.append((x, y))
- attdict = {}
- for r, key in zip(rec, fields[1:]):
- attdict[key[0]] = r
- attributes.append(attdict)
- else: # a Polyline or Polygon shape.
- parts = shp.parts.tolist()
- ringnum = 0
- for indx1, indx2 in zip(parts, parts[1:] + [len(verts)]):
- ringnum = ringnum + 1
- lons, lats = list(zip(*verts[indx1:indx2]))
- if max(lons) > 721. or min(lons) < -721. or max(lats) > 90.01 or min(lats) < -90.01:
- raise ValueError(msg)
- # if latitude is slightly greater than 90, truncate to 90
- lats = [max(min(lat, 90.0), -90.0) for lat in lats]
- x, y = lons, lats
- coords.append(list(zip(x, y)))
- attdict = {}
- for r, key in zip(rec, fields[1:]):
- attdict[key[0]] = r
- # add information about ring number to dictionary.
- attdict['RINGNUM'] = ringnum
- attdict['SHAPENUM'] = npoly
- attributes.append(attdict)
- # draw shape boundaries for polylines, polygons using LineCollection.
- if shptype not in [1, 8] and drawbounds:
- # get current axes instance (if none specified).
- import matplotlib.pyplot as plt
- ax = ax or plt.gca()
- # make LineCollections for each polygon.
- lines = LineCollection(coords, antialiaseds=(antialiased,))
- lines.set_color(color)
- lines.set_linewidth(linewidth)
- lines.set_label('_nolabel_')
- if zorder is not None:
- lines.set_zorder(zorder)
- ax.add_collection(lines)
- # set axes limits to fit map region.
- # self.set_axes_limits(ax=ax)
- # # clip boundaries to map limbs
- # lines,c = self._cliplimb(ax,lines)
- # info = info + (lines,)
- info[name] = coords
- info[name + '_info'] = attributes
- return info
- if __name__ == '__main__':
- file = 'test.shp'
- readshapefile(file.replace('.shp', ''), os.path.basename(file), color='k', linewidth=1)
复制代码
|
评分
-
查看全部评分
|