首页 > 编程语言 >【Python】将网格数据写入到VTK文件

【Python】将网格数据写入到VTK文件

时间:2024-08-29 14:50:20浏览次数:6  
标签:cell Python VTK 网格 write shape array data vtk

1. vtk 文件格式

根据官网进行总结

vtk文件组成:5个部分.

第一部分,第一行:表明文件版本.写"# vtk DataFile Version 2.0"就行

第二部分,第二行:表明标题(title).随便写.

第三部分,第三行:ASCII或者 BINARY

第四部分,开始定义dataset structure.这部分用于描述数据集的几何和拓扑结构.以关键字"DATASET type"的一行开始.后续部分根据不同的dataset type,使用其他关键字/数据组合定义实际数据.

支持以下type:
STRUCTURED_POINTS
STRUCTURED_GRID
UNSTRUCTURED_GRID
POLYDATA
STRUCTURED_POINTS
RECTILINEAR_GRID
FIELD
关键字不区分大小写,可以用空格分隔.

第五部分,定义点数据或者实体数据等.称为:dataset attributes 如:
POINT_DATA type
...
CELL_DATA type
...

注意:Indices are 0-offset. Thus the first point is point id 0.;Cell types and indices are of type int; The geometry/topology description must occur prior to the data attribute description.

1.1 Dataset Format _ 定义几何/拓扑数据和关系

VTK支持5种数据集格式:structured points, structured grid, rectilinear grid, unstructured grid, and polygonal data.

这里只描述非结构化网格,其他不说,用不到.

1.2 Unstructured Grid

非结构化网格数据集由任何可用的单元类型的任意组合组成(比如四六面体混合).非结构化网格由点、单元格和单元格类型定义.

CELLS keyword 需要两个参数:

  • n : the number of cells
  • size : the size of the cell list. The cell list size is CELLS关键字下所有整数的个数 (i.e., sum of numPoints and connectivity indices over each cell).

例如:60代表的是从第一行以下所有整数的个数

CELLS 11 60
8 0 1 4 3 6 7 10 9
8 1 2 4 5 7 8 10 11
4 6 10 9 12
4 11 14 10 13
6 15 16 17 14 13 12
6 18 15 19 16 20 17
4 22 23 20 19
3 21 22 18
3 22 19 18
2 26 25
1 24

CELL_TYPES keyword需要一个参数: the number of cells n.这个参数值对应于CELLS的n参数.这个关键字的数据行,是指定每个单元格的单元类型的单个整数值

案例:定义非结构化网格的拓扑

DATASET UNSTRUCTURED_GRID
POINTS n dataType
p0x p0y p0z
p1x p1y p1z
…
p(n-1)x p(n-1)y p(n-1)z

CELLS n size
numPoints0, i0, j0, k0, …
numPoints1, i1, j1, k1, …
numPoints2, i2, j2, k2, …
…
numPointsn-1, in-1, jn-1, kn-1, …

CELL_TYPES n
type0
type1
type2
…
typen-1

1.3 Dataset Attribute Format --- 定义附着在节点或者单元上的数据

支持以下数据集属性:

  • 标量(一到四个分量)
  • 向量
  • 法线
  • 纹理坐标(1D, 2D和3D)
  • 张量
  • field data

此外,可以使用RGBA颜色规范定义lookup table,与标量数据关联.

定义dataset Attribute 要给定一个独特的dataName,不能有空格.一个文件中可以包含多个相同类型的dataset Attribute. For example, two different scalar fields defined on the dataset points, pressure and temperature, can be contained in the same file.

1.3.1 Scalars.

SCALARS dataName dataType numComp
LOOKUP_TABLE tableName
s0
s1
…
sn-1

标量定义包括lookup table的指定.lookup table 是可选的,如果不指定,vtk会使用默认表(tableName指定为default);numComp选项也是可选的,如果不给定,默认为1.参数范围:1~4

color scalars( 直接映射到颜色的无符号字符值 )的定义varies depending upon the number of values (nValues) per scalar.** If the file format is ASCII, the color scalars are defined using nValues float values between (0,1). **

COLOR_SCALARS dataName nValues
c00 c01 … c0(nValues-1)
c10 c11 … c1(nValues-1)
…
c(n-1)0 c(n-1)1 … c(n-1)(nValues-1)

1.3.2 Lookup Table.

