• 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
    
    • 1
    • 2

    2 初始化:

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

     static class Program
        {
            /// 
            /// The main entry point for the application.
            /// 
            [STAThread]
            static void Main()
            {
                // 初始化
                AnyCAD.Foundation.GlobalInstance.Initialize();
                Application.EnableVisualStyles();
                Application.SetCompatibleTextRenderingDefault(false);
                Application.Run(new MainForm());
                AnyCAD.Foundation.GlobalInstance.Destroy();
            }
        }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16

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

    Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load     
    
            AnyCAD.Foundation.GlobalInstance.Initialize()
          
    End Sub
    
    • 1
    • 2
    • 3
    • 4
    • 5

    释放资源:

     Private Sub Form1_FormClosed(sender As Object, e As FormClosedEventArgs) Handles Me.FormClosed
    
            AnyCAD.Foundation.GlobalInstance.Destroy()
    End Sub
    
    • 1
    • 2
    • 3
    • 4

    3 控件显示:

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

        public partial class MainForm : Form
        {
            RenderControl mRenderView;
            public MainForm()
            {
                InitializeComponent();
    
                mRenderView = new RenderControl(this.splitContainer1.Panel2);
                // 这里不能调用AnyCAD其他的API
            }
            ...
        }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12

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

    mrenderview = New RenderControl(Picturebox2)
    
    • 1

    以上,一个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)
    
    • 1
    • 2
    • 3

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

    类似的,创建球体:

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

    立方体:

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

    等等。

    创建一个三维图形,算是最简单的使用了,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(); // 把模型缩放到合适位置
            }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15

    利用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)); // 显示指定个灰白色
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10

    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");
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11

    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();
                });
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11

    但在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
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14

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

    mrenderview.SetAnimationCallback(Nothing)
    
    • 1

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

    mrenderview.SetAnimationCallback(cb3)
    
    • 1

    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)
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9

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

    官网示例是C#:

    for(var itr = scene.CreateIterator();itr.More(); itr.Next())
    {
        var node = itr.Current();
        //....
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5

    转换成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			
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8

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

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

  • 相关阅读:
    在UE5中使用OverlayMaterial制作多材质效果
    Python中的numpy库
    [iOS]-消息传递和消息转发机制
    【网络原理】应用层协议概述
    springcloud入门
    不完全微分PD控制器(CODESYS源代码+算法详细介绍)
    HTML+CSS
    10 年国内算法大神经验总结的数据结构与算法详解终于学完
    1.Android逆向协议-环境搭建
    SpringCloud Alibaba-Seata
  • 原文地址:https://blog.csdn.net/normer123456/article/details/126699933