C#

自定义autolisp 函数 研究

本人是lisp爱好者,初学C#对AutoCAD编程。

从教材上看到C#可以自定义autolisp函数。

教材例子:

定义一个命名为 DisplayFullName 的 AutoLISP 函数。 虽然在 .NET 工程中定义的这个方法接收一个值,但是这个 AutoLISP 函数期待两个字符串值以给出合适的输出。

加载 .NET 工程到 AutoCAD 中。

预期运行效果如下:

在命令提示中输入下列的命令:

(displayfullname "First" "Last")

下面是这个 AutoLISP 函数执行后输出窗口中显示的:

Name:

First Last

自定义代码如下:

C#

using

Autodesk.AutoCAD.Runtime;

using

Autodesk.AutoCAD.ApplicationServices;

[LispFunction("DisplayFullName")]

public

static void DisplayFullName(ResultBuffer rbArgs)

{

if (rbArgs != null)

{

string strVal1 = "";

string strVal2 = "";

int nCnt = 0;

foreach (TypedValue rb in rbArgs)

{

if

(rb.TypeCode ==

(int)Autodesk.AutoCAD.Runtime.LispDataType.Text)

{

switch(nCnt)

{

case

0:

strVal1

= rb.Value.ToString();

break;

case

1:

strVal2

= rb.Value.ToString();

break;

}

nCnt

= nCnt + 1;

}

}

Application.DocumentManager.MdiActiveDocument.Editor.

WriteMessage("\nName:

" + strVal1 + " " + strVal2);

}

}

(注:本例子来自于《AutoCAD.net开发人员手册中文版》)

我们看到这个例子中自定义的autolisp函数是(displayfullname),它接收两个字符串参数,没有返回参数。因为是Void。功能是在命令行写出这两个字符串。

书上只提供了这样一个例子,没有更详细的介绍,这样的功能对于autolisp来说有多大意义吗?没有!

我们要定义一个autolisp函数,我们需要的功能是:

1.

传递autolisp的参数给这个函数,所传递的参数可以是autolisp的各种数据类型。

2.

在C#中使用这些参数,运用C#(AutoCAD.net)提供的强大功能进行各种操作。最重要的是实现autolisp所无法实现的功能。

3.

在这个自定义函数运行完成之后,我们需要这个函数有返回值。这个返回值既是C#中的数据类型,也能够在autolisp中使用。比如在C#中画好的一条或几条线传递回来,供autolisp继续对他们进行操作。

而例题中并没有介绍返回值的方法。

我们来研究一下如何实现我们所需要的这些功能。

最主要的问题就是如何设置函数的参数,如何调用这些参数,如何设置返回值,在lisp中又如何调用这些返回值。

首先,例题中给出了函数的参数,是一个ResultBuffer 数据。ResultBuffer 数据是一个放置了若干个TypedValue数据的数据。可以理解为ResultBuffer数据是TypedValue数据的集合。

所以,就如同在例题中看到的,我们可以用

foreach

(TypedValue rb in rbArgs) { }

把ResultBuffer rbArgs 中的成员提取出来。

而TypedValue数据根据字面理解就是“类-值”,它里面放的是两个元素(类型,值);就是把一个数据和这个数据的类型相对应的放在一起。理论上这个数据类型可以放任何类型的数据在里面。不过我们要想放入可供Autolisp使用的数据,那么就要放入LispDataType中有的类型。LispDataType中有double,txt,point3d,objectid等等类型。

比如,我们要把一条线line的ObjectId放到这个TypedValue数据里,就可以这样写:

TypedValue ty  =

new TypedValue((int)LispDataType.ObjectId,

line.ObjectId);

比如,我们要把一个点Point3d pp放到这个TypedValue数据里,就可以这样写:

TypedValue ty  =

new TypedValue((int)LispDataType.Point3d, pp);

当然,还可以放入双精度、整型、字符串等等类型的数据。

搞清楚TypedValue数据之后,我们就知道如何使用ResultBuffer 数据参数了。

首先用foreach

(TypedValue rb in rbArgs) { } 把ResultBuffer rbArgs 中的成员rb提取出来。然后可以用rb.TypeCode来判断数据的类型,用rb.Value获得数据的值。然后根据类型来尽情使用这些来自autolisp的数据。

以上就是调用参数的方法。

同理,设置返回值也是如此。我们同样可以利用ResultBuffer数据类型设置返回值。比如自定义一个带ResultBuffer数据类型返回值的函数:

[LispFunction("text")]

public static ResultBuffer text (ResultBuffer rbArgs)

{ }

因为我们要返回的内容不可能只有一个数据,很可能是一组数据,而ResultBuffer就是放置了一组TypedValue的数据集合。所以,我们需要定义一个TypedValue的数组作为ResultBuffer返回值的元素。

TypedValue[] ty = new TypedValue[3];(数组长度取决于你想返回多少个数据。)

然后经过程序运行之后,将你要返回的数据,和数据的LispDataType一起放入ty[i]之中。

ty[0]

= new TypedValue((int)LispDataType. ObjectId,

line.ObjectId);

ty[1]

= new TypedValue((int)LispDataType.Point3d, p1);

ty[2]

= new TypedValue((int)LispDataType.Point3d, p2);

然后用ResultBuffer的构造函数构造ResultBuffer类型的返回变量

ResultBuffer rbrtn = new ResultBuffer(ty);

然后:return rbrtn;

这样就哦了!

我测试的这个定义好的autolisp函数test在lisp中的返回值是这样的:

(<图元名:

7ff6b4005df0> (1000.0 1000.0 0.0) (2000.0 2000.0

0.0))

我这里第一个元素放入的是线的ObjectId,到lisp里之后就变成了(car (entsel))得到的那个<图元名:

7ff6b4305e00>,第二个和第三个元素我放入的是Point3d,到lisp里就还是一个三维点。而整个返回值就是一个lisp中的串表,我们可以用car,cadr,nth等调用其中的元素。

附:我的测试程序源码:

[LispFunction("test")]

public static ResultBuffer test(ResultBuffer rbArgs)

{

Document acDoc = Application.DocumentManager.MdiActiveDocument;

Database acCurDb =

acDoc.Database;

Editor acEd = Application.DocumentManager.MdiActiveDocument.Editor;

ResultBuffer rbrtn = new ResultBuffer();

TypedValue[] ty = new TypedValue[3];

Point3d p1 = new Point3d(1000, 1000, 0);

Point3d p2 = new Point3d(2000, 2000, 0);

if (rbArgs != null)

{

foreach (TypedValue rb in rbArgs)

{

acEd.WriteMessage("\n rb.ToString()=" +

rb.ToString());

acEd.WriteMessage("\n rb.TypeCode.ToString()=" +

rb.TypeCode.ToString());

acEd.WriteMessage("\n rb.Value.ToString()=" +

rb.Value.ToString());

}

}

Line line = new Line(p1, p2);

using (Transaction trans =

acCurDb.TransactionManager.StartTransaction())

{

BlockTable acBlkTbl =

trans.GetObject(acCurDb.BlockTableId, OpenMode.ForRead) as BlockTable;

BlockTableRecord acBlkTblRec =

trans.GetObject(acBlkTbl[BlockTableRecord.ModelSpace],

OpenMode.ForWrite) as BlockTableRecord;

line.SetDatabaseDefaults();

acBlkTblRec.AppendEntity(line);

trans.AddNewlyCreatedDBObject(line, true);

trans.Commit();

}

try

{

ty[0] = new TypedValue((int)LispDataType.ObjectId,

line.ObjectId);

ty[1] = new TypedValue((int)LispDataType.Point3d, p1);

ty[2] = new TypedValue((int)LispDataType.Point3d, p2);

rbrtn = new ResultBuffer(ty);

acEd.WriteMessage("\n rbrtn=" +

rbrtn.ToString());

}

catch (System.Exception ex)

{

acEd.WriteMessage(ex.Message);

}

return rbrtn;

}

在cad中先用netload加载编译好的dll文件,然后在Visual

LISP中测试如下代码:

(test (getpoint))

在Visual

LISP控制台中返回结果:

(<图元名:

7ff6b4005df0> (1000.0 1000.0 0.0) (2000.0 2000.0

0.0))

在AutoCAD命令行中返回结果:

命令:

rb.ToString()=(5009,(3350.78961272028,1554.84066563435,0))

rb.TypeCode.ToString()=5009

rb.Value.ToString()=(3350.78961272028,1554.84066563435,0)

rbrtn=((5006,(140697558605296))(5009,(1000,1000,0))(5009,(2000,2000,0)))

以上就是我这几天研究C#自定义autolisp函数的结果。这个功能可以使我们这些爱好lisp的又苦于lisp无法实现一些功能的人利用C#和AutoCAD.net的超强功能扩展lisp的函数功能。毕竟lisp在某些方面还是很强大和方便的。

想要交流的朋友加我qq:307501169

lisp 图元 天正 自定义_C# 自定义autolisp 函数 研究相关推荐

  1. lisp 图元 天正 自定义_AutoLISP查询图元信息

    (defun c:getppt    () (setq ss (car (entsel "请选择要查询的图元:"))) (setq ssob (vlax-ename->vla ...

  2. QGraphicsItem图元旋转缩放和自定义图元(三)

    系列文章目录 QGraphicsItem图元的简单使用(一) QGraphicsItem图元拖动绘制(二) 文章目录 系列文章目录 前言 一.缩放和旋转 二.自定义图元 总结 前言 接上一章,图元绘制 ...

  3. php 二维数组排序函数,php自定义二维数组排序函数array

    这次给大家带来php自定义二维数组排序函数array,php自定义二维数组排序函数array的注意事项有哪些,下面就是实战案例,一起来看一下. 这篇文章主要介绍了php自定义二维数组排序函数array ...

  4. R语言用户自定义函数的语法结构、编写自定义统计值计算函数(使用ifelse结构计算均值和标准差等)、编写自定义日期格式化(format)函数(switch函数使用不同分枝格式化日期数据)、应用自定函数

    R语言用户自定义函数的语法结构.编写自定义统计值计算函数(使用ifelse结构计算均值和标准差等).编写自定义日期格式化(format)函数(switch函数使用不同分枝格式化日期数据).应用自定函数 ...

  5. R语言编写自定义函数、创建使用ggplot2生成图标(icon)的主题(theme)函数、使用ggplot2以及自定义的图标主题函数创建箱图(boxplot)图标、ggsave保存图标(png、svg

    R语言编写自定义函数.创建使用ggplot2生成图标(icon)的主题(theme)函数.使用ggplot2以及自定义的图标主题函数创建箱图(boxplot)图标.ggsave保存图标(png.svg ...

  6. Python matplotlib可视化:自定义轴标签格式化函数(在轴刻度上添加自定义的数值以及符号形式)、使用自定义函数在Matplotlib中为坐标轴刻度添加自定义符号(例如,货币符号¥$等)

    Python matplotlib可视化:自定义轴标签格式化函数(在轴刻度上添加自定义的数值以及符号形式).使用自定义函数在Matplotlib中为坐标轴刻度添加自定义符号(例如,货币符号¥$等) 目 ...

  7. DL之DNN:利用numpy自定义三层结构+softmax函数建立3层完整神经网络全部代码实现(探究BP神经网络的底层思想)

    DL之DNN:利用numpy自定义三层结构+softmax函数建立3层完整神经网络全部代码实现(探究BP神经网络的底层思想) 目录 输出结果 代码实现 输出结果 代码实现 #DL之NN:利用numpy ...

  8. vue自定义指令封装节流_Vue自定义指令封装节流函数的方法示例

    节流函数是web前端开发中经常用到的一个开发技巧,在input实时搜索,滚动事件等,为了避免过多消耗性能,我们都会使用节流函数.在<JavaScript高级程序设计>一书中有这样的一个例子 ...

  9. matlab子函数调用变量,matlab中,怎么样用function自定义函数调用另一个函数名为输入?...

    点击查看matlab中,怎么样用function自定义函数调用另一个函数名为输入?具体信息 答:test定义两个参数,一个是函数,一个是函数的变量. function [z]=test11(funna ...

最新文章

  1. 基于链表的快速排序C语言,双向链表的快速排序算法,编译通过,程序会崩溃,求助一下各位...
  2. 计算机专业核心技术,计算机系多媒体核心技术实验室建设专业方案(10页)-原创力文档...
  3. eclipseEE连接mysql_mysql-eclipseEE连接MySQL出现问题,哪位大神可以帮我看看*^__^*,非常感谢...
  4. journalctl -xe mysql_journalctl 日志查看方法
  5. 2018年湖南居民人均可支配收入25241元 出行餐饮成消费热点
  6. 教你如何用R进行数据挖掘
  7. ArrayList的removeAll和retainAll方法
  8. 基于FPGA的可控倒计时计数器
  9. 微信小程序获得二维码
  10. Python数据分析学习 二
  11. JavaWeb之servlet(1)
  12. python心得总结知识点和收获,千锋Python培训心得 在总结中收获提升
  13. Hash 哈希 PTA 相关题目解析
  14. 小苹果活动助手1.27最新版电脑版
  15. 计算机组成原理各章测试错题
  16. qt5不支持的视频格式:doRender:Unresolved error code 80040266
  17. win10xbox下载慢解决方法
  18. 神器PanDownload没了,还能用什么?
  19. 中国建设招标网,可以查询企业资质
  20. 百面机器学习(8)——采样

热门文章

  1. C#LeetCode刷题-树状数组
  2. 面向对象设计原则之6-合成复用原则
  3. projecteuler_介绍#ProjectEuler100挑战:编码成就的“黑暗灵魂”
  4. javascript中索引_如何在JavaScript中找到数字在数组中所属的索引
  5. 科技与我:在数字时代成长
  6. SAS在金融中的应用六
  7. Stateflow历史节点的使用
  8. C/C++字符串处理库
  9. pexpect与fabric
  10. 通俗理解“Schmidt正交化”和“正交矩阵” 此博文包含图片 (2015-05-19 09:50:47) 施密特正交化在空间上是不断建立垂直于原次维空间的新向量的过程。 如图β2垂直于β1(1维)