<SYSTEM_TASK:>
Given the following text description, write Python code to implement the functionality described below step by step
<END_TASK>
<USER_TASK:>
Description:
 Working with shapes
Shapes are object created using the package Shapely which know about their geometry. They don't need to be associated with a map in any way. We will start with basic shapes, and then use shapes on a map, since shape functions have been included in cartopy.
Step1:  0D shapes
Step2:  1D shapes
Step3:  2D shapes, Polygons and Buffers
Step4:  We can also create 2D objects by adding buffers to existing 0D and 1D objects
Step5:  Operations
<ASSISTANT_TASK:>
Python Code:
import numpy as np
import matplotlib.pyplot as plt
%matplotlib inline
import shapely.geometry
import shapely.ops
import cartopy
import cartopy.io.shapereader as shpreader
Explanation: Working with shapes
Shapes are object created using the package Shapely which know about their geometry. They don't need to be associated with a map in any way. We will start with basic shapes, and then use shapes on a map, since shape functions have been included in cartopy.
End of explanation
point = shapely.geometry.Point(0.2, 1.0)
# Notice, the ipython '__repr__' (representation) displays the point as the output
point
# See some of the point attributes
print(point.geom_type)
print(point.area)
print(point.length)
print(point.bounds)
print(point.coords)   # explore this object...
print(point.coords[:])
# A collection of random points...
point1 = shapely.geometry.Point(0.2, 1.0)
point2 = shapely.geometry.Point(0.1, 0.2)
point3 = shapely.geometry.Point(0.5, 0.0)
point4 = shapely.geometry.Point(0.8, 0.5)
# We can see the distance of the points from one another
point2.distance(point1)
Explanation: 0D shapes: Points
End of explanation
# An ordered sequence of points is a `LineString'
line = shapely.geometry.LineString((point1, point2, point3, point4))
line
# To make a closed shape, use a `LinearRing'
closed_line = shapely.geometry.LinearRing(line)
closed_line
# Some of the attributes of the LinearRing..
print(closed_line.area)   # no area since it is not 'filled'
print(closed_line.length) # the perimeter of the shape
print(closed_line.bounds) # an xy-plane bounding box
Explanation: 1D shapes: Lines and Rings
End of explanation
# Let's make a circle, with some noise
N = 50
x = np.cos(np.linspace(0, 2.0*np.pi, N+1))[:-1] + 0.05*np.random.randn(50)
y = np.sin(np.linspace(0, 2.0*np.pi, N+1))[:-1] + 0.05*np.random.randn(50)
plt.plot(x, y, '-')
xy = zip(x, y)
poly = shapely.geometry.Polygon(xy)
poly
# Some of the Polygon attributes
print(poly.area)  # does this make sense?
print(poly.centroid)
print(poly.contains(point1), poly.contains(point2))
poly.boundary
Explanation: 2D shapes, Polygons and Buffers
End of explanation
dialated = line.buffer(0.3)
eroded = dialated.buffer(-0.2)
plt.plot(*line.xy)
plt.fill(*dialated.boundary.xy, 'g', alpha=0.2)
plt.fill(*eroded.boundary.xy, 'b', alpha=0.2)
poly.buffer(-.8)
Explanation: We can also create 2D objects by adding buffers to existing 0D and 1D objects
End of explanation
# First, let's make a collection of fat points.
xy = np.random.rand(20, 2)
points = shapely.geometry.MultiPoint(xy).buffer(0.1)
points
points.boundary
# make a new line
line2 = shapely.geometry.LineString([(0, 0), (1, 1)])
# loop over the polygons in the regions and plot, colored 
# differently if they intersect line1
for poly in points.boundary:
    if poly.intersects(line2):
        color = 'r'
    else:
        color = 'k'
    coords = poly.coords[:]
    x, y = zip(*coords)
    plt.fill(x, y, color=color, alpha=0.3)
# Plot the line also
x, y = zip(*line2.coords[:])
plt.plot(x, y, '--k')
plt.gca().set_aspect(1.0)
Explanation: Operations
End of explanation
<END_TASK>