>>> from env_helper import info; info()
页面更新时间: 2023-12-24 17:30:47
运行环境:
    Linux发行版本: Debian GNU/Linux 12 (bookworm)
    操作系统内核: Linux-6.1.0-15-amd64-x86_64-with-glibc2.36
    Python版本: 3.11.2

15.3. Descartes

Descartes 是一个图像,数据和函数的绘图仪。 函数参数可以手动调整(或自动拟合,不过尚未实现)给定的xy数据。 高级脚本功能(尚未实现)由底层Python编程语言提供。

  • Descartes与平台无关; 它在Linux下及非自由操作系统下运行。

  • Descartes是开源软件; 它是免费分发的,受GNU公共许可证保护。

  • 所依赖的scipy 库 经历了重大的重组; 不再支持scipy.plt模块。

  • 程序的使用是相当直观的; 用户手册目前仅包含几个关于特殊主题的注释,例如数学公式和输入数据格式。

该程序可以在任何PC上运行。 唯一的要求是使用SciPy和wxPython模块完成Python安装。上述均可以在网上免费获得。

15.3.1. 安装配置

这个模块没有进入 Debian/Ubuntu 软件仓储,可以通过 pip 安装:

pip install descartes

15.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
---------------------------------------------------------------------------

ModuleNotFoundError                       Traceback (most recent call last)

Cell In[1], line 1
----> 1 from matplotlib import pyplot
      2 from shapely.geometry import LineString
      3 from descartes import PolygonPatch


ModuleNotFoundError: No module named 'matplotlib'

导入库:

>>> 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)

创建一幅图。

>>> 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)
>>>
>>> # 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()

展示结果。

>>> from matplotlib import pyplot
>>> from shapely.geometry import *
>>>
>>> from descartes import PolygonPatch
>>>
>>>
>>> fig = pyplot.figure(num=1, figsize=(10, 4), dpi=180)

创建一个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)
>>>

将多边形变成补丁,将其添加到子图中:

>>>
>>> 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()