IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> Python知识库 -> 跟着 gma 学 Python:矢量面文件的空间绘图 -> 正文阅读

[Python知识库]跟着 gma 学 Python:矢量面文件的空间绘图

??得益于 gdal 的强大功能,gma 继承了其对各类栅格/矢量(目前支持超过80种矢量文件格式)文件的读取支持,并在其基础上进行简化、优化等改造,以便其符合 gma 的整体建库逻辑。
??本文基于 gma 定义的矢量读取逻辑和方式,重点展示如何结合 Matplotlib,实现矢量面文件的空间绘制。

绘制思路

开始
打开文件
读取图层/要素
读取折点坐标
生成并绘制多边形
结束

gma 矢量读取逻辑介绍

??在 gma 里,所有的打开的矢量数据可分为三级,分别为 数据资源—图层—要素。一般来说,普通的矢量数据均只含一个图层(例如:shp文件等)。一些特殊的文件可能会包含多个图层,这点与含有子数据集的多维栅格类似。可通过如下代码查看支持多图层的矢量格式:

import gma
gma.config.VectorFormatInfo().MultiLayersFormats

{‘AVCBIN’, ‘CAD’, ‘DGN’, ‘DXF’, ‘EDIGEO’, ‘GML’, ‘GPKG’, ‘GPX’, ‘KML’, ‘LIBKML’, ‘MSSQLSpatial’, ‘Memory’, ‘NGW’, ‘ODBC’, ‘ODS’, ‘OSM’, ‘OpenFileGDB’, ‘PDF’, ‘PGeo’, ‘PostgreSQL’, ‘S57’, ‘SQLite’, ‘VRT’, ‘XLS’, ‘XLSX’}

层级之间的关系及应用方式如下图:

注意:在 gdal/ogr 中,Feature 下还有 Geometry(几何)这一层(类),gma 舍弃了这一部分!!

环境与数据

系统: Window 10+ (X64)
Python 版本: 3.8.8 +
gma 版本: 1.1.2 +
其他 Python 第三方库: matplotlib、numpy

试验数据: https://gma.luosgeo.com/Open/China_Province_2022.7z

??gma:地理与气象分析库。安装和详细功能帮助见:地理与气象分析库

绘制矢量的基础代码(详询:Luo_Suppe)

??基于 gma 最小矢量数据单元 Feature 的 PlotFeature (绘制要素)是绘制矢量面的最小算法,用以被 PlotLayer (绘制图层)调用。

注意:下述代码部分内容可忽略,因为其是为后续的标注和图例等功能准备的。
注意:未体现的导入在 from XXX import * 中已经引入。

import matplotlib.patches as ptc

from functools import partial

import numpy as np

from gma.algorithm.core.dataio import *

## 注意:以下两模块会在1.1.2版本中出现(当前最新版:1.1.1)
from gma.algorithm.core.gcreate import CreatePolygon
from gma.extend.mapplot.utils import *

