【问题标题】:Autolisp entity data retrievalAutolisp 实体数据检索
【发布时间】:2016-08-19 13:20:11
【问题描述】:

我正在试用 AutoCAD,我想在矩形和直线之间建立一条“高速公路”。我需要矩形中的 2 个点。有什么想法吗?

(setq en(car(entsel"\Get rectangle : ")))
 (entget en)

我的整个代码

    (defun temaLisp(/  )
  ;HIGHWAY BUILDER
  ;My project is a highwaybulder
  ;How does it work?
  ;Select a rectangle and draw from there to a distance the highway where it meets a stop(Line)
      (princ "TemaLisp ")
   ;get rectangle (prompt "\nSelect the ends of a station")
  (setq en(car(entsel"\Get rectangle : ")))
  (entget en)
  ;get the stop (Line)


     (setq line2 (car (entsel "\nSelect the second line: ")))
            (setq p3 (cdr (assoc 10 (entget line2))))
            (setq p4 (cdr (assoc 11 (entget line2))))

  ;of the highway &optional (size 50)
  (setq mid1 (midpt pt3 pt4)) ; midpoint for dotted line

  ; Draw the lines
  (command "line" mid1 mid2)
)       

【问题讨论】:

    标签: arrays list lisp autocad autolisp


    【解决方案1】:

    在 AutoCAD 中,矩形(使用 AutoCAD RECTANG 命令创建)使用封闭的二维轻量多段线 (LWPOLYLINE) 实体表示。

    LWPOLYLINE 实体包含以下 DXF 数据:

    (
        (-1 . <Entity name: 7ffff706880>)  ;; Pointer to self
        (0 . "LWPOLYLINE")                 ;; Entity Type
        (330 . <Entity name: 7ffff7039f0>) ;; Point to parent
        (5 . "FFF")                        ;; Handle
        (100 . "AcDbEntity")               ;; Class
        (67 . 0)                           ;; Tilemode
        (410 . "Model")                    ;; Layout
        (8 . "0")                          ;; Layer
        (100 . "AcDbPolyline")             ;; Subclass
        (90 . 4)                           ;; Vertices
        (70 . 1)                           ;; Bitwise flag (1=Closed)
        (43 . 0.0)                         ;; Constant width
        (38 . 0.0)                         ;; Elevation
        (39 . 0.0)                         ;; Thickness
        (10 18.9133 17.6315)               ;; Vertex coordinate (OCS)
    
        < ... additional vertex data ... >
    
        (10 18.9133 12.7863)               ;; Vertex coordinate (OCS)
        (40 . 0.0)                         ;; Segment starting width
        (41 . 0.0)                         ;; Segment ending width
        (42 . 0.0)                         ;; Segment bulge
        (91 . 0)                           ;; Vertex identifier
        (210 0.0 0.0 1.0)                  ;; Extrusion (normal) vector
    )
    

    这里,每个顶点的 2D OCS 坐标使用 DXF 数据中的 DXF 组 10 条目存储。

    有很多方法可以获取 DXF 数据中多次出现的 DXF 组所持有的值列表(因此获取折线的顶点列表)。

    由于assoc AutoLISP 函数返回关联列表中第一次出现的键,我将这些函数称为massoc 函数(即m多个assoc强>)。


    1。 foreach

    (defun massoc1 ( key lst / rtn )
        (foreach x lst
            (if (= key (car x))
                (setq rtn (cons (cdr x) rtn))
            )
        )
        (reverse rtn)
    )
    

    第一个示例简单地遍历提供的关联列表中的每个项目,并且如果 a 地址 register 的 c 内容 (项目的car) 等于所需的key,与键关联的值(或d增量r的c内容strong>egister - cdr) 被添加到函数返回的列表中。

    这个列表在返回之前是反向的,因为列表是反向构建的,每个项目都被推到列表的前面 - 这比使用append/list 的组合来构建按顺序列出。


    2。追加/地图车

    (defun massoc2 ( key lst )
        (apply 'append
            (mapcar
                (function
                    (lambda ( x ) (if (= key (car x)) (list (cdr x))))
                )
                lst
            )
        )
    )
    

    然而,另一种迭代列表的方法,因为 mapcar 返回每​​个列表项的所提供函数的评估结果,如果 if 语句不满足条件的那些项目将导致nil 出现在`mapcar 返回的列表中。

    通过利用 AutoLISP 中 nil 和空列表 () 的对偶性,通过应用 append 函数附加所有子列表和由 @987654341 返回的列表中存在的 nil 值来删除这些 nil 值@。


    3。 vl-remove-if-not

    (defun massoc3 ( key lst )
        (mapcar 'cdr
            (vl-remove-if-not
                (function (lambda ( x ) (= key (car x))))
                lst
            )
        )
    )
    

    正如它在锡上所说:如果提供给 vl-remove-if-not 函数的谓词函数返回 nilvl-remove-if 也可以与否定谓词函数一起使用),则删除项目 - 因此第一个元素不是等于所需的密钥被删除。

    然后使用mapcar 函数返回与vl-remove-if-not 返回的每个关联列表项关联的值。


    4。 while / assoc / 成员

    (defun massoc4 ( key lst / itm rtn )
        (while (setq itm (assoc key lst))
            (setq rtn (cons (cdr itm) rtn) lst (cdr (member itm lst)))
        )
        (reverse rtn)
    )
    

    此方法比之前的方法效率更高,因为 assocmember 函数用于直接跳转到提供的列表中的目标项目,而不是迭代和测试每个项目。

    assoc 返回关联列表中第一次出现的键,member 返回列表的尾部,其中第一项等于提供的参数。

    这样,assoc 函数检索目标项,member 函数返回从该项开始的列表的其余部分,并通过使用重复重新定义列表以包含此目标项之后的所有项cdr.


    5。递归/关联/成员

    (defun massoc5 ( key lst / itm )
        (if (setq itm (assoc key lst))
            (cons (cdr itm) (massoc5 key (cdr (member itm lst))))
        )
    )
    

    但是,在这种情况下,不是为找到的每个项目重新定义列表,而是将列表的其余部分作为参数传递给函数的递归评估。


    6。 acet-list-m-assoc(快速工具)

    (defun massoc6 ( key lst )
        (mapcar 'cdr (acet-list-m-assoc key lst))
    )
    

    此版本的函数使用了 acet-list-m-assoc 函数,该函数定义为 Express Tools 库的一部分,作为 AutoCAD 完整版本的可选补充提供。

    但这是作弊! :-)


    7。基本递归

    (defun massoc7 ( key lst )
        (if lst
            (if (= key (caar lst))
                (cons (cdar lst) (massoc7 key (cdr lst)))
                (massoc7 key (cdr lst))
            )
        )
    )
    

    最后一个示例本质上是上面演示的foreach 示例的递归版本。该函数只查看提供的列表中的第一项,如果第一个元素与 key 参数匹配,则它是 cons'd 到由递归调用返回的列表以及列表的其余部分,否则列表的其余部分被传递给递归调用,而没有添加到返回中。


    示例

    既然我们已经讨论了可以定义这样一个函数的各种方式,那么应该如何使用这样一个函数呢?

    上述每个函数都接受两个参数:一个“键”和一个关联列表。这在语法上与标准 AutoLISP assoc 函数相同。

    此类函数可用于获取与 DXF 关联列表中的 DXF 组 10 关联的所有值,使用以下语法:

    (massoc 10 <dxf-data>)
    

    例如(在 Visual LISP IDE 控制台):

    ;; Obtain a LWPOLYLINE entity
    _$ (setq ent (car (entsel)))
    <Entity name: 7ffff706880>
    
    ;; Retrieve the DXF data
    _$ (setq dxf (entget ent))
    ((-1 . <Entity name: 7ffff706880>) (0 . "LWPOLYLINE") ... (91 . 0) (210 0.0 0.0 1.0))
    
    ;; Obtain the values associated with all DXF group 10 entries
    _$ (massoc 10 dxf)
    ((13.0161 12.4807) (25.727 12.4807) (25.727 18.6426) (13.0161 18.6426))
    

    这可以通过以下方式在示例程序中使用:

    (defun c:test ( / dxf ent )
        (if
            (and
                (setq ent (car (entsel "\nSelect rectangle: ")))
                (setq dxf (entget ent))
                (= "LWPOLYLINE" (cdr (assoc 0 dxf)))
            )
            (print (massoc 10 dxf))
        )
        (princ)
    )
    
    (defun massoc ( key lst / rtn )
        (foreach x lst
            (if (= key (car x))
                (setq rtn (cons (cdr x) rtn))
            )
        )
        (reverse rtn)
    )
    

    性能注意事项

    在性能方面,同一函数的上述变体并不相等 - 对提供列表中的每个项目进行迭代的那些比使用内置函数“跳过”直接到目标项目的那些效率低,例如assocmember

    作为快速比较,请考虑以下基准测试结果:

    ;;;Benchmarking ................Elapsed milliseconds / relative speed for 32768 iteration(s):
    ;;;
    ;;;    (MASSOC5 2 L).....1482 / 1.25 <fastest> ;; recursive/assoc/member
    ;;;    (MASSOC4 2 L).....1482 / 1.25           ;; while/assoc/member
    ;;;    (MASSOC6 2 L).....1498 / 1.24           ;; acet-list-m-assoc
    ;;;    (MASSOC3 2 L).....1638 / 1.13           ;; vl-remove-if-not
    ;;;    (MASSOC7 2 L).....1747 / 1.06           ;; basic recursion
    ;;;    (MASSOC1 2 L).....1748 / 1.06           ;; foreach
    ;;;    (MASSOC2 2 L).....1856 / 1 <slowest>    ;; append/mapcar
    

    正如预期的那样,assoc/member 函数被证明是最快的,Express Tools 函数紧随其后。

    【讨论】:

      【解决方案2】:
      (setq rectangle (entget en))
      

      第一点你可以通过:

      (setq P1(assoc 10 rectangle ))
      

      然后删除P1之前的所有内容

      (setq rectangle (cdr (member P1 rectangle)))
      

      然后得到下一点

      (setq P2(assoc 10 rectangle ))
      

      你可以通过while循环播放

      【讨论】:

        猜你喜欢
        • 2021-07-18
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2018-03-28
        • 2012-08-10
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多