# libcell **Repository Path**: wujilingfeng/libcell ## Basic Information - **Project Name**: libcell - **Description**: 高维网格库 - **Primary Language**: C++ - **License**: MIT - **Default Branch**: master - **Homepage**: None - **GVP Project**: No ## Statistics - **Stars**: 3 - **Forks**: 1 - **Created**: 2023-12-15 - **Last Updated**: 2025-11-07 ## Categories & Tags **Categories**: Uncategorized **Tags**: None ## README #### Libcell 一种任意维网格表示结构。能表示高维网格(点,线段,曲面,体结构...),单形和非单形的网格,流形和非流形的网格... #### Motivation 市面不存在能表示任意维复形结构的库,且大多数网格库只能表示单形,接口繁杂不统一.. #### Dependencies * cstructures(1.2.6) * lbmath(1.1) #### Compile ##### compile library only for windows mingw ```bash xmake f -p mingw xmake ``` for windows cmake ```bash xmake f -p mingw xmake project -k cmake ``` for windows cl ```bash xmake f --demo=n xmake ``` xmake for vs ```bash xmake f --demo=y --demo_path="Demo" xmake project -k vs -m release ``` for linux ```bash xmake ``` 如何想要添加clapack需要使用`xmake f --clapack=y` ##### compile library and demo Algorithm依赖Eigen和odaimath,需要把Eigen文件名字改为eigen,然后放到thirdpart文件夹内。 再把cstructures,odai_math编译的库文件放在lib文件夹内。然后运行 ```bash #for mingw on windows xmake f -p mingw --demo=y --demo_path="Demo" xmake ## for linux xmake f --demo=y --demo_path="Demo" xmake ``` #### 算法 包含调和映射,共形模算法,高维最优传输,高维delauny算法,高维凸包算法,几何图像算法... 这些算法在Algorithm文件下,但需整理。 #### 可视化 推荐使用Viewer库。 libcell_tools_view.h文件添加了libcell支持Viewer的j小函数,方便你的使用. #### 支持的网格结构 * cell网格结构。市面上没有针对高维网格的数据结构,cell格式文件为仿照off自定义文件格式,非常简单(意味这极低的学习成本) 当网格为单形时,理论上可以推导各个结构层的信息,所以当simplex=1时,cell文件格式只需要点的信息和单形的信息。 当网格为非单形时,理论上你只能获得cell文件格式提供的信息,无法推导上一层或下一层结构信息(除非提供)。所以cell文件格式需要你提供点,"半面"(n-1维流形),由“半面”组合的“胞腔”的信息(n维流形)。 * tools_formats.h提供了off,obj,mesh文件格式的转换 #### 语言绑定 该库用c/c++完成,如果想要纯c语言的库,那么你可以不包含lib_cell_iterator.h文件即可。然后你就可以将此库绑定到任何支持与c交互的语言上。 #### Turotial ##### 预备知识 * 当你要表示流形时,Mesh的dimension变量储存了当前流形的维数,simplex变量储存了当前流形是否是单形。 * 对于一个n维流形,libcell的网格结构只储存了0维流形(点集),n-1维流形(n维流形的边界),n维流形的信息。 ##### 定义 :欧式子空间的方向 在m维向量空间,存在一个n维子空间,那么对于这个n维子空间可以用反对称张量定义方向: 设$a_i$是n维子空间的一组基底,那么反对称张量$a_i\wedge ...a_j$可以作为n维子空间在m维向量空间的方向。 ##### 定义 cell n维欧式空间的凸集且是n维流形称为n维cell ##### 规定1 给定一组n维欧式子空间的n+1个点$p_0..p_n$,那么它定义的方向是$\left(p_1-p_0\right)\wedge...\wedge\left(p_n-p_0\right)$ ##### 现在讲述libcell如何表示n维流形 下面所述流形均是带边流形或闭流形。 在m维欧式空间$R^m$存在一个n维流形$N$。N由一组n维cell组成[^1] [^1]: 每个cell是n维凸集。 那么每个n维cell由它的边界和方向唯一描述。 给定一个n维cell$C_n^1$,首先可以确定$C_n^1$的方向[^2]。 [^2]: 它由N的方向诱导,所有首先要定义好N的方向。 接下来描述$C_n^1$的边界: 它的边界是n-1维流形$H_n$。这个$H_n$同样可以由一组n-1维cell组成。 给定$H_n$的n-1维cell$H_n^1$ * 我们规定: $H_n^1$的方向朝向n维cell的内部。这样描述了$H_n^1$的方向。 * 我们规定:不描述$H_n^1$的边界,改为给出$H_n^1$的点集$p_0...p_l$。且满足:$p_0..p_{n-2}$定义的方向和$H_n^1$的方向相同。 $C_n^1$的方向信息储存在$H_n$的点顺序中:设$p_1...p_n$是$H_n^1$的点顺序的前n个点,$p_0$是$c_n^1$中的边界点且不属于$H_n^1$,那么按照规定1,,$p_1..p_n p_0$定义了一个方向,这个方向就是$C_n^1$的方向。 上述中$H_n^1$的方向信息储存在$H_n^1$的点序中:假设$p_0...p_m$是$H_n^1$的点顺序,那么$p_0....p_{n-1}$定义的方向就是$H_n^1$的方向。 ##### 遍历接口说明 * libcell还有仿openmesh的网格遍历接口 ```c++ for(auto fit=mesh.f_begin(&mesh);fit!=mesh.f_end(&mesh);fit++)//对面的遍历 { for(auto fvit=mesh.fv_begin(&mesh,*fit);fvit!=mesh.fv_begin(&mesh,*fit);fvit++)//面上点的遍历 { (*fvit)//点(结构体实例,对他修改不会影响到真实的点) quote(cvit)//点(引用指针,直接修改的话会影响到实体) } } ``` 还可以用下面的遍历方式 ```c++ for(auto fit=mesh.f_begin(&mesh);fit!=mesh.f_end(&mesh);fit++)//对面的遍历 { for(int i=0;ivertices_size;i++)//面上点的遍历 { quote(fit)->vertices[i]//点 } } ``` ```c++ for(auto cit=mesh.c_begin(&mesh);cit!=mesh.c_end(&mesh);cit++)//对cell的遍历 { for(auto cvit=mesh.cv_begin(&mesh,*cit);cvit!=mesh.cv_end(&mesh,*cit);cvit++)//cell对点的遍历 { (*cvit)//点(结构体) quote(cvit)//点(引用指针,直接修改的话会影响到实体) } } //还可以用以下方法 for(auto cit=mesh.c_begin(&mesh);cit!=mesh.c_end(&mesh);cit++)//对cell的遍历 { for(int i=0;ivertices_size;i++)//cell对点的遍历 { quote(cit)->vertices[i]//点 } } for(auto cit=mesh.c_begin(&mesh);cit!=mesh.c_end(&mesh);cit++)//对cell的遍历 { for(auto chfit=mesh.chf_begin(&mesh,*cit);chfit!=mesh.chf_begin(&mesh,*cit);chfit++)//cell对face的遍历 { (*chfit)//face(结构体实例) quote(chfit)//face指针(引用指针,直接修改的话会影响到实体) } } for(auto vit=mesh.v_begin(&mesh);vit!=mesh.v_end(&mesh);vit++)//对点的遍历 {//点对cell的遍历 for(auto vcit=mesh.vc_begin(&mesh,*vit);vcit!=mesh.vc_end(&mesh,*vit);vcit++) { (*vcit)// quote(vcit); } } for(auto vit=mesh.v_begin(&mesh);vit!=mesh.v_end(&mesh);vit++)//点的遍历 { //点对face的遍历 for(auto vfit=mesh.vf_begin(&mesh,*vit);vfit!=mesh.vf_end(&mesh,*vit);vfit++) { (*vfit)// quote(vfit);// } } ``` ```c++ template_f* f; f->halfface[0]->cell//face访问halfface,再访问到cell,更多的用法完全仿照openmesh ``` ##### let's start ```c #include #define _ReadOff_ LibCell_ReadOff_ Mesh mesh; Mesh_init(&mesh); _ReadOff(&mesh,bunny.off ,3); Mesh_free(&mesh); ``` #### 笔记 基于RANSAC算法的网格简化。 计算出最大平面内点集,然后其中有些点所在曲面的邻接点都属于内点集,把这些点和所连面删除。之后再补洞。 保面积映射可以用来求点到曲面最短距离,用物竟天择(遗传算法)进行优化。 delaunay剖分的并行运算是每个区域计算cell(没有下层结构),然后合并这些cell(去除重复cell) 如何区分jordan曲线的“内部”和“外部”:两个区域拓扑不同,可以用欧拉示性数。 任何jordan曲线的内部区域由凸集构成,由凸集的并构成:可以用直线扫描区域,然后直线被截取的线段就是凸集。 上述命题的特殊情况:若jordan曲线是折线段,那么直线段的角度一定存在“锐角”:反证法。 求曲面的交,半边要维护一些点集。 点云重建曲面:给定一个点,再给定一个单位方向(或者平面),和一个半径长度(用来诱导邻域),那么可以利用这个平面参数化邻域曲面。 凸多边形的交点。 机器学习f a=a,且收敛,a是神经网络,f是调整算子