【Houdini+Tetgen/CGAL】将生成的网格导入houdini

想试一下tetgen和CGAL的网格生成。
折腾了半天,一个坑接着一个坑

  • tetgen官网上出了最新的版本1.6.0,可惜什么都下不下来,新版本旧版本都下不下来。
  • 发现conda-forge和pip都有tetgen模块,而且都根据最新版本tetgen进行了更新。于是,又折腾了半天,不知道为什么,总是在安装中和import中出错。
  • 只好退而求其次,去github上找到了tetgen的一份旧版本的拷贝1.5.1,并且编译运行成功。实际上tetgen的源代码就3个文件。
  • tetview是tetgen配套的可视化工具。然而不支持windows10,试着下载运行了一下,没有成功。tetgen生成的数据是一个特有的格式,不是obj,也不是fbx一类的。
  • 于是,为了能看结果,还需要自己写一套转换的程序,将tetgen的数据转化为其他软件支持的格式。这里用的可视化软件是houdini。


用python将自定义格式的mesh文件转换为houdini可以读取的文件格式,这里推荐json格式,注意:如果转成obj格式,obj不支持四面体,四面体的primitive就会被转成三角形,拓扑相当于被改变了,不希望这样。

先导出一个json格式的网格,观察里面的结构。
不需要太复杂的信息,总结起来,有这么几点是必要的: 每个点的位置+ 每个tet由哪几个点组成(点的顺序很重要)

将houdini导出的json信息精简过后:


image.png

接下来,需要自己按照格式写出这么一个json文件。作为一个python白痴,还是要先查查python怎么写json~~
python有非常好用的json库,网上资料特别多

写个一个tet的json:

import os
import json
fileversion='17.5.425'
pointcount=4
vertexcount=4
primitivecount=1
# topology: pointref: indices
indices=[0,1,2,3]
pointref=['indices',indices]
topology=['pointref',pointref]

# attributes: pointattributes,
option={"type":{"type":"string","value":"point"}}
posTuples=[[0,0,0],[0,1,0],[1,0,0],[0,0,1]]
op1=["scope","public","type","numeric","name","P",
     "options",option]
op2=["size",3,"storage","fpreal32","defaults",["size",1,"storage","fpreal64","values",[0]],
     "values",["size",3,"storage","fpreal32","tuples",posTuples]]    
pointattributes=[[op1,op2]]
attributes=['pointattributes',pointattributes]

# primitives
primitives=[[["type","Tetrahedron_run"],["startvertex",0,"nprimitives",1]]]

dict=['fileversion',fileversion, 'pointcount',pointcount,'vertexcount',vertexcount,
      'primitivecount',primitivecount,'topology',topology,'attributes',attributes,
      'primitives',primitives]
jsdump=json.dumps(dict)
with open("C:\\Users\\sun\\Desktop\\outjson0.json",'w') as f:
    f.write(jsdump)
    f.close()

一个tet的会写了,数据文件中的tet也不难了,接下来就是读取文件,
得到这些信息,并写成json

观察CGAL mesh文件的格式,分成这么几个部分:
Vertices //顶点,相当于houdini中的point,接下来的n行是点的位置
Triangles // 表面三角,在这里我们不太需要这个信息,只想要tet的信息
Tetrahedra //四面体,接下来的n行是每个tet中顶点的id
End结尾

python读取文本资料也很多,要点:

  • 首行声明字符编码:utf8\gbk\等
  • 打开关闭,以及模式open、close,'r','w','a'
  • 读:readline 每次读取一行,返回字符串
    read 读取整个文件,返回字符串
    readlines 读取,每一行内容作为字符串数组返回
  • 处理:
    Split() 函数将字符串分割为多个字符串的array
    strip()函数去掉头尾指定字符
    比较字符串:is、==

  • 其他知识点:
    * Enum
    * Python里没有switch
    * 处理一行用空格分隔的数字,直接用split转化为数组就行了

这里是一个简单的脚本,后续还需要重新包装一下,方便调用

import os
import json
from enum import Enum

path_cgal="C:\\Users\\sun\\Desktop\\out.mesh"
path_json="C:\\Users\\sun\\Desktop\\outjson1.json"

class DealState(Enum):
    IDLE = 0
    NUMVERT=1
    POSVERT=2
    NUMTET=3
    IDTET=4
    
fileversion='17.5.425'
pointcount=0
vertexcount=0
primitivecount=0

indices=[]

posTuples=[] 

