关于CGAL的介绍可以参考上一篇文章: 尝试用大一统的计算几何库CGAL解决BIM的算法问题(一)
在了解如何新建C++项目使用CGAL之后,我们希望把CGAL的算法能力提供给开发效率更高的高级语言。由于我们在做BIM开发的时候总是无法绕开Revit和Autocad,所以需要考虑C#语言的封装。
把C++的函数封装成C#版本一般有两种做法,一种是通过C++/CLI封装,另外一种是通过P/Invoke进行封装。 C++/CLI是微软提供的一种胶水语言,允许用户通过类似于C++语法的进行C++库的调用,并提供一些托管类和接口给到C#进行调用。 而 P/Invoke是让程序通过C/C++的协议标准对底层库进行调用。 在这里我们选择了使用P/Invoke的方式,因为这种方式同样能用于Python/Java等别的高级语言。
由于CGAL本身的设计稍稍还是有点面向对象的结构,因此P/Invoke无法直接对其进行调用,首先需要做的,是需要新建一个C++项目,提供一些面向过程的标准C语言接口,这里称之为cgal_functions项目。 有了C语言版本的统一出口后,需要新建一个C#版本的项目与之进行对接,这里可以称为CGALInterop。 有了这两个项目之后,再建一个上层C#应用项目CGALConsoleTest,对CGALInterop的接口进行调用。
以CGAL提供的一个接口示例
cgal_function.cpp
// pch.cpp: 与预编译标头对应的源文件 #include "pch.h" // 当使用预编译的头时,需要使用此源文件,编译才能成功。 #include <CGAL/Cartesian.h> #include <CGAL/CORE_algebraic_number_traits.h> #include <CGAL/Arr_conic_traits_2.h> #include <CGAL/Arrangement_2.h> typedef CGAL::CORE_algebraic_number_traits Nt_traits; typedef Nt_traits::Rational Rational; typedef Nt_traits::Algebraic Algebraic; typedef CGAL::Cartesian<Rational> Rat_kernel; typedef Rat_kernel::Point_2 Rat_point_2; typedef Rat_kernel::Segment_2 Rat_segment_2; typedef Rat_kernel::Circle_2 Rat_circle_2; typedef CGAL::Cartesian<Algebraic> Alg_kernel; typedef CGAL::Arr_conic_traits_2<Rat_kernel, Alg_kernel, Nt_traits> Traits_2; typedef Traits_2::Point_2 Point_2; typedef Traits_2::Curve_2 Conic_arc_2; typedef CGAL::Arrangement_2<Traits_2> Arrangement_2; typedef Arrangement_2::Ccb_halfedge_const_circulator Ccb_halfedge_const_circulator; typedef Traits_2::Curve_2 Curve_2; //创建Arrangement对象 Arrangement_2* CreateArrangement() { Arrangement_2* arrangement = new Arrangement_2(); return arrangement; } //获取Arrangement对象有多少个面 int GetFaceCount(Arrangement_2* arrangement) { return arrangement->number_of_faces(); }cgal_function.h
extern "C" __declspec(dllexport) Arrangement_2 * CreateArrangement(); extern "C" __declspec(dllexport) int GetFaceCount(Arrangement_2 * arrangement);