VB.net下使用开源免费三维控件Anycad的应用实例分享

1 visual studio2022 下的anycad控件安装

对于想要试一试自制三维软件的朋友,anycad可能是一个不错的选择,因为它免费。
安装它也很简单,在visual studio 2022中新建一个vb.net项目,然后在nuget包管理中搜索“anycad”即可:

如上图,安装.net后缀的插件即可,安装完成后,可在项目的引用中查看:
在这里插入图片描述
表示anycad的控件安装成功,可以开始调用了。

2 调用anycad及简单示例:

anycad的官网提供了示例程序代码,不过都是用C#写的,C#.net和VB.net毕竟还是有不小的区别的,所以,本文中将会以VB.net的格式来重写:

1 导入命名空间:

在vb.net项目的主窗口代码中,导入命名空间

Imports AnyCAD.Foundation
Imports AnyCAD.Forms

2 初始化:

anycad的调用需要进行初始化,官网的C#程序是这样的:

 static class Program
    {
        /// <summary>
        /// The main entry point for the application.
        /// </summary>
        [STAThread]
        static void Main()
        {
            // 初始化
            AnyCAD.Foundation.GlobalInstance.Initialize();
            Application.EnableVisualStyles();
            Application.SetCompatibleTextRenderingDefault(false);
            Application.Run(new MainForm());
            AnyCAD.Foundation.GlobalInstance.Destroy();
        }
    }

在vb.net中,我们这样改写一下:
初始化:

Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load     

        AnyCAD.Foundation.GlobalInstance.Initialize()
      
End Sub

释放资源:

 Private Sub Form1_FormClosed(sender As Object, e As FormClosedEventArgs) Handles Me.FormClosed

        AnyCAD.Foundation.GlobalInstance.Destroy()
End Sub

3 控件显示:

官网的示例中,控件显示的容器选择的是splitcontainer:

    public partial class MainForm : Form
    {
        RenderControl mRenderView;
        public MainForm()
        {
            InitializeComponent();

            mRenderView = new RenderControl(this.splitContainer1.Panel2);
            // 这里不能调用AnyCAD其他的API
        }
        ...
    }

但实际上,不一定非要用splitcontainer,也可以用其他控件,比如picturebox控件:

mrenderview = New RenderControl(Picturebox2)

以上,一个anycad的三维控件初始化已经完成,如果这时候你点击调试启动按钮,在你的.net窗口上,会显示这样的画面:

在这里插入图片描述
如上图picturebox控件框内显示的蓝色背景的视图,即是anycad的三维空间。这时候,你可以添加代码去绘制三维空间的任何图形,如点、线、面、球体、圆柱、立方体、多面体等。

1 绘制三维体:

Dim shape1= ShapeBuilder.MakeCylinder(New GAx2(New GPnt(-10, 30, 0), GP.DX), 15.0, 10.0, 0.0)
Dim nd = BrepSceneNode.Create(shape1, Nothing, Nothing)  
        mrenderview.ShowSceneNode(nd)

shapebuilder是一个API函数,包含了常见的三维立体对象的创建方法,包括球体、长方体、圆柱体、圆锥、管子等。

类似的,创建球体:

shape1 = ShapeBuilder.MakeSphere(New GPnt(10, 0, 0), 5.0)

立方体:

shape1 = ShapeBuilder.MakeBox(New GAx2(New GPnt(30, 0, 0), GP.DZ), 5.0, 5.0, 5.0)

等等。

创建一个三维图形,算是最简单的使用了,anycad提供了多种图形创建和显示的函数,如SketchBuilder,包含了常见的三维平面基本体对象创建方法,包括点、直线段、圆弧曲线、长方形、多边形、BSpline等。

也可以直接导入一个绘制好的三维图形(支持step、igs等格式):

