[pyshp] 01/10: Imported Upstream version 1.2.1
Ross Gammon
ross-guest at moszumanska.debian.org
Wed Aug 13 20:22:47 UTC 2014
This is an automated email from the git hooks/post-receive script.
ross-guest pushed a commit to branch master
in repository pyshp.
commit 7d4ec3164f7d1f919843474957dc6cb2fd0241af
Author: Ross Gammon <rossgammon at mail.dk>
Date: Wed Aug 13 20:58:31 2014 +0200
Imported Upstream version 1.2.1
---
MANIFEST.in | 1 +
PKG-INFO | 184 +-
README.html | 835 +++++++++
README.pdf | 4130 +++++++++++++++++++++++++++++++++++++++++++
README.txt | 182 +-
changelog.txt | 69 +
pyshp.egg-info/PKG-INFO | 184 +-
pyshp.egg-info/SOURCES.txt | 20 +-
setup.py | 2 +-
shapefile.py | 255 ++-
shapefiles/blockgroups.dbf | Bin 236775 -> 0 bytes
shapefiles/blockgroups.sbn | Bin 6836 -> 0 bytes
shapefiles/blockgroups.sbx | Bin 540 -> 0 bytes
shapefiles/blockgroups.shp | Bin 208572 -> 0 bytes
shapefiles/blockgroups.shx | Bin 5404 -> 0 bytes
shapefiles/test/line.dbf | Bin 259 -> 0 bytes
shapefiles/test/line.shp | Bin 372 -> 0 bytes
shapefiles/test/line.shx | Bin 116 -> 0 bytes
shapefiles/test/point.dbf | Bin 552 -> 0 bytes
shapefiles/test/point.shp | Bin 240 -> 0 bytes
shapefiles/test/point.shx | Bin 140 -> 0 bytes
shapefiles/test/polygon.dbf | Bin 259 -> 0 bytes
shapefiles/test/polygon.shp | Bin 236 -> 0 bytes
shapefiles/test/polygon.shx | Bin 108 -> 0 bytes
24 files changed, 5733 insertions(+), 129 deletions(-)
diff --git a/MANIFEST.in b/MANIFEST.in
new file mode 100644
index 0000000..c003498
--- /dev/null
+++ b/MANIFEST.in
@@ -0,0 +1 @@
+prune shapefiles
\ No newline at end of file
diff --git a/PKG-INFO b/PKG-INFO
index 14f2d63..a2dd472 100644
--- a/PKG-INFO
+++ b/PKG-INFO
@@ -1,51 +1,57 @@
Metadata-Version: 1.0
Name: pyshp
-Version: 1.1.4
+Version: 1.2.1
Summary: Pure Python read/write support for ESRI Shapefile format
Home-page: http://code.google.com/p/pyshp
Author: Joel Lawhead
Author-email: jlawhead at geospatialpython.com
License: MIT
-Description: Python Shapefile Library
+Description: PyShp
========================
- :Author: Joel Lawhead <jlawhead at geospatialpython.com>
- :Revised: October 1, 2011
+
+ :Author: Joel Lawhead - jlawhead at geospatialpython.com
+
+ :Version 1.2.1
+
+ :Revised: May 11, 2014
.. contents::
Overview
--------
- The Python Shapefile Library (pyshp) provides read and write support for the ESRI
+ PyShp provides read and write support for the Esri
Shapefile format. The Shapefile format is a popular Geographic Information
System vector data format created by Esri. For more information about this format
- please read the well-written "ESRI Shapefile Technical Description - July 1998".
+ please read the well-written "ESRI Shapefile Technical Description - July 1998"
+ located at http://www.esri.com/library/whitepapers/pdfs/shapefile.pdf.
The Esri document describes the shp and shx file formats. However a third file
format called dbf is also required. This format is documented on the web as the
"XBase File Format Description" and is a simple file-based database format created
- in the 1960's. Both the Esri and XBase file-formats are very simple in design and
+ in the 1960's. For more on this specification see:
+ http://www.clicketyclick.dk/databases/xbase/format/index.html
+
+ Both the Esri and XBase file-formats are very simple in design and
memory efficient which is part of the reason the shapefile format remains popular
despite the numerous ways to store and exchange GIS data available today.
- This documentation covers the Python 2.x-compatible version of the library. A
- Python 3-compatible version is available in the Subversion trunk of the pyshp
- project on Google Code.
+ Pyshp is compatible with Python 2.4-3.x.
- This document provides examples for using pyshp to read and write shapefiles.
+ This document provides examples for using PyShp to read and write shapefiles.
Currently the sample census blockgroup shapefile referenced in the examples is
only available on the google code project site at http://code.google.com/p/pyshp.
These examples are straight-forward and you can also easily run them against your
own shapefiles manually with minimal modification. Other examples for specific
topics are continually added to the pyshp wiki on google code and the blog
- GeospatialPython.com.
+ http://GeospatialPython.com.
Important: For information about map projections, shapefiles,
and Python please visit: http://code.google.com/p/pyshp/wiki/MapProjections
I sincerely hope this library eliminates the mundane distraction of simply
reading and writing data, and allows you to focus on the challenging and FUN
- part of your project.
+ part of your geospatial project.
Examples
--------
@@ -80,7 +86,7 @@ Description: Python Shapefile Library
OR any of the other 5+ formats which are potentially part of a shapefile.
- The library does not care
+ The library does not care about extensions.
Reading Shapefiles from File-Like Objects
.........................................
@@ -118,6 +124,11 @@ Description: Python Shapefile Library
>>> len(shapes)
663
+ You can iterate through the shapefile's geometry using the iterShapes() method.
+
+ >>> len(list(sf.iterShapes()))
+ 663
+
Each shape record contains the following attributes:
>>> for name in dir(shapes[3]):
@@ -135,7 +146,7 @@ Description: Python Shapefile Library
5
- bbox: If the shape type contains multiple points this tuple describes the
- upper left (x,y) coordinate and lower right corner coordinate creating a
+ lower left (x,y) coordinate and upper right corner coordinate creating a
complete box around the points. If the shapeType is a Null
(shapeType == 0) then an AttributeError is raised.
@@ -227,6 +238,12 @@ Description: Python Shapefile Library
>>> len(records)
663
+ Similar to the geometry methods, you can iterate through dbf records using the
+ recordsIter() method.
+
+ >>> len(list(sf.iterRecords()))
+ 663
+
Each record is a list containing an attribute corresponding to each field in the
field list.
@@ -287,11 +304,11 @@ Description: Python Shapefile Library
Writing Shapefiles
++++++++++++++++++
- The PSL tries to be as flexible as possible when writing shapefiles while
+ PyShp tries to be as flexible as possible when writing shapefiles while
maintaining some degree of automatic validation to make sure you don't
accidentally write an invalid file.
- The PSL can write just one of the component files such as the shp or dbf file
+ PyShp can write just one of the component files such as the shp or dbf file
without writing the others. So in addition to being a complete
shapefile library, it can also be used as a basic dbf (xbase) library. Dbf files are
a common database format which are often useful as a standalone simple
@@ -320,6 +337,22 @@ Description: Python Shapefile Library
several reserved numbers which have not been used yet therefore the numbers of
the existing shape types are not sequential.
+ You can reference shape types by the numbers or by constants defined by PyShp:
+ shapefile.NULL = 0
+ shapefile.POINT = 1
+ shapefile.POLYLINE = 3
+ shapefile.POLYGON = 5
+ shapefile.MULTIPOINT = 8
+ shapefile.POINTZ = 11
+ shapefile.POLYLINEZ = 13
+ shapefile.POLYGONZ = 15
+ shapefile.MULTIPOINTZ = 18
+ shapefile.POINTM = 21
+ shapefile.POLYLINEM = 23
+ shapefile.POLYGONM = 25
+ shapefile.MULTIPOINTM = 28
+ shapefile.MULTIPATCH = 31
+
There are three ways to set the shape type:
- Set it when creating the class instance.
- Set it by assigning a value to an existing class instance.
@@ -329,10 +362,16 @@ Description: Python Shapefile Library
>>> w = shapefile.Writer(shapeType=1)
+ or we can use the constants as explained above:
+
+ >>> w = shapefile.Writer(shapefile.POINT)
+
+ As you can see, specifying the shapeType argument explicitly isn't necessary.
+
>>> w.shapeType
1
- OR you can set it after the Writer is created:
+ OR you can set it after the Writer is created by changing the property:
>>> w.shapeType = 3
@@ -344,7 +383,7 @@ Description: Python Shapefile Library
Because every shape must have a corresponding record it is critical that the
number of records equals the number of shapes to create a valid shapefile. To
- help prevent accidental misalignment the PSL has an "auto balance" feature to
+ help prevent accidental misalignment PyShp has an "auto balance" feature to
make sure when you add either a shape or a record the two sides of the
equation line up. This feature is NOT turned on by default. To activate it
set the attribute autoBalance to 1 (True):
@@ -394,7 +433,7 @@ Description: Python Shapefile Library
Point shapes are added using the "point" method. A point is specified by an
x, y, and optional z (elevation) and m (measure) value.
- >>> w = shapefile.Writer()
+ >>> w = shapefile.Writer(shapefile.POINT)
>>> w.point(122, 37) # No elevation or measure values
@@ -406,20 +445,65 @@ Description: Python Shapefile Library
>>> w.shapes()[1].points
[[118, 36, 4, 8]]
- **Adding a Poly shape**
+ **Adding a Poly Shape**
"Poly" shapes can be either polygons or lines. Shapefile polygons must have at
- least 5 points and the last point must be the same as the first (i.e. you can't
- have a triangle accoring to the shapefile specification even though many popular
- GIS programs support such shapefiles.) A line must have at least two points.
+ least 4 points and the last point must be the same as the first. PyShp automatically
+ enforces closed polygons.
+ A line must have at least two points.
Because of the similarities between these two shape types they are created using
a single method called "poly".
- >>> w = shapefile.Writer()
+ >>> w = shapefile.Writer(shapefile.POLYGON)
>>> w.poly(shapeType=3, parts=[[[122,37,4,9], [117,36,3,4]], [[115,32,8,8],
... [118,20,6,4], [113,24]]])
+ **Adding a Polygon with Rings**
+
+ Polygons consist of rings which mean they are closed. The first point and last point
+ of a ring must be the same. PyShp enforces ring closure if the ring is incomplete when
+ you add the shape. Polygons can have inner rings which create holes. Holes are defined
+ by the order of the points. Normally points in a ring run clockwise. If the points
+ run counter-clockwise then they form a hole. If you don't order the points correctly
+ you'll just have overlapping polygons.
+
+ >>> w = shapefile.Writer(shapefile.POLYGON)
+ >>> outer_ring = [[10,10],[50,50],[100,10],[50,-50],[10,10]]
+ >>> inner_ring = [[40,10],[50,30],[70,10],[50,-30],[40,10]]
+ >>> inner_ring.reverse()
+
+ You can use the "shapefile.signed_area()" method to determine if a ring is clockwise
+ or counter-clockwise. A value >= 0 means the ring is counter-clockwise and < 0 means
+ the ring is clockwise. The value returned is also the area of the polygon.
+
+ >>> # Clockwise ring
+ ... shapefile.signed_area(outer_ring)
+ -4500.0
+ >>> # Counter-clockwise ring
+ ... shapefile.signed_area(inner_ring)
+ 900.0
+
+ **Creating 3D Polygons**
+
+ Elevation values, known as "Z" values allow you to create 3-dimensional shapefiles. The
+ z value is an extra value specified as part of a point.
+
+ >>> w = shapefile.Writer(shapeType=shapefile.POLYGONZ)
+ >>> w.poly([[[-89.0, 33, 12], [-90, 31, 11], [-91, 30, 12]]], shapeType=15)
+ >>> w.field("NAME")
+ >>> w.record("PolyZTest")
+ >>> w.save("shapefiles/test/MyPolyZ")
+
+ The z values are stored in a seperate shape attribute.
+
+ >>> r = shapefile.Reader("shapefiles/test/MyPolyZ")
+ >>> s = r.shape(0)
+ >>> s.points
+ [[-89.0, 33.0], [-90.0, 31.0], [-91.0, 30.0], [-89.0, 33.0]]
+ >>> s.z
+ [12.0, 11.0, 12.0, 12.0]
+
Creating Attributes
...................
@@ -467,6 +551,20 @@ Description: Python Shapefile Library
>>> w.record(FIRST_FLD='First', SECOND_FLD='Line')
>>> w.save('shapefiles/test/line')
+ File Names
+ ..........
+
+ File extensions are optional when reading or writing shapfiles. If you specify them Pyshp
+ ignores them anyway. When you save files you can specify a base file name that is used for
+ all three file types. Or you can specify a nmae for one or more file types. In that case,
+ any file types not assigned will not save and only file types with file names will be saved.
+ If you do not specify any file names (i.e. save()), then a unique file name is generated with
+ the prefix "shapefile\_" followed by random characters which is used for all three files. The
+ unique file name is returned as a string.
+
+ >>> targetName = w.save()
+ >>> assert("shapefile_" in targetName)
+
Saving to File-Like Objects
...........................
@@ -497,6 +595,26 @@ Description: Python Shapefile Library
>>> e = shapefile.Editor(shapefile="shapefiles/test/point.shp")
>>> e.point(0,0,10,2)
>>> e.record("Appended","Point")
+ >>> # We added z and m values so
+ >>> # change the shapetype
+ >>> e.shapeType = shapefile.POINTZ
+ >>> e.save('shapefiles/test/point')
+
+ Edit the appended point to change the "y" and "z" value
+
+ >>> e = shapefile.Editor(shapefile="shapefiles/test/point.shp")
+ >>> # Find the point by the attribute
+ >>> for s in enumerate(e.records):
+ ... i, record = s
+ ... if record[0] == "Appended":
+ ... geom = e._shapes[i]
+ ... # Change the y value to 5
+ ... geom.points[0][1] = 5
+ ... # Change the z value to 9
+ ... if hasattr(geom, "z"):
+ ... geom.z = (9,)
+ ... else:
+ ... geom.points[0][2] = 9
>>> e.save('shapefiles/test/point')
Add a new line to a line shapefile:
@@ -505,6 +623,7 @@ Description: Python Shapefile Library
>>> e.line(parts=[[[10,5],[15,5],[15,1],[13,3],[11,1]]])
>>> e.record('Appended','Line')
>>> e.save('shapefiles/test/line')
+ >>> e = None
Add a new polygon to a polygon shapefile:
@@ -512,6 +631,7 @@ Description: Python Shapefile Library
>>> e.poly(parts=[[[5.1,5],[9.9,5],[9.9,1],[7.5,3],[5.1,1]]])
>>> e.record("Appended","Polygon")
>>> e.save('shapefiles/test/polygon')
+ >>> e = None
Remove the first point in each shapefile - for a point shapefile that is
the first shape and record"
@@ -519,13 +639,27 @@ Description: Python Shapefile Library
>>> e = shapefile.Editor(shapefile="shapefiles/test/point.shp")
>>> e.delete(0)
>>> e.save('shapefiles/test/point')
+ >>> e = None
Remove the last shape in the polygon shapefile.
>>> e = shapefile.Editor(shapefile="shapefiles/test/polygon.shp")
>>> e.delete(-1)
>>> e.save('shapefiles/test/polygon')
+ >>> e = None
+ Python __geo_interface__
+ ++++++++++++++++++++++++
+
+ The Python __geo_interface__ convention provides a data interchange interface
+ among geospatial Python libraries. The interface returns data as GeoJSON.
+ More information on the __geo_interface__ protocol can be found at:
+ https://gist.github.com/sgillies/2217756.
+ More information on GeoJSON is available at http://geojson.org http://geojson.org.
+
+ >>> s = sf.shape(0)
+ >>> s.__geo_interface__["type"]
+ 'MultiPolygon'
Keywords: gis geospatial geographic shapefile shapefiles
diff --git a/README.html b/README.html
new file mode 100644
index 0000000..dc8c0e5
--- /dev/null
+++ b/README.html
@@ -0,0 +1,835 @@
+<?xml version="1.0" encoding="utf-8" ?>
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
+<meta name="generator" content="Docutils 0.9: http://docutils.sourceforge.net/" />
+<title>PyShp</title>
+<meta name="author" content="Joel Lawhead - jlawhead@geospatialpython.com" />
+<style type="text/css">
+
+/*
+:Authors: Ian Bicking, Michael Foord
+:Contact: fuzzyman at voidspace.org.uk
+:Date: 2005/08/26
+:Version: 0.1.0
+:Copyright: This stylesheet has been placed in the public domain.
+
+Stylesheet for Docutils.
+Based on ``blue_box.css`` by Ian Bicking
+and ``html4css1.css`` revision 1.46.
+*/
+
+ at import url(html4css1.css);
+
+body {
+ font-family: Arial, sans-serif;
+}
+
+em, i {
+ /* Typically serif fonts have much nicer italics */
+ font-family: Times New Roman, Times, serif;
+}
+
+a.target {
+ color: blue;
+}
+
+a.target {
+ color: blue;
+}
+
+a.toc-backref {
+ text-decoration: none;
+ color: black;
+}
+
+a.toc-backref:hover {
+ background-color: inherit;
+}
+
+a:hover {
+ background-color: #cccccc;
+}
+
+div.attention, div.caution, div.danger, div.error, div.hint,
+div.important, div.note, div.tip, div.warning {
+ background-color: #cccccc;
+ padding: 3px;
+ width: 80%;
+}
+
+div.admonition p.admonition-title, div.hint p.admonition-title,
+div.important p.admonition-title, div.note p.admonition-title,
+div.tip p.admonition-title {
+ text-align: center;
+ background-color: #999999;
+ display: block;
+ margin: 0;
+}
+
+div.attention p.admonition-title, div.caution p.admonition-title,
+div.danger p.admonition-title, div.error p.admonition-title,
+div.warning p.admonition-title {
+ color: #cc0000;
+ font-family: sans-serif;
+ text-align: center;
+ background-color: #999999;
+ display: block;
+ margin: 0;
+}
+
+h1, h2, h3, h4, h5, h6 {
+ font-family: Helvetica, Arial, sans-serif;
+ border: thin solid black;
+ /* This makes the borders rounded on Mozilla, which pleases me */
+ -moz-border-radius: 8px;
+ padding: 4px;
+}
+
+h1 {
+ background-color: #444499;
+ color: #ffffff;
+ border: medium solid black;
+}
+
+h1 a.toc-backref, h2 a.toc-backref {
+ color: #ffffff;
+}
+
+h2 {
+ background-color: #666666;
+ color: #ffffff;
+ border: medium solid black;
+}
+
+h3, h4, h5, h6 {
+ background-color: #cccccc;
+ color: #000000;
+}
+
+h3 a.toc-backref, h4 a.toc-backref, h5 a.toc-backref,
+h6 a.toc-backref {
+ color: #000000;
+}
+
+h1.title {
+ text-align: center;
+ background-color: #444499;
+ color: #eeeeee;
+ border: thick solid black;
+ -moz-border-radius: 20px;
+}
+
+table.footnote {
+ padding-left: 0.5ex;
+}
+
+table.citation {
+ padding-left: 0.5ex
+}
+
+pre.literal-block, pre.doctest-block {
+ border: thin black solid;
+ padding: 5px;
+}
+
+.image img { border-style : solid;
+ border-width : 2px;
+}
+
+h1 tt, h2 tt, h3 tt, h4 tt, h5 tt, h6 tt {
+ font-size: 100%;
+}
+
+code, tt {
+ color: #000066;
+}
+
+
+</style>
+</head>
+<body>
+<div class="document" id="pyshp">
+<h1 class="title">PyShp</h1>
+<table class="docinfo" frame="void" rules="none">
+<col class="docinfo-name" />
+<col class="docinfo-content" />
+<tbody valign="top">
+<tr><th class="docinfo-name">Author:</th>
+<td>Joel Lawhead - <a class="last reference external" href="mailto:jlawhead@geospatialpython.com">jlawhead@geospatialpython.com</a></td></tr>
+</tbody>
+</table>
+<p>:Version 1.2.1</p>
+<table class="docutils field-list" frame="void" rules="none">
+<col class="field-name" />
+<col class="field-body" />
+<tbody valign="top">
+<tr class="field"><th class="field-name">Revised:</th><td class="field-body">May 11, 2014</td>
+</tr>
+</tbody>
+</table>
+<div class="contents topic" id="contents">
+<p class="topic-title first">Contents</p>
+<ul class="simple">
+<li><a class="reference internal" href="#overview" id="id1">Overview</a></li>
+<li><a class="reference internal" href="#examples" id="id2">Examples</a><ul>
+<li><a class="reference internal" href="#reading-shapefiles" id="id3">Reading Shapefiles</a><ul>
+<li><a class="reference internal" href="#reading-shapefiles-from-file-like-objects" id="id4">Reading Shapefiles from File-Like Objects</a></li>
+<li><a class="reference internal" href="#reading-geometry" id="id5">Reading Geometry</a></li>
+<li><a class="reference internal" href="#reading-records" id="id6">Reading Records</a></li>
+<li><a class="reference internal" href="#reading-geometry-and-records-simultaneously" id="id7">Reading Geometry and Records Simultaneously</a></li>
+</ul>
+</li>
+<li><a class="reference internal" href="#writing-shapefiles" id="id8">Writing Shapefiles</a><ul>
+<li><a class="reference internal" href="#setting-the-shape-type" id="id9">Setting the Shape Type</a></li>
+<li><a class="reference internal" href="#geometry-and-record-balancing" id="id10">Geometry and Record Balancing</a></li>
+<li><a class="reference internal" href="#adding-geometry" id="id11">Adding Geometry</a></li>
+<li><a class="reference internal" href="#creating-attributes" id="id12">Creating Attributes</a></li>
+<li><a class="reference internal" href="#file-names" id="id13">File Names</a></li>
+<li><a class="reference internal" href="#saving-to-file-like-objects" id="id14">Saving to File-Like Objects</a></li>
+</ul>
+</li>
+<li><a class="reference internal" href="#editing-shapefiles" id="id15">Editing Shapefiles</a></li>
+<li><a class="reference internal" href="#python-geo-interface" id="id16">Python __geo_interface__</a></li>
+</ul>
+</li>
+</ul>
+</div>
+<div class="section" id="overview">
+<h1><a class="toc-backref" href="#id1">Overview</a></h1>
+<p>PyShp provides read and write support for the Esri
+Shapefile format. The Shapefile format is a popular Geographic Information
+System vector data format created by Esri. For more information about this format
+please read the well-written "ESRI Shapefile Technical Description - July 1998"
+located at <a class="reference external" href="http://www.esri.com/library/whitepapers/pdfs/shapefile.pdf">http://www.esri.com/library/whitepapers/pdfs/shapefile.pdf</a>.
+The Esri document describes the shp and shx file formats. However a third file
+format called dbf is also required. This format is documented on the web as the
+"XBase File Format Description" and is a simple file-based database format created
+in the 1960's. For more on this specification see:
+<a class="reference external" href="http://www.clicketyclick.dk/databases/xbase/format/index.html">http://www.clicketyclick.dk/databases/xbase/format/index.html</a></p>
+<p>Both the Esri and XBase file-formats are very simple in design and
+memory efficient which is part of the reason the shapefile format remains popular
+despite the numerous ways to store and exchange GIS data available today.</p>
+<p>Pyshp is compatible with Python 2.4-3.x.</p>
+<p>This document provides examples for using PyShp to read and write shapefiles.</p>
+<p>Currently the sample census blockgroup shapefile referenced in the examples is
+only available on the google code project site at <a class="reference external" href="http://code.google.com/p/pyshp">http://code.google.com/p/pyshp</a>.
+These examples are straight-forward and you can also easily run them against your
+own shapefiles manually with minimal modification. Other examples for specific
+topics are continually added to the pyshp wiki on google code and the blog
+<a class="reference external" href="http://GeospatialPython.com">http://GeospatialPython.com</a>.</p>
+<p>Important: For information about map projections, shapefiles,
+and Python please visit: <a class="reference external" href="http://code.google.com/p/pyshp/wiki/MapProjections">http://code.google.com/p/pyshp/wiki/MapProjections</a></p>
+<p>I sincerely hope this library eliminates the mundane distraction of simply
+reading and writing data, and allows you to focus on the challenging and FUN
+part of your geospatial project.</p>
+</div>
+<div class="section" id="examples">
+<h1><a class="toc-backref" href="#id2">Examples</a></h1>
+<p>Before doing anything you must import the library.</p>
+<pre class="doctest-block">
+>>> import shapefile
+</pre>
+<p>The examples below will use a shapefile created from the U.S. Census Bureau
+Blockgroups data set near San Francisco, CA and available in the subversion
+repository of the pyshp google code site.</p>
+<div class="section" id="reading-shapefiles">
+<h2><a class="toc-backref" href="#id3">Reading Shapefiles</a></h2>
+<p>To read a shapefile create a new "Reader" object and pass it the name of an
+existing shapefile. The shapefile format is acutally a collection of three
+files. You specify the base filename of the shapefile or the complete filename
+of any of the shapefile component files.</p>
+<pre class="doctest-block">
+>>> sf = shapefile.Reader("shapefiles/blockgroups")
+</pre>
+<p>OR</p>
+<pre class="doctest-block">
+>>> sf = shapefile.Reader("shapefiles/blockgroups.shp")
+</pre>
+<p>OR</p>
+<pre class="doctest-block">
+>>> sf = shapefile.Reader("shapefiles/blockgroups.dbf")
+</pre>
+<p>OR any of the other 5+ formats which are potentially part of a shapefile.
+The library does not care about extensions.</p>
+<div class="section" id="reading-shapefiles-from-file-like-objects">
+<h3><a class="toc-backref" href="#id4">Reading Shapefiles from File-Like Objects</a></h3>
+<p>You can also load shapefiles from any Python file-like object using keyword
+arguments to specify any of the three files. This feature is very powerful
+and allows you to load shapefiles from a url, from a zip file, serialized
+object, or in some cases a database.</p>
+<pre class="doctest-block">
+>>> myshp = open("shapefiles/blockgroups.shp", "rb")
+>>> mydbf = open("shapefiles/blockgroups.dbf", "rb")
+>>> r = shapefile.Reader(shp=myshp, dbf=mydbf)
+</pre>
+<p>Notice in the examples above the shx file is never used. The shx file is a
+very simple fixed-record index for the variable length records in the shp file.
+This file is optional for reading. If it's available pyshp will use the shx file
+to access shape records a little faster but will do just fine without it.</p>
+</div>
+<div class="section" id="reading-geometry">
+<h3><a class="toc-backref" href="#id5">Reading Geometry</a></h3>
+<p>A shapefile's geometry is the collection of points or shapes made from verticies
+and implied arcs representing physical locations. All types of shapefiles
+just store points. The metadata about the points determine how they are handled by
+software.</p>
+<p>You can get the a list of the shapefile's geometry by calling the shapes()
+method.</p>
+<pre class="doctest-block">
+>>> shapes = sf.shapes()
+</pre>
+<p>The shapes method returns a list of Shape objects describing the
+geometry of each shape record.</p>
+<pre class="doctest-block">
+>>> len(shapes)
+663
+</pre>
+<p>You can iterate through the shapefile's geometry using the iterShapes() method.</p>
+<pre class="doctest-block">
+>>> len(list(sf.iterShapes()))
+663
+</pre>
+<p>Each shape record contains the following attributes:</p>
+<pre class="doctest-block">
+>>> for name in dir(shapes[3]):
+... if not name.startswith('__'):
+... name
+'bbox'
+'parts'
+'points'
+'shapeType'
+</pre>
+<blockquote>
+<ul class="simple">
+<li>shapeType: an integer representing the type of shape as defined by the
+shapefile specification.</li>
+</ul>
+</blockquote>
+<pre class="doctest-block">
+>>> shapes[3].shapeType
+5
+</pre>
+<blockquote>
+<ul class="simple">
+<li>bbox: If the shape type contains multiple points this tuple describes the
+lower left (x,y) coordinate and upper right corner coordinate creating a
+complete box around the points. If the shapeType is a Null
+(shapeType == 0) then an AttributeError is raised.</li>
+</ul>
+</blockquote>
+<pre class="doctest-block">
+>>> # Get the bounding box of the 4th shape.
+>>> # Round coordinates to 3 decimal places
+>>> bbox = shapes[3].bbox
+>>> ['%.3f' % coord for coord in bbox]
+['-122.486', '37.787', '-122.446', '37.811']
+</pre>
+<blockquote>
+<ul class="simple">
+<li>parts: Parts simply group collections of points into shapes. If the shape record
+has multiple parts this attribute contains the index of the first point of each part.
+If there is only one part then a list containing 0 is returned.</li>
+</ul>
+</blockquote>
+<pre class="doctest-block">
+>>> shapes[3].parts
+[0]
+</pre>
+<blockquote>
+<ul class="simple">
+<li>points: The points attribute contains a list of tuples containing an (x,y)
+coordinate for each point in the shape.</li>
+</ul>
+</blockquote>
+<pre class="doctest-block">
+>>> len(shapes[3].points)
+173
+>>> # Get the 8th point of the fourth shape
+>>> # Truncate coordinates to 3 decimal places
+>>> shape = shapes[3].points[7]
+>>> ['%.3f' % coord for coord in shape]
+['-122.471', '37.787']
+</pre>
+<p>To read a single shape by calling its index use the shape() method. The index
+is the shape's count from 0. So to read the 8th shape record you would
+use its index which is 7.</p>
+<pre class="doctest-block">
+>>> s = sf.shape(7)
+</pre>
+<pre class="doctest-block">
+>>> # Read the bbox of the 8th shape to verify
+>>> # Round coordinates to 3 decimal places
+>>> ['%.3f' % coord for coord in s.bbox]
+['-122.450', '37.801', '-122.442', '37.808']
+</pre>
+</div>
+<div class="section" id="reading-records">
+<h3><a class="toc-backref" href="#id6">Reading Records</a></h3>
+<p>A record in a shapefile contains the attributes for each shape in the
+collection of geometry. Records are stored in the dbf file. The link
+between geometry and attributes is the foundation of Geographic Information
+Systems. This critical link is implied by the order of shapes and
+corresponding records in the shp geometry file and the dbf attribute file.</p>
+<p>The field names of a shapefile are available as soon as you read a shapefile.
+You can call the "fields" attribute of the shapefile as a Python list. Each
+field is a Python list with the following information:</p>
+<ul class="simple">
+<li>Field name: the name describing the data at this column index.</li>
+<li>Field type: the type of data at this column index. Types can be: Character, Numbers, Longs, Dates, or Memo.
+The "Memo" type has no meaning within a GIS and is part of the xbase spec instead.</li>
+<li>Field length: the length of the data found at this column index. Older GIS software may truncate this
+length to 8 or 11 characters for "Character" fields.</li>
+<li>Decimal length: the number of decimal places found in "Number" fields.</li>
+</ul>
+<p>To see the fields for the Reader object above (sf) call the "fields" attribute:</p>
+<pre class="doctest-block">
+>>> fields = sf.fields
+</pre>
+<pre class="doctest-block">
+>>> assert fields == [("DeletionFlag", "C", 1, 0), ["AREA", "N", 18, 5],
+... ["BKG_KEY", "C", 12, 0], ["POP1990", "N", 9, 0], ["POP90_SQMI", "N", 10, 1],
+... ["HOUSEHOLDS", "N", 9, 0],
+... ["MALES", "N", 9, 0], ["FEMALES", "N", 9, 0], ["WHITE", "N", 9, 0],
+... ["BLACK", "N", 8, 0], ["AMERI_ES", "N", 7, 0], ["ASIAN_PI", "N", 8, 0],
+... ["OTHER", "N", 8, 0], ["HISPANIC", "N", 8, 0], ["AGE_UNDER5", "N", 8, 0],
+... ["AGE_5_17", "N", 8, 0], ["AGE_18_29", "N", 8, 0], ["AGE_30_49", "N", 8, 0],
+... ["AGE_50_64", "N", 8, 0], ["AGE_65_UP", "N", 8, 0],
+... ["NEVERMARRY", "N", 8, 0], ["MARRIED", "N", 9, 0], ["SEPARATED", "N", 7, 0],
+... ["WIDOWED", "N", 8, 0], ["DIVORCED", "N", 8, 0], ["HSEHLD_1_M", "N", 8, 0],
+... ["HSEHLD_1_F", "N", 8, 0], ["MARHH_CHD", "N", 8, 0],
+... ["MARHH_NO_C", "N", 8, 0], ["MHH_CHILD", "N", 7, 0],
+... ["FHH_CHILD", "N", 7, 0], ["HSE_UNITS", "N", 9, 0], ["VACANT", "N", 7, 0],
+... ["OWNER_OCC", "N", 8, 0], ["RENTER_OCC", "N", 8, 0],
+... ["MEDIAN_VAL", "N", 7, 0], ["MEDIANRENT", "N", 4, 0],
+... ["UNITS_1DET", "N", 8, 0], ["UNITS_1ATT", "N", 7, 0], ["UNITS2", "N", 7, 0],
+... ["UNITS3_9", "N", 8, 0], ["UNITS10_49", "N", 8, 0],
+... ["UNITS50_UP", "N", 8, 0], ["MOBILEHOME", "N", 7, 0]]
+</pre>
+<p>You can get a list of the shapefile's records by calling the records() method:</p>
+<pre class="doctest-block">
+>>> records = sf.records()
+</pre>
+<pre class="doctest-block">
+>>> len(records)
+663
+</pre>
+<p>Similar to the geometry methods, you can iterate through dbf records using the
+recordsIter() method.</p>
+<pre class="doctest-block">
+>>> len(list(sf.iterRecords()))
+663
+</pre>
+<p>Each record is a list containing an attribute corresponding to each field in the
+field list.</p>
+<p>For example in the 4th record of the blockgroups shapefile the 2nd and 3rd
+fields are the blockgroup id and the 1990 population count of
+that San Francisco blockgroup:</p>
+<pre class="doctest-block">
+>>> records[3][1:3]
+['060750601001', 4715]
+</pre>
+<p>To read a single record call the record() method with the record's index:</p>
+<pre class="doctest-block">
+>>> rec = sf.record(3)
+</pre>
+<pre class="doctest-block">
+>>> rec[1:3]
+['060750601001', 4715]
+</pre>
+</div>
+<div class="section" id="reading-geometry-and-records-simultaneously">
+<h3><a class="toc-backref" href="#id7">Reading Geometry and Records Simultaneously</a></h3>
+<p>You way want to examine both the geometry and the attributes for a record at the
+same time. The shapeRecord() and shapeRecords() method let you do just that.</p>
+<p>Calling the shapeRecords() method will return the geometry and attributes for
+all shapes as a list of ShapeRecord objects. Each ShapeRecord instance has a
+"shape" and "record" attribute. The shape attribute is a ShapeRecord object as
+dicussed in the first section "Reading Geometry". The record attribute is a
+list of field values as demonstrated in the "Reading Records" section.</p>
+<pre class="doctest-block">
+>>> shapeRecs = sf.shapeRecords()
+</pre>
+<p>Let's read the blockgroup key and the population for the 4th blockgroup:
+>>> shapeRecs[3].record[1:3]
+['060750601001', 4715]</p>
+<p>Now let's read the first two points for that same record:</p>
+<pre class="doctest-block">
+>>> points = shapeRecs[3].shape.points[0:2]
+</pre>
+<pre class="doctest-block">
+>>> len(points)
+2
+</pre>
+<p>The shapeRec() method reads a single shape/record pair at the specified index.
+To get the 4th shape record from the blockgroups shapfile use the third index:</p>
+<pre class="doctest-block">
+>>> shapeRec = sf.shapeRecord(3)
+</pre>
+<p>The blockgroup key and population count:</p>
+<pre class="doctest-block">
+>>> shapeRec.record[1:3]
+['060750601001', 4715]
+</pre>
+<pre class="doctest-block">
+>>> points = shapeRec.shape.points[0:2]
+</pre>
+<pre class="doctest-block">
+>>> len(points)
+2
+</pre>
+</div>
+</div>
+<div class="section" id="writing-shapefiles">
+<h2><a class="toc-backref" href="#id8">Writing Shapefiles</a></h2>
+<p>PyShp tries to be as flexible as possible when writing shapefiles while
+maintaining some degree of automatic validation to make sure you don't
+accidentally write an invalid file.</p>
+<p>PyShp can write just one of the component files such as the shp or dbf file
+without writing the others. So in addition to being a complete
+shapefile library, it can also be used as a basic dbf (xbase) library. Dbf files are
+a common database format which are often useful as a standalone simple
+database format. And even shp files occasionaly have uses as a standalone
+format. Some web-based GIS systems use an user-uploaded shp file to specify
+an area of interest. Many precision agriculture chemical field sprayers also
+use the shp format as a control file for the sprayer system (usually in
+combination with custom database file formats).</p>
+<p>To create a shapefile you add geometry and/or attributes using methods in the
+Writer class until you are ready to save the file.</p>
+<p>Create an instance of the Writer class to begin creating a shapefile:</p>
+<pre class="doctest-block">
+>>> w = shapefile.Writer()
+</pre>
+<div class="section" id="setting-the-shape-type">
+<h3><a class="toc-backref" href="#id9">Setting the Shape Type</a></h3>
+<p>The shape type defines the type of geometry contained in the shapefile. All of
+the shapes must match the shape type setting.</p>
+<p>Shape types are represented by numbers between 0 and 31 as defined by the
+shapefile specification. It is important to note that numbering system has
+several reserved numbers which have not been used yet therefore the numbers of
+the existing shape types are not sequential.</p>
+<p>You can reference shape types by the numbers or by constants defined by PyShp:
+shapefile.NULL = 0
+shapefile.POINT = 1
+shapefile.POLYLINE = 3
+shapefile.POLYGON = 5
+shapefile.MULTIPOINT = 8
+shapefile.POINTZ = 11
+shapefile.POLYLINEZ = 13
+shapefile.POLYGONZ = 15
+shapefile.MULTIPOINTZ = 18
+shapefile.POINTM = 21
+shapefile.POLYLINEM = 23
+shapefile.POLYGONM = 25
+shapefile.MULTIPOINTM = 28
+shapefile.MULTIPATCH = 31</p>
+<p>There are three ways to set the shape type:
+- Set it when creating the class instance.
+- Set it by assigning a value to an existing class instance.
+- Set it automatically to the type of the first shape by saving the shapefile.</p>
+<p>To manually set the shape type for a Writer object when creating the Writer:</p>
+<pre class="doctest-block">
+>>> w = shapefile.Writer(shapeType=1)
+</pre>
+<p>or we can use the constants as explained above:</p>
+<pre class="doctest-block">
+>>> w = shapefile.Writer(shapefile.POINT)
+</pre>
+<p>As you can see, specifying the shapeType argument explicitly isn't necessary.</p>
+<pre class="doctest-block">
+>>> w.shapeType
+1
+</pre>
+<p>OR you can set it after the Writer is created by changing the property:</p>
+<pre class="doctest-block">
+>>> w.shapeType = 3
+</pre>
+<pre class="doctest-block">
+>>> w.shapeType
+3
+</pre>
+</div>
+<div class="section" id="geometry-and-record-balancing">
+<h3><a class="toc-backref" href="#id10">Geometry and Record Balancing</a></h3>
+<p>Because every shape must have a corresponding record it is critical that the
+number of records equals the number of shapes to create a valid shapefile. To
+help prevent accidental misalignment PyShp has an "auto balance" feature to
+make sure when you add either a shape or a record the two sides of the
+equation line up. This feature is NOT turned on by default. To activate it
+set the attribute autoBalance to 1 (True):</p>
+<pre class="doctest-block">
+>>> w.autoBalance = 1
+</pre>
+<p>You also have the option of manually calling the balance() method each time you
+add a shape or a record to ensure the other side is up to date. When balancing
+is used null shapes are created on the geometry side or a record with a value of
+"NULL" for each field is created on the attribute side.</p>
+<p>The balancing option gives you flexibility in how you build the shapefile.</p>
+<p>Without auto balancing you can add geometry or records at anytime. You can
+create all of the shapes and then create all of the records or vice versa. You
+can use the balance method after creating a shape or record each time and make
+updates later. If you do not use the balance method and forget to manually
+balance the geometry and attributes the shapefile will be viewed as corrupt by
+most shapefile software.</p>
+<p>With auto balanacing you can add either shapes or geometry and update blank
+entries on either side as needed. Even if you forget to update an entry the
+shapefile will still be valid and handled correctly by most shapefile software.</p>
+</div>
+<div class="section" id="adding-geometry">
+<h3><a class="toc-backref" href="#id11">Adding Geometry</a></h3>
+<p>Geometry is added using one of three methods: "null", "point", or "poly". The "null"
+method is used for null shapes, "point" is used for point shapes, and "poly" is
+used for everything else.</p>
+<p><strong>Adding a Null shape</strong></p>
+<p>Because Null shape types (shape type 0) have no geometry the "null" method is
+called without any arguments.</p>
+<pre class="doctest-block">
+>>> w = shapefile.Writer()
+</pre>
+<pre class="doctest-block">
+>>> w.null()
+</pre>
+<p>The writer object's shapes list will now have one null shape:</p>
+<pre class="doctest-block">
+>>> assert w.shapes()[0].shapeType == shapefile.NULL
+</pre>
+<p><strong>Adding a Point shape</strong></p>
+<p>Point shapes are added using the "point" method. A point is specified by an
+x, y, and optional z (elevation) and m (measure) value.</p>
+<pre class="doctest-block">
+>>> w = shapefile.Writer(shapefile.POINT)
+</pre>
+<pre class="doctest-block">
+>>> w.point(122, 37) # No elevation or measure values
+</pre>
+<pre class="doctest-block">
+>>> w.shapes()[0].points
+[[122, 37, 0, 0]]
+</pre>
+<pre class="doctest-block">
+>>> w.point(118, 36, 4, 8)
+</pre>
+<pre class="doctest-block">
+>>> w.shapes()[1].points
+[[118, 36, 4, 8]]
+</pre>
+<p><strong>Adding a Poly Shape</strong></p>
+<p>"Poly" shapes can be either polygons or lines. Shapefile polygons must have at
+least 4 points and the last point must be the same as the first. PyShp automatically
+enforces closed polygons.
+A line must have at least two points.
+Because of the similarities between these two shape types they are created using
+a single method called "poly".</p>
+<pre class="doctest-block">
+>>> w = shapefile.Writer(shapefile.POLYGON)
+</pre>
+<pre class="doctest-block">
+>>> w.poly(shapeType=3, parts=[[[122,37,4,9], [117,36,3,4]], [[115,32,8,8],
+... [118,20,6,4], [113,24]]])
+</pre>
+<p><strong>Adding a Polygon with Rings</strong></p>
+<p>Polygons consist of rings which mean they are closed. The first point and last point
+of a ring must be the same. PyShp enforces ring closure if the ring is incomplete when
+you add the shape. Polygons can have inner rings which create holes. Holes are defined
+by the order of the points. Normally points in a ring run clockwise. If the points
+run counter-clockwise then they form a hole. If you don't order the points correctly
+you'll just have overlapping polygons.</p>
+<pre class="doctest-block">
+>>> w = shapefile.Writer(shapefile.POLYGON)
+>>> outer_ring = [[10,10],[50,50],[100,10],[50,-50],[10,10]]
+>>> inner_ring = [[40,10],[50,30],[70,10],[50,-30],[40,10]]
+>>> inner_ring.reverse()
+</pre>
+<p>You can use the "shapefile.signed_area()" method to determine if a ring is clockwise
+or counter-clockwise. A value >= 0 means the ring is counter-clockwise and < 0 means
+the ring is clockwise. The value returned is also the area of the polygon.</p>
+<pre class="doctest-block">
+>>> # Clockwise ring
+... shapefile.signed_area(outer_ring)
+-4500.0
+>>> # Counter-clockwise ring
+... shapefile.signed_area(inner_ring)
+900.0
+</pre>
+<p><strong>Creating 3D Polygons</strong></p>
+<p>Elevation values, known as "Z" values allow you to create 3-dimensional shapefiles. The
+z value is an extra value specified as part of a point.</p>
+<pre class="doctest-block">
+>>> w = shapefile.Writer(shapeType=shapefile.POLYGONZ)
+>>> w.poly([[[-89.0, 33, 12], [-90, 31, 11], [-91, 30, 12]]], shapeType=15)
+>>> w.field("NAME")
+>>> w.record("PolyZTest")
+>>> w.save("shapefiles/test/MyPolyZ")
+</pre>
+<p>The z values are stored in a seperate shape attribute.</p>
+<pre class="doctest-block">
+>>> r = shapefile.Reader("shapefiles/test/MyPolyZ")
+>>> s = r.shape(0)
+>>> s.points
+[[-89.0, 33.0], [-90.0, 31.0], [-91.0, 30.0], [-89.0, 33.0]]
+>>> s.z
+[12.0, 11.0, 12.0, 12.0]
+</pre>
+</div>
+<div class="section" id="creating-attributes">
+<h3><a class="toc-backref" href="#id12">Creating Attributes</a></h3>
+<p>Creating attributes involves two steps. Step 1 is to create fields to contain
+attribute values and step 2 is to populate the fields with values for each
+shape record.</p>
+<p>The following attempts to create a complete shapefile:</p>
+<pre class="doctest-block">
+>>> w = shapefile.Writer(shapefile.POINT)
+>>> w.point(1,1)
+>>> w.point(3,1)
+>>> w.point(4,3)
+>>> w.point(2,2)
+>>> w.field('FIRST_FLD')
+>>> w.field('SECOND_FLD','C','40')
+>>> w.record('First','Point')
+>>> w.record('Second','Point')
+>>> w.record('Third','Point')
+>>> w.record('Fourth','Point')
+>>> w.save('shapefiles/test/point')
+</pre>
+<pre class="doctest-block">
+>>> w = shapefile.Writer(shapefile.POLYGON)
+>>> w.poly(parts=[[[1,5],[5,5],[5,1],[3,3],[1,1]]])
+>>> w.field('FIRST_FLD','C','40')
+>>> w.field('SECOND_FLD','C','40')
+>>> w.record('First','Polygon')
+>>> w.save('shapefiles/test/polygon')
+</pre>
+<pre class="doctest-block">
+>>> w = shapefile.Writer(shapefile.POLYLINE)
+>>> w.line(parts=[[[1,5],[5,5],[5,1],[3,3],[1,1]]])
+>>> w.poly(parts=[[[1,3],[5,3]]], shapeType=shapefile.POLYLINE)
+>>> w.field('FIRST_FLD','C','40')
+>>> w.field('SECOND_FLD','C','40')
+>>> w.record('First','Line')
+>>> w.record('Second','Line')
+>>> w.save('shapefiles/test/line')
+</pre>
+<p>You can also add attributes using keyword arguments where the keys are field names.</p>
+<pre class="doctest-block">
+>>> w = shapefile.Writer(shapefile.POLYLINE)
+>>> w.line(parts=[[[1,5],[5,5],[5,1],[3,3],[1,1]]])
+>>> w.field('FIRST_FLD','C','40')
+>>> w.field('SECOND_FLD','C','40')
+>>> w.record(FIRST_FLD='First', SECOND_FLD='Line')
+>>> w.save('shapefiles/test/line')
+</pre>
+</div>
+<div class="section" id="file-names">
+<h3><a class="toc-backref" href="#id13">File Names</a></h3>
+<p>File extensions are optional when reading or writing shapfiles. If you specify them Pyshp
+ignores them anyway. When you save files you can specify a base file name that is used for
+all three file types. Or you can specify a nmae for one or more file types. In that case,
+any file types not assigned will not save and only file types with file names will be saved.
+If you do not specify any file names (i.e. save()), then a unique file name is generated with
+the prefix "shapefile_" followed by random characters which is used for all three files. The
+unique file name is returned as a string.</p>
+<pre class="doctest-block">
+>>> targetName = w.save()
+>>> assert("shapefile_" in targetName)
+</pre>
+</div>
+<div class="section" id="saving-to-file-like-objects">
+<h3><a class="toc-backref" href="#id14">Saving to File-Like Objects</a></h3>
+<p>Just as you can read shapefiles from python file-like objects you can also write them.</p>
+<pre class="doctest-block">
+>>> try:
+... from StringIO import StringIO
+... except ImportError:
+... from io import BytesIO as StringIO
+>>> shp = StringIO()
+>>> shx = StringIO()
+>>> dbf = StringIO()
+>>> w.saveShp(shp)
+>>> w.saveShx(shx)
+>>> w.saveDbf(dbf)
+>>> # Normally you would call the "StringIO.getvalue()" method on these objects.
+>>> shp = shx = dbf = None
+</pre>
+</div>
+</div>
+<div class="section" id="editing-shapefiles">
+<h2><a class="toc-backref" href="#id15">Editing Shapefiles</a></h2>
+<p>The Editor class attempts to make changing existing shapefiles easier by handling the reading and writing details behind the scenes.</p>
+<p>Let's add shapes to existing shapefiles:</p>
+<p>Add a point to a point shapefile</p>
+<pre class="doctest-block">
+>>> e = shapefile.Editor(shapefile="shapefiles/test/point.shp")
+>>> e.point(0,0,10,2)
+>>> e.record("Appended","Point")
+>>> # We added z and m values so
+>>> # change the shapetype
+>>> e.shapeType = shapefile.POINTZ
+>>> e.save('shapefiles/test/point')
+</pre>
+<p>Edit the appended point to change the "y" and "z" value</p>
+<pre class="doctest-block">
+>>> e = shapefile.Editor(shapefile="shapefiles/test/point.shp")
+>>> # Find the point by the attribute
+>>> for s in enumerate(e.records):
+... i, record = s
+... if record[0] == "Appended":
+... geom = e._shapes[i]
+... # Change the y value to 5
+... geom.points[0][1] = 5
+... # Change the z value to 9
+... if hasattr(geom, "z"):
+... geom.z = (9,)
+... else:
+... geom.points[0][2] = 9
+>>> e.save('shapefiles/test/point')
+</pre>
+<p>Add a new line to a line shapefile:</p>
+<pre class="doctest-block">
+>>> e = shapefile.Editor(shapefile="shapefiles/test/line.shp")
+>>> e.line(parts=[[[10,5],[15,5],[15,1],[13,3],[11,1]]])
+>>> e.record('Appended','Line')
+>>> e.save('shapefiles/test/line')
+>>> e = None
+</pre>
+<p>Add a new polygon to a polygon shapefile:</p>
+<pre class="doctest-block">
+>>> e = shapefile.Editor(shapefile="shapefiles/test/polygon.shp")
+>>> e.poly(parts=[[[5.1,5],[9.9,5],[9.9,1],[7.5,3],[5.1,1]]])
+>>> e.record("Appended","Polygon")
+>>> e.save('shapefiles/test/polygon')
+>>> e = None
+</pre>
+<p>Remove the first point in each shapefile - for a point shapefile that is
+the first shape and record"</p>
+<pre class="doctest-block">
+>>> e = shapefile.Editor(shapefile="shapefiles/test/point.shp")
+>>> e.delete(0)
+>>> e.save('shapefiles/test/point')
+>>> e = None
+</pre>
+<p>Remove the last shape in the polygon shapefile.</p>
+<pre class="doctest-block">
+>>> e = shapefile.Editor(shapefile="shapefiles/test/polygon.shp")
+>>> e.delete(-1)
+>>> e.save('shapefiles/test/polygon')
+>>> e = None
+</pre>
+</div>
+<div class="section" id="python-geo-interface">
+<h2><a class="toc-backref" href="#id16">Python __geo_interface__</a></h2>
+<p>The Python __geo_interface__ convention provides a data interchange interface
+among geospatial Python libraries. The interface returns data as GeoJSON.
+More information on the __geo_interface__ protocol can be found at:
+<a class="reference external" href="https://gist.github.com/sgillies/2217756">https://gist.github.com/sgillies/2217756</a>.
+More information on GeoJSON is available at <a class="reference external" href="http://geojson.org">http://geojson.org</a> <a class="reference external" href="http://geojson.org">http://geojson.org</a>.</p>
+<pre class="doctest-block">
+>>> s = sf.shape(0)
+>>> s.__geo_interface__["type"]
+'MultiPolygon'
+</pre>
+</div>
+</div>
+</div>
+</body>
+</html>
diff --git a/README.pdf b/README.pdf
new file mode 100644
index 0000000..690c33a
--- /dev/null
+++ b/README.pdf
@@ -0,0 +1,4130 @@
+%PDF-1.4
+%���� ReportLab Generated PDF document http://www.reportlab.com
+% 'BasicFonts': class PDFDictionary
+1 0 obj
+% The standard fonts dictionary
+<< /F1 2 0 R
+ /F2 3 0 R
+ /F3 43 0 R
+ /F4 44 0 R >>
+endobj
+% 'F1': class PDFType1Font
+2 0 obj
+% Font Helvetica
+<< /BaseFont /Helvetica
+ /Encoding /WinAnsiEncoding
+ /Name /F1
+ /Subtype /Type1
+ /Type /Font >>
+endobj
+% 'F2': class PDFType1Font
+3 0 obj
+% Font Helvetica-Bold
+<< /BaseFont /Helvetica-Bold
+ /Encoding /WinAnsiEncoding
+ /Name /F2
+ /Subtype /Type1
+ /Type /Font >>
+endobj
+% 'Annot.NUMBER1': class PDFDictionary
+4 0 obj
+<< /A << /S /URI
+ /Type /Action
+ /URI (mailto:jlawhead at geospatialpython.com) >>
+ /Border [ 0
+ 0
+ 0 ]
+ /Rect [ 224.3223
+ 719.7736
+ 371.2023
+ 731.7736 ]
+ /Subtype /Link
+ /Type /Annot >>
+endobj
+% 'Annot.NUMBER2': class LinkAnnotation
+5 0 obj
+<< /Border [ 0
+ 0
+ 0 ]
+ /Contents ()
+ /Dest [ 41 0 R
+ /XYZ
+ 62.69291
+ 338.0236
+ 0 ]
+ /Rect [ 62.69291
+ 623.7736
+ 107.1629
+ 635.7736 ]
+ /Subtype /Link
+ /Type /Annot >>
+endobj
+% 'Annot.NUMBER3': class LinkAnnotation
+6 0 obj
+<< /Border [ 0
+ 0
+ 0 ]
+ /Contents ()
+ /Dest [ 41 0 R
+ /XYZ
+ 62.69291
+ 338.0236
+ 0 ]
+ /Rect [ 527.0227
+ 623.7736
+ 532.5827
+ 635.7736 ]
+ /Subtype /Link
+ /Type /Annot >>
+endobj
+% 'Annot.NUMBER4': class LinkAnnotation
+7 0 obj
+<< /Border [ 0
+ 0
+ 0 ]
+ /Contents ()
+ /Dest [ 45 0 R
+ /XYZ
+ 62.69291
+ 699.0236
+ 0 ]
+ /Rect [ 62.69291
+ 605.7736
+ 109.3829
+ 617.7736 ]
+ /Subtype /Link
+ /Type /Annot >>
+endobj
+% 'Annot.NUMBER5': class LinkAnnotation
+8 0 obj
+<< /Border [ 0
+ 0
+ 0 ]
+ /Contents ()
+ /Dest [ 45 0 R
+ /XYZ
+ 62.69291
+ 699.0236
+ 0 ]
+ /Rect [ 527.0227
+ 605.7736
+ 532.5827
+ 617.7736 ]
+ /Subtype /Link
+ /Type /Annot >>
+endobj
+% 'Annot.NUMBER6': class LinkAnnotation
+9 0 obj
+<< /Border [ 0
+ 0
+ 0 ]
+ /Contents ()
+ /Dest [ 45 0 R
+ /XYZ
+ 62.69291
+ 582.8236
+ 0 ]
+ /Rect [ 82.69291
+ 587.7736
+ 169.4029
+ 599.7736 ]
+ /Subtype /Link
+ /Type /Annot >>
+endobj
+% 'Annot.NUMBER7': class LinkAnnotation
+10 0 obj
+<< /Border [ 0
+ 0
+ 0 ]
+ /Contents ()
+ /Dest [ 45 0 R
+ /XYZ
+ 62.69291
+ 582.8236
+ 0 ]
+ /Rect [ 527.0227
+ 587.7736
+ 532.5827
+ 599.7736 ]
+ /Subtype /Link
+ /Type /Annot >>
+endobj
+% 'Annot.NUMBER8': class LinkAnnotation
+11 0 obj
+<< /Border [ 0
+ 0
+ 0 ]
+ /Contents ()
+ /Dest [ 45 0 R
+ /XYZ
+ 62.69291
+ 339.2236
+ 0 ]
+ /Rect [ 102.6929
+ 569.7736
+ 289.4229
+ 581.7736 ]
+ /Subtype /Link
+ /Type /Annot >>
+endobj
+% 'Annot.NUMBER9': class LinkAnnotation
+12 0 obj
+<< /Border [ 0
+ 0
+ 0 ]
+ /Contents ()
+ /Dest [ 45 0 R
+ /XYZ
+ 62.69291
+ 339.2236
+ 0 ]
+ /Rect [ 527.0227
+ 569.7736
+ 532.5827
+ 581.7736 ]
+ /Subtype /Link
+ /Type /Annot >>
+endobj
+% 'Annot.NUMBER10': class LinkAnnotation
+13 0 obj
+<< /Border [ 0
+ 0
+ 0 ]
+ /Contents ()
+ /Dest [ 45 0 R
+ /XYZ
+ 62.69291
+ 169.0236
+ 0 ]
+ /Rect [ 102.6929
+ 551.7736
+ 186.6129
+ 563.7736 ]
+ /Subtype /Link
+ /Type /Annot >>
+endobj
+% 'Annot.NUMBER11': class LinkAnnotation
+14 0 obj
+<< /Border [ 0
+ 0
+ 0 ]
+ /Contents ()
+ /Dest [ 45 0 R
+ /XYZ
+ 62.69291
+ 169.0236
+ 0 ]
+ /Rect [ 527.0227
+ 551.7736
+ 532.5827
+ 563.7736 ]
+ /Subtype /Link
+ /Type /Annot >>
+endobj
+% 'Annot.NUMBER12': class LinkAnnotation
+15 0 obj
+<< /Border [ 0
+ 0
+ 0 ]
+ /Contents ()
+ /Dest [ 47 0 R
+ /XYZ
+ 62.69291
+ 545.4236
+ 0 ]
+ /Rect [ 102.6929
+ 533.7736
+ 179.9429
+ 545.7736 ]
+ /Subtype /Link
+ /Type /Annot >>
+endobj
+% 'Annot.NUMBER13': class LinkAnnotation
+16 0 obj
+<< /Border [ 0
+ 0
+ 0 ]
+ /Contents ()
+ /Dest [ 47 0 R
+ /XYZ
+ 62.69291
+ 545.4236
+ 0 ]
+ /Rect [ 527.0227
+ 533.7736
+ 532.5827
+ 545.7736 ]
+ /Subtype /Link
+ /Type /Annot >>
+endobj
+% 'Annot.NUMBER14': class LinkAnnotation
+17 0 obj
+<< /Border [ 0
+ 0
+ 0 ]
+ /Contents ()
+ /Dest [ 48 0 R
+ /XYZ
+ 62.69291
+ 358.6236
+ 0 ]
+ /Rect [ 102.6929
+ 515.7736
+ 316.6629
+ 527.7736 ]
+ /Subtype /Link
+ /Type /Annot >>
+endobj
+% 'Annot.NUMBER15': class LinkAnnotation
+18 0 obj
+<< /Border [ 0
+ 0
+ 0 ]
+ /Contents ()
+ /Dest [ 48 0 R
+ /XYZ
+ 62.69291
+ 358.6236
+ 0 ]
+ /Rect [ 527.0227
+ 515.7736
+ 532.5827
+ 527.7736 ]
+ /Subtype /Link
+ /Type /Annot >>
+endobj
+% 'Annot.NUMBER16': class LinkAnnotation
+19 0 obj
+<< /Border [ 0
+ 0
+ 0 ]
+ /Contents ()
+ /Dest [ 49 0 R
+ /XYZ
+ 62.69291
+ 552.2236
+ 0 ]
+ /Rect [ 82.69291
+ 497.7736
+ 163.2729
+ 509.7736 ]
+ /Subtype /Link
+ /Type /Annot >>
+endobj
+% 'Annot.NUMBER17': class LinkAnnotation
+20 0 obj
+<< /Border [ 0
+ 0
+ 0 ]
+ /Contents ()
+ /Dest [ 49 0 R
+ /XYZ
+ 62.69291
+ 552.2236
+ 0 ]
+ /Rect [ 527.0227
+ 497.7736
+ 532.5827
+ 509.7736 ]
+ /Subtype /Link
+ /Type /Annot >>
+endobj
+% 'Annot.NUMBER18': class LinkAnnotation
+21 0 obj
+<< /Border [ 0
+ 0
+ 0 ]
+ /Contents ()
+ /Dest [ 49 0 R
+ /XYZ
+ 62.69291
+ 321.0236
+ 0 ]
+ /Rect [ 102.6929
+ 479.7736
+ 207.2029
+ 491.7736 ]
+ /Subtype /Link
+ /Type /Annot >>
+endobj
+% 'Annot.NUMBER19': class LinkAnnotation
+22 0 obj
+<< /Border [ 0
+ 0
+ 0 ]
+ /Contents ()
+ /Dest [ 49 0 R
+ /XYZ
+ 62.69291
+ 321.0236
+ 0 ]
+ /Rect [ 527.0227
+ 479.7736
+ 532.5827
+ 491.7736 ]
+ /Subtype /Link
+ /Type /Annot >>
+endobj
+% 'Annot.NUMBER20': class LinkAnnotation
+23 0 obj
+<< /Border [ 0
+ 0
+ 0 ]
+ /Contents ()
+ /Dest [ 50 0 R
+ /XYZ
+ 62.69291
+ 511.0236
+ 0 ]
+ /Rect [ 102.6929
+ 461.7736
+ 247.7529
+ 473.7736 ]
+ /Subtype /Link
+ /Type /Annot >>
+endobj
+% 'Annot.NUMBER21': class LinkAnnotation
+24 0 obj
+<< /Border [ 0
+ 0
+ 0 ]
+ /Contents ()
+ /Dest [ 50 0 R
+ /XYZ
+ 62.69291
+ 511.0236
+ 0 ]
+ /Rect [ 527.0227
+ 461.7736
+ 532.5827
+ 473.7736 ]
+ /Subtype /Link
+ /Type /Annot >>
+endobj
+% 'Annot.NUMBER22': class LinkAnnotation
+25 0 obj
+<< /Border [ 0
+ 0
+ 0 ]
+ /Contents ()
+ /Dest [ 50 0 R
+ /XYZ
+ 62.69291
+ 226.8236
+ 0 ]
+ /Rect [ 102.6929
+ 443.7736
+ 180.5029
+ 455.7736 ]
+ /Subtype /Link
+ /Type /Annot >>
+endobj
+% 'Annot.NUMBER23': class LinkAnnotation
+26 0 obj
+<< /Border [ 0
+ 0
+ 0 ]
+ /Contents ()
+ /Dest [ 50 0 R
+ /XYZ
+ 62.69291
+ 226.8236
+ 0 ]
+ /Rect [ 527.0227
+ 443.7736
+ 532.5827
+ 455.7736 ]
+ /Subtype /Link
+ /Type /Annot >>
+endobj
+% 'Annot.NUMBER24': class LinkAnnotation
+27 0 obj
+<< /Border [ 0
+ 0
+ 0 ]
+ /Contents ()
+ /Dest [ 52 0 R
+ /XYZ
+ 62.69291
+ 423.4236
+ 0 ]
+ /Rect [ 102.6929
+ 425.7736
+ 185.5029
+ 437.7736 ]
+ /Subtype /Link
+ /Type /Annot >>
+endobj
+% 'Annot.NUMBER25': class LinkAnnotation
+28 0 obj
+<< /Border [ 0
+ 0
+ 0 ]
+ /Contents ()
+ /Dest [ 52 0 R
+ /XYZ
+ 62.69291
+ 423.4236
+ 0 ]
+ /Rect [ 527.0227
+ 425.7736
+ 532.5827
+ 437.7736 ]
+ /Subtype /Link
+ /Type /Annot >>
+endobj
+% 'Annot.NUMBER26': class LinkAnnotation
+29 0 obj
+<< /Border [ 0
+ 0
+ 0 ]
+ /Contents ()
+ /Dest [ 53 0 R
+ /XYZ
+ 62.69291
+ 530.6236
+ 0 ]
+ /Rect [ 102.6929
+ 407.7736
+ 153.2529
+ 419.7736 ]
+ /Subtype /Link
+ /Type /Annot >>
+endobj
+% 'Annot.NUMBER27': class LinkAnnotation
+30 0 obj
+<< /Border [ 0
+ 0
+ 0 ]
+ /Contents ()
+ /Dest [ 53 0 R
+ /XYZ
+ 62.69291
+ 530.6236
+ 0 ]
+ /Rect [ 521.4627
+ 407.7736
+ 532.5827
+ 419.7736 ]
+ /Subtype /Link
+ /Type /Annot >>
+endobj
+% 'Annot.NUMBER28': class LinkAnnotation
+31 0 obj
+<< /Border [ 0
+ 0
+ 0 ]
+ /Contents ()
+ /Dest [ 53 0 R
+ /XYZ
+ 62.69291
+ 380.4236
+ 0 ]
+ /Rect [ 102.6929
+ 389.7736
+ 221.6229
+ 401.7736 ]
+ /Subtype /Link
+ /Type /Annot >>
+endobj
+% 'Annot.NUMBER29': class LinkAnnotation
+32 0 obj
+<< /Border [ 0
+ 0
+ 0 ]
+ /Contents ()
+ /Dest [ 53 0 R
+ /XYZ
+ 62.69291
+ 380.4236
+ 0 ]
+ /Rect [ 521.4627
+ 389.7736
+ 532.5827
+ 401.7736 ]
+ /Subtype /Link
+ /Type /Annot >>
+endobj
+% 'Annot.NUMBER30': class LinkAnnotation
+33 0 obj
+<< /Border [ 0
+ 0
+ 0 ]
+ /Contents ()
+ /Dest [ 53 0 R
+ /XYZ
+ 62.69291
+ 177.6534
+ 0 ]
+ /Rect [ 82.69291
+ 371.7736
+ 162.7329
+ 383.7736 ]
+ /Subtype /Link
+ /Type /Annot >>
+endobj
+% 'Annot.NUMBER31': class LinkAnnotation
+34 0 obj
+<< /Border [ 0
+ 0
+ 0 ]
+ /Contents ()
+ /Dest [ 53 0 R
+ /XYZ
+ 62.69291
+ 177.6534
+ 0 ]
+ /Rect [ 521.4627
+ 371.7736
+ 532.5827
+ 383.7736 ]
+ /Subtype /Link
+ /Type /Annot >>
+endobj
+% 'Annot.NUMBER32': class LinkAnnotation
+35 0 obj
+<< /Border [ 0
+ 0
+ 0 ]
+ /Contents ()
+ /Dest [ 58 0 R
+ /XYZ
+ 62.69291
+ 765.0236
+ 0 ]
+ /Rect [ 82.69291
+ 353.7736
+ 199.4329
+ 365.7736 ]
+ /Subtype /Link
+ /Type /Annot >>
+endobj
+% 'Annot.NUMBER33': class LinkAnnotation
+36 0 obj
+<< /Border [ 0
+ 0
+ 0 ]
+ /Contents ()
+ /Dest [ 58 0 R
+ /XYZ
+ 62.69291
+ 765.0236
+ 0 ]
+ /Rect [ 521.4627
+ 353.7736
+ 532.5827
+ 365.7736 ]
+ /Subtype /Link
+ /Type /Annot >>
+endobj
+% 'Annot.NUMBER34': class PDFDictionary
+37 0 obj
+<< /A << /S /URI
+ /Type /Action
+ /URI (http://www.esri.com/library/whitepapers/pdfs/shapefile.pdf) >>
+ /Border [ 0
+ 0
+ 0 ]
+ /Rect [ 62.69291
+ 263.7736
+ 317.7829
+ 275.7736 ]
+ /Subtype /Link
+ /Type /Annot >>
+endobj
+% 'Annot.NUMBER35': class PDFDictionary
+38 0 obj
+<< /A << /S /URI
+ /Type /Action
+ /URI (http://www.clicketyclick.dk/databases/xbase/format/index.html) >>
+ /Border [ 0
+ 0
+ 0 ]
+ /Rect [ 217.7529
+ 227.7736
+ 490.6229
+ 239.7736 ]
+ /Subtype /Link
+ /Type /Annot >>
+endobj
+% 'Annot.NUMBER36': class PDFDictionary
+39 0 obj
+<< /A << /S /URI
+ /Type /Action
+ /URI (http://code.google.com/p/pyshp) >>
+ /Border [ 0
+ 0
+ 0 ]
+ /Rect [ 184.321
+ 119.7736
+ 323.291
+ 131.7736 ]
+ /Subtype /Link
+ /Type /Annot >>
+endobj
+% 'Annot.NUMBER37': class PDFDictionary
+40 0 obj
+<< /A << /S /URI
+ /Type /Action
+ /URI (http://GeospatialPython.com) >>
+ /Border [ 0
+ 0
+ 0 ]
+ /Rect [ 62.69291
+ 83.77362
+ 188.3129
+ 95.77362 ]
+ /Subtype /Link
+ /Type /Annot >>
+endobj
+% 'Page1': class PDFPage
+41 0 obj
+% Page dictionary
+<< /Annots [ 4 0 R
+ 5 0 R
+ 6 0 R
+ 7 0 R
+ 8 0 R
+ 9 0 R
+ 10 0 R
+ 11 0 R
+ 12 0 R
+ 13 0 R
+ 14 0 R
+ 15 0 R
+ 16 0 R
+ 17 0 R
+ 18 0 R
+ 19 0 R
+ 20 0 R
+ 21 0 R
+ 22 0 R
+ 23 0 R
+ 24 0 R
+ 25 0 R
+ 26 0 R
+ 27 0 R
+ 28 0 R
+ 29 0 R
+ 30 0 R
+ 31 0 R
+ 32 0 R
+ 33 0 R
+ 34 0 R
+ 35 0 R
+ 36 0 R
+ 37 0 R
+ 38 0 R
+ 39 0 R
+ 40 0 R ]
+ /Contents 79 0 R
+ /MediaBox [ 0
+ 0
+ 595.2756
+ 841.8898 ]
+ /Parent 78 0 R
+ /Resources << /Font 1 0 R
+ /ProcSet [ /PDF
+ /Text
+ /ImageB
+ /ImageC
+ /ImageI ] >>
+ /Rotate 0
+ /Trans << >>
+ /Type /Page >>
+endobj
+% 'Annot.NUMBER38': class PDFDictionary
+42 0 obj
+<< /A << /S /URI
+ /Type /Action
+ /URI (http://code.google.com/p/pyshp/wiki/MapProjections) >>
+ /Border [ 0
+ 0
+ 0 ]
+ /Rect [ 62.69291
+ 741.7736
+ 292.7929
+ 753.7736 ]
+ /Subtype /Link
+ /Type /Annot >>
+endobj
+% 'F3': class PDFType1Font
+43 0 obj
+% Font Courier
+<< /BaseFont /Courier
+ /Encoding /WinAnsiEncoding
+ /Name /F3
+ /Subtype /Type1
+ /Type /Font >>
+endobj
+% 'F4': class PDFType1Font
+44 0 obj
+% Font Helvetica-BoldOblique
+<< /BaseFont /Helvetica-BoldOblique
+ /Encoding /WinAnsiEncoding
+ /Name /F4
+ /Subtype /Type1
+ /Type /Font >>
+endobj
+% 'Page2': class PDFPage
+45 0 obj
+% Page dictionary
+<< /Annots [ 42 0 R ]
+ /Contents 80 0 R
+ /MediaBox [ 0
+ 0
+ 595.2756
+ 841.8898 ]
+ /Parent 78 0 R
+ /Resources << /Font 1 0 R
+ /ProcSet [ /PDF
+ /Text
+ /ImageB
+ /ImageC
+ /ImageI ] >>
+ /Rotate 0
+ /Trans << >>
+ /Type /Page >>
+endobj
+% 'Page3': class PDFPage
+46 0 obj
+% Page dictionary
+<< /Contents 81 0 R
+ /MediaBox [ 0
+ 0
+ 595.2756
+ 841.8898 ]
+ /Parent 78 0 R
+ /Resources << /Font 1 0 R
+ /ProcSet [ /PDF
+ /Text
+ /ImageB
+ /ImageC
+ /ImageI ] >>
+ /Rotate 0
+ /Trans << >>
+ /Type /Page >>
+endobj
+% 'Page4': class PDFPage
+47 0 obj
+% Page dictionary
+<< /Contents 82 0 R
+ /MediaBox [ 0
+ 0
+ 595.2756
+ 841.8898 ]
+ /Parent 78 0 R
+ /Resources << /Font 1 0 R
+ /ProcSet [ /PDF
+ /Text
+ /ImageB
+ /ImageC
+ /ImageI ] >>
+ /Rotate 0
+ /Trans << >>
+ /Type /Page >>
+endobj
+% 'Page5': class PDFPage
+48 0 obj
+% Page dictionary
+<< /Contents 83 0 R
+ /MediaBox [ 0
+ 0
+ 595.2756
+ 841.8898 ]
+ /Parent 78 0 R
+ /Resources << /Font 1 0 R
+ /ProcSet [ /PDF
+ /Text
+ /ImageB
+ /ImageC
+ /ImageI ] >>
+ /Rotate 0
+ /Trans << >>
+ /Type /Page >>
+endobj
+% 'Page6': class PDFPage
+49 0 obj
+% Page dictionary
+<< /Contents 84 0 R
+ /MediaBox [ 0
+ 0
+ 595.2756
+ 841.8898 ]
+ /Parent 78 0 R
+ /Resources << /Font 1 0 R
+ /ProcSet [ /PDF
+ /Text
+ /ImageB
+ /ImageC
+ /ImageI ] >>
+ /Rotate 0
+ /Trans << >>
+ /Type /Page >>
+endobj
+% 'Page7': class PDFPage
+50 0 obj
+% Page dictionary
+<< /Contents 85 0 R
+ /MediaBox [ 0
+ 0
+ 595.2756
+ 841.8898 ]
+ /Parent 78 0 R
+ /Resources << /Font 1 0 R
+ /ProcSet [ /PDF
+ /Text
+ /ImageB
+ /ImageC
+ /ImageI ] >>
+ /Rotate 0
+ /Trans << >>
+ /Type /Page >>
+endobj
+% 'Page8': class PDFPage
+51 0 obj
+% Page dictionary
+<< /Contents 86 0 R
+ /MediaBox [ 0
+ 0
+ 595.2756
+ 841.8898 ]
+ /Parent 78 0 R
+ /Resources << /Font 1 0 R
+ /ProcSet [ /PDF
+ /Text
+ /ImageB
+ /ImageC
+ /ImageI ] >>
+ /Rotate 0
+ /Trans << >>
+ /Type /Page >>
+endobj
+% 'Page9': class PDFPage
+52 0 obj
+% Page dictionary
+<< /Contents 87 0 R
+ /MediaBox [ 0
+ 0
+ 595.2756
+ 841.8898 ]
+ /Parent 78 0 R
+ /Resources << /Font 1 0 R
+ /ProcSet [ /PDF
+ /Text
+ /ImageB
+ /ImageC
+ /ImageI ] >>
+ /Rotate 0
+ /Trans << >>
+ /Type /Page >>
+endobj
+% 'Page10': class PDFPage
+53 0 obj
+% Page dictionary
+<< /Contents 88 0 R
+ /MediaBox [ 0
+ 0
+ 595.2756
+ 841.8898 ]
+ /Parent 78 0 R
+ /Resources << /Font 1 0 R
+ /ProcSet [ /PDF
+ /Text
+ /ImageB
+ /ImageC
+ /ImageI ] >>
+ /Rotate 0
+ /Trans << >>
+ /Type /Page >>
+endobj
+% 'Page11': class PDFPage
+54 0 obj
+% Page dictionary
+<< /Contents 89 0 R
+ /MediaBox [ 0
+ 0
+ 595.2756
+ 841.8898 ]
+ /Parent 78 0 R
+ /Resources << /Font 1 0 R
+ /ProcSet [ /PDF
+ /Text
+ /ImageB
+ /ImageC
+ /ImageI ] >>
+ /Rotate 0
+ /Trans << >>
+ /Type /Page >>
+endobj
+% 'Annot.NUMBER39': class PDFDictionary
+55 0 obj
+<< /A << /S /URI
+ /Type /Action
+ /URI (https://gist.github.com/sgillies/2217756) >>
+ /Border [ 0
+ 0
+ 0 ]
+ /Rect [ 191.7728
+ 705.7736
+ 363.5228
+ 717.7736 ]
+ /Subtype /Link
+ /Type /Annot >>
+endobj
+% 'Annot.NUMBER40': class PDFDictionary
+56 0 obj
+<< /A << /S /URI
+ /Type /Action
+ /URI (http://geojson.org) >>
+ /Border [ 0
+ 0
+ 0 ]
+ /Rect [ 116.0529
+ 693.7736
+ 193.3229
+ 705.7736 ]
+ /Subtype /Link
+ /Type /Annot >>
+endobj
+% 'Annot.NUMBER41': class PDFDictionary
+57 0 obj
+<< /A << /S /URI
+ /Type /Action
+ /URI (http://geojson.org) >>
+ /Border [ 0
+ 0
+ 0 ]
+ /Rect [ 196.1029
+ 693.7736
+ 273.3729
+ 705.7736 ]
+ /Subtype /Link
+ /Type /Annot >>
+endobj
+% 'Page12': class PDFPage
+58 0 obj
+% Page dictionary
+<< /Annots [ 55 0 R
+ 56 0 R
+ 57 0 R ]
+ /Contents 90 0 R
+ /MediaBox [ 0
+ 0
+ 595.2756
+ 841.8898 ]
+ /Parent 78 0 R
+ /Resources << /Font 1 0 R
+ /ProcSet [ /PDF
+ /Text
+ /ImageB
+ /ImageC
+ /ImageI ] >>
+ /Rotate 0
+ /Trans << >>
+ /Type /Page >>
+endobj
+% 'R59': class PDFCatalog
+59 0 obj
+% Document Root
+<< /Outlines 61 0 R
+ /PageLabels 91 0 R
+ /PageMode /UseNone
+ /Pages 78 0 R
+ /Type /Catalog >>
+endobj
+% 'R60': class PDFInfo
+60 0 obj
+<< /Author (Joel Lawhead - jlawhead at geospatialpython.com)
+ /CreationDate (D:20140511215809+06'00')
+ /Creator (\(unspecified\))
+ /Keywords ()
+ /Producer (ReportLab PDF Library - www.reportlab.com)
+ /Subject (\(unspecified\))
+ /Title (PyShp) >>
+endobj
+% 'R61': class PDFOutlines
+61 0 obj
+<< /Count 19
+ /First 62 0 R
+ /Last 63 0 R
+ /Type /Outlines >>
+endobj
+% 'Outline.0': class OutlineEntryObject
+62 0 obj
+<< /Dest [ 41 0 R
+ /XYZ
+ 62.69291
+ 338.0236
+ 0 ]
+ /Next 63 0 R
+ /Parent 61 0 R
+ /Title (Overview) >>
+endobj
+% 'Outline.1': class OutlineEntryObject
+63 0 obj
+<< /Count 14
+ /Dest [ 45 0 R
+ /XYZ
+ 62.69291
+ 699.0236
+ 0 ]
+ /First 64 0 R
+ /Last 77 0 R
+ /Parent 61 0 R
+ /Prev 62 0 R
+ /Title (Examples) >>
+endobj
+% 'Outline.17.0': class OutlineEntryObject
+64 0 obj
+<< /Count 4
+ /Dest [ 45 0 R
+ /XYZ
+ 62.69291
+ 582.8236
+ 0 ]
+ /First 65 0 R
+ /Last 68 0 R
+ /Next 69 0 R
+ /Parent 63 0 R
+ /Title (Reading Shapefiles) >>
+endobj
+% 'Outline.18.0': class OutlineEntryObject
+65 0 obj
+<< /Dest [ 45 0 R
+ /XYZ
+ 62.69291
+ 339.2236
+ 0 ]
+ /Next 66 0 R
+ /Parent 64 0 R
+ /Title (Reading Shapefiles from File-Like Objects) >>
+endobj
+% 'Outline.18.1': class OutlineEntryObject
+66 0 obj
+<< /Dest [ 45 0 R
+ /XYZ
+ 62.69291
+ 169.0236
+ 0 ]
+ /Next 67 0 R
+ /Parent 64 0 R
+ /Prev 65 0 R
+ /Title (Reading Geometry) >>
+endobj
+% 'Outline.18.2': class OutlineEntryObject
+67 0 obj
+<< /Dest [ 47 0 R
+ /XYZ
+ 62.69291
+ 545.4236
+ 0 ]
+ /Next 68 0 R
+ /Parent 64 0 R
+ /Prev 66 0 R
+ /Title (Reading Records) >>
+endobj
+% 'Outline.18.3': class OutlineEntryObject
+68 0 obj
+<< /Dest [ 48 0 R
+ /XYZ
+ 62.69291
+ 358.6236
+ 0 ]
+ /Parent 64 0 R
+ /Prev 67 0 R
+ /Title (Reading Geometry and Records Simultaneously) >>
+endobj
+% 'Outline.17.1': class OutlineEntryObject
+69 0 obj
+<< /Count 6
+ /Dest [ 49 0 R
+ /XYZ
+ 62.69291
+ 552.2236
+ 0 ]
+ /First 70 0 R
+ /Last 75 0 R
+ /Next 76 0 R
+ /Parent 63 0 R
+ /Prev 64 0 R
+ /Title (Writing Shapefiles) >>
+endobj
+% 'Outline.19.0': class OutlineEntryObject
+70 0 obj
+<< /Dest [ 49 0 R
+ /XYZ
+ 62.69291
+ 321.0236
+ 0 ]
+ /Next 71 0 R
+ /Parent 69 0 R
+ /Title (Setting the Shape Type) >>
+endobj
+% 'Outline.19.1': class OutlineEntryObject
+71 0 obj
+<< /Dest [ 50 0 R
+ /XYZ
+ 62.69291
+ 511.0236
+ 0 ]
+ /Next 72 0 R
+ /Parent 69 0 R
+ /Prev 70 0 R
+ /Title (Geometry and Record Balancing) >>
+endobj
+% 'Outline.19.2': class OutlineEntryObject
+72 0 obj
+<< /Dest [ 50 0 R
+ /XYZ
+ 62.69291
+ 226.8236
+ 0 ]
+ /Next 73 0 R
+ /Parent 69 0 R
+ /Prev 71 0 R
+ /Title (Adding Geometry) >>
+endobj
+% 'Outline.19.3': class OutlineEntryObject
+73 0 obj
+<< /Dest [ 52 0 R
+ /XYZ
+ 62.69291
+ 423.4236
+ 0 ]
+ /Next 74 0 R
+ /Parent 69 0 R
+ /Prev 72 0 R
+ /Title (Creating Attributes) >>
+endobj
+% 'Outline.19.4': class OutlineEntryObject
+74 0 obj
+<< /Dest [ 53 0 R
+ /XYZ
+ 62.69291
+ 530.6236
+ 0 ]
+ /Next 75 0 R
+ /Parent 69 0 R
+ /Prev 73 0 R
+ /Title (File Names) >>
+endobj
+% 'Outline.19.5': class OutlineEntryObject
+75 0 obj
+<< /Dest [ 53 0 R
+ /XYZ
+ 62.69291
+ 380.4236
+ 0 ]
+ /Parent 69 0 R
+ /Prev 74 0 R
+ /Title (Saving to File-Like Objects) >>
+endobj
+% 'Outline.17.2': class OutlineEntryObject
+76 0 obj
+<< /Dest [ 53 0 R
+ /XYZ
+ 62.69291
+ 177.6534
+ 0 ]
+ /Next 77 0 R
+ /Parent 63 0 R
+ /Prev 69 0 R
+ /Title (Editing Shapefiles) >>
+endobj
+% 'Outline.17.3': class OutlineEntryObject
+77 0 obj
+<< /Dest [ 58 0 R
+ /XYZ
+ 62.69291
+ 765.0236
+ 0 ]
+ /Parent 63 0 R
+ /Prev 76 0 R
+ /Title (Python __geo_interface__) >>
+endobj
+% 'R78': class PDFPages
+78 0 obj
+% page tree
+<< /Count 12
+ /Kids [ 41 0 R
+ 45 0 R
+ 46 0 R
+ 47 0 R
+ 48 0 R
+ 49 0 R
+ 50 0 R
+ 51 0 R
+ 52 0 R
+ 53 0 R
+ 54 0 R
+ 58 0 R ]
+ /Type /Pages >>
+endobj
+% 'R79': class PDFStream
+79 0 obj
+% page stream
+<< /Length 7701 >>
+stream
+1 0 0 1 0 0 cm BT /F1 12 Tf 14.4 TL ET
+q
+1 0 0 1 62.69291 741.0236 cm
+q
+0 0 0 rg
+BT 1 0 0 1 0 4 Tm /F2 20 Tf 24 TL 203.8249 0 Td (PyShp) Tj T* -203.8249 0 Td ET
+Q
+Q
+q
+1 0 0 1 62.69291 716.0236 cm
+0 0 0 rg
+BT /F1 10 Tf 12 TL ET
+q
+1 0 0 1 6 3 cm
+q
+0 0 0 rg
+BT 1 0 0 1 0 2 Tm /F2 10 Tf 12 TL 36.93937 0 Td (Author:) Tj T* -36.93937 0 Td ET
+Q
+Q
+q
+1 0 0 1 91.03937 3 cm
+q
+BT 1 0 0 1 0 2 Tm 12 TL /F1 10 Tf 0 0 0 rg (Joel Lawhead - ) Tj 0 0 .501961 rg (jlawhead at geospatialpython.com) Tj T* ET
+Q
+Q
+q
+Q
+Q
+q
+1 0 0 1 62.69291 698.0236 cm
+q
+BT 1 0 0 1 0 2 Tm 12 TL /F1 10 Tf 0 0 0 rg (:Version 1.2.1) Tj T* ET
+Q
+Q
+q
+1 0 0 1 62.69291 692.0236 cm
+Q
+q
+1 0 0 1 62.69291 677.0236 cm
+0 0 0 rg
+BT /F1 10 Tf 12 TL ET
+q
+1 0 0 1 6 3 cm
+q
+0 0 0 rg
+BT 1 0 0 1 0 2 Tm /F2 10 Tf 12 TL 31.35937 0 Td (Revised:) Tj T* -31.35937 0 Td ET
+Q
+Q
+q
+1 0 0 1 91.03937 3 cm
+q
+0 0 0 rg
+BT 1 0 0 1 0 2 Tm /F1 10 Tf 12 TL (May 11, 2014) Tj T* ET
+Q
+Q
+q
+Q
+Q
+q
+1 0 0 1 62.69291 644.0236 cm
+q
+BT 1 0 0 1 0 3.5 Tm 21 TL /F2 17.5 Tf 0 0 0 rg (Contents) Tj T* ET
+Q
+Q
+q
+1 0 0 1 62.69291 350.0236 cm
+0 0 0 rg
+BT /F1 10 Tf 12 TL ET
+q
+1 0 0 1 0 273 cm
+q
+BT 1 0 0 1 0 2 Tm 12 TL /F2 10 Tf 0 0 .501961 rg (Overview) Tj T* ET
+Q
+Q
+q
+1 0 0 1 397.8898 273 cm
+q
+0 0 .501961 rg
+0 0 .501961 RG
+BT 1 0 0 1 0 2 Tm /F2 10 Tf 12 TL 66.44 0 Td (1) Tj T* -66.44 0 Td ET
+Q
+Q
+q
+1 0 0 1 0 255 cm
+q
+BT 1 0 0 1 0 2 Tm 12 TL /F2 10 Tf 0 0 .501961 rg (Examples) Tj T* ET
+Q
+Q
+q
+1 0 0 1 397.8898 255 cm
+q
+0 0 .501961 rg
+0 0 .501961 RG
+BT 1 0 0 1 0 2 Tm /F2 10 Tf 12 TL 66.44 0 Td (2) Tj T* -66.44 0 Td ET
+Q
+Q
+q
+1 0 0 1 0 237 cm
+q
+BT 1 0 0 1 20 2 Tm 12 TL /F1 10 Tf 0 0 .501961 rg (Reading Shapefiles) Tj T* ET
+Q
+Q
+q
+1 0 0 1 397.8898 237 cm
+q
+0 0 .501961 rg
+0 0 .501961 RG
+BT 1 0 0 1 0 2 Tm /F1 10 Tf 12 TL 66.44 0 Td (2) Tj T* -66.44 0 Td ET
+Q
+Q
+q
+1 0 0 1 0 219 cm
+q
+BT 1 0 0 1 40 2 Tm 12 TL /F1 10 Tf 0 0 .501961 rg (Reading Shapefiles from File-Like Objects) Tj T* ET
+Q
+Q
+q
+1 0 0 1 397.8898 219 cm
+q
+0 0 .501961 rg
+0 0 .501961 RG
+BT 1 0 0 1 0 2 Tm /F1 10 Tf 12 TL 66.44 0 Td (2) Tj T* -66.44 0 Td ET
+Q
+Q
+q
+1 0 0 1 0 201 cm
+q
+BT 1 0 0 1 40 2 Tm 12 TL /F1 10 Tf 0 0 .501961 rg (Reading Geometry) Tj T* ET
+Q
+Q
+q
+1 0 0 1 397.8898 201 cm
+q
+0 0 .501961 rg
+0 0 .501961 RG
+BT 1 0 0 1 0 2 Tm /F1 10 Tf 12 TL 66.44 0 Td (2) Tj T* -66.44 0 Td ET
+Q
+Q
+q
+1 0 0 1 0 183 cm
+q
+BT 1 0 0 1 40 2 Tm 12 TL /F1 10 Tf 0 0 .501961 rg (Reading Records) Tj T* ET
+Q
+Q
+q
+1 0 0 1 397.8898 183 cm
+q
+0 0 .501961 rg
+0 0 .501961 RG
+BT 1 0 0 1 0 2 Tm /F1 10 Tf 12 TL 66.44 0 Td (4) Tj T* -66.44 0 Td ET
+Q
+Q
+q
+1 0 0 1 0 165 cm
+q
+BT 1 0 0 1 40 2 Tm 12 TL /F1 10 Tf 0 0 .501961 rg (Reading Geometry and Records Simultaneously) Tj T* ET
+Q
+Q
+q
+1 0 0 1 397.8898 165 cm
+q
+0 0 .501961 rg
+0 0 .501961 RG
+BT 1 0 0 1 0 2 Tm /F1 10 Tf 12 TL 66.44 0 Td (5) Tj T* -66.44 0 Td ET
+Q
+Q
+q
+1 0 0 1 0 147 cm
+q
+BT 1 0 0 1 20 2 Tm 12 TL /F1 10 Tf 0 0 .501961 rg (Writing Shapefiles) Tj T* ET
+Q
+Q
+q
+1 0 0 1 397.8898 147 cm
+q
+0 0 .501961 rg
+0 0 .501961 RG
+BT 1 0 0 1 0 2 Tm /F1 10 Tf 12 TL 66.44 0 Td (6) Tj T* -66.44 0 Td ET
+Q
+Q
+q
+1 0 0 1 0 129 cm
+q
+BT 1 0 0 1 40 2 Tm 12 TL /F1 10 Tf 0 0 .501961 rg (Setting the Shape Type) Tj T* ET
+Q
+Q
+q
+1 0 0 1 397.8898 129 cm
+q
+0 0 .501961 rg
+0 0 .501961 RG
+BT 1 0 0 1 0 2 Tm /F1 10 Tf 12 TL 66.44 0 Td (6) Tj T* -66.44 0 Td ET
+Q
+Q
+q
+1 0 0 1 0 111 cm
+q
+BT 1 0 0 1 40 2 Tm 12 TL /F1 10 Tf 0 0 .501961 rg (Geometry and Record Balancing) Tj T* ET
+Q
+Q
+q
+1 0 0 1 397.8898 111 cm
+q
+0 0 .501961 rg
+0 0 .501961 RG
+BT 1 0 0 1 0 2 Tm /F1 10 Tf 12 TL 66.44 0 Td (7) Tj T* -66.44 0 Td ET
+Q
+Q
+q
+1 0 0 1 0 93 cm
+q
+BT 1 0 0 1 40 2 Tm 12 TL /F1 10 Tf 0 0 .501961 rg (Adding Geometry) Tj T* ET
+Q
+Q
+q
+1 0 0 1 397.8898 93 cm
+q
+0 0 .501961 rg
+0 0 .501961 RG
+BT 1 0 0 1 0 2 Tm /F1 10 Tf 12 TL 66.44 0 Td (7) Tj T* -66.44 0 Td ET
+Q
+Q
+q
+1 0 0 1 0 75 cm
+q
+BT 1 0 0 1 40 2 Tm 12 TL /F1 10 Tf 0 0 .501961 rg (Creating Attributes) Tj T* ET
+Q
+Q
+q
+1 0 0 1 397.8898 75 cm
+q
+0 0 .501961 rg
+0 0 .501961 RG
+BT 1 0 0 1 0 2 Tm /F1 10 Tf 12 TL 66.44 0 Td (9) Tj T* -66.44 0 Td ET
+Q
+Q
+q
+1 0 0 1 0 57 cm
+q
+BT 1 0 0 1 40 2 Tm 12 TL /F1 10 Tf 0 0 .501961 rg (File Names) Tj T* ET
+Q
+Q
+q
+1 0 0 1 397.8898 57 cm
+q
+0 0 .501961 rg
+0 0 .501961 RG
+BT 1 0 0 1 0 2 Tm /F1 10 Tf 12 TL 60.88 0 Td (10) Tj T* -60.88 0 Td ET
+Q
+Q
+q
+1 0 0 1 0 39 cm
+q
+BT 1 0 0 1 40 2 Tm 12 TL /F1 10 Tf 0 0 .501961 rg (Saving to File-Like Objects) Tj T* ET
+Q
+Q
+q
+1 0 0 1 397.8898 39 cm
+q
+0 0 .501961 rg
+0 0 .501961 RG
+BT 1 0 0 1 0 2 Tm /F1 10 Tf 12 TL 60.88 0 Td (10) Tj T* -60.88 0 Td ET
+Q
+Q
+q
+1 0 0 1 0 21 cm
+q
+BT 1 0 0 1 20 2 Tm 12 TL /F1 10 Tf 0 0 .501961 rg (Editing Shapefiles) Tj T* ET
+Q
+Q
+q
+1 0 0 1 397.8898 21 cm
+q
+0 0 .501961 rg
+0 0 .501961 RG
+BT 1 0 0 1 0 2 Tm /F1 10 Tf 12 TL 60.88 0 Td (10) Tj T* -60.88 0 Td ET
+Q
+Q
+q
+1 0 0 1 0 3 cm
+q
+BT 1 0 0 1 20 2 Tm 12 TL /F1 10 Tf 0 0 .501961 rg (Python __geo_interface__) Tj T* ET
+Q
+Q
+q
+1 0 0 1 397.8898 3 cm
+q
+0 0 .501961 rg
+0 0 .501961 RG
+BT 1 0 0 1 0 2 Tm /F1 10 Tf 12 TL 60.88 0 Td (12) Tj T* -60.88 0 Td ET
+Q
+Q
+q
+Q
+Q
+q
+1 0 0 1 62.69291 317.0236 cm
+q
+BT 1 0 0 1 0 3.5 Tm 21 TL /F2 17.5 Tf 0 0 0 rg (Overview) Tj T* ET
+Q
+Q
+q
+1 0 0 1 62.69291 227.0236 cm
+q
+BT 1 0 0 1 0 74 Tm 1.126235 Tw 12 TL /F1 10 Tf 0 0 0 rg (PyShp provides read and write support for the Esri Shapefile format. The Shapefile format is a popular) Tj T* 0 Tw .058555 Tw (Geographic Information System vector data format created by Esri. For more information about this format) Tj T* 0 Tw 6.191647 Tw (please read the well-written "ESRI Shapefile Technical Description - July 1998" located at) Tj T* 0 Tw .79622 Tw 0 0 .501961 rg (http://www.esri.com/library/whitepapers/pdfs/shap [...]
+Q
+Q
+q
+1 0 0 1 62.69291 185.0236 cm
+q
+0 0 0 rg
+BT 1 0 0 1 0 26 Tm /F1 10 Tf 12 TL .755542 Tw (Both the Esri and XBase file-formats are very simple in design and memory efficient which is part of the) Tj T* 0 Tw .384651 Tw (reason the shapefile format remains popular despite the numerous ways to store and exchange GIS data) Tj T* 0 Tw (available today.) Tj T* ET
+Q
+Q
+q
+1 0 0 1 62.69291 167.0236 cm
+q
+0 0 0 rg
+BT 1 0 0 1 0 2 Tm /F1 10 Tf 12 TL (Pyshp is compatible with Python 2.4-3.x.) Tj T* ET
+Q
+Q
+q
+1 0 0 1 62.69291 149.0236 cm
+q
+0 0 0 rg
+BT 1 0 0 1 0 2 Tm /F1 10 Tf 12 TL (This document provides examples for using PyShp to read and write shapefiles.) Tj T* ET
+Q
+Q
+q
+1 0 0 1 62.69291 83.02362 cm
+q
+BT 1 0 0 1 0 50 Tm 1.525697 Tw 12 TL /F1 10 Tf 0 0 0 rg (Currently the sample census blockgroup shapefile referenced in the examples is only available on the) Tj T* 0 Tw .423615 Tw (google code project site at ) Tj 0 0 .501961 rg (http://code.google.com/p/pyshp) Tj 0 0 0 rg (. These examples are straight-forward and you) Tj T* 0 Tw .218555 Tw (can also easily run them against your own shapefiles manually with minimal modification. Other examples) Tj T* 0 Tw 5.979318 Tw (for specific topi [...]
+Q
+Q
+
+endstream
+endobj
+% 'R80': class PDFStream
+80 0 obj
+% page stream
+<< /Length 5611 >>
+stream
+1 0 0 1 0 0 cm BT /F1 12 Tf 14.4 TL ET
+q
+1 0 0 1 62.69291 741.0236 cm
+q
+BT 1 0 0 1 0 14 Tm 9.193976 Tw 12 TL /F1 10 Tf 0 0 0 rg (Important: For information about map projections, shapefiles, and Python please visit:) Tj T* 0 Tw 0 0 .501961 rg (http://code.google.com/p/pyshp/wiki/MapProjections) Tj T* ET
+Q
+Q
+q
+1 0 0 1 62.69291 711.0236 cm
+q
+0 0 0 rg
+BT 1 0 0 1 0 14 Tm /F1 10 Tf 12 TL 1.350651 Tw (I sincerely hope this library eliminates the mundane distraction of simply reading and writing data, and) Tj T* 0 Tw (allows you to focus on the challenging and FUN part of your geospatial project.) Tj T* ET
+Q
+Q
+q
+1 0 0 1 62.69291 678.0236 cm
+q
+BT 1 0 0 1 0 3.5 Tm 21 TL /F2 17.5 Tf 0 0 0 rg (Examples) Tj T* ET
+Q
+Q
+q
+1 0 0 1 62.69291 660.0236 cm
+q
+0 0 0 rg
+BT 1 0 0 1 0 2 Tm /F1 10 Tf 12 TL (Before doing anything you must import the library.) Tj T* ET
+Q
+Q
+q
+1 0 0 1 62.69291 626.8236 cm
+q
+q
+1 0 0 1 0 0 cm
+q
+1 0 0 1 6.6 6.6 cm
+q
+.662745 .662745 .662745 RG
+.5 w
+.960784 .960784 .862745 rg
+n -6 -6 468.6898 24 re B*
+Q
+q
+BT 1 0 0 1 0 2 Tm 12 TL /F3 10 Tf 0 0 0 rg (>) Tj (>) Tj (>) Tj ( import shapefile) Tj T* ET
+Q
+Q
+Q
+Q
+Q
+q
+1 0 0 1 62.69291 594.8236 cm
+q
+0 0 0 rg
+BT 1 0 0 1 0 14 Tm /F1 10 Tf 12 TL .188735 Tw (The examples below will use a shapefile created from the U.S. Census Bureau Blockgroups data set near) Tj T* 0 Tw (San Francisco, CA and available in the subversion repository of the pyshp google code site.) Tj T* ET
+Q
+Q
+q
+1 0 0 1 62.69291 564.8236 cm
+q
+BT 1 0 0 1 0 3 Tm 18 TL /F2 15 Tf 0 0 0 rg (Reading Shapefiles) Tj T* ET
+Q
+Q
+q
+1 0 0 1 62.69291 522.8236 cm
+q
+0 0 0 rg
+BT 1 0 0 1 0 26 Tm /F1 10 Tf 12 TL 1.623876 Tw (To read a shapefile create a new "Reader" object and pass it the name of an existing shapefile. The) Tj T* 0 Tw .22832 Tw (shapefile format is acutally a collection of three files. You specify the base filename of the shapefile or the) Tj T* 0 Tw (complete filename of any of the shapefile component files.) Tj T* ET
+Q
+Q
+q
+1 0 0 1 62.69291 489.6236 cm
+q
+q
+1 0 0 1 0 0 cm
+q
+1 0 0 1 6.6 6.6 cm
+q
+.662745 .662745 .662745 RG
+.5 w
+.960784 .960784 .862745 rg
+n -6 -6 468.6898 24 re B*
+Q
+q
+BT 1 0 0 1 0 2 Tm 12 TL /F3 10 Tf 0 0 0 rg (>) Tj (>) Tj (>) Tj ( sf = shapefile.Reader\("shapefiles/blockgroups"\)) Tj T* ET
+Q
+Q
+Q
+Q
+Q
+q
+1 0 0 1 62.69291 469.6236 cm
+q
+0 0 0 rg
+BT 1 0 0 1 0 2 Tm /F1 10 Tf 12 TL (OR) Tj T* ET
+Q
+Q
+q
+1 0 0 1 62.69291 436.4236 cm
+q
+q
+1 0 0 1 0 0 cm
+q
+1 0 0 1 6.6 6.6 cm
+q
+.662745 .662745 .662745 RG
+.5 w
+.960784 .960784 .862745 rg
+n -6 -6 468.6898 24 re B*
+Q
+q
+BT 1 0 0 1 0 2 Tm 12 TL /F3 10 Tf 0 0 0 rg (>) Tj (>) Tj (>) Tj ( sf = shapefile.Reader\("shapefiles/blockgroups.shp"\)) Tj T* ET
+Q
+Q
+Q
+Q
+Q
+q
+1 0 0 1 62.69291 416.4236 cm
+q
+0 0 0 rg
+BT 1 0 0 1 0 2 Tm /F1 10 Tf 12 TL (OR) Tj T* ET
+Q
+Q
+q
+1 0 0 1 62.69291 383.2236 cm
+q
+q
+1 0 0 1 0 0 cm
+q
+1 0 0 1 6.6 6.6 cm
+q
+.662745 .662745 .662745 RG
+.5 w
+.960784 .960784 .862745 rg
+n -6 -6 468.6898 24 re B*
+Q
+q
+BT 1 0 0 1 0 2 Tm 12 TL /F3 10 Tf 0 0 0 rg (>) Tj (>) Tj (>) Tj ( sf = shapefile.Reader\("shapefiles/blockgroups.dbf"\)) Tj T* ET
+Q
+Q
+Q
+Q
+Q
+q
+1 0 0 1 62.69291 351.2236 cm
+q
+0 0 0 rg
+BT 1 0 0 1 0 14 Tm /F1 10 Tf 12 TL .669461 Tw (OR any of the other 5+ formats which are potentially part of a shapefile. The library does not care about) Tj T* 0 Tw (extensions.) Tj T* ET
+Q
+Q
+q
+1 0 0 1 62.69291 324.2236 cm
+q
+BT 1 0 0 1 0 2.5 Tm 15 TL /F4 12.5 Tf 0 0 0 rg (Reading Shapefiles from File-Like Objects) Tj T* ET
+Q
+Q
+q
+1 0 0 1 62.69291 282.2236 cm
+q
+0 0 0 rg
+BT 1 0 0 1 0 26 Tm /F1 10 Tf 12 TL .74436 Tw (You can also load shapefiles from any Python file-like object using keyword arguments to specify any of) Tj T* 0 Tw .846488 Tw (the three files. This feature is very powerful and allows you to load shapefiles from a url, from a zip file,) Tj T* 0 Tw (serialized object, or in some cases a database.) Tj T* ET
+Q
+Q
+q
+1 0 0 1 62.69291 225.0236 cm
+q
+q
+1 0 0 1 0 0 cm
+q
+1 0 0 1 6.6 6.6 cm
+q
+.662745 .662745 .662745 RG
+.5 w
+.960784 .960784 .862745 rg
+n -6 -6 468.6898 48 re B*
+Q
+q
+BT 1 0 0 1 0 26 Tm 12 TL /F3 10 Tf 0 0 0 rg (>) Tj (>) Tj (>) Tj ( myshp = open\("shapefiles/blockgroups.shp", "rb"\)) Tj T* (>) Tj (>) Tj (>) Tj ( mydbf = open\("shapefiles/blockgroups.dbf", "rb"\)) Tj T* (>) Tj (>) Tj (>) Tj ( r = shapefile.Reader\(shp=myshp, dbf=mydbf\)) Tj T* ET
+Q
+Q
+Q
+Q
+Q
+q
+1 0 0 1 62.69291 181.0236 cm
+q
+0 0 0 rg
+BT 1 0 0 1 0 26 Tm /F1 10 Tf 12 TL .040988 Tw (Notice in the examples above the shx file is never used. The shx file is a very simple fixed-record index for) Tj T* 0 Tw .110988 Tw (the variable length records in the shp file. This file is optional for reading. If it's available pyshp will use the) Tj T* 0 Tw (shx file to access shape records a little faster but will do just fine without it.) Tj T* ET
+Q
+Q
+q
+1 0 0 1 62.69291 154.0236 cm
+q
+BT 1 0 0 1 0 2.5 Tm 15 TL /F4 12.5 Tf 0 0 0 rg (Reading Geometry) Tj T* ET
+Q
+Q
+q
+1 0 0 1 62.69291 112.0236 cm
+q
+0 0 0 rg
+BT 1 0 0 1 0 26 Tm /F1 10 Tf 12 TL 3.002651 Tw (A shapefile's geometry is the collection of points or shapes made from verticies and implied arcs) Tj T* 0 Tw 1.206412 Tw (representing physical locations. All types of shapefiles just store points. The metadata about the points) Tj T* 0 Tw (determine how they are handled by software.) Tj T* ET
+Q
+Q
+q
+1 0 0 1 62.69291 94.02362 cm
+q
+0 0 0 rg
+BT 1 0 0 1 0 2 Tm /F1 10 Tf 12 TL (You can get the a list of the shapefile's geometry by calling the shapes\(\) method.) Tj T* ET
+Q
+Q
+
+endstream
+endobj
+% 'R81': class PDFStream
+81 0 obj
+% page stream
+<< /Length 6199 >>
+stream
+1 0 0 1 0 0 cm BT /F1 12 Tf 14.4 TL ET
+q
+1 0 0 1 62.69291 739.8236 cm
+q
+q
+1 0 0 1 0 0 cm
+q
+1 0 0 1 6.6 6.6 cm
+q
+.662745 .662745 .662745 RG
+.5 w
+.960784 .960784 .862745 rg
+n -6 -6 468.6898 24 re B*
+Q
+q
+BT 1 0 0 1 0 2 Tm 12 TL /F3 10 Tf 0 0 0 rg (>) Tj (>) Tj (>) Tj ( shapes = sf.shapes\(\)) Tj T* ET
+Q
+Q
+Q
+Q
+Q
+q
+1 0 0 1 62.69291 719.8236 cm
+q
+0 0 0 rg
+BT 1 0 0 1 0 2 Tm /F1 10 Tf 12 TL (The shapes method returns a list of Shape objects describing the geometry of each shape record.) Tj T* ET
+Q
+Q
+q
+1 0 0 1 62.69291 674.6236 cm
+q
+q
+1 0 0 1 0 0 cm
+q
+1 0 0 1 6.6 6.6 cm
+q
+.662745 .662745 .662745 RG
+.5 w
+.960784 .960784 .862745 rg
+n -6 -6 468.6898 36 re B*
+Q
+q
+BT 1 0 0 1 0 14 Tm 12 TL /F3 10 Tf 0 0 0 rg (>) Tj (>) Tj (>) Tj ( len\(shapes\)) Tj T* (663) Tj T* ET
+Q
+Q
+Q
+Q
+Q
+q
+1 0 0 1 62.69291 654.6236 cm
+q
+0 0 0 rg
+BT 1 0 0 1 0 2 Tm /F1 10 Tf 12 TL (You can iterate through the shapefile's geometry using the iterShapes\(\) method.) Tj T* ET
+Q
+Q
+q
+1 0 0 1 62.69291 609.4236 cm
+q
+q
+1 0 0 1 0 0 cm
+q
+1 0 0 1 6.6 6.6 cm
+q
+.662745 .662745 .662745 RG
+.5 w
+.960784 .960784 .862745 rg
+n -6 -6 468.6898 36 re B*
+Q
+q
+BT 1 0 0 1 0 14 Tm 12 TL /F3 10 Tf 0 0 0 rg (>) Tj (>) Tj (>) Tj ( len\(list\(sf.iterShapes\(\)\)\)) Tj T* (663) Tj T* ET
+Q
+Q
+Q
+Q
+Q
+q
+1 0 0 1 62.69291 589.4236 cm
+q
+0 0 0 rg
+BT 1 0 0 1 0 2 Tm /F1 10 Tf 12 TL (Each shape record contains the following attributes:) Tj T* ET
+Q
+Q
+q
+1 0 0 1 62.69291 484.2236 cm
+q
+q
+1 0 0 1 0 0 cm
+q
+1 0 0 1 6.6 6.6 cm
+q
+.662745 .662745 .662745 RG
+.5 w
+.960784 .960784 .862745 rg
+n -6 -6 468.6898 96 re B*
+Q
+q
+BT 1 0 0 1 0 74 Tm 12 TL /F3 10 Tf 0 0 0 rg (>) Tj (>) Tj (>) Tj ( for name in dir\(shapes[3]\):) Tj T* (... if not name.startswith\('__'\):) Tj T* (... name) Tj T* ('bbox') Tj T* ('parts') Tj T* ('points') Tj T* ('shapeType') Tj T* ET
+Q
+Q
+Q
+Q
+Q
+q
+1 0 0 1 62.69291 470.2236 cm
+Q
+q
+1 0 0 1 62.69291 452.2236 cm
+0 0 0 rg
+BT /F1 10 Tf 12 TL ET
+BT 1 0 0 1 0 2 Tm T* ET
+q
+1 0 0 1 20 12 cm
+Q
+q
+1 0 0 1 20 12 cm
+Q
+q
+1 0 0 1 20 0 cm
+0 0 0 rg
+BT /F1 10 Tf 12 TL ET
+q
+1 0 0 1 6 -3 cm
+q
+0 0 0 rg
+BT 1 0 0 1 0 2 Tm /F1 10 Tf 12 TL 10.5 0 Td (\177) Tj T* -10.5 0 Td ET
+Q
+Q
+q
+1 0 0 1 23 -3 cm
+q
+0 0 0 rg
+BT 1 0 0 1 0 2 Tm /F1 10 Tf 12 TL (shapeType: an integer representing the type of shape as defined by the shapefile specification.) Tj T* ET
+Q
+Q
+q
+Q
+Q
+q
+1 0 0 1 20 0 cm
+Q
+q
+Q
+Q
+q
+1 0 0 1 62.69291 452.2236 cm
+Q
+q
+1 0 0 1 62.69291 407.0236 cm
+q
+q
+1 0 0 1 0 0 cm
+q
+1 0 0 1 6.6 6.6 cm
+q
+.662745 .662745 .662745 RG
+.5 w
+.960784 .960784 .862745 rg
+n -6 -6 468.6898 36 re B*
+Q
+q
+BT 1 0 0 1 0 14 Tm 12 TL /F3 10 Tf 0 0 0 rg (>) Tj (>) Tj (>) Tj ( shapes[3].shapeType) Tj T* (5) Tj T* ET
+Q
+Q
+Q
+Q
+Q
+q
+1 0 0 1 62.69291 393.0236 cm
+Q
+q
+1 0 0 1 62.69291 351.0236 cm
+0 0 0 rg
+BT /F1 10 Tf 12 TL ET
+BT 1 0 0 1 0 2 Tm T* ET
+q
+1 0 0 1 20 36 cm
+Q
+q
+1 0 0 1 20 36 cm
+Q
+q
+1 0 0 1 20 0 cm
+0 0 0 rg
+BT /F1 10 Tf 12 TL ET
+q
+1 0 0 1 6 21 cm
+q
+0 0 0 rg
+BT 1 0 0 1 0 2 Tm /F1 10 Tf 12 TL 10.5 0 Td (\177) Tj T* -10.5 0 Td ET
+Q
+Q
+q
+1 0 0 1 23 -3 cm
+q
+0 0 0 rg
+BT 1 0 0 1 0 26 Tm /F1 10 Tf 12 TL 3.495697 Tw (bbox: If the shape type contains multiple points this tuple describes the lower left \(x,y\)) Tj T* 0 Tw .91284 Tw (coordinate and upper right corner coordinate creating a complete box around the points. If the) Tj T* 0 Tw (shapeType is a Null \(shapeType == 0\) then an AttributeError is raised.) Tj T* ET
+Q
+Q
+q
+Q
+Q
+q
+1 0 0 1 20 0 cm
+Q
+q
+Q
+Q
+q
+1 0 0 1 62.69291 351.0236 cm
+Q
+q
+1 0 0 1 62.69291 269.8236 cm
+q
+q
+1 0 0 1 0 0 cm
+q
+1 0 0 1 6.6 6.6 cm
+q
+.662745 .662745 .662745 RG
+.5 w
+.960784 .960784 .862745 rg
+n -6 -6 468.6898 72 re B*
+Q
+q
+BT 1 0 0 1 0 50 Tm 12 TL /F3 10 Tf 0 0 0 rg (>) Tj (>) Tj (>) Tj ( # Get the bounding box of the 4th shape.) Tj T* (>) Tj (>) Tj (>) Tj ( # Round coordinates to 3 decimal places) Tj T* (>) Tj (>) Tj (>) Tj ( bbox = shapes[3].bbox) Tj T* (>) Tj (>) Tj (>) Tj ( ['%.3f' % coord for coord in bbox]) Tj T* (['-122.486', '37.787', '-122.446', '37.811']) Tj T* ET
+Q
+Q
+Q
+Q
+Q
+q
+1 0 0 1 62.69291 255.8236 cm
+Q
+q
+1 0 0 1 62.69291 213.8236 cm
+0 0 0 rg
+BT /F1 10 Tf 12 TL ET
+BT 1 0 0 1 0 2 Tm T* ET
+q
+1 0 0 1 20 36 cm
+Q
+q
+1 0 0 1 20 36 cm
+Q
+q
+1 0 0 1 20 0 cm
+0 0 0 rg
+BT /F1 10 Tf 12 TL ET
+q
+1 0 0 1 6 21 cm
+q
+0 0 0 rg
+BT 1 0 0 1 0 2 Tm /F1 10 Tf 12 TL 10.5 0 Td (\177) Tj T* -10.5 0 Td ET
+Q
+Q
+q
+1 0 0 1 23 -3 cm
+q
+0 0 0 rg
+BT 1 0 0 1 0 26 Tm /F1 10 Tf 12 TL .150651 Tw (parts: Parts simply group collections of points into shapes. If the shape record has multiple parts) Tj T* 0 Tw .471988 Tw (this attribute contains the index of the first point of each part. If there is only one part then a list) Tj T* 0 Tw (containing 0 is returned.) Tj T* ET
+Q
+Q
+q
+Q
+Q
+q
+1 0 0 1 20 0 cm
+Q
+q
+Q
+Q
+q
+1 0 0 1 62.69291 213.8236 cm
+Q
+q
+1 0 0 1 62.69291 168.6236 cm
+q
+q
+1 0 0 1 0 0 cm
+q
+1 0 0 1 6.6 6.6 cm
+q
+.662745 .662745 .662745 RG
+.5 w
+.960784 .960784 .862745 rg
+n -6 -6 468.6898 36 re B*
+Q
+q
+BT 1 0 0 1 0 14 Tm 12 TL /F3 10 Tf 0 0 0 rg (>) Tj (>) Tj (>) Tj ( shapes[3].parts) Tj T* ([0]) Tj T* ET
+Q
+Q
+Q
+Q
+Q
+q
+1 0 0 1 62.69291 154.6236 cm
+Q
+q
+1 0 0 1 62.69291 124.6236 cm
+0 0 0 rg
+BT /F1 10 Tf 12 TL ET
+BT 1 0 0 1 0 2 Tm T* ET
+q
+1 0 0 1 20 24 cm
+Q
+q
+1 0 0 1 20 24 cm
+Q
+q
+1 0 0 1 20 0 cm
+0 0 0 rg
+BT /F1 10 Tf 12 TL ET
+q
+1 0 0 1 6 9 cm
+q
+0 0 0 rg
+BT 1 0 0 1 0 2 Tm /F1 10 Tf 12 TL 10.5 0 Td (\177) Tj T* -10.5 0 Td ET
+Q
+Q
+q
+1 0 0 1 23 -3 cm
+q
+0 0 0 rg
+BT 1 0 0 1 0 14 Tm /F1 10 Tf 12 TL .519318 Tw (points: The points attribute contains a list of tuples containing an \(x,y\) coordinate for each point) Tj T* 0 Tw (in the shape.) Tj T* ET
+Q
+Q
+q
+Q
+Q
+q
+1 0 0 1 20 0 cm
+Q
+q
+Q
+Q
+q
+1 0 0 1 62.69291 124.6236 cm
+Q
+q
+1 0 0 1 62.69291 79.42362 cm
+q
+q
+1 0 0 1 0 0 cm
+q
+1 0 0 1 6.6 6.6 cm
+q
+.662745 .662745 .662745 RG
+.5 w
+.960784 .960784 .862745 rg
+n -6 -6 468.6898 36 re B*
+Q
+q
+BT 1 0 0 1 0 14 Tm 12 TL /F3 10 Tf 0 0 0 rg (>) Tj (>) Tj (>) Tj ( len\(shapes[3].points\)) Tj T* (173) Tj T* ET
+Q
+Q
+Q
+Q
+Q
+
+endstream
+endobj
+% 'R82': class PDFStream
+82 0 obj
+% page stream
+<< /Length 6444 >>
+stream
+1 0 0 1 0 0 cm BT /F1 12 Tf 14.4 TL ET
+q
+1 0 0 1 62.69291 691.8236 cm
+q
+q
+1 0 0 1 0 0 cm
+q
+1 0 0 1 6.6 6.6 cm
+q
+.662745 .662745 .662745 RG
+.5 w
+.960784 .960784 .862745 rg
+n -6 -6 468.6898 72 re B*
+Q
+q
+BT 1 0 0 1 0 50 Tm 12 TL /F3 10 Tf 0 0 0 rg (>) Tj (>) Tj (>) Tj ( # Get the 8th point of the fourth shape) Tj T* (>) Tj (>) Tj (>) Tj ( # Truncate coordinates to 3 decimal places) Tj T* (>) Tj (>) Tj (>) Tj ( shape = shapes[3].points[7]) Tj T* (>) Tj (>) Tj (>) Tj ( ['%.3f' % coord for coord in shape]) Tj T* (['-122.471', '37.787']) Tj T* ET
+Q
+Q
+Q
+Q
+Q
+q
+1 0 0 1 62.69291 659.8236 cm
+q
+0 0 0 rg
+BT 1 0 0 1 0 14 Tm /F1 10 Tf 12 TL .081988 Tw (To read a single shape by calling its index use the shape\(\) method. The index is the shape's count from 0.) Tj T* 0 Tw (So to read the 8th shape record you would use its index which is 7.) Tj T* ET
+Q
+Q
+q
+1 0 0 1 62.69291 626.6236 cm
+q
+q
+1 0 0 1 0 0 cm
+q
+1 0 0 1 6.6 6.6 cm
+q
+.662745 .662745 .662745 RG
+.5 w
+.960784 .960784 .862745 rg
+n -6 -6 468.6898 24 re B*
+Q
+q
+BT 1 0 0 1 0 2 Tm 12 TL /F3 10 Tf 0 0 0 rg (>) Tj (>) Tj (>) Tj ( s = sf.shape\(7\)) Tj T* ET
+Q
+Q
+Q
+Q
+Q
+q
+1 0 0 1 62.69291 557.4236 cm
+q
+q
+1 0 0 1 0 0 cm
+q
+1 0 0 1 6.6 6.6 cm
+q
+.662745 .662745 .662745 RG
+.5 w
+.960784 .960784 .862745 rg
+n -6 -6 468.6898 60 re B*
+Q
+q
+BT 1 0 0 1 0 38 Tm 12 TL /F3 10 Tf 0 0 0 rg (>) Tj (>) Tj (>) Tj ( # Read the bbox of the 8th shape to verify) Tj T* (>) Tj (>) Tj (>) Tj ( # Round coordinates to 3 decimal places) Tj T* (>) Tj (>) Tj (>) Tj ( ['%.3f' % coord for coord in s.bbox]) Tj T* (['-122.450', '37.801', '-122.442', '37.808']) Tj T* ET
+Q
+Q
+Q
+Q
+Q
+q
+1 0 0 1 62.69291 530.4236 cm
+q
+BT 1 0 0 1 0 2.5 Tm 15 TL /F4 12.5 Tf 0 0 0 rg (Reading Records) Tj T* ET
+Q
+Q
+q
+1 0 0 1 62.69291 476.4236 cm
+q
+0 0 0 rg
+BT 1 0 0 1 0 38 Tm /F1 10 Tf 12 TL .797633 Tw (A record in a shapefile contains the attributes for each shape in the collection of geometry. Records are) Tj T* 0 Tw 3.459318 Tw (stored in the dbf file. The link between geometry and attributes is the foundation of Geographic) Tj T* 0 Tw .607485 Tw (Information Systems. This critical link is implied by the order of shapes and corresponding records in the) Tj T* 0 Tw (shp geometry file and the dbf attribute file.) Tj T* ET
+Q
+Q
+q
+1 0 0 1 62.69291 446.4236 cm
+q
+0 0 0 rg
+BT 1 0 0 1 0 14 Tm /F1 10 Tf 12 TL 1.21683 Tw (The field names of a shapefile are available as soon as you read a shapefile. You can call the "fields") Tj T* 0 Tw (attribute of the shapefile as a Python list. Each field is a Python list with the following information:) Tj T* ET
+Q
+Q
+q
+1 0 0 1 62.69291 440.4236 cm
+Q
+q
+1 0 0 1 62.69291 440.4236 cm
+Q
+q
+1 0 0 1 62.69291 428.4236 cm
+0 0 0 rg
+BT /F1 10 Tf 12 TL ET
+q
+1 0 0 1 6 -3 cm
+q
+0 0 0 rg
+BT 1 0 0 1 0 2 Tm /F1 10 Tf 12 TL 10.5 0 Td (\177) Tj T* -10.5 0 Td ET
+Q
+Q
+q
+1 0 0 1 23 -3 cm
+q
+0 0 0 rg
+BT 1 0 0 1 0 2 Tm /F1 10 Tf 12 TL (Field name: the name describing the data at this column index.) Tj T* ET
+Q
+Q
+q
+Q
+Q
+q
+1 0 0 1 62.69291 422.4236 cm
+Q
+q
+1 0 0 1 62.69291 398.4236 cm
+0 0 0 rg
+BT /F1 10 Tf 12 TL ET
+q
+1 0 0 1 6 9 cm
+q
+0 0 0 rg
+BT 1 0 0 1 0 2 Tm /F1 10 Tf 12 TL 10.5 0 Td (\177) Tj T* -10.5 0 Td ET
+Q
+Q
+q
+1 0 0 1 23 -3 cm
+q
+0 0 0 rg
+BT 1 0 0 1 0 14 Tm /F1 10 Tf 12 TL .591235 Tw (Field type: the type of data at this column index. Types can be: Character, Numbers, Longs, Dates,) Tj T* 0 Tw (or Memo. The "Memo" type has no meaning within a GIS and is part of the xbase spec instead.) Tj T* ET
+Q
+Q
+q
+Q
+Q
+q
+1 0 0 1 62.69291 392.4236 cm
+Q
+q
+1 0 0 1 62.69291 368.4236 cm
+0 0 0 rg
+BT /F1 10 Tf 12 TL ET
+q
+1 0 0 1 6 9 cm
+q
+0 0 0 rg
+BT 1 0 0 1 0 2 Tm /F1 10 Tf 12 TL 10.5 0 Td (\177) Tj T* -10.5 0 Td ET
+Q
+Q
+q
+1 0 0 1 23 -3 cm
+q
+0 0 0 rg
+BT 1 0 0 1 0 14 Tm /F1 10 Tf 12 TL .424692 Tw (Field length: the length of the data found at this column index. Older GIS software may truncate this) Tj T* 0 Tw (length to 8 or 11 characters for "Character" fields.) Tj T* ET
+Q
+Q
+q
+Q
+Q
+q
+1 0 0 1 62.69291 362.4236 cm
+Q
+q
+1 0 0 1 62.69291 350.4236 cm
+0 0 0 rg
+BT /F1 10 Tf 12 TL ET
+q
+1 0 0 1 6 -3 cm
+q
+0 0 0 rg
+BT 1 0 0 1 0 2 Tm /F1 10 Tf 12 TL 10.5 0 Td (\177) Tj T* -10.5 0 Td ET
+Q
+Q
+q
+1 0 0 1 23 -3 cm
+q
+0 0 0 rg
+BT 1 0 0 1 0 2 Tm /F1 10 Tf 12 TL (Decimal length: the number of decimal places found in "Number" fields.) Tj T* ET
+Q
+Q
+q
+Q
+Q
+q
+1 0 0 1 62.69291 350.4236 cm
+Q
+q
+1 0 0 1 62.69291 332.4236 cm
+q
+0 0 0 rg
+BT 1 0 0 1 0 2 Tm /F1 10 Tf 12 TL (To see the fields for the Reader object above \(sf\) call the "fields" attribute:) Tj T* ET
+Q
+Q
+q
+1 0 0 1 62.69291 299.2236 cm
+q
+q
+1 0 0 1 0 0 cm
+q
+1 0 0 1 6.6 6.6 cm
+q
+.662745 .662745 .662745 RG
+.5 w
+.960784 .960784 .862745 rg
+n -6 -6 468.6898 24 re B*
+Q
+q
+BT 1 0 0 1 0 2 Tm 12 TL /F3 10 Tf 0 0 0 rg (>) Tj (>) Tj (>) Tj ( fields = sf.fields) Tj T* ET
+Q
+Q
+Q
+Q
+Q
+q
+1 0 0 1 62.69291 95.72204 cm
+q
+q
+.952737 0 0 .952737 0 0 cm
+q
+1 0 0 1 6.6 6.927412 cm
+q
+.662745 .662745 .662745 RG
+.5 w
+.960784 .960784 .862745 rg
+n -6 -6 492 204 re B*
+Q
+q
+BT 1 0 0 1 0 182 Tm 12 TL /F3 10 Tf 0 0 0 rg (>) Tj (>) Tj (>) Tj ( assert fields == [\("DeletionFlag", "C", 1, 0\), ["AREA", "N", 18, 5],) Tj T* (... ["BKG_KEY", "C", 12, 0], ["POP1990", "N", 9, 0], ["POP90_SQMI", "N", 10, 1],) Tj T* (... ["HOUSEHOLDS", "N", 9, 0],) Tj T* (... ["MALES", "N", 9, 0], ["FEMALES", "N", 9, 0], ["WHITE", "N", 9, 0],) Tj T* (... ["BLACK", "N", 8, 0], ["AMERI_ES", "N", 7, 0], ["ASIAN_PI", "N", 8, 0],) Tj T* (... ["OTHER", "N", 8, 0], ["HISPANIC", "N", 8, 0], [" [...]
+Q
+Q
+Q
+Q
+Q
+
+endstream
+endobj
+% 'R83': class PDFStream
+83 0 obj
+% page stream
+<< /Length 5569 >>
+stream
+1 0 0 1 0 0 cm BT /F1 12 Tf 14.4 TL ET
+q
+1 0 0 1 62.69291 727.8236 cm
+q
+q
+1 0 0 1 0 0 cm
+q
+1 0 0 1 6.6 6.6 cm
+q
+.662745 .662745 .662745 RG
+.5 w
+.960784 .960784 .862745 rg
+n -6 -6 468.6898 36 re B*
+Q
+q
+BT 1 0 0 1 0 14 Tm 12 TL /F3 10 Tf 0 0 0 rg (... ["UNITS3_9", "N", 8, 0], ["UNITS10_49", "N", 8, 0],) Tj T* (... ["UNITS50_UP", "N", 8, 0], ["MOBILEHOME", "N", 7, 0]]) Tj T* ET
+Q
+Q
+Q
+Q
+Q
+q
+1 0 0 1 62.69291 707.8236 cm
+q
+0 0 0 rg
+BT 1 0 0 1 0 2 Tm /F1 10 Tf 12 TL (You can get a list of the shapefile's records by calling the records\(\) method:) Tj T* ET
+Q
+Q
+q
+1 0 0 1 62.69291 674.6236 cm
+q
+q
+1 0 0 1 0 0 cm
+q
+1 0 0 1 6.6 6.6 cm
+q
+.662745 .662745 .662745 RG
+.5 w
+.960784 .960784 .862745 rg
+n -6 -6 468.6898 24 re B*
+Q
+q
+BT 1 0 0 1 0 2 Tm 12 TL /F3 10 Tf 0 0 0 rg (>) Tj (>) Tj (>) Tj ( records = sf.records\(\)) Tj T* ET
+Q
+Q
+Q
+Q
+Q
+q
+1 0 0 1 62.69291 629.4236 cm
+q
+q
+1 0 0 1 0 0 cm
+q
+1 0 0 1 6.6 6.6 cm
+q
+.662745 .662745 .662745 RG
+.5 w
+.960784 .960784 .862745 rg
+n -6 -6 468.6898 36 re B*
+Q
+q
+BT 1 0 0 1 0 14 Tm 12 TL /F3 10 Tf 0 0 0 rg (>) Tj (>) Tj (>) Tj ( len\(records\)) Tj T* (663) Tj T* ET
+Q
+Q
+Q
+Q
+Q
+q
+1 0 0 1 62.69291 609.4236 cm
+q
+0 0 0 rg
+BT 1 0 0 1 0 2 Tm /F1 10 Tf 12 TL (Similar to the geometry methods, you can iterate through dbf records using the recordsIter\(\) method.) Tj T* ET
+Q
+Q
+q
+1 0 0 1 62.69291 564.2236 cm
+q
+q
+1 0 0 1 0 0 cm
+q
+1 0 0 1 6.6 6.6 cm
+q
+.662745 .662745 .662745 RG
+.5 w
+.960784 .960784 .862745 rg
+n -6 -6 468.6898 36 re B*
+Q
+q
+BT 1 0 0 1 0 14 Tm 12 TL /F3 10 Tf 0 0 0 rg (>) Tj (>) Tj (>) Tj ( len\(list\(sf.iterRecords\(\)\)\)) Tj T* (663) Tj T* ET
+Q
+Q
+Q
+Q
+Q
+q
+1 0 0 1 62.69291 544.2236 cm
+q
+0 0 0 rg
+BT 1 0 0 1 0 2 Tm /F1 10 Tf 12 TL (Each record is a list containing an attribute corresponding to each field in the field list.) Tj T* ET
+Q
+Q
+q
+1 0 0 1 62.69291 514.2236 cm
+q
+0 0 0 rg
+BT 1 0 0 1 0 14 Tm /F1 10 Tf 12 TL .937765 Tw (For example in the 4th record of the blockgroups shapefile the 2nd and 3rd fields are the blockgroup id) Tj T* 0 Tw (and the 1990 population count of that San Francisco blockgroup:) Tj T* ET
+Q
+Q
+q
+1 0 0 1 62.69291 469.0236 cm
+q
+q
+1 0 0 1 0 0 cm
+q
+1 0 0 1 6.6 6.6 cm
+q
+.662745 .662745 .662745 RG
+.5 w
+.960784 .960784 .862745 rg
+n -6 -6 468.6898 36 re B*
+Q
+q
+BT 1 0 0 1 0 14 Tm 12 TL /F3 10 Tf 0 0 0 rg (>) Tj (>) Tj (>) Tj ( records[3][1:3]) Tj T* (['060750601001', 4715]) Tj T* ET
+Q
+Q
+Q
+Q
+Q
+q
+1 0 0 1 62.69291 449.0236 cm
+q
+0 0 0 rg
+BT 1 0 0 1 0 2 Tm /F1 10 Tf 12 TL (To read a single record call the record\(\) method with the record's index:) Tj T* ET
+Q
+Q
+q
+1 0 0 1 62.69291 415.8236 cm
+q
+q
+1 0 0 1 0 0 cm
+q
+1 0 0 1 6.6 6.6 cm
+q
+.662745 .662745 .662745 RG
+.5 w
+.960784 .960784 .862745 rg
+n -6 -6 468.6898 24 re B*
+Q
+q
+BT 1 0 0 1 0 2 Tm 12 TL /F3 10 Tf 0 0 0 rg (>) Tj (>) Tj (>) Tj ( rec = sf.record\(3\)) Tj T* ET
+Q
+Q
+Q
+Q
+Q
+q
+1 0 0 1 62.69291 370.6236 cm
+q
+q
+1 0 0 1 0 0 cm
+q
+1 0 0 1 6.6 6.6 cm
+q
+.662745 .662745 .662745 RG
+.5 w
+.960784 .960784 .862745 rg
+n -6 -6 468.6898 36 re B*
+Q
+q
+BT 1 0 0 1 0 14 Tm 12 TL /F3 10 Tf 0 0 0 rg (>) Tj (>) Tj (>) Tj ( rec[1:3]) Tj T* (['060750601001', 4715]) Tj T* ET
+Q
+Q
+Q
+Q
+Q
+q
+1 0 0 1 62.69291 343.6236 cm
+q
+BT 1 0 0 1 0 2.5 Tm 15 TL /F4 12.5 Tf 0 0 0 rg (Reading Geometry and Records Simultaneously) Tj T* ET
+Q
+Q
+q
+1 0 0 1 62.69291 313.6236 cm
+q
+0 0 0 rg
+BT 1 0 0 1 0 14 Tm /F1 10 Tf 12 TL 2.17332 Tw (You way want to examine both the geometry and the attributes for a record at the same time. The) Tj T* 0 Tw (shapeRecord\(\) and shapeRecords\(\) method let you do just that.) Tj T* ET
+Q
+Q
+q
+1 0 0 1 62.69291 259.6236 cm
+q
+0 0 0 rg
+BT 1 0 0 1 0 38 Tm /F1 10 Tf 12 TL 2.03061 Tw (Calling the shapeRecords\(\) method will return the geometry and attributes for all shapes as a list of) Tj T* 0 Tw 2.353314 Tw (ShapeRecord objects. Each ShapeRecord instance has a "shape" and "record" attribute. The shape) Tj T* 0 Tw 2.725697 Tw (attribute is a ShapeRecord object as dicussed in the first section "Reading Geometry". The record) Tj T* 0 Tw (attribute is a list of field values as demonstrated in the "Reading Records" section. [...]
+Q
+Q
+q
+1 0 0 1 62.69291 226.4236 cm
+q
+q
+1 0 0 1 0 0 cm
+q
+1 0 0 1 6.6 6.6 cm
+q
+.662745 .662745 .662745 RG
+.5 w
+.960784 .960784 .862745 rg
+n -6 -6 468.6898 24 re B*
+Q
+q
+BT 1 0 0 1 0 2 Tm 12 TL /F3 10 Tf 0 0 0 rg (>) Tj (>) Tj (>) Tj ( shapeRecs = sf.shapeRecords\(\)) Tj T* ET
+Q
+Q
+Q
+Q
+Q
+q
+1 0 0 1 62.69291 194.4236 cm
+q
+BT 1 0 0 1 0 14 Tm 1.34152 Tw 12 TL /F1 10 Tf 0 0 0 rg (Let's read the blockgroup key and the population for the 4th blockgroup: >) Tj (>) Tj (> shapeRecs[3].record[1:3]) Tj T* 0 Tw (['060750601001', 4715]) Tj T* ET
+Q
+Q
+q
+1 0 0 1 62.69291 176.4236 cm
+q
+0 0 0 rg
+BT 1 0 0 1 0 2 Tm /F1 10 Tf 12 TL (Now let's read the first two points for that same record:) Tj T* ET
+Q
+Q
+q
+1 0 0 1 62.69291 143.2236 cm
+q
+q
+1 0 0 1 0 0 cm
+q
+1 0 0 1 6.6 6.6 cm
+q
+.662745 .662745 .662745 RG
+.5 w
+.960784 .960784 .862745 rg
+n -6 -6 468.6898 24 re B*
+Q
+q
+BT 1 0 0 1 0 2 Tm 12 TL /F3 10 Tf 0 0 0 rg (>) Tj (>) Tj (>) Tj ( points = shapeRecs[3].shape.points[0:2]) Tj T* ET
+Q
+Q
+Q
+Q
+Q
+q
+1 0 0 1 62.69291 98.02362 cm
+q
+q
+1 0 0 1 0 0 cm
+q
+1 0 0 1 6.6 6.6 cm
+q
+.662745 .662745 .662745 RG
+.5 w
+.960784 .960784 .862745 rg
+n -6 -6 468.6898 36 re B*
+Q
+q
+BT 1 0 0 1 0 14 Tm 12 TL /F3 10 Tf 0 0 0 rg (>) Tj (>) Tj (>) Tj ( len\(points\)) Tj T* (2) Tj T* ET
+Q
+Q
+Q
+Q
+Q
+
+endstream
+endobj
+% 'R84': class PDFStream
+84 0 obj
+% page stream
+<< /Length 5654 >>
+stream
+1 0 0 1 0 0 cm BT /F1 12 Tf 14.4 TL ET
+q
+1 0 0 1 62.69291 741.0236 cm
+q
+0 0 0 rg
+BT 1 0 0 1 0 14 Tm /F1 10 Tf 12 TL 1.402485 Tw (The shapeRec\(\) method reads a single shape/record pair at the specified index. To get the 4th shape) Tj T* 0 Tw (record from the blockgroups shapfile use the third index:) Tj T* ET
+Q
+Q
+q
+1 0 0 1 62.69291 707.8236 cm
+q
+q
+1 0 0 1 0 0 cm
+q
+1 0 0 1 6.6 6.6 cm
+q
+.662745 .662745 .662745 RG
+.5 w
+.960784 .960784 .862745 rg
+n -6 -6 468.6898 24 re B*
+Q
+q
+BT 1 0 0 1 0 2 Tm 12 TL /F3 10 Tf 0 0 0 rg (>) Tj (>) Tj (>) Tj ( shapeRec = sf.shapeRecord\(3\)) Tj T* ET
+Q
+Q
+Q
+Q
+Q
+q
+1 0 0 1 62.69291 687.8236 cm
+q
+0 0 0 rg
+BT 1 0 0 1 0 2 Tm /F1 10 Tf 12 TL (The blockgroup key and population count:) Tj T* ET
+Q
+Q
+q
+1 0 0 1 62.69291 642.6236 cm
+q
+q
+1 0 0 1 0 0 cm
+q
+1 0 0 1 6.6 6.6 cm
+q
+.662745 .662745 .662745 RG
+.5 w
+.960784 .960784 .862745 rg
+n -6 -6 468.6898 36 re B*
+Q
+q
+BT 1 0 0 1 0 14 Tm 12 TL /F3 10 Tf 0 0 0 rg (>) Tj (>) Tj (>) Tj ( shapeRec.record[1:3]) Tj T* (['060750601001', 4715]) Tj T* ET
+Q
+Q
+Q
+Q
+Q
+q
+1 0 0 1 62.69291 609.4236 cm
+q
+q
+1 0 0 1 0 0 cm
+q
+1 0 0 1 6.6 6.6 cm
+q
+.662745 .662745 .662745 RG
+.5 w
+.960784 .960784 .862745 rg
+n -6 -6 468.6898 24 re B*
+Q
+q
+BT 1 0 0 1 0 2 Tm 12 TL /F3 10 Tf 0 0 0 rg (>) Tj (>) Tj (>) Tj ( points = shapeRec.shape.points[0:2]) Tj T* ET
+Q
+Q
+Q
+Q
+Q
+q
+1 0 0 1 62.69291 564.2236 cm
+q
+q
+1 0 0 1 0 0 cm
+q
+1 0 0 1 6.6 6.6 cm
+q
+.662745 .662745 .662745 RG
+.5 w
+.960784 .960784 .862745 rg
+n -6 -6 468.6898 36 re B*
+Q
+q
+BT 1 0 0 1 0 14 Tm 12 TL /F3 10 Tf 0 0 0 rg (>) Tj (>) Tj (>) Tj ( len\(points\)) Tj T* (2) Tj T* ET
+Q
+Q
+Q
+Q
+Q
+q
+1 0 0 1 62.69291 534.2236 cm
+q
+BT 1 0 0 1 0 3 Tm 18 TL /F2 15 Tf 0 0 0 rg (Writing Shapefiles) Tj T* ET
+Q
+Q
+q
+1 0 0 1 62.69291 504.2236 cm
+q
+0 0 0 rg
+BT 1 0 0 1 0 14 Tm /F1 10 Tf 12 TL 2.387984 Tw (PyShp tries to be as flexible as possible when writing shapefiles while maintaining some degree of) Tj T* 0 Tw (automatic validation to make sure you don't accidentally write an invalid file.) Tj T* ET
+Q
+Q
+q
+1 0 0 1 62.69291 414.2236 cm
+q
+0 0 0 rg
+BT 1 0 0 1 0 74 Tm /F1 10 Tf 12 TL .036655 Tw (PyShp can write just one of the component files such as the shp or dbf file without writing the others. So in) Tj T* 0 Tw .568409 Tw (addition to being a complete shapefile library, it can also be used as a basic dbf \(xbase\) library. Dbf files) Tj T* 0 Tw .18686 Tw (are a common database format which are often useful as a standalone simple database format. And even) Tj T* 0 Tw 3.549983 Tw (shp files occasionaly have uses as a standalone fo [...]
+Q
+Q
+q
+1 0 0 1 62.69291 384.2236 cm
+q
+0 0 0 rg
+BT 1 0 0 1 0 14 Tm /F1 10 Tf 12 TL .667633 Tw (To create a shapefile you add geometry and/or attributes using methods in the Writer class until you are) Tj T* 0 Tw (ready to save the file.) Tj T* ET
+Q
+Q
+q
+1 0 0 1 62.69291 366.2236 cm
+q
+0 0 0 rg
+BT 1 0 0 1 0 2 Tm /F1 10 Tf 12 TL (Create an instance of the Writer class to begin creating a shapefile:) Tj T* ET
+Q
+Q
+q
+1 0 0 1 62.69291 333.0236 cm
+q
+q
+1 0 0 1 0 0 cm
+q
+1 0 0 1 6.6 6.6 cm
+q
+.662745 .662745 .662745 RG
+.5 w
+.960784 .960784 .862745 rg
+n -6 -6 468.6898 24 re B*
+Q
+q
+BT 1 0 0 1 0 2 Tm 12 TL /F3 10 Tf 0 0 0 rg (>) Tj (>) Tj (>) Tj ( w = shapefile.Writer\(\)) Tj T* ET
+Q
+Q
+Q
+Q
+Q
+q
+1 0 0 1 62.69291 306.0236 cm
+q
+BT 1 0 0 1 0 2.5 Tm 15 TL /F4 12.5 Tf 0 0 0 rg (Setting the Shape Type) Tj T* ET
+Q
+Q
+q
+1 0 0 1 62.69291 276.0236 cm
+q
+0 0 0 rg
+BT 1 0 0 1 0 14 Tm /F1 10 Tf 12 TL .28832 Tw (The shape type defines the type of geometry contained in the shapefile. All of the shapes must match the) Tj T* 0 Tw (shape type setting.) Tj T* ET
+Q
+Q
+q
+1 0 0 1 62.69291 234.0236 cm
+q
+0 0 0 rg
+BT 1 0 0 1 0 26 Tm /F1 10 Tf 12 TL .174692 Tw (Shape types are represented by numbers between 0 and 31 as defined by the shapefile specification. It is) Tj T* 0 Tw 1.237984 Tw (important to note that numbering system has several reserved numbers which have not been used yet) Tj T* 0 Tw (therefore the numbers of the existing shape types are not sequential.) Tj T* ET
+Q
+Q
+q
+1 0 0 1 62.69291 168.0236 cm
+q
+0 0 0 rg
+BT 1 0 0 1 0 50 Tm /F1 10 Tf 12 TL 1.07186 Tw (You can reference shape types by the numbers or by constants defined by PyShp: shapefile.NULL = 0) Tj T* 0 Tw 3.001797 Tw (shapefile.POINT = 1 shapefile.POLYLINE = 3 shapefile.POLYGON = 5 shapefile.MULTIPOINT = 8) Tj T* 0 Tw .023976 Tw (shapefile.POINTZ = 11 shapefile.POLYLINEZ = 13 shapefile.POLYGONZ = 15 shapefile.MULTIPOINTZ =) Tj T* 0 Tw 11.1722 Tw (18 shapefile.POINTM = 21 shapefile.POLYLINEM = 23 shapefile.POLYGONM = 25) Tj T* 0 Tw (sh [...]
+Q
+Q
+q
+1 0 0 1 62.69291 126.0236 cm
+q
+0 0 0 rg
+BT 1 0 0 1 0 26 Tm /F1 10 Tf 12 TL .24856 Tw (There are three ways to set the shape type: - Set it when creating the class instance. - Set it by assigning) Tj T* 0 Tw 1.344488 Tw (a value to an existing class instance. - Set it automatically to the type of the first shape by saving the) Tj T* 0 Tw (shapefile.) Tj T* ET
+Q
+Q
+q
+1 0 0 1 62.69291 108.0236 cm
+q
+0 0 0 rg
+BT 1 0 0 1 0 2 Tm /F1 10 Tf 12 TL (To manually set the shape type for a Writer object when creating the Writer:) Tj T* ET
+Q
+Q
+
+endstream
+endobj
+% 'R85': class PDFStream
+85 0 obj
+% page stream
+<< /Length 5706 >>
+stream
+1 0 0 1 0 0 cm BT /F1 12 Tf 14.4 TL ET
+q
+1 0 0 1 62.69291 739.8236 cm
+q
+q
+1 0 0 1 0 0 cm
+q
+1 0 0 1 6.6 6.6 cm
+q
+.662745 .662745 .662745 RG
+.5 w
+.960784 .960784 .862745 rg
+n -6 -6 468.6898 24 re B*
+Q
+q
+BT 1 0 0 1 0 2 Tm 12 TL /F3 10 Tf 0 0 0 rg (>) Tj (>) Tj (>) Tj ( w = shapefile.Writer\(shapeType=1\)) Tj T* ET
+Q
+Q
+Q
+Q
+Q
+q
+1 0 0 1 62.69291 719.8236 cm
+q
+0 0 0 rg
+BT 1 0 0 1 0 2 Tm /F1 10 Tf 12 TL (or we can use the constants as explained above:) Tj T* ET
+Q
+Q
+q
+1 0 0 1 62.69291 686.6236 cm
+q
+q
+1 0 0 1 0 0 cm
+q
+1 0 0 1 6.6 6.6 cm
+q
+.662745 .662745 .662745 RG
+.5 w
+.960784 .960784 .862745 rg
+n -6 -6 468.6898 24 re B*
+Q
+q
+BT 1 0 0 1 0 2 Tm 12 TL /F3 10 Tf 0 0 0 rg (>) Tj (>) Tj (>) Tj ( w = shapefile.Writer\(shapefile.POINT\)) Tj T* ET
+Q
+Q
+Q
+Q
+Q
+q
+1 0 0 1 62.69291 666.6236 cm
+q
+0 0 0 rg
+BT 1 0 0 1 0 2 Tm /F1 10 Tf 12 TL (As you can see, specifying the shapeType argument explicitly isn't necessary.) Tj T* ET
+Q
+Q
+q
+1 0 0 1 62.69291 621.4236 cm
+q
+q
+1 0 0 1 0 0 cm
+q
+1 0 0 1 6.6 6.6 cm
+q
+.662745 .662745 .662745 RG
+.5 w
+.960784 .960784 .862745 rg
+n -6 -6 468.6898 36 re B*
+Q
+q
+BT 1 0 0 1 0 14 Tm 12 TL /F3 10 Tf 0 0 0 rg (>) Tj (>) Tj (>) Tj ( w.shapeType) Tj T* (1) Tj T* ET
+Q
+Q
+Q
+Q
+Q
+q
+1 0 0 1 62.69291 601.4236 cm
+q
+0 0 0 rg
+BT 1 0 0 1 0 2 Tm /F1 10 Tf 12 TL (OR you can set it after the Writer is created by changing the property:) Tj T* ET
+Q
+Q
+q
+1 0 0 1 62.69291 568.2236 cm
+q
+q
+1 0 0 1 0 0 cm
+q
+1 0 0 1 6.6 6.6 cm
+q
+.662745 .662745 .662745 RG
+.5 w
+.960784 .960784 .862745 rg
+n -6 -6 468.6898 24 re B*
+Q
+q
+BT 1 0 0 1 0 2 Tm 12 TL /F3 10 Tf 0 0 0 rg (>) Tj (>) Tj (>) Tj ( w.shapeType = 3) Tj T* ET
+Q
+Q
+Q
+Q
+Q
+q
+1 0 0 1 62.69291 523.0236 cm
+q
+q
+1 0 0 1 0 0 cm
+q
+1 0 0 1 6.6 6.6 cm
+q
+.662745 .662745 .662745 RG
+.5 w
+.960784 .960784 .862745 rg
+n -6 -6 468.6898 36 re B*
+Q
+q
+BT 1 0 0 1 0 14 Tm 12 TL /F3 10 Tf 0 0 0 rg (>) Tj (>) Tj (>) Tj ( w.shapeType) Tj T* (3) Tj T* ET
+Q
+Q
+Q
+Q
+Q
+q
+1 0 0 1 62.69291 496.0236 cm
+q
+BT 1 0 0 1 0 2.5 Tm 15 TL /F4 12.5 Tf 0 0 0 rg (Geometry and Record Balancing) Tj T* ET
+Q
+Q
+q
+1 0 0 1 62.69291 430.0236 cm
+q
+0 0 0 rg
+BT 1 0 0 1 0 50 Tm /F1 10 Tf 12 TL .079398 Tw (Because every shape must have a corresponding record it is critical that the number of records equals the) Tj T* 0 Tw 1.607984 Tw (number of shapes to create a valid shapefile. To help prevent accidental misalignment PyShp has an) Tj T* 0 Tw 2.093672 Tw ("auto balance" feature to make sure when you add either a shape or a record the two sides of the) Tj T* 0 Tw .214724 Tw (equation line up. This feature is NOT turned on by default. To activa [...]
+Q
+Q
+q
+1 0 0 1 62.69291 396.8236 cm
+q
+q
+1 0 0 1 0 0 cm
+q
+1 0 0 1 6.6 6.6 cm
+q
+.662745 .662745 .662745 RG
+.5 w
+.960784 .960784 .862745 rg
+n -6 -6 468.6898 24 re B*
+Q
+q
+BT 1 0 0 1 0 2 Tm 12 TL /F3 10 Tf 0 0 0 rg (>) Tj (>) Tj (>) Tj ( w.autoBalance = 1) Tj T* ET
+Q
+Q
+Q
+Q
+Q
+q
+1 0 0 1 62.69291 352.8236 cm
+q
+0 0 0 rg
+BT 1 0 0 1 0 26 Tm /F1 10 Tf 12 TL .186303 Tw (You also have the option of manually calling the balance\(\) method each time you add a shape or a record) Tj T* 0 Tw .741567 Tw (to ensure the other side is up to date. When balancing is used null shapes are created on the geometry) Tj T* 0 Tw (side or a record with a value of "NULL" for each field is created on the attribute side.) Tj T* ET
+Q
+Q
+q
+1 0 0 1 62.69291 334.8236 cm
+q
+0 0 0 rg
+BT 1 0 0 1 0 2 Tm /F1 10 Tf 12 TL (The balancing option gives you flexibility in how you build the shapefile.) Tj T* ET
+Q
+Q
+q
+1 0 0 1 62.69291 280.8236 cm
+q
+0 0 0 rg
+BT 1 0 0 1 0 38 Tm /F1 10 Tf 12 TL .103876 Tw (Without auto balancing you can add geometry or records at anytime. You can create all of the shapes and) Tj T* 0 Tw 1.093145 Tw (then create all of the records or vice versa. You can use the balance method after creating a shape or) Tj T* 0 Tw .906098 Tw (record each time and make updates later. If you do not use the balance method and forget to manually) Tj T* 0 Tw (balance the geometry and attributes the shapefile will be viewed as corrupt [...]
+Q
+Q
+q
+1 0 0 1 62.69291 238.8236 cm
+q
+0 0 0 rg
+BT 1 0 0 1 0 26 Tm /F1 10 Tf 12 TL .698221 Tw (With auto balanacing you can add either shapes or geometry and update blank entries on either side as) Tj T* 0 Tw .157356 Tw (needed. Even if you forget to update an entry the shapefile will still be valid and handled correctly by most) Tj T* 0 Tw (shapefile software.) Tj T* ET
+Q
+Q
+q
+1 0 0 1 62.69291 211.8236 cm
+q
+BT 1 0 0 1 0 2.5 Tm 15 TL /F4 12.5 Tf 0 0 0 rg (Adding Geometry) Tj T* ET
+Q
+Q
+q
+1 0 0 1 62.69291 181.8236 cm
+q
+0 0 0 rg
+BT 1 0 0 1 0 14 Tm /F1 10 Tf 12 TL .256098 Tw (Geometry is added using one of three methods: "null", "point", or "poly". The "null" method is used for null) Tj T* 0 Tw (shapes, "point" is used for point shapes, and "poly" is used for everything else.) Tj T* ET
+Q
+Q
+q
+1 0 0 1 62.69291 163.8236 cm
+q
+0 0 0 rg
+BT 1 0 0 1 0 2 Tm /F2 10 Tf 12 TL (Adding a Null shape) Tj T* ET
+Q
+Q
+q
+1 0 0 1 62.69291 133.8236 cm
+q
+0 0 0 rg
+BT 1 0 0 1 0 14 Tm /F1 10 Tf 12 TL 2.14061 Tw (Because Null shape types \(shape type 0\) have no geometry the "null" method is called without any) Tj T* 0 Tw (arguments.) Tj T* ET
+Q
+Q
+q
+1 0 0 1 62.69291 100.6236 cm
+q
+q
+1 0 0 1 0 0 cm
+q
+1 0 0 1 6.6 6.6 cm
+q
+.662745 .662745 .662745 RG
+.5 w
+.960784 .960784 .862745 rg
+n -6 -6 468.6898 24 re B*
+Q
+q
+BT 1 0 0 1 0 2 Tm 12 TL /F3 10 Tf 0 0 0 rg (>) Tj (>) Tj (>) Tj ( w = shapefile.Writer\(\)) Tj T* ET
+Q
+Q
+Q
+Q
+Q
+
+endstream
+endobj
+% 'R86': class PDFStream
+86 0 obj
+% page stream
+<< /Length 5780 >>
+stream
+1 0 0 1 0 0 cm BT /F1 12 Tf 14.4 TL ET
+q
+1 0 0 1 62.69291 739.8236 cm
+q
+q
+1 0 0 1 0 0 cm
+q
+1 0 0 1 6.6 6.6 cm
+q
+.662745 .662745 .662745 RG
+.5 w
+.960784 .960784 .862745 rg
+n -6 -6 468.6898 24 re B*
+Q
+q
+BT 1 0 0 1 0 2 Tm 12 TL /F3 10 Tf 0 0 0 rg (>) Tj (>) Tj (>) Tj ( w.null\(\)) Tj T* ET
+Q
+Q
+Q
+Q
+Q
+q
+1 0 0 1 62.69291 719.8236 cm
+q
+0 0 0 rg
+BT 1 0 0 1 0 2 Tm /F1 10 Tf 12 TL (The writer object's shapes list will now have one null shape:) Tj T* ET
+Q
+Q
+q
+1 0 0 1 62.69291 686.6236 cm
+q
+q
+1 0 0 1 0 0 cm
+q
+1 0 0 1 6.6 6.6 cm
+q
+.662745 .662745 .662745 RG
+.5 w
+.960784 .960784 .862745 rg
+n -6 -6 468.6898 24 re B*
+Q
+q
+BT 1 0 0 1 0 2 Tm 12 TL /F3 10 Tf 0 0 0 rg (>) Tj (>) Tj (>) Tj ( assert w.shapes\(\)[0].shapeType == shapefile.NULL) Tj T* ET
+Q
+Q
+Q
+Q
+Q
+q
+1 0 0 1 62.69291 666.6236 cm
+q
+0 0 0 rg
+BT 1 0 0 1 0 2 Tm /F2 10 Tf 12 TL (Adding a Point shape) Tj T* ET
+Q
+Q
+q
+1 0 0 1 62.69291 636.6236 cm
+q
+0 0 0 rg
+BT 1 0 0 1 0 14 Tm /F1 10 Tf 12 TL .075251 Tw (Point shapes are added using the "point" method. A point is specified by an x, y, and optional z \(elevation\)) Tj T* 0 Tw (and m \(measure\) value.) Tj T* ET
+Q
+Q
+q
+1 0 0 1 62.69291 603.4236 cm
+q
+q
+1 0 0 1 0 0 cm
+q
+1 0 0 1 6.6 6.6 cm
+q
+.662745 .662745 .662745 RG
+.5 w
+.960784 .960784 .862745 rg
+n -6 -6 468.6898 24 re B*
+Q
+q
+BT 1 0 0 1 0 2 Tm 12 TL /F3 10 Tf 0 0 0 rg (>) Tj (>) Tj (>) Tj ( w = shapefile.Writer\(shapefile.POINT\)) Tj T* ET
+Q
+Q
+Q
+Q
+Q
+q
+1 0 0 1 62.69291 570.2236 cm
+q
+q
+1 0 0 1 0 0 cm
+q
+1 0 0 1 6.6 6.6 cm
+q
+.662745 .662745 .662745 RG
+.5 w
+.960784 .960784 .862745 rg
+n -6 -6 468.6898 24 re B*
+Q
+q
+BT 1 0 0 1 0 2 Tm 12 TL /F3 10 Tf 0 0 0 rg (>) Tj (>) Tj (>) Tj ( w.point\(122, 37\) # No elevation or measure values) Tj T* ET
+Q
+Q
+Q
+Q
+Q
+q
+1 0 0 1 62.69291 525.0236 cm
+q
+q
+1 0 0 1 0 0 cm
+q
+1 0 0 1 6.6 6.6 cm
+q
+.662745 .662745 .662745 RG
+.5 w
+.960784 .960784 .862745 rg
+n -6 -6 468.6898 36 re B*
+Q
+q
+BT 1 0 0 1 0 14 Tm 12 TL /F3 10 Tf 0 0 0 rg (>) Tj (>) Tj (>) Tj ( w.shapes\(\)[0].points) Tj T* ([[122, 37, 0, 0]]) Tj T* ET
+Q
+Q
+Q
+Q
+Q
+q
+1 0 0 1 62.69291 491.8236 cm
+q
+q
+1 0 0 1 0 0 cm
+q
+1 0 0 1 6.6 6.6 cm
+q
+.662745 .662745 .662745 RG
+.5 w
+.960784 .960784 .862745 rg
+n -6 -6 468.6898 24 re B*
+Q
+q
+BT 1 0 0 1 0 2 Tm 12 TL /F3 10 Tf 0 0 0 rg (>) Tj (>) Tj (>) Tj ( w.point\(118, 36, 4, 8\)) Tj T* ET
+Q
+Q
+Q
+Q
+Q
+q
+1 0 0 1 62.69291 446.6236 cm
+q
+q
+1 0 0 1 0 0 cm
+q
+1 0 0 1 6.6 6.6 cm
+q
+.662745 .662745 .662745 RG
+.5 w
+.960784 .960784 .862745 rg
+n -6 -6 468.6898 36 re B*
+Q
+q
+BT 1 0 0 1 0 14 Tm 12 TL /F3 10 Tf 0 0 0 rg (>) Tj (>) Tj (>) Tj ( w.shapes\(\)[1].points) Tj T* ([[118, 36, 4, 8]]) Tj T* ET
+Q
+Q
+Q
+Q
+Q
+q
+1 0 0 1 62.69291 426.6236 cm
+q
+0 0 0 rg
+BT 1 0 0 1 0 2 Tm /F2 10 Tf 12 TL (Adding a Poly Shape) Tj T* ET
+Q
+Q
+q
+1 0 0 1 62.69291 372.6236 cm
+q
+0 0 0 rg
+BT 1 0 0 1 0 38 Tm /F1 10 Tf 12 TL .20332 Tw ("Poly" shapes can be either polygons or lines. Shapefile polygons must have at least 4 points and the last) Tj T* 0 Tw .863516 Tw (point must be the same as the first. PyShp automatically enforces closed polygons. A line must have at) Tj T* 0 Tw 1.646235 Tw (least two points. Because of the similarities between these two shape types they are created using a) Tj T* 0 Tw (single method called "poly".) Tj T* ET
+Q
+Q
+q
+1 0 0 1 62.69291 339.4236 cm
+q
+q
+1 0 0 1 0 0 cm
+q
+1 0 0 1 6.6 6.6 cm
+q
+.662745 .662745 .662745 RG
+.5 w
+.960784 .960784 .862745 rg
+n -6 -6 468.6898 24 re B*
+Q
+q
+BT 1 0 0 1 0 2 Tm 12 TL /F3 10 Tf 0 0 0 rg (>) Tj (>) Tj (>) Tj ( w = shapefile.Writer\(shapefile.POLYGON\)) Tj T* ET
+Q
+Q
+Q
+Q
+Q
+q
+1 0 0 1 62.69291 294.2236 cm
+q
+q
+1 0 0 1 0 0 cm
+q
+1 0 0 1 6.6 6.6 cm
+q
+.662745 .662745 .662745 RG
+.5 w
+.960784 .960784 .862745 rg
+n -6 -6 468.6898 36 re B*
+Q
+q
+BT 1 0 0 1 0 14 Tm 12 TL /F3 10 Tf 0 0 0 rg (>) Tj (>) Tj (>) Tj ( w.poly\(shapeType=3, parts=[[[122,37,4,9], [117,36,3,4]], [[115,32,8,8],) Tj T* (... [118,20,6,4], [113,24]]]\)) Tj T* ET
+Q
+Q
+Q
+Q
+Q
+q
+1 0 0 1 62.69291 274.2236 cm
+q
+0 0 0 rg
+BT 1 0 0 1 0 2 Tm /F2 10 Tf 12 TL (Adding a Polygon with Rings) Tj T* ET
+Q
+Q
+q
+1 0 0 1 62.69291 208.2236 cm
+q
+0 0 0 rg
+BT 1 0 0 1 0 50 Tm /F1 10 Tf 12 TL .511488 Tw (Polygons consist of rings which mean they are closed. The first point and last point of a ring must be the) Tj T* 0 Tw .470574 Tw (same. PyShp enforces ring closure if the ring is incomplete when you add the shape. Polygons can have) Tj T* 0 Tw .539461 Tw (inner rings which create holes. Holes are defined by the order of the points. Normally points in a ring run) Tj T* 0 Tw .392339 Tw (clockwise. If the points run counter-clockwise then they [...]
+Q
+Q
+q
+1 0 0 1 62.69291 139.0236 cm
+q
+q
+1 0 0 1 0 0 cm
+q
+1 0 0 1 6.6 6.6 cm
+q
+.662745 .662745 .662745 RG
+.5 w
+.960784 .960784 .862745 rg
+n -6 -6 468.6898 60 re B*
+Q
+q
+BT 1 0 0 1 0 38 Tm 12 TL /F3 10 Tf 0 0 0 rg (>) Tj (>) Tj (>) Tj ( w = shapefile.Writer\(shapefile.POLYGON\)) Tj T* (>) Tj (>) Tj (>) Tj ( outer_ring = [[10,10],[50,50],[100,10],[50,-50],[10,10]]) Tj T* (>) Tj (>) Tj (>) Tj ( inner_ring = [[40,10],[50,30],[70,10],[50,-30],[40,10]]) Tj T* (>) Tj (>) Tj (>) Tj ( inner_ring.reverse\(\)) Tj T* ET
+Q
+Q
+Q
+Q
+Q
+q
+1 0 0 1 62.69291 95.02362 cm
+q
+BT 1 0 0 1 0 26 Tm .067126 Tw 12 TL /F1 10 Tf 0 0 0 rg (You can use the "shapefile.signed_area\(\)" method to determine if a ring is clockwise or counter-clockwise.) Tj T* 0 Tw .115251 Tw (A value >) Tj (= 0 means the ring is counter-clockwise and < 0 means the ring is clockwise. The value returned) Tj T* 0 Tw (is also the area of the polygon.) Tj T* ET
+Q
+Q
+
+endstream
+endobj
+% 'R87': class PDFStream
+87 0 obj
+% page stream
+<< /Length 4296 >>
+stream
+1 0 0 1 0 0 cm BT /F1 12 Tf 14.4 TL ET
+q
+1 0 0 1 62.69291 679.8236 cm
+q
+q
+1 0 0 1 0 0 cm
+q
+1 0 0 1 6.6 6.6 cm
+q
+.662745 .662745 .662745 RG
+.5 w
+.960784 .960784 .862745 rg
+n -6 -6 468.6898 84 re B*
+Q
+q
+BT 1 0 0 1 0 62 Tm 12 TL /F3 10 Tf 0 0 0 rg (>) Tj (>) Tj (>) Tj ( # Clockwise ring) Tj T* (... shapefile.signed_area\(outer_ring\)) Tj T* (-4500.0) Tj T* (>) Tj (>) Tj (>) Tj ( # Counter-clockwise ring) Tj T* (... shapefile.signed_area\(inner_ring\)) Tj T* (900.0) Tj T* ET
+Q
+Q
+Q
+Q
+Q
+q
+1 0 0 1 62.69291 659.8236 cm
+q
+0 0 0 rg
+BT 1 0 0 1 0 2 Tm /F2 10 Tf 12 TL (Creating 3D Polygons) Tj T* ET
+Q
+Q
+q
+1 0 0 1 62.69291 629.8236 cm
+q
+0 0 0 rg
+BT 1 0 0 1 0 14 Tm /F1 10 Tf 12 TL 1.34311 Tw (Elevation values, known as "Z" values allow you to create 3-dimensional shapefiles. The z value is an) Tj T* 0 Tw (extra value specified as part of a point.) Tj T* ET
+Q
+Q
+q
+1 0 0 1 62.69291 548.6236 cm
+q
+q
+1 0 0 1 0 0 cm
+q
+1 0 0 1 6.6 6.6 cm
+q
+.662745 .662745 .662745 RG
+.5 w
+.960784 .960784 .862745 rg
+n -6 -6 468.6898 72 re B*
+Q
+q
+BT 1 0 0 1 0 50 Tm 12 TL /F3 10 Tf 0 0 0 rg (>) Tj (>) Tj (>) Tj ( w = shapefile.Writer\(shapeType=shapefile.POLYGONZ\)) Tj T* (>) Tj (>) Tj (>) Tj ( w.poly\([[[-89.0, 33, 12], [-90, 31, 11], [-91, 30, 12]]], shapeType=15\)) Tj T* (>) Tj (>) Tj (>) Tj ( w.field\("NAME"\)) Tj T* (>) Tj (>) Tj (>) Tj ( w.record\("PolyZTest"\)) Tj T* (>) Tj (>) Tj (>) Tj ( w.save\("shapefiles/test/MyPolyZ"\)) Tj T* ET
+Q
+Q
+Q
+Q
+Q
+q
+1 0 0 1 62.69291 528.6236 cm
+q
+0 0 0 rg
+BT 1 0 0 1 0 2 Tm /F1 10 Tf 12 TL (The z values are stored in a seperate shape attribute.) Tj T* ET
+Q
+Q
+q
+1 0 0 1 62.69291 435.4236 cm
+q
+q
+1 0 0 1 0 0 cm
+q
+1 0 0 1 6.6 6.6 cm
+q
+.662745 .662745 .662745 RG
+.5 w
+.960784 .960784 .862745 rg
+n -6 -6 468.6898 84 re B*
+Q
+q
+BT 1 0 0 1 0 62 Tm 12 TL /F3 10 Tf 0 0 0 rg (>) Tj (>) Tj (>) Tj ( r = shapefile.Reader\("shapefiles/test/MyPolyZ"\)) Tj T* (>) Tj (>) Tj (>) Tj ( s = r.shape\(0\)) Tj T* (>) Tj (>) Tj (>) Tj ( s.points) Tj T* ([[-89.0, 33.0], [-90.0, 31.0], [-91.0, 30.0], [-89.0, 33.0]]) Tj T* (>) Tj (>) Tj (>) Tj ( s.z) Tj T* ([12.0, 11.0, 12.0, 12.0]) Tj T* ET
+Q
+Q
+Q
+Q
+Q
+q
+1 0 0 1 62.69291 408.4236 cm
+q
+BT 1 0 0 1 0 2.5 Tm 15 TL /F4 12.5 Tf 0 0 0 rg (Creating Attributes) Tj T* ET
+Q
+Q
+q
+1 0 0 1 62.69291 378.4236 cm
+q
+0 0 0 rg
+BT 1 0 0 1 0 14 Tm /F1 10 Tf 12 TL .245251 Tw (Creating attributes involves two steps. Step 1 is to create fields to contain attribute values and step 2 is to) Tj T* 0 Tw (populate the fields with values for each shape record.) Tj T* ET
+Q
+Q
+q
+1 0 0 1 62.69291 360.4236 cm
+q
+0 0 0 rg
+BT 1 0 0 1 0 2 Tm /F1 10 Tf 12 TL (The following attempts to create a complete shapefile:) Tj T* ET
+Q
+Q
+q
+1 0 0 1 62.69291 195.2236 cm
+q
+q
+1 0 0 1 0 0 cm
+q
+1 0 0 1 6.6 6.6 cm
+q
+.662745 .662745 .662745 RG
+.5 w
+.960784 .960784 .862745 rg
+n -6 -6 468.6898 156 re B*
+Q
+q
+BT 1 0 0 1 0 134 Tm 12 TL /F3 10 Tf 0 0 0 rg (>) Tj (>) Tj (>) Tj ( w = shapefile.Writer\(shapefile.POINT\)) Tj T* (>) Tj (>) Tj (>) Tj ( w.point\(1,1\)) Tj T* (>) Tj (>) Tj (>) Tj ( w.point\(3,1\)) Tj T* (>) Tj (>) Tj (>) Tj ( w.point\(4,3\)) Tj T* (>) Tj (>) Tj (>) Tj ( w.point\(2,2\)) Tj T* (>) Tj (>) Tj (>) Tj ( w.field\('FIRST_FLD'\)) Tj T* (>) Tj (>) Tj (>) Tj ( w.field\('SECOND_FLD','C','40'\)) Tj T* (>) Tj (>) Tj (>) Tj ( w.record\('First','Point'\)) Tj T* (>) Tj (>) Tj (>) Tj ( [...]
+Q
+Q
+Q
+Q
+Q
+q
+1 0 0 1 62.69291 102.0236 cm
+q
+q
+1 0 0 1 0 0 cm
+q
+1 0 0 1 6.6 6.6 cm
+q
+.662745 .662745 .662745 RG
+.5 w
+.960784 .960784 .862745 rg
+n -6 -6 468.6898 84 re B*
+Q
+q
+BT 1 0 0 1 0 62 Tm 12 TL /F3 10 Tf 0 0 0 rg (>) Tj (>) Tj (>) Tj ( w = shapefile.Writer\(shapefile.POLYGON\)) Tj T* (>) Tj (>) Tj (>) Tj ( w.poly\(parts=[[[1,5],[5,5],[5,1],[3,3],[1,1]]]\)) Tj T* (>) Tj (>) Tj (>) Tj ( w.field\('FIRST_FLD','C','40'\)) Tj T* (>) Tj (>) Tj (>) Tj ( w.field\('SECOND_FLD','C','40'\)) Tj T* (>) Tj (>) Tj (>) Tj ( w.record\('First','Polygon'\)) Tj T* (>) Tj (>) Tj (>) Tj ( w.save\('shapefiles/test/polygon'\)) Tj T* ET
+Q
+Q
+Q
+Q
+Q
+
+endstream
+endobj
+% 'R88': class PDFStream
+88 0 obj
+% page stream
+<< /Length 4785 >>
+stream
+1 0 0 1 0 0 cm BT /F1 12 Tf 14.4 TL ET
+q
+1 0 0 1 62.69291 655.8236 cm
+q
+q
+1 0 0 1 0 0 cm
+q
+1 0 0 1 6.6 6.6 cm
+q
+.662745 .662745 .662745 RG
+.5 w
+.960784 .960784 .862745 rg
+n -6 -6 468.6898 108 re B*
+Q
+q
+BT 1 0 0 1 0 86 Tm 12 TL /F3 10 Tf 0 0 0 rg (>) Tj (>) Tj (>) Tj ( w = shapefile.Writer\(shapefile.POLYLINE\)) Tj T* (>) Tj (>) Tj (>) Tj ( w.line\(parts=[[[1,5],[5,5],[5,1],[3,3],[1,1]]]\)) Tj T* (>) Tj (>) Tj (>) Tj ( w.poly\(parts=[[[1,3],[5,3]]], shapeType=shapefile.POLYLINE\)) Tj T* (>) Tj (>) Tj (>) Tj ( w.field\('FIRST_FLD','C','40'\)) Tj T* (>) Tj (>) Tj (>) Tj ( w.field\('SECOND_FLD','C','40'\)) Tj T* (>) Tj (>) Tj (>) Tj ( w.record\('First','Line'\)) Tj T* (>) Tj (>) Tj (>) Tj [...]
+Q
+Q
+Q
+Q
+Q
+q
+1 0 0 1 62.69291 635.8236 cm
+q
+0 0 0 rg
+BT 1 0 0 1 0 2 Tm /F1 10 Tf 12 TL (You can also add attributes using keyword arguments where the keys are field names.) Tj T* ET
+Q
+Q
+q
+1 0 0 1 62.69291 542.6236 cm
+q
+q
+1 0 0 1 0 0 cm
+q
+1 0 0 1 6.6 6.6 cm
+q
+.662745 .662745 .662745 RG
+.5 w
+.960784 .960784 .862745 rg
+n -6 -6 468.6898 84 re B*
+Q
+q
+BT 1 0 0 1 0 62 Tm 12 TL /F3 10 Tf 0 0 0 rg (>) Tj (>) Tj (>) Tj ( w = shapefile.Writer\(shapefile.POLYLINE\)) Tj T* (>) Tj (>) Tj (>) Tj ( w.line\(parts=[[[1,5],[5,5],[5,1],[3,3],[1,1]]]\)) Tj T* (>) Tj (>) Tj (>) Tj ( w.field\('FIRST_FLD','C','40'\)) Tj T* (>) Tj (>) Tj (>) Tj ( w.field\('SECOND_FLD','C','40'\)) Tj T* (>) Tj (>) Tj (>) Tj ( w.record\(FIRST_FLD='First', SECOND_FLD='Line'\)) Tj T* (>) Tj (>) Tj (>) Tj ( w.save\('shapefiles/test/line'\)) Tj T* ET
+Q
+Q
+Q
+Q
+Q
+q
+1 0 0 1 62.69291 515.6236 cm
+q
+BT 1 0 0 1 0 2.5 Tm 15 TL /F4 12.5 Tf 0 0 0 rg (File Names) Tj T* ET
+Q
+Q
+q
+1 0 0 1 62.69291 437.6236 cm
+q
+0 0 0 rg
+BT 1 0 0 1 0 62 Tm /F1 10 Tf 12 TL 1.313318 Tw (File extensions are optional when reading or writing shapfiles. If you specify them Pyshp ignores them) Tj T* 0 Tw .408084 Tw (anyway. When you save files you can specify a base file name that is used for all three file types. Or you) Tj T* 0 Tw .619036 Tw (can specify a nmae for one or more file types. In that case, any file types not assigned will not save and) Tj T* 0 Tw 1.596488 Tw (only file types with file names will be saved. If you [...]
+Q
+Q
+q
+1 0 0 1 62.69291 392.4236 cm
+q
+q
+1 0 0 1 0 0 cm
+q
+1 0 0 1 6.6 6.6 cm
+q
+.662745 .662745 .662745 RG
+.5 w
+.960784 .960784 .862745 rg
+n -6 -6 468.6898 36 re B*
+Q
+q
+BT 1 0 0 1 0 14 Tm 12 TL /F3 10 Tf 0 0 0 rg (>) Tj (>) Tj (>) Tj ( targetName = w.save\(\)) Tj T* (>) Tj (>) Tj (>) Tj ( assert\("shapefile_" in targetName\)) Tj T* ET
+Q
+Q
+Q
+Q
+Q
+q
+1 0 0 1 62.69291 365.4236 cm
+q
+BT 1 0 0 1 0 2.5 Tm 15 TL /F4 12.5 Tf 0 0 0 rg (Saving to File-Like Objects) Tj T* ET
+Q
+Q
+q
+1 0 0 1 62.69291 347.4236 cm
+q
+0 0 0 rg
+BT 1 0 0 1 0 2 Tm /F1 10 Tf 12 TL (Just as you can read shapefiles from python file-like objects you can also write them.) Tj T* ET
+Q
+Q
+q
+1 0 0 1 62.69291 189.6534 cm
+q
+q
+.952737 0 0 .952737 0 0 cm
+q
+1 0 0 1 6.6 6.927412 cm
+q
+.662745 .662745 .662745 RG
+.5 w
+.960784 .960784 .862745 rg
+n -6 -6 492 156 re B*
+Q
+q
+BT 1 0 0 1 0 134 Tm 12 TL /F3 10 Tf 0 0 0 rg (>) Tj (>) Tj (>) Tj ( try:) Tj T* (... from StringIO import StringIO) Tj T* (... except ImportError:) Tj T* (... from io import BytesIO as StringIO) Tj T* (>) Tj (>) Tj (>) Tj ( shp = StringIO\(\)) Tj T* (>) Tj (>) Tj (>) Tj ( shx = StringIO\(\)) Tj T* (>) Tj (>) Tj (>) Tj ( dbf = StringIO\(\)) Tj T* (>) Tj (>) Tj (>) Tj ( w.saveShp\(shp\)) Tj T* (>) Tj (>) Tj (>) Tj ( w.saveShx\(shx\)) Tj T* (>) Tj (>) Tj (>) Tj ( w.saveDbf\(dbf\)) T [...]
+Q
+Q
+Q
+Q
+Q
+q
+1 0 0 1 62.69291 159.6534 cm
+q
+BT 1 0 0 1 0 3 Tm 18 TL /F2 15 Tf 0 0 0 rg (Editing Shapefiles) Tj T* ET
+Q
+Q
+q
+1 0 0 1 62.69291 129.6534 cm
+q
+0 0 0 rg
+BT 1 0 0 1 0 14 Tm /F1 10 Tf 12 TL .200651 Tw (The Editor class attempts to make changing existing shapefiles easier by handling the reading and writing) Tj T* 0 Tw (details behind the scenes.) Tj T* ET
+Q
+Q
+q
+1 0 0 1 62.69291 111.6534 cm
+q
+0 0 0 rg
+BT 1 0 0 1 0 2 Tm /F1 10 Tf 12 TL (Let's add shapes to existing shapefiles:) Tj T* ET
+Q
+Q
+q
+1 0 0 1 62.69291 93.65341 cm
+q
+0 0 0 rg
+BT 1 0 0 1 0 2 Tm /F1 10 Tf 12 TL (Add a point to a point shapefile) Tj T* ET
+Q
+Q
+
+endstream
+endobj
+% 'R89': class PDFStream
+89 0 obj
+% page stream
+<< /Length 4562 >>
+stream
+1 0 0 1 0 0 cm BT /F1 12 Tf 14.4 TL ET
+q
+1 0 0 1 62.69291 667.8236 cm
+q
+q
+1 0 0 1 0 0 cm
+q
+1 0 0 1 6.6 6.6 cm
+q
+.662745 .662745 .662745 RG
+.5 w
+.960784 .960784 .862745 rg
+n -6 -6 468.6898 96 re B*
+Q
+q
+BT 1 0 0 1 0 74 Tm 12 TL /F3 10 Tf 0 0 0 rg (>) Tj (>) Tj (>) Tj ( e = shapefile.Editor\(shapefile="shapefiles/test/point.shp"\)) Tj T* (>) Tj (>) Tj (>) Tj ( e.point\(0,0,10,2\)) Tj T* (>) Tj (>) Tj (>) Tj ( e.record\("Appended","Point"\)) Tj T* (>) Tj (>) Tj (>) Tj ( # We added z and m values so) Tj T* (>) Tj (>) Tj (>) Tj ( # change the shapetype) Tj T* (>) Tj (>) Tj (>) Tj ( e.shapeType = shapefile.POINTZ) Tj T* (>) Tj (>) Tj (>) Tj ( e.save\('shapefiles/test/point'\)) Tj T* ET
+Q
+Q
+Q
+Q
+Q
+q
+1 0 0 1 62.69291 647.8236 cm
+q
+0 0 0 rg
+BT 1 0 0 1 0 2 Tm /F1 10 Tf 12 TL (Edit the appended point to change the "y" and "z" value) Tj T* ET
+Q
+Q
+q
+1 0 0 1 62.69291 458.6236 cm
+q
+q
+1 0 0 1 0 0 cm
+q
+1 0 0 1 6.6 6.6 cm
+q
+.662745 .662745 .662745 RG
+.5 w
+.960784 .960784 .862745 rg
+n -6 -6 468.6898 180 re B*
+Q
+q
+BT 1 0 0 1 0 158 Tm 12 TL /F3 10 Tf 0 0 0 rg (>) Tj (>) Tj (>) Tj ( e = shapefile.Editor\(shapefile="shapefiles/test/point.shp"\)) Tj T* (>) Tj (>) Tj (>) Tj ( # Find the point by the attribute) Tj T* (>) Tj (>) Tj (>) Tj ( for s in enumerate\(e.records\):) Tj T* (... i, record = s) Tj T* (... if record[0] == "Appended":) Tj T* (... geom = e._shapes[i]) Tj T* (... # Change the y value to 5) Tj T* (... geom.points[0][1] = 5) Tj T* (... # Change [...]
+Q
+Q
+Q
+Q
+Q
+q
+1 0 0 1 62.69291 438.6236 cm
+q
+0 0 0 rg
+BT 1 0 0 1 0 2 Tm /F1 10 Tf 12 TL (Add a new line to a line shapefile:) Tj T* ET
+Q
+Q
+q
+1 0 0 1 62.69291 357.4236 cm
+q
+q
+1 0 0 1 0 0 cm
+q
+1 0 0 1 6.6 6.6 cm
+q
+.662745 .662745 .662745 RG
+.5 w
+.960784 .960784 .862745 rg
+n -6 -6 468.6898 72 re B*
+Q
+q
+BT 1 0 0 1 0 50 Tm 12 TL /F3 10 Tf 0 0 0 rg (>) Tj (>) Tj (>) Tj ( e = shapefile.Editor\(shapefile="shapefiles/test/line.shp"\)) Tj T* (>) Tj (>) Tj (>) Tj ( e.line\(parts=[[[10,5],[15,5],[15,1],[13,3],[11,1]]]\)) Tj T* (>) Tj (>) Tj (>) Tj ( e.record\('Appended','Line'\)) Tj T* (>) Tj (>) Tj (>) Tj ( e.save\('shapefiles/test/line'\)) Tj T* (>) Tj (>) Tj (>) Tj ( e = None) Tj T* ET
+Q
+Q
+Q
+Q
+Q
+q
+1 0 0 1 62.69291 337.4236 cm
+q
+0 0 0 rg
+BT 1 0 0 1 0 2 Tm /F1 10 Tf 12 TL (Add a new polygon to a polygon shapefile:) Tj T* ET
+Q
+Q
+q
+1 0 0 1 62.69291 256.2236 cm
+q
+q
+1 0 0 1 0 0 cm
+q
+1 0 0 1 6.6 6.6 cm
+q
+.662745 .662745 .662745 RG
+.5 w
+.960784 .960784 .862745 rg
+n -6 -6 468.6898 72 re B*
+Q
+q
+BT 1 0 0 1 0 50 Tm 12 TL /F3 10 Tf 0 0 0 rg (>) Tj (>) Tj (>) Tj ( e = shapefile.Editor\(shapefile="shapefiles/test/polygon.shp"\)) Tj T* (>) Tj (>) Tj (>) Tj ( e.poly\(parts=[[[5.1,5],[9.9,5],[9.9,1],[7.5,3],[5.1,1]]]\)) Tj T* (>) Tj (>) Tj (>) Tj ( e.record\("Appended","Polygon"\)) Tj T* (>) Tj (>) Tj (>) Tj ( e.save\('shapefiles/test/polygon'\)) Tj T* (>) Tj (>) Tj (>) Tj ( e = None) Tj T* ET
+Q
+Q
+Q
+Q
+Q
+q
+1 0 0 1 62.69291 236.2236 cm
+q
+0 0 0 rg
+BT 1 0 0 1 0 2 Tm /F1 10 Tf 12 TL (Remove the first point in each shapefile - for a point shapefile that is the first shape and record") Tj T* ET
+Q
+Q
+q
+1 0 0 1 62.69291 167.0236 cm
+q
+q
+1 0 0 1 0 0 cm
+q
+1 0 0 1 6.6 6.6 cm
+q
+.662745 .662745 .662745 RG
+.5 w
+.960784 .960784 .862745 rg
+n -6 -6 468.6898 60 re B*
+Q
+q
+BT 1 0 0 1 0 38 Tm 12 TL /F3 10 Tf 0 0 0 rg (>) Tj (>) Tj (>) Tj ( e = shapefile.Editor\(shapefile="shapefiles/test/point.shp"\)) Tj T* (>) Tj (>) Tj (>) Tj ( e.delete\(0\)) Tj T* (>) Tj (>) Tj (>) Tj ( e.save\('shapefiles/test/point'\)) Tj T* (>) Tj (>) Tj (>) Tj ( e = None) Tj T* ET
+Q
+Q
+Q
+Q
+Q
+q
+1 0 0 1 62.69291 147.0236 cm
+q
+0 0 0 rg
+BT 1 0 0 1 0 2 Tm /F1 10 Tf 12 TL (Remove the last shape in the polygon shapefile.) Tj T* ET
+Q
+Q
+q
+1 0 0 1 62.69291 77.82362 cm
+q
+q
+1 0 0 1 0 0 cm
+q
+1 0 0 1 6.6 6.6 cm
+q
+.662745 .662745 .662745 RG
+.5 w
+.960784 .960784 .862745 rg
+n -6 -6 468.6898 60 re B*
+Q
+q
+BT 1 0 0 1 0 38 Tm 12 TL /F3 10 Tf 0 0 0 rg (>) Tj (>) Tj (>) Tj ( e = shapefile.Editor\(shapefile="shapefiles/test/polygon.shp"\)) Tj T* (>) Tj (>) Tj (>) Tj ( e.delete\(-1\)) Tj T* (>) Tj (>) Tj (>) Tj ( e.save\('shapefiles/test/polygon'\)) Tj T* (>) Tj (>) Tj (>) Tj ( e = None) Tj T* ET
+Q
+Q
+Q
+Q
+Q
+
+endstream
+endobj
+% 'R90': class PDFStream
+90 0 obj
+% page stream
+<< /Length 1160 >>
+stream
+1 0 0 1 0 0 cm BT /F1 12 Tf 14.4 TL ET
+q
+1 0 0 1 62.69291 747.0236 cm
+q
+BT 1 0 0 1 0 3 Tm 18 TL /F2 15 Tf 0 0 0 rg (Python __geo_interface__) Tj T* ET
+Q
+Q
+q
+1 0 0 1 62.69291 693.0236 cm
+q
+BT 1 0 0 1 0 38 Tm 3.297976 Tw 12 TL /F1 10 Tf 0 0 0 rg (The Python __geo_interface__ convention provides a data interchange interface among geospatial) Tj T* 0 Tw 1.871647 Tw (Python libraries. The interface returns data as GeoJSON. More information on the __geo_interface__) Tj T* 0 Tw 3.245976 Tw (protocol can be found at: ) Tj 0 0 .501961 rg (https://gist.github.com/sgillies/2217756) Tj 0 0 0 rg (. More information on GeoJSON is) Tj T* 0 Tw (available at ) Tj 0 0 .501961 rg (http://ge [...]
+Q
+Q
+q
+1 0 0 1 62.69291 635.8236 cm
+q
+q
+1 0 0 1 0 0 cm
+q
+1 0 0 1 6.6 6.6 cm
+q
+.662745 .662745 .662745 RG
+.5 w
+.960784 .960784 .862745 rg
+n -6 -6 468.6898 48 re B*
+Q
+q
+BT 1 0 0 1 0 26 Tm 12 TL /F3 10 Tf 0 0 0 rg (>) Tj (>) Tj (>) Tj ( s = sf.shape\(0\)) Tj T* (>) Tj (>) Tj (>) Tj ( s.__geo_interface__["type"]) Tj T* ('MultiPolygon') Tj T* ET
+Q
+Q
+Q
+Q
+Q
+
+endstream
+endobj
+% 'R91': class PDFPageLabels
+91 0 obj
+% Document Root
+<< /Nums [ 0
+ 92 0 R
+ 1
+ 93 0 R
+ 2
+ 94 0 R
+ 3
+ 95 0 R
+ 4
+ 96 0 R
+ 5
+ 97 0 R
+ 6
+ 98 0 R
+ 7
+ 99 0 R
+ 8
+ 100 0 R
+ 9
+ 101 0 R
+ 10
+ 102 0 R
+ 11
+ 103 0 R ] >>
+endobj
+% 'R92': class PDFPageLabel
+92 0 obj
+% None
+<< /S /D
+ /St 1 >>
+endobj
+% 'R93': class PDFPageLabel
+93 0 obj
+% None
+<< /S /D
+ /St 2 >>
+endobj
+% 'R94': class PDFPageLabel
+94 0 obj
+% None
+<< /S /D
+ /St 3 >>
+endobj
+% 'R95': class PDFPageLabel
+95 0 obj
+% None
+<< /S /D
+ /St 4 >>
+endobj
+% 'R96': class PDFPageLabel
+96 0 obj
+% None
+<< /S /D
+ /St 5 >>
+endobj
+% 'R97': class PDFPageLabel
+97 0 obj
+% None
+<< /S /D
+ /St 6 >>
+endobj
+% 'R98': class PDFPageLabel
+98 0 obj
+% None
+<< /S /D
+ /St 7 >>
+endobj
+% 'R99': class PDFPageLabel
+99 0 obj
+% None
+<< /S /D
+ /St 8 >>
+endobj
+% 'R100': class PDFPageLabel
+100 0 obj
+% None
+<< /S /D
+ /St 9 >>
+endobj
+% 'R101': class PDFPageLabel
+101 0 obj
+% None
+<< /S /D
+ /St 10 >>
+endobj
+% 'R102': class PDFPageLabel
+102 0 obj
+% None
+<< /S /D
+ /St 11 >>
+endobj
+% 'R103': class PDFPageLabel
+103 0 obj
+% None
+<< /S /D
+ /St 12 >>
+endobj
+xref
+0 104
+0000000000 65535 f
+0000000113 00000 n
+0000000247 00000 n
+0000000412 00000 n
+0000000599 00000 n
+0000000854 00000 n
+0000001095 00000 n
+0000001336 00000 n
+0000001577 00000 n
+0000001818 00000 n
+0000002059 00000 n
+0000002301 00000 n
+0000002543 00000 n
+0000002786 00000 n
+0000003029 00000 n
+0000003272 00000 n
+0000003515 00000 n
+0000003758 00000 n
+0000004001 00000 n
+0000004244 00000 n
+0000004487 00000 n
+0000004730 00000 n
+0000004973 00000 n
+0000005216 00000 n
+0000005459 00000 n
+0000005702 00000 n
+0000005945 00000 n
+0000006188 00000 n
+0000006431 00000 n
+0000006674 00000 n
+0000006917 00000 n
+0000007160 00000 n
+0000007403 00000 n
+0000007646 00000 n
+0000007889 00000 n
+0000008132 00000 n
+0000008375 00000 n
+0000008617 00000 n
+0000008895 00000 n
+0000009176 00000 n
+0000009424 00000 n
+0000009656 00000 n
+0000010290 00000 n
+0000010547 00000 n
+0000010709 00000 n
+0000010897 00000 n
+0000011198 00000 n
+0000011478 00000 n
+0000011758 00000 n
+0000012038 00000 n
+0000012318 00000 n
+0000012598 00000 n
+0000012878 00000 n
+0000013159 00000 n
+0000013440 00000 n
+0000013735 00000 n
+0000013995 00000 n
+0000014233 00000 n
+0000014457 00000 n
+0000014777 00000 n
+0000014936 00000 n
+0000015233 00000 n
+0000015359 00000 n
+0000015528 00000 n
+0000015743 00000 n
+0000015967 00000 n
+0000016172 00000 n
+0000016367 00000 n
+0000016561 00000 n
+0000016768 00000 n
+0000017007 00000 n
+0000017193 00000 n
+0000017401 00000 n
+0000017595 00000 n
+0000017793 00000 n
+0000017982 00000 n
+0000018173 00000 n
+0000018370 00000 n
+0000018539 00000 n
+0000018747 00000 n
+0000026547 00000 n
+0000032257 00000 n
+0000038555 00000 n
+0000045098 00000 n
+0000050766 00000 n
+0000056519 00000 n
+0000062324 00000 n
+0000068203 00000 n
+0000072598 00000 n
+0000077482 00000 n
+0000082143 00000 n
+0000083406 00000 n
+0000083648 00000 n
+0000083725 00000 n
+0000083802 00000 n
+0000083879 00000 n
+0000083956 00000 n
+0000084033 00000 n
+0000084110 00000 n
+0000084187 00000 n
+0000084265 00000 n
+0000084344 00000 n
+0000084424 00000 n
+0000084504 00000 n
+trailer
+<< /ID
+ % ReportLab generated PDF document -- digest (http://www.reportlab.com)
+ [(\317\331s\275\0069x\241n:\236\316\022\315\016\321) (\317\331s\275\0069x\241n:\236\316\022\315\016\321)]
+
+ /Info 60 0 R
+ /Root 59 0 R
+ /Size 104 >>
+startxref
+84553
+%%EOF
diff --git a/README.txt b/README.txt
index f520680..db9c054 100644
--- a/README.txt
+++ b/README.txt
@@ -1,43 +1,49 @@
-Python Shapefile Library
+PyShp
========================
-:Author: Joel Lawhead <jlawhead at geospatialpython.com>
-:Revised: October 1, 2011
+
+:Author: Joel Lawhead - jlawhead at geospatialpython.com
+
+:Version 1.2.1
+
+:Revised: May 11, 2014
.. contents::
Overview
--------
-The Python Shapefile Library (pyshp) provides read and write support for the ESRI
+PyShp provides read and write support for the Esri
Shapefile format. The Shapefile format is a popular Geographic Information
System vector data format created by Esri. For more information about this format
-please read the well-written "ESRI Shapefile Technical Description - July 1998".
+please read the well-written "ESRI Shapefile Technical Description - July 1998"
+located at http://www.esri.com/library/whitepapers/pdfs/shapefile.pdf.
The Esri document describes the shp and shx file formats. However a third file
format called dbf is also required. This format is documented on the web as the
"XBase File Format Description" and is a simple file-based database format created
-in the 1960's. Both the Esri and XBase file-formats are very simple in design and
+in the 1960's. For more on this specification see:
+http://www.clicketyclick.dk/databases/xbase/format/index.html
+
+Both the Esri and XBase file-formats are very simple in design and
memory efficient which is part of the reason the shapefile format remains popular
despite the numerous ways to store and exchange GIS data available today.
-This documentation covers the Python 2.x-compatible version of the library. A
-Python 3-compatible version is available in the Subversion trunk of the pyshp
-project on Google Code.
+Pyshp is compatible with Python 2.4-3.x.
-This document provides examples for using pyshp to read and write shapefiles.
+This document provides examples for using PyShp to read and write shapefiles.
Currently the sample census blockgroup shapefile referenced in the examples is
only available on the google code project site at http://code.google.com/p/pyshp.
These examples are straight-forward and you can also easily run them against your
own shapefiles manually with minimal modification. Other examples for specific
topics are continually added to the pyshp wiki on google code and the blog
-GeospatialPython.com.
+http://GeospatialPython.com.
Important: For information about map projections, shapefiles,
and Python please visit: http://code.google.com/p/pyshp/wiki/MapProjections
I sincerely hope this library eliminates the mundane distraction of simply
reading and writing data, and allows you to focus on the challenging and FUN
-part of your project.
+part of your geospatial project.
Examples
--------
@@ -72,7 +78,7 @@ OR
OR any of the other 5+ formats which are potentially part of a shapefile.
-The library does not care
+The library does not care about extensions.
Reading Shapefiles from File-Like Objects
.........................................
@@ -110,6 +116,11 @@ geometry of each shape record.
>>> len(shapes)
663
+You can iterate through the shapefile's geometry using the iterShapes() method.
+
+>>> len(list(sf.iterShapes()))
+663
+
Each shape record contains the following attributes:
>>> for name in dir(shapes[3]):
@@ -127,7 +138,7 @@ Each shape record contains the following attributes:
5
- bbox: If the shape type contains multiple points this tuple describes the
- upper left (x,y) coordinate and lower right corner coordinate creating a
+ lower left (x,y) coordinate and upper right corner coordinate creating a
complete box around the points. If the shapeType is a Null
(shapeType == 0) then an AttributeError is raised.
@@ -219,6 +230,12 @@ You can get a list of the shapefile's records by calling the records() method:
>>> len(records)
663
+Similar to the geometry methods, you can iterate through dbf records using the
+recordsIter() method.
+
+>>> len(list(sf.iterRecords()))
+663
+
Each record is a list containing an attribute corresponding to each field in the
field list.
@@ -279,11 +296,11 @@ The blockgroup key and population count:
Writing Shapefiles
++++++++++++++++++
-The PSL tries to be as flexible as possible when writing shapefiles while
+PyShp tries to be as flexible as possible when writing shapefiles while
maintaining some degree of automatic validation to make sure you don't
accidentally write an invalid file.
-The PSL can write just one of the component files such as the shp or dbf file
+PyShp can write just one of the component files such as the shp or dbf file
without writing the others. So in addition to being a complete
shapefile library, it can also be used as a basic dbf (xbase) library. Dbf files are
a common database format which are often useful as a standalone simple
@@ -312,6 +329,22 @@ shapefile specification. It is important to note that numbering system has
several reserved numbers which have not been used yet therefore the numbers of
the existing shape types are not sequential.
+You can reference shape types by the numbers or by constants defined by PyShp:
+shapefile.NULL = 0
+shapefile.POINT = 1
+shapefile.POLYLINE = 3
+shapefile.POLYGON = 5
+shapefile.MULTIPOINT = 8
+shapefile.POINTZ = 11
+shapefile.POLYLINEZ = 13
+shapefile.POLYGONZ = 15
+shapefile.MULTIPOINTZ = 18
+shapefile.POINTM = 21
+shapefile.POLYLINEM = 23
+shapefile.POLYGONM = 25
+shapefile.MULTIPOINTM = 28
+shapefile.MULTIPATCH = 31
+
There are three ways to set the shape type:
- Set it when creating the class instance.
- Set it by assigning a value to an existing class instance.
@@ -321,10 +354,16 @@ To manually set the shape type for a Writer object when creating the Writer:
>>> w = shapefile.Writer(shapeType=1)
+or we can use the constants as explained above:
+
+>>> w = shapefile.Writer(shapefile.POINT)
+
+As you can see, specifying the shapeType argument explicitly isn't necessary.
+
>>> w.shapeType
1
-OR you can set it after the Writer is created:
+OR you can set it after the Writer is created by changing the property:
>>> w.shapeType = 3
@@ -336,7 +375,7 @@ Geometry and Record Balancing
Because every shape must have a corresponding record it is critical that the
number of records equals the number of shapes to create a valid shapefile. To
-help prevent accidental misalignment the PSL has an "auto balance" feature to
+help prevent accidental misalignment PyShp has an "auto balance" feature to
make sure when you add either a shape or a record the two sides of the
equation line up. This feature is NOT turned on by default. To activate it
set the attribute autoBalance to 1 (True):
@@ -386,7 +425,7 @@ The writer object's shapes list will now have one null shape:
Point shapes are added using the "point" method. A point is specified by an
x, y, and optional z (elevation) and m (measure) value.
->>> w = shapefile.Writer()
+>>> w = shapefile.Writer(shapefile.POINT)
>>> w.point(122, 37) # No elevation or measure values
@@ -398,20 +437,65 @@ x, y, and optional z (elevation) and m (measure) value.
>>> w.shapes()[1].points
[[118, 36, 4, 8]]
-**Adding a Poly shape**
+**Adding a Poly Shape**
"Poly" shapes can be either polygons or lines. Shapefile polygons must have at
-least 5 points and the last point must be the same as the first (i.e. you can't
-have a triangle accoring to the shapefile specification even though many popular
-GIS programs support such shapefiles.) A line must have at least two points.
+least 4 points and the last point must be the same as the first. PyShp automatically
+enforces closed polygons.
+A line must have at least two points.
Because of the similarities between these two shape types they are created using
a single method called "poly".
->>> w = shapefile.Writer()
+>>> w = shapefile.Writer(shapefile.POLYGON)
>>> w.poly(shapeType=3, parts=[[[122,37,4,9], [117,36,3,4]], [[115,32,8,8],
... [118,20,6,4], [113,24]]])
+**Adding a Polygon with Rings**
+
+Polygons consist of rings which mean they are closed. The first point and last point
+of a ring must be the same. PyShp enforces ring closure if the ring is incomplete when
+you add the shape. Polygons can have inner rings which create holes. Holes are defined
+by the order of the points. Normally points in a ring run clockwise. If the points
+run counter-clockwise then they form a hole. If you don't order the points correctly
+you'll just have overlapping polygons.
+
+>>> w = shapefile.Writer(shapefile.POLYGON)
+>>> outer_ring = [[10,10],[50,50],[100,10],[50,-50],[10,10]]
+>>> inner_ring = [[40,10],[50,30],[70,10],[50,-30],[40,10]]
+>>> inner_ring.reverse()
+
+You can use the "shapefile.signed_area()" method to determine if a ring is clockwise
+or counter-clockwise. A value >= 0 means the ring is counter-clockwise and < 0 means
+the ring is clockwise. The value returned is also the area of the polygon.
+
+>>> # Clockwise ring
+... shapefile.signed_area(outer_ring)
+-4500.0
+>>> # Counter-clockwise ring
+... shapefile.signed_area(inner_ring)
+900.0
+
+**Creating 3D Polygons**
+
+Elevation values, known as "Z" values allow you to create 3-dimensional shapefiles. The
+z value is an extra value specified as part of a point.
+
+>>> w = shapefile.Writer(shapeType=shapefile.POLYGONZ)
+>>> w.poly([[[-89.0, 33, 12], [-90, 31, 11], [-91, 30, 12]]], shapeType=15)
+>>> w.field("NAME")
+>>> w.record("PolyZTest")
+>>> w.save("shapefiles/test/MyPolyZ")
+
+The z values are stored in a seperate shape attribute.
+
+>>> r = shapefile.Reader("shapefiles/test/MyPolyZ")
+>>> s = r.shape(0)
+>>> s.points
+[[-89.0, 33.0], [-90.0, 31.0], [-91.0, 30.0], [-89.0, 33.0]]
+>>> s.z
+[12.0, 11.0, 12.0, 12.0]
+
Creating Attributes
...................
@@ -459,6 +543,20 @@ You can also add attributes using keyword arguments where the keys are field nam
>>> w.record(FIRST_FLD='First', SECOND_FLD='Line')
>>> w.save('shapefiles/test/line')
+File Names
+..........
+
+File extensions are optional when reading or writing shapfiles. If you specify them Pyshp
+ignores them anyway. When you save files you can specify a base file name that is used for
+all three file types. Or you can specify a nmae for one or more file types. In that case,
+any file types not assigned will not save and only file types with file names will be saved.
+If you do not specify any file names (i.e. save()), then a unique file name is generated with
+the prefix "shapefile\_" followed by random characters which is used for all three files. The
+unique file name is returned as a string.
+
+>>> targetName = w.save()
+>>> assert("shapefile_" in targetName)
+
Saving to File-Like Objects
...........................
@@ -489,6 +587,26 @@ Add a point to a point shapefile
>>> e = shapefile.Editor(shapefile="shapefiles/test/point.shp")
>>> e.point(0,0,10,2)
>>> e.record("Appended","Point")
+>>> # We added z and m values so
+>>> # change the shapetype
+>>> e.shapeType = shapefile.POINTZ
+>>> e.save('shapefiles/test/point')
+
+Edit the appended point to change the "y" and "z" value
+
+>>> e = shapefile.Editor(shapefile="shapefiles/test/point.shp")
+>>> # Find the point by the attribute
+>>> for s in enumerate(e.records):
+... i, record = s
+... if record[0] == "Appended":
+... geom = e._shapes[i]
+... # Change the y value to 5
+... geom.points[0][1] = 5
+... # Change the z value to 9
+... if hasattr(geom, "z"):
+... geom.z = (9,)
+... else:
+... geom.points[0][2] = 9
>>> e.save('shapefiles/test/point')
Add a new line to a line shapefile:
@@ -497,6 +615,7 @@ Add a new line to a line shapefile:
>>> e.line(parts=[[[10,5],[15,5],[15,1],[13,3],[11,1]]])
>>> e.record('Appended','Line')
>>> e.save('shapefiles/test/line')
+>>> e = None
Add a new polygon to a polygon shapefile:
@@ -504,6 +623,7 @@ Add a new polygon to a polygon shapefile:
>>> e.poly(parts=[[[5.1,5],[9.9,5],[9.9,1],[7.5,3],[5.1,1]]])
>>> e.record("Appended","Polygon")
>>> e.save('shapefiles/test/polygon')
+>>> e = None
Remove the first point in each shapefile - for a point shapefile that is
the first shape and record"
@@ -511,11 +631,25 @@ the first shape and record"
>>> e = shapefile.Editor(shapefile="shapefiles/test/point.shp")
>>> e.delete(0)
>>> e.save('shapefiles/test/point')
+>>> e = None
Remove the last shape in the polygon shapefile.
>>> e = shapefile.Editor(shapefile="shapefiles/test/polygon.shp")
>>> e.delete(-1)
>>> e.save('shapefiles/test/polygon')
+>>> e = None
+Python __geo_interface__
+++++++++++++++++++++++++
+
+The Python __geo_interface__ convention provides a data interchange interface
+among geospatial Python libraries. The interface returns data as GeoJSON.
+More information on the __geo_interface__ protocol can be found at:
+https://gist.github.com/sgillies/2217756.
+More information on GeoJSON is available at http://geojson.org http://geojson.org.
+
+>>> s = sf.shape(0)
+>>> s.__geo_interface__["type"]
+'MultiPolygon'
diff --git a/changelog.txt b/changelog.txt
new file mode 100644
index 0000000..10d4955
--- /dev/null
+++ b/changelog.txt
@@ -0,0 +1,69 @@
+VERSION 1.2.1
+
+2014-05-11 Joel Lawhead <jlawhead at geospatialpython.com>
+ *shapefile.py (u) fixed bug which failed to properly read some dbf fields in Python 3
+
+VERSION 1.2.0
+
+2013-09-05 Joel Lawhead <jlawhead at geospatialpython.com>
+ *README.txt add example/test for writing a 3D polygon
+
+VERSION 1.1.9
+
+2013-07-27 Joel Lawhead <jlawhead at geospatialpython.com>
+ *shapefile.py (Writer.__shpRecords) fixed inconsistency between Reader and Writer
+ when referencing "z" and "m" values. This bug caused errors only when editing
+ 3D shapefiles.
+
+VERSION 1.1.8
+
+2013-07-02 Joel Lawhead <jlawhead at geospatialpython.com>
+ *shapefile.py (Writer.poly()) fixed a bug that resulted in incorrect part indexes
+ *README.txt updated several errors in the documentation.
+
+2013-06-25 Joel Lawhead <jlawhead at geospatialpython.com>
+ *shapefile.py (Reader.shapes(),Reader.iterShapes()) Updated to verify the file length by
+ seeking to the end. A user reported shapefiles in the wild which had incorrect .shp file
+ lengths reported in the header which crashed when reading or iterating shapes. Most
+ insist on using the .shx file but there's no real reason to do so.
+
+VERSION 1.1.7
+
+2013-06-22 Joel Lawhead <jlawhead at geospatialpython.com>
+
+ *shapefile.py (_Shape.__geo_interface__) Added Python __geo_interface__ convention
+ to export shapefiles as GeoJSON.
+
+ *shapefile.py (Reader.__init__) Used is_string() method to detect filenames passed
+ as unicode strings.
+
+ *shapefile.py (Reader.iterShapes) Added iterShapes() method to iterate through
+ geometry records for parsing large files efficiently.
+
+ *shapefile.py (Reader.iterRecords) Added iterRecords() method to iterate through
+ dbf records efficiently in large files.
+
+ *shapefile.py (Reader.shape) Modified shape() method to use iterShapes() if shx
+ file is not available.
+
+ *shapefile.py (main) Added __version__ attribute.
+
+ *shapefile.py (Writer.record) Fixed bug which prevents writing the number 0 to
+ dbf fields.
+
+ *shapefile.py (Reader.__shape) Updated to calculate and seek the start of the next record. The
+ shapefile spec does not require the content of a geometry record to be as long as the content
+ length defined in the header. The result is you can delete features without modifying the
+ record header allowing for empty space in records.
+
+ *shapefile.py (Writer.poly) Added enforcement of closed polygons
+
+ *shapefile.py (Writer.save) Added unique file name generator to use if no file names are passed
+ to a writer instance when saving (ex. w.save()). The unique file name is returned as a string.
+
+ *README.txt (main) Added tests for iterShapes(), iterRecords(), __geo_interface__()
+
+ *README.txt (main) Updated "bbox" property documentation to match Esri specification.
+
+
+
\ No newline at end of file
diff --git a/pyshp.egg-info/PKG-INFO b/pyshp.egg-info/PKG-INFO
index 14f2d63..a2dd472 100644
--- a/pyshp.egg-info/PKG-INFO
+++ b/pyshp.egg-info/PKG-INFO
@@ -1,51 +1,57 @@
Metadata-Version: 1.0
Name: pyshp
-Version: 1.1.4
+Version: 1.2.1
Summary: Pure Python read/write support for ESRI Shapefile format
Home-page: http://code.google.com/p/pyshp
Author: Joel Lawhead
Author-email: jlawhead at geospatialpython.com
License: MIT
-Description: Python Shapefile Library
+Description: PyShp
========================
- :Author: Joel Lawhead <jlawhead at geospatialpython.com>
- :Revised: October 1, 2011
+
+ :Author: Joel Lawhead - jlawhead at geospatialpython.com
+
+ :Version 1.2.1
+
+ :Revised: May 11, 2014
.. contents::
Overview
--------
- The Python Shapefile Library (pyshp) provides read and write support for the ESRI
+ PyShp provides read and write support for the Esri
Shapefile format. The Shapefile format is a popular Geographic Information
System vector data format created by Esri. For more information about this format
- please read the well-written "ESRI Shapefile Technical Description - July 1998".
+ please read the well-written "ESRI Shapefile Technical Description - July 1998"
+ located at http://www.esri.com/library/whitepapers/pdfs/shapefile.pdf.
The Esri document describes the shp and shx file formats. However a third file
format called dbf is also required. This format is documented on the web as the
"XBase File Format Description" and is a simple file-based database format created
- in the 1960's. Both the Esri and XBase file-formats are very simple in design and
+ in the 1960's. For more on this specification see:
+ http://www.clicketyclick.dk/databases/xbase/format/index.html
+
+ Both the Esri and XBase file-formats are very simple in design and
memory efficient which is part of the reason the shapefile format remains popular
despite the numerous ways to store and exchange GIS data available today.
- This documentation covers the Python 2.x-compatible version of the library. A
- Python 3-compatible version is available in the Subversion trunk of the pyshp
- project on Google Code.
+ Pyshp is compatible with Python 2.4-3.x.
- This document provides examples for using pyshp to read and write shapefiles.
+ This document provides examples for using PyShp to read and write shapefiles.
Currently the sample census blockgroup shapefile referenced in the examples is
only available on the google code project site at http://code.google.com/p/pyshp.
These examples are straight-forward and you can also easily run them against your
own shapefiles manually with minimal modification. Other examples for specific
topics are continually added to the pyshp wiki on google code and the blog
- GeospatialPython.com.
+ http://GeospatialPython.com.
Important: For information about map projections, shapefiles,
and Python please visit: http://code.google.com/p/pyshp/wiki/MapProjections
I sincerely hope this library eliminates the mundane distraction of simply
reading and writing data, and allows you to focus on the challenging and FUN
- part of your project.
+ part of your geospatial project.
Examples
--------
@@ -80,7 +86,7 @@ Description: Python Shapefile Library
OR any of the other 5+ formats which are potentially part of a shapefile.
- The library does not care
+ The library does not care about extensions.
Reading Shapefiles from File-Like Objects
.........................................
@@ -118,6 +124,11 @@ Description: Python Shapefile Library
>>> len(shapes)
663
+ You can iterate through the shapefile's geometry using the iterShapes() method.
+
+ >>> len(list(sf.iterShapes()))
+ 663
+
Each shape record contains the following attributes:
>>> for name in dir(shapes[3]):
@@ -135,7 +146,7 @@ Description: Python Shapefile Library
5
- bbox: If the shape type contains multiple points this tuple describes the
- upper left (x,y) coordinate and lower right corner coordinate creating a
+ lower left (x,y) coordinate and upper right corner coordinate creating a
complete box around the points. If the shapeType is a Null
(shapeType == 0) then an AttributeError is raised.
@@ -227,6 +238,12 @@ Description: Python Shapefile Library
>>> len(records)
663
+ Similar to the geometry methods, you can iterate through dbf records using the
+ recordsIter() method.
+
+ >>> len(list(sf.iterRecords()))
+ 663
+
Each record is a list containing an attribute corresponding to each field in the
field list.
@@ -287,11 +304,11 @@ Description: Python Shapefile Library
Writing Shapefiles
++++++++++++++++++
- The PSL tries to be as flexible as possible when writing shapefiles while
+ PyShp tries to be as flexible as possible when writing shapefiles while
maintaining some degree of automatic validation to make sure you don't
accidentally write an invalid file.
- The PSL can write just one of the component files such as the shp or dbf file
+ PyShp can write just one of the component files such as the shp or dbf file
without writing the others. So in addition to being a complete
shapefile library, it can also be used as a basic dbf (xbase) library. Dbf files are
a common database format which are often useful as a standalone simple
@@ -320,6 +337,22 @@ Description: Python Shapefile Library
several reserved numbers which have not been used yet therefore the numbers of
the existing shape types are not sequential.
+ You can reference shape types by the numbers or by constants defined by PyShp:
+ shapefile.NULL = 0
+ shapefile.POINT = 1
+ shapefile.POLYLINE = 3
+ shapefile.POLYGON = 5
+ shapefile.MULTIPOINT = 8
+ shapefile.POINTZ = 11
+ shapefile.POLYLINEZ = 13
+ shapefile.POLYGONZ = 15
+ shapefile.MULTIPOINTZ = 18
+ shapefile.POINTM = 21
+ shapefile.POLYLINEM = 23
+ shapefile.POLYGONM = 25
+ shapefile.MULTIPOINTM = 28
+ shapefile.MULTIPATCH = 31
+
There are three ways to set the shape type:
- Set it when creating the class instance.
- Set it by assigning a value to an existing class instance.
@@ -329,10 +362,16 @@ Description: Python Shapefile Library
>>> w = shapefile.Writer(shapeType=1)
+ or we can use the constants as explained above:
+
+ >>> w = shapefile.Writer(shapefile.POINT)
+
+ As you can see, specifying the shapeType argument explicitly isn't necessary.
+
>>> w.shapeType
1
- OR you can set it after the Writer is created:
+ OR you can set it after the Writer is created by changing the property:
>>> w.shapeType = 3
@@ -344,7 +383,7 @@ Description: Python Shapefile Library
Because every shape must have a corresponding record it is critical that the
number of records equals the number of shapes to create a valid shapefile. To
- help prevent accidental misalignment the PSL has an "auto balance" feature to
+ help prevent accidental misalignment PyShp has an "auto balance" feature to
make sure when you add either a shape or a record the two sides of the
equation line up. This feature is NOT turned on by default. To activate it
set the attribute autoBalance to 1 (True):
@@ -394,7 +433,7 @@ Description: Python Shapefile Library
Point shapes are added using the "point" method. A point is specified by an
x, y, and optional z (elevation) and m (measure) value.
- >>> w = shapefile.Writer()
+ >>> w = shapefile.Writer(shapefile.POINT)
>>> w.point(122, 37) # No elevation or measure values
@@ -406,20 +445,65 @@ Description: Python Shapefile Library
>>> w.shapes()[1].points
[[118, 36, 4, 8]]
- **Adding a Poly shape**
+ **Adding a Poly Shape**
"Poly" shapes can be either polygons or lines. Shapefile polygons must have at
- least 5 points and the last point must be the same as the first (i.e. you can't
- have a triangle accoring to the shapefile specification even though many popular
- GIS programs support such shapefiles.) A line must have at least two points.
+ least 4 points and the last point must be the same as the first. PyShp automatically
+ enforces closed polygons.
+ A line must have at least two points.
Because of the similarities between these two shape types they are created using
a single method called "poly".
- >>> w = shapefile.Writer()
+ >>> w = shapefile.Writer(shapefile.POLYGON)
>>> w.poly(shapeType=3, parts=[[[122,37,4,9], [117,36,3,4]], [[115,32,8,8],
... [118,20,6,4], [113,24]]])
+ **Adding a Polygon with Rings**
+
+ Polygons consist of rings which mean they are closed. The first point and last point
+ of a ring must be the same. PyShp enforces ring closure if the ring is incomplete when
+ you add the shape. Polygons can have inner rings which create holes. Holes are defined
+ by the order of the points. Normally points in a ring run clockwise. If the points
+ run counter-clockwise then they form a hole. If you don't order the points correctly
+ you'll just have overlapping polygons.
+
+ >>> w = shapefile.Writer(shapefile.POLYGON)
+ >>> outer_ring = [[10,10],[50,50],[100,10],[50,-50],[10,10]]
+ >>> inner_ring = [[40,10],[50,30],[70,10],[50,-30],[40,10]]
+ >>> inner_ring.reverse()
+
+ You can use the "shapefile.signed_area()" method to determine if a ring is clockwise
+ or counter-clockwise. A value >= 0 means the ring is counter-clockwise and < 0 means
+ the ring is clockwise. The value returned is also the area of the polygon.
+
+ >>> # Clockwise ring
+ ... shapefile.signed_area(outer_ring)
+ -4500.0
+ >>> # Counter-clockwise ring
+ ... shapefile.signed_area(inner_ring)
+ 900.0
+
+ **Creating 3D Polygons**
+
+ Elevation values, known as "Z" values allow you to create 3-dimensional shapefiles. The
+ z value is an extra value specified as part of a point.
+
+ >>> w = shapefile.Writer(shapeType=shapefile.POLYGONZ)
+ >>> w.poly([[[-89.0, 33, 12], [-90, 31, 11], [-91, 30, 12]]], shapeType=15)
+ >>> w.field("NAME")
+ >>> w.record("PolyZTest")
+ >>> w.save("shapefiles/test/MyPolyZ")
+
+ The z values are stored in a seperate shape attribute.
+
+ >>> r = shapefile.Reader("shapefiles/test/MyPolyZ")
+ >>> s = r.shape(0)
+ >>> s.points
+ [[-89.0, 33.0], [-90.0, 31.0], [-91.0, 30.0], [-89.0, 33.0]]
+ >>> s.z
+ [12.0, 11.0, 12.0, 12.0]
+
Creating Attributes
...................
@@ -467,6 +551,20 @@ Description: Python Shapefile Library
>>> w.record(FIRST_FLD='First', SECOND_FLD='Line')
>>> w.save('shapefiles/test/line')
+ File Names
+ ..........
+
+ File extensions are optional when reading or writing shapfiles. If you specify them Pyshp
+ ignores them anyway. When you save files you can specify a base file name that is used for
+ all three file types. Or you can specify a nmae for one or more file types. In that case,
+ any file types not assigned will not save and only file types with file names will be saved.
+ If you do not specify any file names (i.e. save()), then a unique file name is generated with
+ the prefix "shapefile\_" followed by random characters which is used for all three files. The
+ unique file name is returned as a string.
+
+ >>> targetName = w.save()
+ >>> assert("shapefile_" in targetName)
+
Saving to File-Like Objects
...........................
@@ -497,6 +595,26 @@ Description: Python Shapefile Library
>>> e = shapefile.Editor(shapefile="shapefiles/test/point.shp")
>>> e.point(0,0,10,2)
>>> e.record("Appended","Point")
+ >>> # We added z and m values so
+ >>> # change the shapetype
+ >>> e.shapeType = shapefile.POINTZ
+ >>> e.save('shapefiles/test/point')
+
+ Edit the appended point to change the "y" and "z" value
+
+ >>> e = shapefile.Editor(shapefile="shapefiles/test/point.shp")
+ >>> # Find the point by the attribute
+ >>> for s in enumerate(e.records):
+ ... i, record = s
+ ... if record[0] == "Appended":
+ ... geom = e._shapes[i]
+ ... # Change the y value to 5
+ ... geom.points[0][1] = 5
+ ... # Change the z value to 9
+ ... if hasattr(geom, "z"):
+ ... geom.z = (9,)
+ ... else:
+ ... geom.points[0][2] = 9
>>> e.save('shapefiles/test/point')
Add a new line to a line shapefile:
@@ -505,6 +623,7 @@ Description: Python Shapefile Library
>>> e.line(parts=[[[10,5],[15,5],[15,1],[13,3],[11,1]]])
>>> e.record('Appended','Line')
>>> e.save('shapefiles/test/line')
+ >>> e = None
Add a new polygon to a polygon shapefile:
@@ -512,6 +631,7 @@ Description: Python Shapefile Library
>>> e.poly(parts=[[[5.1,5],[9.9,5],[9.9,1],[7.5,3],[5.1,1]]])
>>> e.record("Appended","Polygon")
>>> e.save('shapefiles/test/polygon')
+ >>> e = None
Remove the first point in each shapefile - for a point shapefile that is
the first shape and record"
@@ -519,13 +639,27 @@ Description: Python Shapefile Library
>>> e = shapefile.Editor(shapefile="shapefiles/test/point.shp")
>>> e.delete(0)
>>> e.save('shapefiles/test/point')
+ >>> e = None
Remove the last shape in the polygon shapefile.
>>> e = shapefile.Editor(shapefile="shapefiles/test/polygon.shp")
>>> e.delete(-1)
>>> e.save('shapefiles/test/polygon')
+ >>> e = None
+ Python __geo_interface__
+ ++++++++++++++++++++++++
+
+ The Python __geo_interface__ convention provides a data interchange interface
+ among geospatial Python libraries. The interface returns data as GeoJSON.
+ More information on the __geo_interface__ protocol can be found at:
+ https://gist.github.com/sgillies/2217756.
+ More information on GeoJSON is available at http://geojson.org http://geojson.org.
+
+ >>> s = sf.shape(0)
+ >>> s.__geo_interface__["type"]
+ 'MultiPolygon'
Keywords: gis geospatial geographic shapefile shapefiles
diff --git a/pyshp.egg-info/SOURCES.txt b/pyshp.egg-info/SOURCES.txt
index 2a96c65..3ce2591 100644
--- a/pyshp.egg-info/SOURCES.txt
+++ b/pyshp.egg-info/SOURCES.txt
@@ -1,22 +1,12 @@
+MANIFEST.in
+README.html
+README.pdf
README.txt
+changelog.txt
setup.py
shapefile.py
pyshp.egg-info/PKG-INFO
pyshp.egg-info/SOURCES.txt
pyshp.egg-info/dependency_links.txt
pyshp.egg-info/not-zip-safe
-pyshp.egg-info/top_level.txt
-shapefiles/blockgroups.dbf
-shapefiles/blockgroups.sbn
-shapefiles/blockgroups.sbx
-shapefiles/blockgroups.shp
-shapefiles/blockgroups.shx
-shapefiles/test/line.dbf
-shapefiles/test/line.shp
-shapefiles/test/line.shx
-shapefiles/test/point.dbf
-shapefiles/test/point.shp
-shapefiles/test/point.shx
-shapefiles/test/polygon.dbf
-shapefiles/test/polygon.shp
-shapefiles/test/polygon.shx
\ No newline at end of file
+pyshp.egg-info/top_level.txt
\ No newline at end of file
diff --git a/setup.py b/setup.py
index 809be36..91be422 100644
--- a/setup.py
+++ b/setup.py
@@ -1,7 +1,7 @@
from setuptools import setup
setup(name='pyshp',
- version='1.1.4',
+ version='1.2.1',
description='Pure Python read/write support for ESRI Shapefile format',
long_description=open('README.txt').read(),
author='Joel Lawhead',
diff --git a/shapefile.py b/shapefile.py
index 65ac515..1fae493 100644
--- a/shapefile.py
+++ b/shapefile.py
@@ -2,16 +2,21 @@
shapefile.py
Provides read and write support for ESRI Shapefiles.
author: jlawhead<at>geospatialpython.com
-date: 20110927
-version: 1.1.4
+date: 20140507
+version: 1.2.1
Compatible with Python versions 2.4-3.x
+version changelog: Fixed u() to just return the byte sequence on exception
"""
+__version__ = "1.2.1"
+
from struct import pack, unpack, calcsize, error
import os
import sys
import time
import array
+import tempfile
+
#
# Constants for shape types
NULL = 0
@@ -31,6 +36,9 @@ MULTIPATCH = 31
PYTHON3 = sys.version_info[0] == 3
+if PYTHON3:
+ xrange = range
+
def b(v):
if PYTHON3:
if isinstance(v, str):
@@ -48,15 +56,24 @@ def b(v):
def u(v):
if PYTHON3:
- if isinstance(v, bytes):
- # For python 3 decode bytes to str.
- return v.decode('utf-8')
- elif isinstance(v, str):
- # Already str.
- return v
- else:
- # Error.
- raise Exception('Unknown input type')
+ # try/catch added 2014/05/07
+ # returned error on dbf of shapefile
+ # from www.naturalearthdata.com named
+ # "ne_110m_admin_0_countries".
+ # Just returning v as is seemed to fix
+ # the problem. This function could
+ # be condensed further.
+ try:
+ if isinstance(v, bytes):
+ # For python 3 decode bytes to str.
+ return v.decode('utf-8')
+ elif isinstance(v, str):
+ # Already str.
+ return v
+ else:
+ # Error.
+ raise Exception('Unknown input type')
+ except: return v
else:
# For python 2 assume str passed in and return str.
return v
@@ -73,6 +90,16 @@ class _Array(array.array):
def __repr__(self):
return str(self.tolist())
+def signed_area(coords):
+ """Return the signed area enclosed by a ring using the linear time
+ algorithm at http://www.cgafaq.info/wiki/Polygon_Area. A value >= 0
+ indicates a counter-clockwise oriented ring.
+ """
+ xs, ys = map(list, zip(*coords))
+ xs.append(xs[1])
+ ys.append(ys[1])
+ return sum(xs[i]*(ys[i+1]-ys[i-1]) for i in range(1, len(coords)))/2.0
+
class _Shape:
def __init__(self, shapeType=None):
"""Stores the geometry of the different shape types
@@ -87,6 +114,78 @@ class _Shape:
self.shapeType = shapeType
self.points = []
+ @property
+ def __geo_interface__(self):
+ if self.shapeType in [POINT, POINTM, POINTZ]:
+ return {
+ 'type': 'Point',
+ 'coordinates': tuple(self.points[0])
+ }
+ elif self.shapeType in [MULTIPOINT, MULTIPOINTM, MULTIPOINTZ]:
+ return {
+ 'type': 'MultiPoint',
+ 'coordinates': tuple([tuple(p) for p in self.points])
+ }
+ elif self.shapeType in [POLYLINE, POLYLINEM, POLYLINEZ]:
+ if len(self.parts) == 1:
+ return {
+ 'type': 'LineString',
+ 'coordinates': tuple([tuple(p) for p in self.points])
+ }
+ else:
+ ps = None
+ coordinates = []
+ for part in self.parts:
+ if ps == None:
+ ps = part
+ continue
+ else:
+ coordinates.append(tuple([tuple(p) for p in self.points[ps:part]]))
+ ps = part
+ else:
+ coordinates.append(tuple([tuple(p) for p in self.points[part:]]))
+ return {
+ 'type': 'MultiLineString',
+ 'coordinates': tuple(coordinates)
+ }
+ elif self.shapeType in [POLYGON, POLYGONM, POLYGONZ]:
+ if len(self.parts) == 1:
+ return {
+ 'type': 'Polygon',
+ 'coordinates': (tuple([tuple(p) for p in self.points]),)
+ }
+ else:
+ ps = None
+ coordinates = []
+ for part in self.parts:
+ if ps == None:
+ ps = part
+ continue
+ else:
+ coordinates.append(tuple([tuple(p) for p in self.points[ps:part]]))
+ ps = part
+ else:
+ coordinates.append(tuple([tuple(p) for p in self.points[part:]]))
+ polys = []
+ poly = [coordinates[0]]
+ for coord in coordinates[1:]:
+ if signed_area(coord) < 0:
+ polys.append(poly)
+ poly = [coord]
+ else:
+ poly.append(coord)
+ polys.append(poly)
+ if len(polys) == 1:
+ return {
+ 'type': 'Polygon',
+ 'coordinates': tuple(polys[0])
+ }
+ elif len(polys) > 1:
+ return {
+ 'type': 'MultiPolygon',
+ 'coordinates': polys
+ }
+
class _ShapeRecord:
"""A shape object of any type."""
def __init__(self, shape=None, record=None):
@@ -127,7 +226,7 @@ class Reader:
self.__dbfHdrLength = 0
# See if a shapefile name was passed as an argument
if len(args) > 0:
- if type(args[0]) is type("stringTest"):
+ if is_string(args[0]):
self.load(args[0])
return
if "shp" in kwargs.keys():
@@ -220,6 +319,8 @@ class Reader:
record = _Shape()
nParts = nPoints = zmin = zmax = mmin = mmax = None
(recNum, recLength) = unpack(">2i", f.read(8))
+ # Determine the start of the next record
+ next = f.tell() + (2 * recLength)
shapeType = unpack("<i", f.read(4))[0]
record.shapeType = shapeType
# For Null shapes create an empty points list for consistency
@@ -247,12 +348,12 @@ class Reader:
if shapeType in (13,15,18,31):
(zmin, zmax) = unpack("<2d", f.read(16))
record.z = _Array('d', unpack("<%sd" % nPoints, f.read(nPoints * 8)))
- # Read m extremes and values
- if shapeType in (13,15,18,23,25,28,31):
+ # Read m extremes and values if header m values do not equal 0.0
+ if shapeType in (13,15,18,23,25,28,31) and not 0.0 in self.measure:
(mmin, mmax) = unpack("<2d", f.read(16))
# Measure values less than -10e38 are nodata values according to the spec
record.m = []
- for m in _Array('d', unpack("%sd" % nPoints, f.read(nPoints * 8))):
+ for m in _Array('d', unpack("<%sd" % nPoints, f.read(nPoints * 8))):
if m > -10e38:
record.m.append(m)
else:
@@ -266,6 +367,10 @@ class Reader:
# Read a single M value
if shapeType in (11,21):
record.m = unpack("<d", f.read(8))
+ # Seek to the end of this record as defined by the record header because
+ # the shapefile spec doesn't require the actual content to meet the header
+ # definition. Probably allowed for lazy feature deletion.
+ f.seek(next)
return record
def __shapeIndex(self, i=None):
@@ -295,21 +400,38 @@ class Reader:
i = self.__restrictIndex(i)
offset = self.__shapeIndex(i)
if not offset:
- # Shx index not available so use the full list.
- shapes = self.shapes()
- return shapes[i]
+ # Shx index not available so iterate the full list.
+ for j,k in enumerate(self.iterShapes()):
+ if j == i:
+ return k
shp.seek(offset)
return self.__shape()
def shapes(self):
"""Returns all shapes in a shapefile."""
shp = self.__getFileObj(self.shp)
+ # Found shapefiles which report incorrect
+ # shp file length in the header. Can't trust
+ # that so we seek to the end of the file
+ # and figure it out.
+ shp.seek(0,2)
+ self.shpLength = shp.tell()
shp.seek(100)
shapes = []
while shp.tell() < self.shpLength:
shapes.append(self.__shape())
return shapes
+ def iterShapes(self):
+ """Serves up shapes in a shapefile as an iterator. Useful
+ for handling large shapefiles."""
+ shp = self.__getFileObj(self.shp)
+ shp.seek(0,2)
+ self.shpLength = shp.tell()
+ shp.seek(100)
+ while shp.tell() < self.shpLength:
+ yield self.__shape()
+
def __dbfHeaderLength(self):
"""Retrieves the header length of a dbf file header."""
if not self.__dbfHdrLength:
@@ -415,12 +537,23 @@ class Reader:
records.append(r)
return records
+ def iterRecords(self):
+ """Serves up records in a dbf file as an iterator.
+ Useful for large shapefiles or dbf files."""
+ if not self.numRecords:
+ self.__dbfHeader()
+ f = self.__getFileObj(self.dbf)
+ f.seek(self.__dbfHeaderLength())
+ for i in xrange(self.numRecords):
+ r = self.__record()
+ if r:
+ yield r
+
def shapeRecord(self, i=0):
"""Returns a combination geometry and attribute record for the
supplied record index."""
i = self.__restrictIndex(i)
- return _ShapeRecord(shape=self.shape(i),
- record=self.record(i))
+ return _ShapeRecord(shape=self.shape(i), record=self.record(i))
def shapeRecords(self):
"""Returns a list of combination geometry/attribute records for
@@ -638,6 +771,8 @@ class Writer:
recNum += 1
start = f.tell()
# Shape Type
+ if self.shapeType != 31:
+ s.shapeType = self.shapeType
f.write(pack("<i", s.shapeType))
# All shape types capable of having a bounding box
if s.shapeType in (3,5,8,13,15,18,23,25,28,31):
@@ -674,13 +809,19 @@ class Writer:
except error:
raise ShapefileException("Failed to write elevation extremes for record %s. Expected floats." % recNum)
try:
- [f.write(pack("<d", p[2])) for p in s.points]
+ if hasattr(s,"z"):
+ f.write(pack("<%sd" % len(s.z), *s.z))
+ else:
+ [f.write(pack("<d", p[2])) for p in s.points]
except error:
raise ShapefileException("Failed to write elevation values for record %s. Expected floats." % recNum)
# Write m extremes and values
- if s.shapeType in (23,25,31):
+ if s.shapeType in (13,15,18,23,25,28,31):
try:
- f.write(pack("<2d", *self.__mbox([s])))
+ if hasattr(s,"m"):
+ f.write(pack("<%sd" % len(s.m), *s.m))
+ else:
+ f.write(pack("<2d", *self.__mbox([s])))
except error:
raise ShapefileException("Failed to write measure extremes for record %s. Expected floats" % recNum)
try:
@@ -695,16 +836,36 @@ class Writer:
raise ShapefileException("Failed to write point for record %s. Expected floats." % recNum)
# Write a single Z value
if s.shapeType == 11:
- try:
- f.write(pack("<1d", s.points[0][2]))
- except error:
- raise ShapefileException("Failed to write elevation value for record %s. Expected floats." % recNum)
+ if hasattr(s, "z"):
+ try:
+ if not s.z:
+ s.z = (0,)
+ f.write(pack("<d", s.z[0]))
+ except error:
+ raise ShapefileException("Failed to write elevation value for record %s. Expected floats." % recNum)
+ else:
+ try:
+ if len(s.points[0])<3:
+ s.points[0].append(0)
+ f.write(pack("<d", s.points[0][2]))
+ except error:
+ raise ShapefileException("Failed to write elevation value for record %s. Expected floats." % recNum)
# Write a single M value
if s.shapeType in (11,21):
- try:
- f.write(pack("<1d", s.points[0][3]))
- except error:
- raise ShapefileException("Failed to write measure value for record %s. Expected floats." % recNum)
+ if hasattr(s, "m"):
+ try:
+ if not s.m:
+ s.m = (0,)
+ f.write(pack("<1d", s.m[0]))
+ except error:
+ raise ShapefileException("Failed to write measure value for record %s. Expected floats." % recNum)
+ else:
+ try:
+ if len(s.points[0])<4:
+ s.points[0].append(0)
+ f.write(pack("<1d", s.points[0][3]))
+ except error:
+ raise ShapefileException("Failed to write measure value for record %s. Expected floats." % recNum)
# Finalize record length as 16-bit words
finish = f.tell()
length = (finish - start) // 2
@@ -766,6 +927,11 @@ class Writer:
polyShape = _Shape(shapeType)
polyShape.parts = []
polyShape.points = []
+ # Make sure polygons are closed
+ if shapeType in (5,15,25,31):
+ for part in parts:
+ if part[0] != part[-1]:
+ part.append(part[0])
for part in parts:
polyShape.parts.append(len(polyShape.points))
for point in part:
@@ -805,10 +971,10 @@ class Writer:
for field in self.fields:
if field[0] in recordDict:
val = recordDict[field[0]]
- if val:
- record.append(val)
- else:
+ if val is None:
record.append("")
+ else:
+ record.append(val)
if record:
self.records.append(record)
@@ -850,22 +1016,33 @@ class Writer:
def save(self, target=None, shp=None, shx=None, dbf=None):
"""Save the shapefile data to three files or
three file-like objects. SHP and DBF files can also
- be written exclusively using saveShp, saveShx, and saveDbf respectively."""
- # TODO: Create a unique filename for target if None.
+ be written exclusively using saveShp, saveShx, and saveDbf respectively.
+ If target is specified but not shp,shx, or dbf then the target path and
+ file name are used. If no options or specified, a unique base file name
+ is generated to save the files and the base file name is returned as a
+ string.
+ """
+ # Create a unique file name if one is not defined
if shp:
self.saveShp(shp)
if shx:
self.saveShx(shx)
if dbf:
self.saveDbf(dbf)
- elif target:
+ elif not shp and not shx and not dbf:
+ generated = False
+ if not target:
+ temp = tempfile.NamedTemporaryFile(prefix="shapefile_",dir=os.getcwd())
+ target = temp.name
+ generated = True
self.saveShp(target)
self.shp.close()
self.saveShx(target)
self.shx.close()
self.saveDbf(target)
self.dbf.close()
-
+ if generated:
+ return target
class Editor(Writer):
def __init__(self, shapefile=None, shapeType=POINT, autoBalance=1):
self.autoBalance = autoBalance
@@ -991,7 +1168,7 @@ def test():
if __name__ == "__main__":
"""
- Doctests are contained in the module 'pyshp_usage.py'. This library was developed
+ Doctests are contained in the file 'README.txt'. This library was originally developed
using Python 2.3. Python 2.4 and above have some excellent improvements in the built-in
testing libraries but for now unit testing is done using what's available in
2.3.
diff --git a/shapefiles/blockgroups.dbf b/shapefiles/blockgroups.dbf
deleted file mode 100644
index 7ff63cf..0000000
Binary files a/shapefiles/blockgroups.dbf and /dev/null differ
diff --git a/shapefiles/blockgroups.sbn b/shapefiles/blockgroups.sbn
deleted file mode 100644
index f7e3484..0000000
Binary files a/shapefiles/blockgroups.sbn and /dev/null differ
diff --git a/shapefiles/blockgroups.sbx b/shapefiles/blockgroups.sbx
deleted file mode 100644
index eefaf4b..0000000
Binary files a/shapefiles/blockgroups.sbx and /dev/null differ
diff --git a/shapefiles/blockgroups.shp b/shapefiles/blockgroups.shp
deleted file mode 100644
index f1734a3..0000000
Binary files a/shapefiles/blockgroups.shp and /dev/null differ
diff --git a/shapefiles/blockgroups.shx b/shapefiles/blockgroups.shx
deleted file mode 100644
index a2f62ac..0000000
Binary files a/shapefiles/blockgroups.shx and /dev/null differ
diff --git a/shapefiles/test/line.dbf b/shapefiles/test/line.dbf
deleted file mode 100644
index 5882280..0000000
Binary files a/shapefiles/test/line.dbf and /dev/null differ
diff --git a/shapefiles/test/line.shp b/shapefiles/test/line.shp
deleted file mode 100644
index 9e742d9..0000000
Binary files a/shapefiles/test/line.shp and /dev/null differ
diff --git a/shapefiles/test/line.shx b/shapefiles/test/line.shx
deleted file mode 100644
index fcfa194..0000000
Binary files a/shapefiles/test/line.shx and /dev/null differ
diff --git a/shapefiles/test/point.dbf b/shapefiles/test/point.dbf
deleted file mode 100644
index 78824b3..0000000
Binary files a/shapefiles/test/point.dbf and /dev/null differ
diff --git a/shapefiles/test/point.shp b/shapefiles/test/point.shp
deleted file mode 100644
index 8972b85..0000000
Binary files a/shapefiles/test/point.shp and /dev/null differ
diff --git a/shapefiles/test/point.shx b/shapefiles/test/point.shx
deleted file mode 100644
index bfbeac1..0000000
Binary files a/shapefiles/test/point.shx and /dev/null differ
diff --git a/shapefiles/test/polygon.dbf b/shapefiles/test/polygon.dbf
deleted file mode 100644
index 737c203..0000000
Binary files a/shapefiles/test/polygon.dbf and /dev/null differ
diff --git a/shapefiles/test/polygon.shp b/shapefiles/test/polygon.shp
deleted file mode 100644
index 7e62f36..0000000
Binary files a/shapefiles/test/polygon.shp and /dev/null differ
diff --git a/shapefiles/test/polygon.shx b/shapefiles/test/polygon.shx
deleted file mode 100644
index 6cf9c82..0000000
Binary files a/shapefiles/test/polygon.shx and /dev/null differ
--
Alioth's /usr/local/bin/git-commit-notice on /srv/git.debian.org/git/pkg-grass/pyshp.git
More information about the Pkg-grass-devel
mailing list