C_sharp:一个菜鸟学习历程

这篇博客记录了作者作为菜鸟学习C#的过程,重点探讨了值类型的特性,包括简单值类型、结构体(struct)和枚举(enum)。文章指出值类型数据存储在栈中,并且提到了它们在ValueType类中的实现。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

本文只是记录本人的学习历程,没别的用意,如有错误欢迎大家留言指点,谢谢!

值类型:

1.值类型的数据是在栈上申请内存来储存的,它寄存的类是ValueType

2.值类型有三种:简单值类型,结构体(关键字:struct),枚举(关键字:enum)

简单值类型:

                byte: 0到255   
                sbyte: -128到127  
                shotr:短整形-32768到32767   
                ushotr:无符号短整形0到65535
                int:整形 -2147483648 到 2147483647  
                uint:无符号整形 0到4294967295  
                long:无符号长整形
                ulong:有符号长整形   
                char:16位字符    
                float:32位单精度浮点后缀以f/F结束不分大小写(1.15f) (single32)  
                double:64位双精度浮点后缀(10.00)后面可以以d结束或不写系统会默认
                decimal:货币值128位        
                boll:true/false   (boolean)   

结构体:   

 class Program
    {   //结构体
        struct Point                        //结构体和类的区别是:它只能定义变量,不能初始化赋值
        {
            public double b;    
<think>我们正在讨论的是CGAL库中的PolygonMeshProcessing(PMP)模块。用户想计算一个clipper(可能是某个表面网格或部分网格)的法线。根据引用,PMP库提供了丰富的网格处理功能,包括法线计算。在PMP中,法线计算通常有两种:1.顶点法线(vertexnormal)2.面法线(facenormal)此外,对于边缘(特别是锐边)可能还需要计算边法线,但通常我们关注的是顶点和面的法线。计算法线的基本步骤:-读取网格(或已经有一个网格数据结构)-调用PMP中的法线计算函数注意:在计算之前,需要确保网格是流形(manifold)的,否则可能需要先修复网格。具体函数:1.计算面法线:可以使用`CGAL::Polygon_mesh_processing::compute_face_normal()`2.计算顶点法线:可以使用`CGAL::Polygon_mesh_processing::compute_vertex_normal()`另外,如果网格有顶点法线属性,我们也可以直接访问属性。但如果没有,我们需要先分配属性,然后计算。示例代码结构(基于CGAL的Surface_mesh数据结构):假设我们有一个Surface_mesh对象:```cpp#include<CGAL/Surface_mesh.h>#include<CGAL/Polygon_mesh_processing/compute_normal.h>typedefCGAL::Simple_cartesian<double>K;typedefCGAL::Surface_mesh<K::Point_3>Mesh;typedefboost::graph_traits<Mesh>::vertex_descriptorvertex_descriptor;typedefboost::graph_traits<Mesh>::face_descriptorface_descriptor;```计算面法线并存储:```cpp//假设mesh是已经创建并读入了数据的Surface_mesh对象//为面法线创建属性映射autoface_normals=mesh.add_property_map<face_descriptor,K::Vector_3>("f:normals",CGAL::NULL_VECTOR).first;//计算每个面的法线for(face_descriptorf:faces(mesh)){//计算法线face_normals[f]=CGAL::Polygon_mesh_processing::compute_face_normal(f,mesh);}```计算顶点法线:```cpp//为顶点法线创建属性映射autovertex_normals=mesh.add_property_map<vertex_descriptor,K::Vector_3>("v:normals",CGAL::NULL_VECTOR).first;//计算每个顶点的法线,通常基于相邻面的法线取平均CGAL::Polygon_mesh_processing::compute_vertex_normals(mesh,vertex_normals);//或者,我们也可以使用循环逐个计算,但PMP提供了批量计算的函数```注意:计算顶点法线时,可以指定不同的加权方式(如面积加权),PMP的`compute_vertex_normals`函数默认使用平均加权。如果用户想计算clipper(可能是一个工具网格)的法线,那么需要先有这个网格。然后按照上述方法计算。另外,引用[1]中提到Delaunay细化算法,这个可能与网格重建有关,但用户的问题是关于法线计算,所以我们集中在这方面。如果用户提到要保留锐边,那么可能需要计算顶点法线时考虑锐边,这通常是通过在锐边处不进行平滑(即不跨越锐边取平均)来实现。在PMP中,锐边可以通过边的二面角来检测,然后在计算法线时,只对相邻且不跨越锐边的面进行平均。PMP提供了带锐边支持的法线计算函数:```cpp//首先,检测锐边并标记//标记锐边的属性映射autoecm=mesh.add_property_map<edge_descriptor,bool>("e:is_sharp",false).first;//检测锐边:当相邻两个面的二面角大于某个阈值时,标记为锐边doublesharp_edge_threshold=60.0;//阈值,例如60度CGAL::Polygon_mesh_processing::detect_sharp_edges(mesh,sharp_edge_threshold,ecm);//然后,计算顶点法线,并传入这个锐边标记,函数会自动处理//注意:我们还需要一个边-面邻接的关系,但该函数会处理CGAL::Polygon_mesh_processing::compute_vertex_normals(mesh,vertex_normals,CGAL::parameters::edge_is_sharp_map(ecm));```这样,在锐边处,顶点法线会分别计算,从而保留锐边效果。总结步骤:1.读取网格(Surface_mesh或Polyhedron)2.(可选)如果需要锐边,检测锐边并标记3.根据需求计算面法线或顶点法线,并存储在属性映射中4.使用这些法线(例如,用于可视化或进一步处理)注意:PMP中的函数需要包含头文件`#include<CGAL/Polygon_mesh_processing/compute_normal.h>`,以及`#include<CGAL/Polygon_mesh_processing/detect_features.h>`(用于锐边检测)。由于用户的问题没有明确是顶点法线还是面法线,也没有说明是否需要锐边支持,我们可以提供一般的方法,并提示可选步骤。另外,如果用户使用的是其他网格数据结构(如Polyhedron_3),操作类似,只是属性映射的获取方式可能稍有不同。最后,用户可能需要将计算出的法线输出或使用,根据需求后续处理。希望这能帮助用户解决问题。如果用户需要更具体的代码示例,可以参考CGAL文档中关于法线计算的例子,例如:-https://doc.cgal.org/latest/Polygon_mesh_processing/Polygon_mesh_processing_2compute_normals_example_8cpp-example.html或引用[1]中提到的例子(但那个例子主要关于重网格化)。§§相关问题§§1.如何选择计算顶点法线的加权方式(如面积加权)?2.如果网格不是流形的,计算法线会有什么问题?如何修复网格?3.除了锐边,还有哪些特征需要特殊处理法线计算?4.如何将计算的法线用于平滑或光照渲染?</think> ### 使用 Polygon_mesh_processing 计算网格法线 在 CGAL 的 Polygon_mesh_processing (PMP) 库中,计算网格法线主要通过以下步骤实现,特别强调保留锐边特征: #### **核心步骤** 1. **读取输入网格** 使用 `read_polygon_mesh()` 加载三角表面网格文件(如 .off 或 .obj 格式): ```cpp Surface_mesh mesh; if (!PMP::IO::read_polygon_mesh("input.obj", mesh)) return EXIT_FAILURE; ``` 2. **创建法线属性映射** 为顶点和面添加法线存储属性: ```cpp auto vnormals = mesh.add_property_map<vertex_descriptor, Vector>("v:normals", CGAL::NULL_VECTOR).first; auto fnormals = mesh.add_property_map<face_descriptor, Vector>("f:normals", CGAL::NULL_VECTOR).first; ``` 3. **计算面法线** 使用 `compute_face_normal()` 计算所有面的几何法向: ```cpp for(face_descriptor f : faces(mesh)) { fnormals[f] = PMP::compute_face_normal(f, mesh); } ``` 4. **计算顶点法线(保留锐边)** - **检测锐边**(当二面角 > 60° 视为锐边): ```cpp auto ecmap = mesh.add_property_map<edge_descriptor, bool>("e:sharp", false).first; PMP::detect_sharp_edges(mesh, 60, ecmap); // 角度阈值可调 ``` - **计算顶点法线**(锐边处不进行平滑): ```cpp PMP::compute_vertex_normals(mesh, vnormals, CGAL::parameters::edge_is_sharp_map(ecmap).face_normal_map(fnormals)); ``` #### **关键函数说明** - `compute_face_normal()`:基于三个顶点坐标计算面法向向量 公式: $$ \vec{n} = \frac{(\vec{b} - \vec{a}) \times (\vec{c} - \vec{a})}{\| (\vec{b} - \vec{a}) \times (\vec{c} - \vec{a}) \|} $$ - `compute_vertex_normals()`:基于相邻面法线加权平均,锐边处中断平滑过渡 #### **完整示例** ```cpp #include <CGAL/Surface_mesh.h> #include <CGAL/Polygon_mesh_processing/compute_normal.h> #include <CGAL/Polygon_mesh_processing/IO/polygon_mesh_io.h> #include <CGAL/Simple_cartesian.h> namespace PMP = CGAL::Polygon_mesh_processing; using Kernel = CGAL::Simple_cartesian<double>; using Point_3 = Kernel::Point_3; using Vector = Kernel::Vector_3; using Surface_mesh = CGAL::Surface_mesh<Point_3; int main() { Surface_mesh mesh; PMP::IO::read_polygon_mesh("mesh.obj", mesh); // [^1] // 添加法线属性 auto vnormals = mesh.add_property_map<Surface_mesh::Vertex_index, Vector>("v:normals").first; auto fnormals = mesh.add_property_map<Surface_mesh::Face_index, Vector>("f:normals").first; auto sharp_edges = mesh.add_property_map<Surface_mesh::Edge_index, bool>("e:sharp", false).first; // 计算面法线 for(auto f : mesh.faces()) fnormals[f] = PMP::compute_face_normal(f, mesh); // 检测锐边 PMP::detect_sharp_edges(mesh, 60.0, sharp_edges); // 计算顶点法线(保留锐边) PMP::compute_vertex_normals(mesh, vnormals, CGAL::parameters::edge_is_sharp_map(sharp_edges).face_normal_map(fnormals)); // 用法线数据(例如导出或可视化) return EXIT_SUCCESS; } ``` #### **注意事项** 1. **锐边保留机制**:当顶点关联的相邻面间存在锐边时,该顶点会生成**多套法线**,保证在渲染时锐边不出现平滑过渡 2. **数据依赖**:需链接 CGAL 库并包含头文件: ```cpp #include <CGAL/Polygon_mesh_processing/compute_normal.h> ``` 3. **性能优化**:对大型网格建议使用 `PMP::compute_face_normals()` 和 `PMP::compute_vertex_normals()` 批量计算接口
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值