LOOKUP_TABLE tableName size
r0 g0 b0 a0
r1 g1 b1 a1
…
rsize-1 gsize-1 bsize-1 asize-1

tableName 是表的标识,不能有空格.每一行表示rgba数组.a表示透明度,a=0时颜色透明.如果文件是ASCII格式,每个值范围为(0-1的浮点数;

1.3.3 Vectors.

VECTORS dataName dataType
v0x v0y v0z
v1x v1y v1z
…
v(n-1)x v(n-1)y v(n-1)z

1.3.4 Normals.

Normals are assumed normalized |n| = 1.

NORMALS dataName dataType
n0x n0y n0z
n1x n1y n1z
…
n(n-1)x n(n-1)y n(n-1)z

1.3.5 Tensors.

Currently only real-valued, symmetric tensors are supported.

TENSORS dataName dataType
t000 t001 t002
t010 t011 t012
t020 t021 t022

t100 t101 t102
t110 t111 t112
t120 t121 t122

tn - 100 tn - 101 tn - 102
tn - 110 tn - 111 tn - 112
tn - 120 tn - 121 tn - 122

1.4 example

# vtk DataFile Version 2.0
Unstructured Grid Example
ASCII
DATASET UNSTRUCTURED_GRID

POINTS 27 float
0 0 0  1 0 0  2 0 0  0 1 0  1 1 0  2 1 0
0 0 1  1 0 1  2 0 1  0 1 1  1 1 1  2 1 1
0 1 2  1 1 2  2 1 2  0 1 3  1 1 3  2 1 3
0 1 4  1 1 4  2 1 4  0 1 5  1 1 5  2 1 5
0 1 6  1 1 6  2 1 6

CELLS 11 60
8 0 1 4 3 6 7 10 9
8 1 2 4 5 7 8 10 11
4 6 10 9 12
4 11 14 10 13
6 15 16 17 14 13 12
6 18 15 19 16 20 17
4 22 23 20 19
3 21 22 18
3 22 19 18
2 26 25
1 24

CELL_TYPES 11
12
11
10
8
7
6
9
5
4
3
1

POINT_DATA 27
SCALARS scalars float 1
LOOKUP_TABLE default
0.0 1.0 2.0 3.0 4.0 5.0
6.0 7.0 8.0 9.0 10.0 11.0
12.0 13.0 14.0 15.0 16.0 17.0
18.0 19.0 20.0 21.0 22.0 23.0
24.0 25.0 26.0

VECTORS vectors float
1 0 0  1 1 0  0 2 0  1 0 0  1 1 0  0 2 0
1 0 0  1 1 0  0 2 0  1 0 0  1 1 0  0 2 0
0 0 1  0 0 1  0 0 1  0 0 1  0 0 1  0 0 1
0 0 1  0 0 1  0 0 1  0 0 1  0 0 1  0 0 1
0 0 1  0 0 1  0 0 1

CELL_DATA 11
SCALARS scalars float 1
LOOKUP_TABLE CellColors
0.0 1.0 2.0 3.0 4.0 5.0
6.0 7.0 8.0 9.0 10.0

LOOKUP_TABLE CellColors 11
.4 .4 1 1
.4 1 .4 1
.4 1 1 1
1 .4 .4 1
1 .4 1 1
1 1 .4 1
1 1 1 1
1 .5 .5 1
.5 1 .5 1
.5 .5 .5 1
1 .5 .4 1

2.使用python将网格和数据写入vtk文件

def export_vtk(output_file:str,
                nodes:np.ndarray,
                element_Blocks:List[np.ndarray],
                element_types:List[str],
                point_data: Dict[str:Dict[str:np.ndarray]] = {},
                cell_data:  Dict[str:Dict[str:np.ndarray]] = {},
                **kwargs)->bool:
    """导出vtk格式的网格数据文件
    inputs:
    output_file: 输出文件名
    nodes: 节点坐标矩阵,shape=(n,3)
    element_Blocks: 单元列表,
    element_types: 单元类型列表,
    point_data: 节点数据字典.e.g. {'SCALARS':{'disp':disp_array,'stress':stress_array},'VECTORS':{'velocity':velocity_array}}
    cell_data: 单元数据字典.e.g. {'SCALARS':{'disp':disp_array,'stress':stress_array},'VECTORS':{'velocity':velocity_array}}
    """
    def cal_cell_num(element_Blocks:List[np.ndarray])->tuple:
        cell_num,cell_piont_num=0,0
        for _,block in enumerate(element_Blocks):
            cell_num+=block.shape[0]
            cell_piont_num+=block.shape[0]*(block.shape[1]+1)
        return cell_num,cell_piont_num
    
    SEP="  " if 'sep'not in kwargs.keys()  else kwargs['sep']
    
    type_dict={"beam": 3, # vtk_line, 梁单元
                "tri": 5, # vtk_triangle, 三角形单元
                "quad":9, # vtk_quad, 四边形单元
                "tet":10, # vtk_tetra, 四面体单元
                "hex":12, # vtk_hexahedron, 六面体单元
                "wedge":13, # vtk_wedge, 三棱柱单元
                "pyramid":14, # vtk_pyramid, 四棱锥单元
                }
    
    f=open(output_file,'w')
    
    # 写入文件头
    f.write('# vtk DataFile Version 3.0\n')
    f.write(f'{kwargs["title"]}\n') if 'title' in kwargs.keys() else f.write('Finite Element Results\n')
    f.write('ASCII\n')
    f.write('DATASET UNSTRUCTURED_GRID\n')
    
    # 写入点坐标
    f.write(f'\nPOINTS {nodes.shape[0]} float\n')
    for i in range(nodes.shape[0]):
        f.write(SEP.join(map(str,nodes[i,:]))+'\n')
        
    # 写入单元数据
    n,size=cal_cell_num(element_Blocks)
    
    # 构造单元数据
    f.write(f'\nCELLS {n} {size}\n')
    cells_lines,cell_type_lines="",""
    for block ,typeStr in zip(element_Blocks,element_types):
        for i in range(block.shape[0]):
            cells_lines+=f"{block.shape[1]} "+SEP.join(map(str,block[i,:]))+'\n'
            cell_type_lines+=f"{type_dict[typeStr]}\n"
    f.write(cells_lines)
    
    # 写入单元类型数据
    f.write(f'\nCELL_TYPES {n}\n')
    f.write(cell_type_lines)
    
    # 写入节点数据,节点字典数据为空则跳过
    if point_data:
        f.write(f'\nPOINT_DATA {nodes.shape[0]}\n') 
        if 'SCALARS' in point_data.keys():
            for var_name,array in point_data['SCALARS'].items():
                if array.ndim==1:
                    # 如果是一维数组,则扩展成二维数组
                    array=array.reshape((-1,1))
                # 标量的Ncomp=1~4
                f.write(f'SCALARS {var_name} float {array.shape[1]}\n')
                f.write(f'LOOKUP_TABLE default\n')
                for i in range(array.shape[0]):
                    f.write(SEP.join(map(str,array[i,:]))+'\n')
        
        # VECTORS dataName dataType
        # v0x v0y v0z
        # v1x v1y v1z
        # …
        # v(n-1)x v(n-1)y v(n-1)z
        if 'VECTORS' in point_data.keys():
            for var_name,array in point_data['VECTORS'].items():
                if array.ndim==1:
                    # 如果是一维数组,则扩展成二维数组,向量必须是(-1,3)
                    array=array.reshape((-1,3))
                assert array.shape[1]==3, "VECTORS data must be (-1,3) shape"
                
                f.write(f'VECTORS {var_name} float\n')
                for i in range(array.shape[0]):
                    f.write(SEP.join(map(str,array[i,:]))+'\n')
    else:
        pass
    
    # 写入单元数据,单元字典数据为空则跳过
    if cell_data:
        f.write(f'\nCELL_DATA {n}\n')
        if 'SCALARS' in cell_data.keys():
            for var_name,array in cell_data['SCALARS'].items():
                if array.ndim==1:
                    # 如果是一维数组,则扩展成二维数组
                    array=array.reshape((-1,1))
                # 标量的Ncomp=1~4
                f.write(f'SCALARS {var_name} float {array.shape[1]}\n')
                f.write(f'LOOKUP_TABLE default\n')
                for i in range(array.shape[0]):
                    f.write(SEP.join(map(str,array[i,:]))+'\n')
                    
        if 'VECTORS' in cell_data.keys():
            for var_name,array in cell_data['VECTORS'].items():
                if array.ndim==1:
                    # 如果是一维数组,则扩展成二维数组,向量必须是(-1,3)
                    array=array.reshape((-1,3))
                assert array.shape[1]==3, "VECTORS data must be (-1,3) shape"
                
                f.write(f'VECTORS {var_name} float\n')
                for i in range(array.shape[0]):
                    f.write(SEP.join(map(str,array[i,:]))+'\n')
    else:
        pass

标签:cell,Python,VTK,网格,write,shape,array,data,vtk
From: https://www.cnblogs.com/aksoam/p/18386638

相关文章

  • Python模块之functools.partial
    在Python编程中,functools.partial是一个强大的工具,它提供了一种部分应用函数的方式,能够在创建新函数时固定部分参数,从而在后续调用中减少需要传递的参数数量。本文将深入介绍functools.partial的基本概念、使用方法,并通过丰富的示例代码演示其在不同场景中的实际应用。什么是func......
  • Python模块之subprocess
    转载:https://www.cnblogs.com/goldsunshine/p/17558075.html subprocess是Python中执行操作系统级别的命令的模块,所谓系级级别的命令就是如ls/etc/userifconfig等和操作系统有关的命令。subprocess创建子进程来执行相关命令,并连接它们的输入、输出和错误管道,获取它们的......
  • Python 中常用的人工智能库和工具
    在Python中,有许多强大的人工智能库和工具,它们为开发各种人工智能应用提供了有力的支持。以下是一些常用的人工智能库和工具介绍:一、机器学习库Scikit-learnScikit-learn是一个广泛应用于机器学习的Python库。它提供了各种经典的机器学习算法,包括分类、回归、聚类等......
  • 如何使用python实现批量ping,附代码
    以下为使用Python实现批量ping的多种方法及代码示例:方法一:importsubprocesswithopen('hosts.txt','r')asf:hosts=f.readlines()forhostinhosts:result=subprocess.check_output(('ping','-c','1',host.stri......
  • python+flask计算机毕业设计大学生闲置物品交易网站(程序+开题+论文)
    本系统(程序+源码+数据库+调试部署+开发环境)带论文文档1万字以上,文末可获取,系统界面在最后面。系统程序文件列表开题报告内容研究背景随着互联网技术的飞速发展,电子商务已成为人们日常生活不可或缺的一部分,极大地促进了商品交易的便捷性与效率。然而,在大学校园内,一个普遍存......
  • python+flask计算机毕业设计二手车交易管理系统的设计与开发(程序+开题+论文)
    本系统(程序+源码+数据库+调试部署+开发环境)带论文文档1万字以上,文末可获取,系统界面在最后面。系统程序文件列表开题报告内容研究背景随着汽车消费市场的日益成熟与车辆更新换代速度的加快,二手车交易已成为汽车市场不可或缺的一部分。然而,传统二手车交易过程中存在信息不对......
  • python+flask计算机毕业设计基于的零食销售商城(程序+开题+论文)
    本系统(程序+源码+数据库+调试部署+开发环境)带论文文档1万字以上,文末可获取,系统界面在最后面。系统程序文件列表开题报告内容研究背景随着互联网的飞速发展,电子商务已成为现代商业不可或缺的一部分,深刻改变着人们的消费习惯。零食作为日常消费的重要组成部分,其市场潜力巨大......
  • LeetCode-Python-1539. 第 k 个缺失的正整数(二分)
    给你一个 严格升序排列 的正整数数组 arr 和一个整数 k 。请你找到这个数组里第 k 个缺失的正整数。示例1:输入:arr=[2,3,4,7,11],k=5输出:9解释:缺失的正整数包括[1,5,6,8,9,10,12,13,...]。第5个缺失的正整数为9。示例2:输入:arr=[1,2,3,4],k=2......
  • 探索 AI Agents:从理念到 Python 实际运用
    作者:老余捞鱼原创不易,转载请标明出处及原作者。写在前面的话:    本文主要介绍了如何利用人工智能代理(AIAgents)从概念到Python中的实际应用,以及如何构建一个内容创作工作流程,通过多个代理协作完成从视频分析到博客撰写的复杂任务,完成后也许这会改变你对人工智能......
  • 期权定价模型(如Black-Scholes模型)和利率模型中的单因子模型的Python实现案例
    一:期权定价模型(如Black-Scholes模型)的实现期权定价模型(如Black-Scholes模型)是用来确定期权合理价格的数学模型。这些模型基于一定的假设,考虑了多种因素,如标的资产价格、期权的行权价格、期权的到期时间、无风险利率以及标的资产的波动性等。接下来将使用Python来实现这个模......