class PlotFeature:
    '''绘制矢量要素'''
    def __init__(self, GMAFeature, Axes, **kwargs):
            
        if isinstance(GMAFeature, Feature):
            self.GMAFeature = GMAFeature
        else:
            raise
           
        if issubclass(plt.Subplot, type(Axes)) is False:
            raise
        else:
            self.Axes = Axes
        
        plt.axis('equal')
  
        self.ELECollection = self.ELECollections()
          
    def ELECollections(self):
        '''解包多要素集合'''
        ## 本方法的目的是:将包含多个几何体的单个要素拆分,从而方便绘制
        P = self.GMAFeature.Points

        while isinstance(P[0], list):
            if isinstance(P[0][0], list):
                if isinstance(P[0][0][0], list) is False:
                    break
            P = sum(P, [])
        return P
            
    def DrawPolygon(self, FaceColor = None, EdgeColor = None, Hatch = None, LineStyle = None, LineWidth = None, ADBoundary = True, **kwargs):
        '''绘制多边形'''
        ## 清除重复的参数
        for k in ['facecolor', 'edgecolor', 'hatch', 'linestyle', 'linewidth']:
            if k in kwargs:
                kwargs.pop(k)

        XMIN, XMAX, YMIN, YMAX = [np.inf, -np.inf, np.inf, -np.inf]
        FaceColor, EdgeColor, Hatch, LineStyle, LineWidth = PlotOptions(FaceColor, EdgeColor, Hatch, LineStyle, LineWidth)

        for ELE in self.ELECollection:
            ELE = np.array(ELE)[:, :2]
            if len(ELE) < 3 or ELE[0] == []:
                continue
            
            XMIN, YMIN = np.concatenate([ELE, [[XMIN, YMIN]]], axis = 0).min(axis = 0)
            XMAX, YMAX = np.concatenate([ELE, [[XMAX, YMAX]]], axis = 0).max(axis = 0)
            
            Poly = ptc.Polygon(ELE, 
                               facecolor = FaceColor, 
                               edgecolor = EdgeColor, 
                               hatch = Hatch,
                               linestyle = LineStyle,
                               linewidth = LineWidth,
                               **kwargs)
            
            self.Axes.add_patch(Poly)
            
        if ADBoundary == True:
            self.Axes.set_xlim(XMIN - (XMAX - XMIN) * 0.05, XMAX + (XMAX - XMIN) * 0.05)
            self.Axes.set_ylim(YMIN - (YMAX - YMIN) * 0.05, YMAX + (YMAX - YMIN) * 0.05)  

class PlotLayer: 
    '''绘制矢量图层'''
    
    def __init__(self, GMALayer, Axes = None, Boundary = None, **kwargs):
        
        if isinstance(GMALayer, Layer):
            self.GMALayer = GMALayer
        else:
            raise
            
        self.BBox = self.GMALayer.Boundary
        
        if Boundary is None:    
            self.Left = self.BBox[0] - (self.BBox[2] - self.BBox[0]) * 0.05
            self.Right = self.BBox[2] + (self.BBox[2] - self.BBox[0]) * 0.05
            self.Bottom = self.BBox[1] - (self.BBox[3] - self.BBox[1]) * 0.05
            self.Top = self.BBox[3] + (self.BBox[3] - self.BBox[1]) * 0.05
        else:
            self.Left, self.Bottom, self.Right, self.Top = INITBoundary(Boundary)

            
        self.BFeature = self._CreateBGeom()
        
        if Axes is None:
            ## 根据图层范围自动调整长宽比
            X = self.Right - self.Left
            Y = self.Top - self.Bottom
            if X > Y:
                Width = 10
                Height = Y / X * Width
            else:
                Height = 10
                Width = X / Y * Height
                
            Fig = plt.figure(figsize = (Width, Height), dpi = 100)
            Axes = plt.subplot(1, 1, 1, **kwargs) 
            
        elif issubclass(plt.Subplot, type(Axes)) is False:
            raise

        self.Axes = Axes
        
        # 是否进行绘制的标志
        self.ColorOPT = []
        
        # 记录需要绘制要素的 ID
        self.DrawFeatureInfo = list(self._FeatureIterator())
 
    def _CreateBGeom(self):
        '''创建一个视图范围内的几何体'''
        ## 只绘制视图范围内的几何体,从而节约绘制时间
        Points = [[self.Left, self.Top], 
                  [self.Left, self.Bottom],
                  [self.Right, self.Bottom],
                  [self.Right, self.Top]]
        
        self.BPolygon = CreatePolygon(Points)
    
    def _FeatureIterator(self):
        '''要素迭代器'''
        i = -1
        for FID in range(self.GMALayer.FeatureCount):
            FU = self.GMALayer.GetFeature(FID)
            if FU._Geometry.Intersects(self.BPolygon):
                FEA = ogr.Feature(ogr.FeatureDefn())
                FEA.SetGeometry(FU._Geometry.Intersection(self.BPolygon))
                i = i + 1
                yield i, FID, FU, Feature(FEA)
        
    def DrawPolygon(self, FaceColor = None, EdgeColor = None, Hatch = None, LineStyle = None, LineWidth = None, **kwargs):
        '''绘制图层'''
        GetP = partial(GetPOptions, FaceColor = FaceColor, EdgeColor = EdgeColor, 
                       Hatch = Hatch, LineStyle = LineStyle, LineWidth = LineWidth)

        for i, FID, FU, FPlot in self.DrawFeatureInfo:
            
            gmp = PlotFeature(FPlot, self.Axes)
            
            FC, EC, H, LS, LW = GetP(i)
            self.ColorOPT.append([FC, EC, H, LS, LW])

            gmp.DrawPolygon(FaceColor = FC, EdgeColor = EC, Hatch = H, LineStyle = LS, LineWidth = LW, ADBoundary = False, **kwargs)

            
        self.Axes.set_xlim(self.Left, self.Right)
        self.Axes.set_ylim(self.Bottom, self.Top) 

        return self.Axes