# real cgal file
with open(path_cgal,'r',encoding="utf-8") as inputFile:
    # read each line
    
    inputState=DealState.IDLE
    
    for line in inputFile:  
       
        thisline=line.strip('\n')        
       
        # state transfer
        if(thisline=='Vertices'):
            inputState=DealState.NUMVERT
            print('Begin to read Vertices.....\n')
            continue
        if(thisline=='Triangles'):
            inputState=DealState.IDLE
            print('Skip reading of Triangles....\n')
            continue
        if(thisline=='Tetrahedra'):
            inputState=DealState.NUMTET
            print('Begin to read Tetrahedron....\n')
            continue
        if(thisline=='End'):
            inputState=DealState.IDLE
            print('CGAL READING FINISHED !!\n')
            break

        # check state to deal with this line

        if(inputState==DealState.IDLE):
            continue
        if(inputState==DealState.NUMVERT):
            # pointcount and transfer state
            pointcount=int(thisline)
            inputState=DealState.POSVERT
            print('numpoints=',int(pointcount))
        elif(inputState==DealState.POSVERT):
            # input point pos
            pos=thisline.split()
            pos=pos[0:-1]
            pos=list(map(float,pos))
            # append posTuples
            posTuples.append(pos)
                        
        if(inputState==DealState.NUMTET):
            # primitivecount and vertexcount and state transfer
            primitivecount=int(thisline)
            vertexcount=4*int(primitivecount)
            inputState=DealState.IDTET
            print('numtets=',int(primitivecount))
            print('numverts=',vertexcount)
        elif(inputState==DealState.IDTET):
            # indices append
            ids=thisline.split()
            ids=ids[0:-1]            
            ids= list(map(int,ids))
            result = [x - 1 for x in ids] 
            indices=indices+result           

    inputFile.close()



# topology: pointref: indices
pointref=['indices',indices]
topology=['pointref',pointref]

# attributes: pointattributes,
option={"type":{"type":"string","value":"point"}}

op1=["scope","public","type","numeric","name","P",
     "options",option]
op2=["size",3,"storage","fpreal32","defaults",["size",1,"storage","fpreal64","values",[0]],
     "values",["size",3,"storage","fpreal32","tuples",posTuples]]    
pointattributes=[[op1,op2]]
attributes=['pointattributes',pointattributes]

# primitives
primitives=[[["type","Tetrahedron_run"],["startvertex",0,"nprimitives",primitivecount]]]

dict=['fileversion',fileversion, 'pointcount',pointcount,'vertexcount',vertexcount,
      'primitivecount',primitivecount,'topology',topology,'attributes',attributes,
      'primitives',primitives]
jsdump=json.dumps(dict)
with open(path_json,'w') as jsonFile:
    jsonFile.write(jsdump)
    jsonFile.close()

注意!!!! CGAL的顶点ID是从1开始的,而houdini是从0开始的。。。。


参考资料:
TetGen用户手册中文版 - 百度文库 (baidu.com)

Tetgen软件学习和使用_Shrekul的博客-CSDN博客

tetgen/tetgen/cython/tetgen at master · pyvista/tetgen (github.com)

https://www.sidefx.com/tutorials/how-to-import-files-in-houdini-with-python-part-1-2/

©著作权归作者所有,转载或内容合作请联系作者
【社区内容提示】社区部分内容疑似由AI辅助生成,浏览时请结合常识与多方信息审慎甄别。
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

相关阅读更多精彩内容

  • 常用库: fuzzywuzzy,字符串模糊匹配。 esmre,正则表达式的加速器。 Chardet字符编码探测器,...
    AlastairYuan阅读 6,872评论 0 43
  • 转自:Python开源平台链接:https://www.jianshu.com/p/2642f9d28f34 Ch...
    道听Tao说阅读 1,504评论 0 0
  • python库的字典诞生了 Chardet字符编码探测器,可以自动检测文本、网页、xml的编码。 colorama...
    佑___阅读 1,747评论 0 1
  • 文件处理 图像处理 游戏和多媒体 大数据与科学计算 人工智能与机器学习 系统与命令行 数据库 GUI @雾霾 _2...
    古佛青灯度流年阅读 10,364评论 1 35
  • 渐变的面目拼图要我怎么拼? 我是疲乏了还是投降了? 不是不允许自己坠落, 我没有滴水不进的保护膜。 就是害怕变得面...
    闷热当乘凉阅读 9,796评论 0 13

友情链接更多精彩内容