AnyCAD中的Editor示例代码学习1

  AnyCAD Rapid SDK(ARS)是一个包含三维几何造型、图形显示、数据管理等模块综合三维图形平台,支持Windows、Linux、MacOS多操作系统,支持.NET、Python、Java多开发语言,可以用于开发CAD/CAE/CAM/SIM应用程序,用于机械、建筑、电力、教育、机器人、科学计算等领域。目前计划基于Anycad编写一个三维桥梁设计功能的软件。

  Editor是一个与图形界面进行交互的机制,在AutoCAD的二次开发中,也有Editor对象,对应的是CAD界面中的命令行,也是用于与CAD进行交互。交互式操作,简单来说是输入与输出的交互,输入可以是鼠标、键盘等设备信号。输出则是内容的展示。交互式操作中,对于使用者更弱化了数据的实际数值。

  AnyCAD 中的 Editor 定义为编辑器。可以理解为,当 Editor 激活时,会对键盘、鼠标等设备输入进行响应,而响应的具体内容可以由用户自行实现。如下是一段交互式操作的代码,用于实现通过选择几何边来创建标注对象(Dimension):当选择的两条边平行时,创建尺寸标注;如果选择的边不平行,则创建的是角度标注。如下图所示:

   任何交互式对象,都要继承自Editor对象,并重载其中的一些方法,如Start()、OnMouseMove()、 Finish()等。

 1 namespace Rapid.Sketch.Plugin.Dimension
 2 {
 3 
 4     class CreateDimensionEditor : Editor
 5     {
 6       #region Constructor
 7         public CreateDimensionEditor()
 8         {
 9             SetName("CreateDimensionTrial");
10         }
11         #endregion
12     }
13 }

  构造函数中SetName(),用于表示编辑器的功能。

  然后重写该类的 Start 函数,用于表示当 Editor 被激活时,需要进行的准备工作。

        // Editor启动时执行
        public override EnumEditorCode Start(ViewContext ctx)
        {
            var tmp = ctx.GetTempContext();
            tmp.Start();
            tmp.SetPickFilter(EnumShapeFilter.Edge); // 这里只处理选择边,如果需要选择点、面可更改参数
        //TODO
return base.Start(ctx); }

  这里,在Start函数中,定义了一个临时视图上下文tmp,并启动(tmp.Start()。同时设置了交互式选择图形对象的类型,此处是允许用户选择Edge对象。在许多的场景中,

  接下来就是首先各种鼠标操作的功能,比如当鼠标移动时,需要重载OnMouseMove函数:

public override EnumEditorCode OnMouseMove(ViewContext ctx, InputEvent evt)
{
  if (evt.GetButtons() == EnumMouseButton.Zero)
  {
    switch (mEditStep)
    {
      //这里预设了几种编辑步骤(EnumerateEditStep),用于不同情境下的行为
      case EnumEditStep.Target1:       case EnumEditStep.Target2:       {   
       // 吸附拓扑边并进行高亮

        var item = ctx.SnapPoint(evt.GetX(), evt.GetY());//在鼠标点处拾取对象(SnapPoint,拾取通过点的对象)
        if (!item.IsNull())
        {
          ctx.GetSelectionManager().GetHilight().Add(item, false);//将item添加到高亮集合中
        }
        else
        {
          ctx.ClearSelection();
        }
        ctx.RequestUpdate(EnumUpdateFlags.Selection);//更新选择集
        return EnumEditorCode.Processed;//返回

      }
      case EnumEditStep.Location:
      {
        // 更新尺寸标注
        if (mDimNode == null)

          {
            MessageBox.Show("创建尺寸标注失败");
            return EnumEditorCode.Failed;
          }

          //更新图元标注,UpdateDimensionNode(ctx, evt)为自定义方法,获取当前鼠标射线与给定平面的交点
          if (UpdateDimensionNode(ctx, evt))
          {
            // 更新标注成功,通知场景更新渲染
            ctx.RequestUpdate(EnumUpdateFlags.Scene);
          }
          return EnumEditorCode.Processed;

        }

    }

  }  
  
return base.OnMouseMove(ctx, evt); }

  其中,InputEvent类型的变量evt表示鼠标事件,evt.GetButtons用于获取相应的鼠标按键:

 if (evt.GetButtons() == EnumMouseButton.Zero)
表示鼠标在移动的过程中没有按下任何按键,evt.GetButtons()还有其它几种取值,如下:
public enum EnumMouseButton
{
    Zero = 0,//
    Left = 1,//左键
    Middle = 2,//中键
    Right = 4,//右键
    LeftRight = 5,//左键和右键
    LeftMiddle = 3,//左键和中键
    RightMiddle = 6,//右键和中键
    All = 7   //全部按键,左/中/右
}

  鼠标按键事件处理函数用OnMouseUp函数,鼠标按键有两个事件,分别是按下(OnMouseDown)和抬起(OnMouseUp),这里处理鼠标左键的OnMouseUp事件。

        // 鼠标点击时执行
        public override EnumEditorCode OnMouseUp(ViewContext ctx, InputEvent evt)
        {
            //判断是否为鼠标左键,只处理鼠标左键事件
            if (evt.GetButtons() == EnumMouseButton.Left)
            {
                if (mEditStep == EnumEditStep.Location)
                {
                    // 自定义Editor的Commit方法,用于提交当前编辑的结果
                    Commit(ctx);

                    // 重置,继续下一个标注创建
                    Reset(ctx);
                    return EnumEditorCode.Processed;
                }

                // 获取被高亮的拓扑边
                var hilight = ctx.GetSelectionManager().GetHilight();
                if (hilight.GetCount() > 0)
                {
                    var pickedItem = hilight.GetItem(0);
                    // 自定义方法,用于处理拓扑边的选择
                    return SetPickedEdge(ctx, pickedItem);
                }
            }

            return base.OnMouseUp(ctx, evt);
        }

  当Editor编辑结束后,需通过重载Finish方法来关闭视图上下文。

        // Editor结束时执行
        public override void Finish(ViewContext ctx)
        {
            ctx.GetTempContext().Close();
            base.Finish(ctx);
        }

  同时,在重启Editor操作时,还需要重载Reset方法,设置命令启动的状态。

        // 重置Editor状态
        public override void Reset(ViewContext ctx)
        {
           ....
        }

  当需要其它功能时候,还可以重载其它的Editor方法,或者自定义方法。

 

  上述代码来自于A你要CAD提供的官方代码,通过学习,对Editor的进行简单总结如下:

  1.Editor是一种定义交互式操作的基类,可以继承之并扩展自己的功能。此时需要对基类的方法进行重载;

  2.在继承类的构造函数中SetName(""),以描述编辑器的功能;当给编辑器添加界面时,编辑器作为ViewModel,在构造函数中定义RelayCommand,供交互界面进行调用。

  3.重载Start方法,完成编辑器启动时的准备工作。如果定义了交互式界面,就可以在Start方法中进行实例化。

  4.根据需要重载OnMouseMove、OnMouseDown、OnMouseUp等方法,实现相应的行为逻辑。

  5.当退出编辑器时,一定要通过重载的Finish方法进行视图上下文的清理。

posted @ 2024-05-30 14:55  骑士向东  阅读(20)  评论(0编辑  收藏  举报