Opennurbs
是Rhion
的一个开源几何库,用起来挺舒服的,虽然不带大部分几何运算功能(什么曲线相交、长度、曲面相交等等),但是用它做一些基本的几何数据存储和分发还是妥妥的足够了。
它是MIT License
。妙啊。
Opennurbs
的下载地址是 https://github.com/mcneel/opennurbs 。
目前,笔者只成功地编译了它的静态库。
有经验的同学们如果在使用 Visual Studio 编译
Opernnubs
时遇到了Freetype 2.6.3
相关问题, 具体表现为:Error C2065 'AF_SCRIPT_CYRL': undeclared identifier freetype263_staticlib ...\opennurbs\freetype263\src\autofit\afstyles.h 100
那么问题很简单,仅需修改一个地方即可成功:
- 在
freetype263_staticlib
项目的External Dependencies(外部依赖项)
中找到afscript.h
文件;- 在该文件的第44行找到带
/* */
的注释;- 删掉该注释,或者在
*/
注释结束符号前加入一个空格即可。这个bug是微软VC++编译器的锅,该编译器在遇到 “某些特定
Unicode
字符后紧跟*/
多行注释结束符” 时,会出现无法正确识别注释结束符号的情况。
准备工作
- Visual Studio
提笔写这篇文章的时候,VS2017以前的版本也挺难下载到了,好在2017、2019都能编译,这里就用2019,区别不大 - 下载好的opennurbs
无论是git clone
或者是直接打包下载源码,只要确保所有的文件能下载下来就行
笔者这里使用的是git
,存放在E:\demo
文件夹下。
别的好像也没了,直接打开源码,找到 opennurbs_public.sln
这个VS解决方案文件,直接进行一个打开,进入熟悉的VS界面,准备开工。
尝试编译静态库…
我们可以看到一共有9个C++项目,其中6个是Example,也就是示例,我们并不关心它们。
我们关心的是 opennurbs_public_staticlib
这个静态库项目。直接在该项目上点击右键,选择build
编译。
成功了,nice。
妙啊!那现在我们就直接来试试用刚刚编译成功的静态库来创建自己的一个C++程序吧!
使用opennurbs
创建自己的C++项目
再打开一个Visual Studio,创建一个C++的Console项目,放在与刚刚openurbs平级的文件夹下。
在main
函数里加入下面的测试代码,创建几个三维点,然后求它们之间的距离:
#include <iostream>
#include "..\..\opennurbs\opennurbs_public.h"
int main()
{
ON_3dPoint pts[4];
pts[0] = ON_3dPoint{ 1,3,5 };
pts[1] = ON_3dPoint{ 3,4,5 };
pts[2] = ON_3dPoint{ 3,1,5 };
pts[3] = ON_3dPoint{ 3,4,9 };
std::cout << pts[3].DistanceTo(pts[1]) << std::endl;
}
直接进行一个运行…… 报错了! 熟悉C++的同学肯定已经发现了,光添加了头文件,还没把刚刚我们编译好的.lib
文件告诉链接器,当然会报错。
.h
文件就如同一本书的目录,而.lib
就是正文了。光是把目录在哪里告诉了我们的测试程序,正文却没有告诉它在哪里,它照着目录去找到时候发现是一堆空气,当然要报错了,嘿嘿,赶紧补上.lib
文件的位置说明。
右键点击我们的项目,选择属性,在Linker中把我们在上一步骤中编译好的opennurbs静态链接库加入。
这里有2个步骤,先要添加lib
文件所在的文件夹,再添加所需要链接的具体的lib
文件。
这回应该没问题了吧!直接运行
还是报错?熟悉的 LINK 2019
错误。链接器未能找到函数blablablabla…… 理论上来说,我们的程序应该只依赖了opennurbs
这一个库,这个库的.h
文件和.lib
文件我们已经正确地引用了,不应该出现别的文件缺失了。只可能是opennurbs
的静态库文件中引用了别的库文件,而这个文件我们没有添加到自己的项目中来。
这只能去看opennurbs
源码来确定它链接了哪些库文件了。
寻找缺失的lib文件
仔细一看,提示缺少的函数都是在 ON_FileSystem
空间下的4个函数,名字分别是
IsFile(char const*)
IsFile(wchar_t const*)
IsDirectory(char const*)
IsDirectory(wchar_t const*)
我们看看源码中的函数定义吧。找到对应的opennurbs_file_utilities.h
和opennurbs_file_utilities.cpp
,这里其实主要是看.cpp
文件,因为这里面有具体的函数实现。
果然我们找到了IsFile(char const*)
这个函数的实现
发现它这里会判断是否是微软的编译器(MSC, MicroSoftCompiler),如果是的话,则会使用微软的api函数PathFileExistsA(LPCSTR)
和PathIsDirectoryA(LPCSTR)
。这不就正好是我们自己测试程序中链接器报错提示的函数吗?
看来是我们自己的测试程序中少了对微软api的链接。
进行一个网络搜索,发现该函数是在Shlwapi.h
头文件内,需要在链接库内加入Shlwapi.lib
。
https://docs.microsoft.com/en-us/windows/win32/api/shlwapi/nf-shlwapi-pathfileexistsa
回到我们的测试程序,在链接器的链接目标中加入Shlwapi.lib
再次运行我们的测试程序,运行成功!
显示结果是4
,让我们来看看这两个点的坐标 { 3, 4, 5 } 和 { 3, 4, 9 },距离的确是4,没问题。再多测几个:
#include <iostream>
#include "..\..\opennurbs\opennurbs_public.h"
int main()
{
ON_3dPoint pts[4];
pts[0] = ON_3dPoint{ 1,3,5 };
pts[1] = ON_3dPoint{ 3,4,5 };
pts[2] = ON_3dPoint{ 3,1,5 };
pts[3] = ON_3dPoint{ 3,4,9 };
for (auto& i : pts)
{
for (auto& j : pts)
{
if (i != j)
{
printf_s("Distance from (%1.0f, %1.0f, %1.0f) to (%1.0f, %1.0f, %1.0f) is: ",
i.x, i.y, i.z, j.x, j.y, j.z);
std::cout << i.DistanceTo(j) << std::endl;
}
}
}
}
完美运行。
愉快地玩耍opennurbs即将开始。