应用及说明(详询:Luo_Suppe)

import gma
DS = gma.Open('China_Province_2022.shp')
LY = DS.GetLayer(0)

# 这里是根据 matplotlib 色带抽取颜色,也可以自己定义
from gma.extend.mapplot import plot
Colors = plot.GetColorFromCMap('jet', N = LY.FeatureCount, Alpha=1)

# 开始绘制
PlotP = PlotLayer(LY, Boundary = None)
Axes = PlotP.DrawPolygon(FaceColor = Colors,
                         EdgeColor = 'gray', 
                         Hatch = ['/', '\\', '|', '-', '+', 'x', 'o', 'O', '.', '*'] * 10,
                         LineStyle = '-',
                         LineWidth = 1)
# 返回 matplotlib axes,可以进一步修改轴、刻度等内容,详情参考:matplotlib。                       

# 绘制部分区域
PlotP = plot.PlotLayer(LY, Boundary = [109,31,118,38])
Axes = PlotP.DrawPolygon(FaceColor = 'lightblue',
                         EdgeColor = 'gray', 
                         Hatch = None,
                         LineStyle = '-.',
                         LineWidth = None)             

注意:左右边界处有缝隙,暂不清楚问题出在哪里。

参数说明

PlotLayer(GMALayer, Axes=None, Boundary=None, **kwargs)


GMALayer: 通过 gma.Open 打开并获取的矢量图层。

Axes: matplotlib 子图,不存在则自动生成。

Boundary: 绘图范围(左、下、右、上),默认是输入矢量范围外扩 0.05 倍。

**kwargs: 自动生成 matplotlib 子图时传递给 plt.subplot 的其他参数。



PlotP.DrawPolygon(FaceColor=None, EdgeColor=None, LineStyle=None, Hatch=None, LineWidth=None, **kwargs)

FaceColor: 填充颜色。可为每个多边形分配不同的颜色。详见 matplotlib.patches.Polygon。

EdgeColor: 边界线颜色。可为每个边分配不同的颜色。详见 matplotlib.patches.Polygon。

LineStyle: 边界线线形。可为每个边分配不同的线性。详见 matplotlib.patches.Polygon。

LineWidth: 边界线线宽。可为每个边分配不同的线宽。详见 matplotlib.patches.Polygon。

Hatch: 填充纹理。可为每个多边形分配不同的纹理。详见 matplotlib.patches.Polygon。

**kwargs: 绘制多边形时传递给 matplotlib.patches.Polygon 的其他参数。

  Python知识库 最新文章
Python中String模块
【Python】 14-CVS文件操作
python的panda库读写文件
使用Nordic的nrf52840实现蓝牙DFU过程
【Python学习记录】numpy数组用法整理
Python学习笔记
python字符串和列表
python如何从txt文件中解析出有效的数据
Python编程从入门到实践自学/3.1-3.2
python变量
上一篇文章      下一篇文章      查看所有文章
加:2022-12-25 11:04:55  更:2022-12-25 11:05:06 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年12日历 -2024/12/26 3:41:14-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码
数据统计