1 Star 2 Fork 1

wujilingfeng / libcell

加入 Gitee
与超过 1200万 开发者一起发现、参与优秀开源项目,私有仓库也完全免费 :)
免费加入
克隆/下载
README.md 7.95 KB
一键复制 编辑 原始数据 按行查看 历史
wujilingfeng 提交于 2024-02-21 10:07 . test

Libcell

一种任意维网格表示结构。能表示高维网格(点,线段,曲面,体结构...),单形和非单形的网格,流形和非流形的网格...

Motivation

市面不存在能表示任意维复形结构的库,且大多数网格库只能表示单形,接口繁杂不统一..

Dependencies

  • cstructures
  • lbmath

Compile

compile library only

for windows mingw

xmake f -p mingw 
xmake

for windows cmake

xmake f -p mingw
xmake project -k cmake

for windows cl

xmake f --demo=n
xmake

xmake for vs

xmake f --demo=y --demo_path="Demo"
xmake project -k vs -m release

for linux

xmake

如何想要添加clapack需要使用xmake f --clapack=y

compile library and demo

Algorithm依赖Eigen和odaimath,需要把Eigen文件名字改为eigen,然后放到thirdpart文件夹内。

再把cstructures,odai_math编译的库文件放在lib文件夹内。然后运行

#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

那么每个n维cell由它的边界和方向唯一描述。

给定一个n维cell$C_n^1$,首先可以确定$C_n^1$的方向^2

接下来描述$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的网格遍历接口

    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)//点(引用指针,直接修改的话会影响到实体)
        }
    }

    还可以用下面的遍历方式

    for(auto fit=mesh.f_begin(&mesh);fit!=mesh.f_end(&mesh);fit++)//对面的遍历 
    {
        for(int i=0;i<quote(fit)->vertices_size;i++)//面上点的遍历
        {
            quote(fit)->vertices[i]//点
        }
    }
    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;i<quote(cit)->vertices_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);//
        }
    
    }
    template_f* f;
    f->halfface[0]->cell//face访问halfface,再访问到cell,更多的用法完全仿照openmesh
let's start
#include <Mesh_IO/Mesh_IO.h>
#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是调整算子

1
https://gitee.com/wujilingfeng/libcell.git
git@gitee.com:wujilingfeng/libcell.git
wujilingfeng
libcell
libcell
master

搜索帮助