>>> from env_helper import info; info()
页面更新时间: 2023-04-15 20:03:52
运行环境:
Linux发行版本: Debian GNU/Linux 12 (bookworm)
操作系统内核: Linux-6.1.0-7-amd64-x86_64-with-glibc2.36
Python版本: 3.11.2
14.3. Descartes¶
Descartes 是一个图像,数据和函数的绘图仪。 函数参数可以手动调整(或自动拟合,不过尚未实现)给定的xy数据。 高级脚本功能(尚未实现)由底层Python编程语言提供。
Descartes与平台无关; 它在Linux下及非自由操作系统下运行。
Descartes是开源软件; 它是免费分发的,受GNU公共许可证保护。
所依赖的scipy 库 经历了重大的重组; 不再支持scipy.plt模块。
程序的使用是相当直观的; 用户手册目前仅包含几个关于特殊主题的注释,例如数学公式和输入数据格式。
该程序可以在任何PC上运行。 唯一的要求是使用SciPy和wxPython模块完成Python安装。上述均可以在网上免费获得。
14.3.2. 数据输入¶
可以从CSV文件输入x-y数据。 虽然CSV最初是逗号分隔,但是descartes也允许使用分号,制表符和空格作为分隔符。 CSV文件的第一行可能包含用双引号括起来的x和y坐标的名字。
使用Shapely或GeoJSON类几何对象可作为matplotlib的路径和补丁。
Descartes 的安装与运行需要 Matplotlib,NumPy和可选择的Shapely 1.2+ 。
下面是导入库的例子:
>>> from matplotlib import pyplot
>>> from shapely.geometry import LineString
>>> from descartes import PolygonPatch
导入库:
>>> BLUE = '#6699cc'
>>> GRAY = '#999999'
分别给BLUE、GRAY赋颜色值。
>>>
>>> def plot_line(ax, ob):
>>> x, y = ob.xy
>>> ax.plot(x, y, color=GRAY, linewidth=3, solid_capstyle='round', zorder=1)
定义函数plot_line(变量1,变量2)。
>>>
>>> line = LineString([(0, 0), (1, 1), (0, 2), (2, 2), (3, 1), (1, 0)])
>>>
>>> fig = pyplot.figure(1, figsize=(10, 4), dpi=180)
<Figure size 1800x720 with 0 Axes>
创建一幅图。
>>> ax = fig.add_subplot(121)
将图像分割成1行2列,将图像画在从左到右从上到下的第1块
>>>
>>>
>>> dilated = line.buffer(0.5)
>>> patch1 = PolygonPatch(dilated, fc=BLUE, ec=BLUE, alpha=0.5, zorder=2)
>>> ax.add_patch(patch1)
>>>
>>>
>>> ax = fig.add_subplot(122)
>>>
>>> patch2a = PolygonPatch(dilated, fc=GRAY, ec=GRAY, alpha=0.5, zorder=1)
>>> ax.add_patch(patch2a)
>>>
>>> eroded = dilated.buffer(-0.3)
---------------------------------------------------------------------------
IndexError Traceback (most recent call last)
Cell In[9], line 2
1 dilated = line.buffer(0.5)
----> 2 patch1 = PolygonPatch(dilated, fc=BLUE, ec=BLUE, alpha=0.5, zorder=2)
3 ax.add_patch(patch1)
6 ax = fig.add_subplot(122)
File /opt/jupyterhub/lib/python3.11/site-packages/descartes/patch.py:87, in PolygonPatch(polygon, **kwargs)
73 def PolygonPatch(polygon, **kwargs):
74 """Constructs a matplotlib patch from a geometric object
75
76 The `polygon` may be a Shapely or GeoJSON-like object with or without holes.
(...)
85
86 """
---> 87 return PathPatch(PolygonPath(polygon), **kwargs)
File /opt/jupyterhub/lib/python3.11/site-packages/descartes/patch.py:62, in PolygonPath(polygon)
58 else:
59 raise ValueError(
60 "A polygon or multi-polygon representation is required")
---> 62 vertices = concatenate([
63 concatenate([asarray(t.exterior)[:, :2]] +
64 [asarray(r)[:, :2] for r in t.interiors])
65 for t in polygon])
66 codes = concatenate([
67 concatenate([coding(t.exterior)] +
68 [coding(r) for r in t.interiors]) for t in polygon])
70 return Path(vertices, codes)
File /opt/jupyterhub/lib/python3.11/site-packages/descartes/patch.py:63, in <listcomp>(.0)
58 else:
59 raise ValueError(
60 "A polygon or multi-polygon representation is required")
62 vertices = concatenate([
---> 63 concatenate([asarray(t.exterior)[:, :2]] +
64 [asarray(r)[:, :2] for r in t.interiors])
65 for t in polygon])
66 codes = concatenate([
67 concatenate([coding(t.exterior)] +
68 [coding(r) for r in t.interiors]) for t in polygon])
70 return Path(vertices, codes)
IndexError: too many indices for array: array is 0-dimensional, but 2 were indexed
>>>
>>> # GeoJSON-like data works as well
>>>
>>> polygon = eroded.__geo_interface__
>>> patch2b = PolygonPatch(polygon, fc=BLUE, ec=BLUE, alpha=0.5, zorder=2)
>>> ax.add_patch(patch2b)
>>>
>>> pyplot.show()
---------------------------------------------------------------------------
NameError Traceback (most recent call last)
Cell In[10], line 3
1 # GeoJSON-like data works as well
----> 3 polygon = eroded.__geo_interface__
4 patch2b = PolygonPatch(polygon, fc=BLUE, ec=BLUE, alpha=0.5, zorder=2)
5 ax.add_patch(patch2b)
NameError: name 'eroded' is not defined
展示结果。
>>> from matplotlib import pyplot
>>> from shapely.geometry import *
>>>
>>> from descartes import PolygonPatch
>>>
>>>
>>> fig = pyplot.figure(num=1, figsize=(10, 4), dpi=180)
<Figure size 1800x720 with 0 Axes>
创建一个matplotlib图
>>>
>>> polygon = Point(0, 0).buffer(10.0).difference(
>>> MultiPoint([(-5, 0), (5, 0)]).buffer(3.0))
>>>
>>> polygon
使用缓冲区和差分方法创建一个有2个孔的多边形
>>> ax = fig.add_subplot(221)
创建子图
>>>
>>> patch = PolygonPatch(polygon, facecolor='#cccccc', edgecolor='#999999')
>>> ax.add_patch(patch)
>>>
---------------------------------------------------------------------------
IndexError Traceback (most recent call last)
Cell In[14], line 1
----> 1 patch = PolygonPatch(polygon, facecolor='#cccccc', edgecolor='#999999')
2 ax.add_patch(patch)
File /opt/jupyterhub/lib/python3.11/site-packages/descartes/patch.py:87, in PolygonPatch(polygon, **kwargs)
73 def PolygonPatch(polygon, **kwargs):
74 """Constructs a matplotlib patch from a geometric object
75
76 The `polygon` may be a Shapely or GeoJSON-like object with or without holes.
(...)
85
86 """
---> 87 return PathPatch(PolygonPath(polygon), **kwargs)
File /opt/jupyterhub/lib/python3.11/site-packages/descartes/patch.py:62, in PolygonPath(polygon)
58 else:
59 raise ValueError(
60 "A polygon or multi-polygon representation is required")
---> 62 vertices = concatenate([
63 concatenate([asarray(t.exterior)[:, :2]] +
64 [asarray(r)[:, :2] for r in t.interiors])
65 for t in polygon])
66 codes = concatenate([
67 concatenate([coding(t.exterior)] +
68 [coding(r) for r in t.interiors]) for t in polygon])
70 return Path(vertices, codes)
File /opt/jupyterhub/lib/python3.11/site-packages/descartes/patch.py:63, in <listcomp>(.0)
58 else:
59 raise ValueError(
60 "A polygon or multi-polygon representation is required")
62 vertices = concatenate([
---> 63 concatenate([asarray(t.exterior)[:, :2]] +
64 [asarray(r)[:, :2] for r in t.interiors])
65 for t in polygon])
66 codes = concatenate([
67 concatenate([coding(t.exterior)] +
68 [coding(r) for r in t.interiors]) for t in polygon])
70 return Path(vertices, codes)
IndexError: too many indices for array: array is 0-dimensional, but 2 were indexed
将多边形变成补丁,将其添加到子图中:
>>>
>>> minx, miny, maxx, maxy = polygon.bounds
>>> w, h = maxx - minx, maxy - miny
>>> ax.set_xlim(minx - 0.2*w, maxx + 0.2*w)
>>> ax.set_ylim(miny - 0.2*h, maxy + 0.2*h)
>>> ax.set_aspect(1)
>>>
在多边形边界周围绘制图形,渲染并保存:
>>> ax = fig.add_subplot(222)
创建子图
>>> geo = polygon.__geo_interface__
>>> patch = PolygonPatch(geo, facecolor='#cccccc', edgecolor='#999999')
>>> ax.add_patch(patch)
将赋值为1的多边形的GeoJSON-ish dict格式转换为补丁:
>>>
>>> minx, miny, maxx, maxy = polygon.bounds
>>> w, h = maxx - minx, maxy - miny
>>> ax.set_xlim(minx - 0.2*w, maxx + 0.2*w)
>>> ax.set_ylim(miny - 0.2*h, maxy + 0.2*h)
>>> ax.set_aspect(1)
>>>
>>>
在多边形边界周围绘制图形,渲染并保存:
>>>
>>> multipolygon = Point(0, 0).buffer(10.0).difference(
>>> MultiPoint([(-5, 0), (5, 0)]).buffer(3.0)).union(
>>> MultiPoint([(-10, 10), (10, -10)]).buffer(2.0))
>>>
使用缓冲区创建一个具有2个孔和2个卫星多边形的多边形,difference和union方法:
>>> ax = fig.add_subplot(223)
创建子图
>>>
>>> patch = PolygonPatch(multipolygon, facecolor='#cccccc', edgecolor='#999999')
>>> ax.add_patch(patch)
>>>
将多边形变成补丁并将其添加到子图中
>>>
>>> minx, miny, maxx, maxy = polygon.bounds
>>> w, h = maxx - minx, maxy - miny
>>> ax.set_xlim(minx - 0.2*w, maxx + 0.2*w)
>>> ax.set_ylim(miny - 0.2*h, maxy + 0.2*h)
>>> ax.set_aspect(1)
>>>
在多边形边界周围绘制图形,渲染并保存
>>> ax = fig.add_subplot(224)
>>>
创建子图
>>>
>>> geo = multipolygon.__geo_interface__
>>> patch = PolygonPatch(geo, facecolor='#cccccc', edgecolor='#999999')
>>> ax.add_patch(patch)
>>>
将赋值为1的多边形的GeoJSON-ish dict格式转换为补丁
>>>
>>> minx, miny, maxx, maxy = polygon.bounds
>>> w, h = maxx - minx, maxy - miny
>>> ax.set_xlim(minx - 0.2*w, maxx + 0.2*w)
>>> ax.set_ylim(miny - 0.2*h, maxy + 0.2*h)
>>> ax.set_aspect(1)
在多边形边界周围绘制图形,渲染和保存
>>> %matplotlib inline
>>> from matplotlib import pyplot
>>> from shapely.geometry import *
>>>
>>> from descartes import PolygonPatch
>>>
>>> # Create a matplotlib figure
>>> fig = pyplot.figure(num=1, figsize=(10, 4), dpi=180)
>>>
>>> # Create a polygon with 2 holes using buffer and difference methods
>>> polygon = Point(0, 0).buffer(10.0).difference(
>>> MultiPoint([(-5, 0), (5, 0)]).buffer(3.0))
>>>
>>> # 1
>>> # Create a subplot
>>> ax = fig.add_subplot(221)
>>>
>>> # Make the polygon into a patch and add it to the subplot
>>> patch = PolygonPatch(polygon, facecolor='#cccccc', edgecolor='#999999')
>>> ax.add_patch(patch)
>>>
>>> # Fit the figure around the polygon's bounds, render, and save
>>> minx, miny, maxx, maxy = polygon.bounds
>>> w, h = maxx - minx, maxy - miny
>>> ax.set_xlim(minx - 0.2*w, maxx + 0.2*w)
>>> ax.set_ylim(miny - 0.2*h, maxy + 0.2*h)
>>> ax.set_aspect(1)
>>>
>>> # 2
>>> # Create a subplot
>>> ax = fig.add_subplot(222)
>>>
>>> # Turn the GeoJSON-ish dict form of the polygon from #1 into a patch
>>> geo = polygon.__geo_interface__
>>> patch = PolygonPatch(geo, facecolor='#cccccc', edgecolor='#999999')
>>> ax.add_patch(patch)
>>>
>>> # Fit the figure around the polygon's bounds, render, and save
>>> minx, miny, maxx, maxy = polygon.bounds
>>> w, h = maxx - minx, maxy - miny
>>> ax.set_xlim(minx - 0.2*w, maxx + 0.2*w)
>>> ax.set_ylim(miny - 0.2*h, maxy + 0.2*h)
>>> ax.set_aspect(1)
>>>
>>>
>>> # Create a multi-polygon with 2 holes and 2 satelite polygons using buffer,
>>> # difference and union methods
>>> multipolygon = Point(0, 0).buffer(10.0).difference(
>>> MultiPoint([(-5, 0), (5, 0)]).buffer(3.0)).union(
>>> MultiPoint([(-10, 10), (10, -10)]).buffer(2.0))
>>>
>>> # 3
>>> # Create a subplot
>>> ax = fig.add_subplot(223)
>>>
>>> # Make the polygon into a patch and add it to the subplot
>>> patch = PolygonPatch(multipolygon, facecolor='#cccccc', edgecolor='#999999')
>>> ax.add_patch(patch)
>>>
>>> # Fit the figure around the polygon's bounds, render, and save
>>> minx, miny, maxx, maxy = polygon.bounds
>>> w, h = maxx - minx, maxy - miny
>>> ax.set_xlim(minx - 0.2*w, maxx + 0.2*w)
>>> ax.set_ylim(miny - 0.2*h, maxy + 0.2*h)
>>> ax.set_aspect(1)
>>>
>>> # 4
>>> # Create a subplot
>>> ax = fig.add_subplot(224)
>>>
>>> # Turn the GeoJSON-ish dict form of the polygon from #1 into a patch
>>> geo = multipolygon.__geo_interface__
>>> patch = PolygonPatch(geo, facecolor='#cccccc', edgecolor='#999999')
>>> ax.add_patch(patch)
>>>
>>> # Fit the figure around the polygon's bounds, render, and save
>>> minx, miny, maxx, maxy = polygon.bounds
>>> w, h = maxx - minx, maxy - miny
>>> ax.set_xlim(minx - 0.2*w, maxx + 0.2*w)
>>> ax.set_ylim(miny - 0.2*h, maxy + 0.2*h)
>>> ax.set_aspect(1)
>>>
>>>
>>> # fig.savefig('patches.png')
>>> pyplot.show()
整合输出。
>>> from matplotlib import pyplot
>>> from shapely.geometry import LineString
>>> from descartes import PolygonPatch
>>>
>>> BLUE = '#6699cc'
>>> GRAY = '#999999'
>>>
>>> def plot_line(ax, ob):
>>> x, y = ob.xy
>>> ax.plot(x, y, color=GRAY, linewidth=3, solid_capstyle='round', zorder=1)
>>>
>>> line = LineString([(0, 0), (1, 1), (0, 2), (2, 2), (3, 1), (1, 0)])
>>>
>>> fig = pyplot.figure(1, figsize=(10, 4), dpi=180)
>>>
>>> # 1
>>> ax = fig.add_subplot(121)
>>>
>>> plot_line(ax, line)
>>>
>>> dilated = line.buffer(0.5)
>>> patch1 = PolygonPatch(dilated, fc=BLUE, ec=BLUE, alpha=0.5, zorder=2)
>>> ax.add_patch(patch1)
>>>
>>> #2
>>> ax = fig.add_subplot(122)
>>>
>>> patch2a = PolygonPatch(dilated, fc=GRAY, ec=GRAY, alpha=0.5, zorder=1)
>>> ax.add_patch(patch2a)
>>>
>>> eroded = dilated.buffer(-0.3)
>>>
>>> # GeoJSON-like data works as well
>>>
>>> polygon = eroded.__geo_interface__
>>>
>>> patch2b = PolygonPatch(polygon, fc=BLUE, ec=BLUE, alpha=0.5, zorder=2)
>>> ax.add_patch(patch2b)
>>>
>>> pyplot.show()