官网示例(C#):

   private void stepToolStripMenuItem1_Click(object sender, EventArgs e)
        {
            OpenFileDialog dialog = new OpenFileDialog();
            dialog.Filter = "STEP (*.stp;*.step)|*.stp;*.step";
            if (dialog.ShowDialog() != DialogResult.OK)
                return;

            var shape = ShapeIO.Open(dialog.FileName);
            if (shape == null)
                return;

            mRenderView.ShowShape(shape, Vector3.LightGray); // 用灰白色来显示模型

            mRenderView.ZoomAll(); // 把模型缩放到合适位置
        }

利用openfiledialog控件获取文件名,然后利用anycad的shapeio读取文件信息,并显示。这个代码比较简单,改成vb.net也很容易,这里就不写vb.net了。

anycad也提供了stepio、igesio来快速读取模型,但总的来说,三维模型的加载都是比较慢的,尤其是模型越大,加载越慢。

stepio:

      OpenFileDialog dialog = new OpenFileDialog();
            dialog.Filter = "STEP (*.stp;*.step)|*.stp;*.step";
            if (dialog.ShowDialog() != DialogResult.OK)
                return;

            var shape = StepIO.Open(dialog.FileName);
            if (shape == null)
                return;

            mRenderView.ShowShape(shape, new Vector3(0.8f)); // 显示指定个灰白色

igesio:

  OpenFileDialog dialog = new OpenFileDialog();
            dialog.Filter = "IGES (*.igs;*.iges)|*.igs;*.iges";
            if (dialog.ShowDialog() != DialogResult.OK)
                return;

            var shape = IgesIO.Open(dialog.FileName);
            if (shape == null)
                return;

            // 转换成BREP格式
            BrepIO.Save(shape, dialog.FileName + ".brep");

4 三维动画:

当你创建了的三维图形或者导入了已经画好的图形结构,你可能有让图形动起来的需求,此时就涉及到如何让三维空间的图形执行动作,anycad提供的动作反馈函数AnimationCallback,用以执行动作。

所谓动画,其实就是对三维图形执行平移、旋转和缩放等矩阵变换放来模拟物体的运动,至于矩阵如何变换或者更深入的数学研究,此处不深入探讨(主要是不懂),作为使用者,只需要知道怎么调用平移、旋转及缩放等函数功能即可。

1 动画设置:

anycad提供了C#下的示例:

 mRenderControl.SetAnimationCallback((float timer)=>{
                
                // 更新构件
                var matrixR = Matrix4.makeRotationAxis(new Vector3(0, 0, 1), time);
                var matrixT = Matrix4.makeTranslation(-50, 0, 0);
                ConeNode1.SetTransform(matrixR * matrixT);
                ConeNode1.RequstUpdate();

                // 更新场景
                mRenderControl.RequestDraw();
            });

但在vb.net下,代码需要转换,如果按照C#一样写,是不行的。

Dim cb3 As RenderControl.AnimationHandler
cb3 = New RenderControl.AnimationHandler(AddressOf ani)
mrenderview.SetAnimationCallback(cb3)
Public Sub ani(time As Single)
'这里添加图形动画代码,即平移、旋转、缩放或者三者组合
 		Dim matt1 As Matrix4 = Matrix4.makeTranslation(-50 * stp, 0, 0)
        Dim matr1 As Matrix4 = Matrix4.makeRotationAxis(New Vector3(0, 0, 1), t)      
        Dim sn1 = scene1.FindNode(nodeid_list(0))
        sn1.SetTransform(matt1)  '先平移
        sn1.SetTransform(matr1)  '再旋转
        sn1.RequstUpdate()		 '请求更新
        mrenderview.RequestDraw(EnumUpdateFlags.Scene) '控件刷新
       
 End Sub

上面关于动画反馈函数的代码,仅是一个简单的示例,大家可以根据自己的需要,将所有关于图形移动的代码全部写在这个函数里,函数会不停的刷新(time是时间,设置动画反馈后,时间就会开始计时,可以停止)。
这个反馈函数只需要设置一次即可,如果想要停止动画,只需要将调用设置为null即可,VB.net中为Nothing。

mrenderview.SetAnimationCallback(Nothing)

再次启用,只需要再设置一次即可。

mrenderview.SetAnimationCallback(cb3)

2 获取三维体的UUID(场景遍历)

uuid是三维空间的每一个实体(圆柱、直线、复合体等)的唯一标志,在每一次载入时,实体的uuid虽然会变化,但在当前空间场景内,uuid都是唯一的,因此可以通过获取实体的uuid,来对其进行单独操作,如获取其点、线、面参数等。

一般来说,在创建三维体或者导入三维体的时候,都可以及时获取其uuid,可以通过list来存储以备后面调用:

		Dim shape = ShapeIO.Open(fl)
        Dim node = BrepSceneNode.Create(shape, mMaterial, Nothing, 1)
        node.SetSubShapePickable(False)

        scene1.AddNode(node)

        Dim nd_id = node.GetUuid()

        nodeid_list.Add(nd_id)

但是,如果不知道三维空间中的实体的uuid怎么办呢?可以利用anycad的场景遍历函数,来获取所有实体对象(scenenode)。

官网示例是C#:

for(var itr = scene.CreateIterator();itr.More(); itr.Next())
{
    var node = itr.Current();
    //....
}

转换成vb.net代码,如下:

	Dim scene1 as SceneNode
   	Dim snin As SceneNodeIterator = scene1.CreateIterator()
        While snin.More		'场景循环遍历
            Dim nd1 As SceneNode = snin.Current()
            Dim nduuid = nd1.GetUuid()
            ListBox2.Items.Add(nduuid)
            snin.Next()
     	 End While			

官网API的解释:
more用于判断是否还有scenenode的标志,next是用于进入下一个scenenode,current是获取当前scenenode对象。
在这里插入图片描述
此外,三维空间还有很多其他参数,如材质,如三维体之间的融合方式(相交、相差、相并):
在这里插入图片描述
计算三维体的距离,进行曲面分析,计算点云等等,所有三维软件的功能,都可以自己用代码实现,只是需要花更多时间去研究,本文只是一个初步的介绍,能够帮你实现一个基本的三维图形显示和动画功能,如果你正好只需要简单应用,那么就可以了。如果要高级的功能,可以去官网看手册。

anycad资料:
[1]: http://www.anycad.cn/guide/
[2]: http://anycad.cn/api/


版权声明:本文为normer123456原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接和本声明。