caocaosasd 发表于 2021-6-28 23:58:55

新人想不明白呀……怎么获得两点多段线的终点呢?

工作繁忙,断断续续学了半个月,在大佬的帮助下会写点画双线的程序了,但是还停留在操作直线阶段,遇到多段线就整不明白了

我想知道怎么把多点多段线的各个点输出来,用car,cdr的组合命令获取他们,进行操作。但是我连两端点多段线都搞不懂
就比如这段代码
(defun c:tta (/ abcstart edd )
(setq start (getpoint))
(setq edd (getpoint start))
(setq abc (entmake (list '(0 . "LWPOLYLINE") '(100 . "AcDbEntity") '(100 . "AcDbPolyline") (cons 90 2) (cons 10 start) (cons 10 edd))))
(princ (assoc 10 abc))
)

abc是两端点的直线,为什么结果只输出一个端点,输出两遍呢?我想知道另一个端点是啥,该怎么做呢?


命令: tta (10 121.633 110.994 0.0)(10 121.633 110.994 0.0)

这是某次运行后输出的结果,可以看到把起点给我整出了两遍,无语了……

masterlong 发表于 2021-6-29 10:13:00

送你几个提取数据的函数

;;返回包含每一出现在列表中的指定键的cdr(点对的后部分)的列表<适合处理pl线>
;;例 (massoc 40 (entget (car (entsel))))        每个顶点的宽度
;;返回 (0.0 0.0 200.0 0.0)
(defun massoc( key alist / x nlist)
        (if (= (type alist) 'ename)
                (setq nlist (entget alist))
                (setq nlist alist)
        )
        (mapcar 'cdr (vl-remove-if-not ''((x) (= (car x) key)) nlist))
)

;;145.1 [功能] 求多段线上每段的起、终点,以及可能的弧线段圆心。
;;运行结果示例
;|
(        (p0 p1)
        (p1 p2)
        (p2 p3 cenpoa)
        (p3 p4 cenpob)
        (p4 p5)
)
|;
(defun getpldata( enttt / ) ;;c mc10 mc42 m pldata startpo endpo centpo td data
        ;;(setq ent (car (entsel)))
(setq ent enttt)
       
        (setq c (entget ent))
        (setq mc10 (massoc 10 c))                ;;各顶点坐标
        (setq mc42 (massoc 42 c))                ;;各顶点凸度
;;(~~~ (length mc10))
;;(~~~ (length mc42))
        (if (vlax-curve-isClosed ent)
                (setq mc10 (append mc10 (list (car mc10)))
                                m (cdr (assoc 90 c))
                )
                (setq m (1- (cdr (assoc 90 c))))
        )

        (setq pldata '())
        (repeat m
                (setq startpo (car mc10)
                                mc10 (cdr mc10)
                                endpo (car mc10)
                                td (car mc42)
                                mc42 (cdr mc42)
                )
                (cond
                        ( (= td 0)
                                (setq data (list startpo endpo))
                        )
                        ( (> td 0)
                                (setq centpo
                                        (mapcar '+
                                                startpo
                                                (vlax-curve-getsecondderiv ent (vlax-curve-getParamAtPoint ent startpo))
                                        )
                                )
                                (setq data (list startpo endpo centpo))
                        )
                        ( (< td 0)
                                (setq centpo
                                        (mapcar '-
                                                startpo
                                                (vlax-curve-getsecondderiv ent (vlax-curve-getParamAtPoint ent startpo))
                                        )
                                )
                                (setq data (list startpo endpo centpo))
                        )
                )
                (setq pldata (cons data pldata))
       
        )
        (reverse pldata)
)

;;145.2返回多段线上指定点所在分段的起、终点,以及可能的圆心坐标
(defun getplnbypo( ent po / pldata podist loop i vpo temp )
        (setq pldata (getpldata ent))
        (if (vlax-curve-isClosed ent)
                (setq m (cdr (assoc 90 (entget ent))))
                (setq m (1- (cdr (assoc 90 (entget ent)))))
        )
        (setq po (trans po 1 0))                ;;po必须转为WCS坐标
        (setq po (vlax-curve-getClosestPointTo (*ent2obj* ent) po))
        (setq podist (vlax-curve-getDistAtPoint (*ent2obj* ent) po))
        (setq loop Ti 1)
        (while loop
                (if (= i m)
                        (setq loop NIL
                                        temp (last pldata)
                        )
                        (progn
                                (setq vpo (car (nth i pldata)))
                                (if (>= (vlax-curve-getDistAtPoint ent vpo) podist)
                                        (setq loop NIL
                                                        temp (nth (1- i) pldata)
                                        )
                                        (setq i (1+ i))
                                )
                        )
                )
        )
)

caocaosasd 发表于 2021-6-29 00:36:09

又仔细看了一下书,发现没有用entget
遂把代码改成这样
(defun c:ttb (/ abc start edd ell)
(setq start (getpoint))
(setq edd (getpoint start))
(setq        abc (entmake (list '(0 . "LWPOLYLINE")
                           '(100 . "AcDbEntity")
                           '(100 . "AcDbPolyline")
                           (cons 90 2)
                           (cons 10 start)
                           (cons 10 edd)
                     )
          )
)
(setq ell (entget abc))
(princ (assoc 10 ell))
(princ)
)


结果返回了一堆,
命令: TTB ; 错误: 参数类型错误: lentityp ((0 . "LWPOLYLINE") (100 . "AcDbEntity") (100 . "AcDbPolyline") (90 . 2) (10 4368.46 1568.42 0.0) (10 4837.59 2010.93 0.0))
命令:

这又是为啥呢……

caocaosasd 发表于 2021-7-11 23:09:50

wyl219 发表于 2021-7-3 13:04
因为是否打印存在于图层的信息表,而ssget筛选的是对象的信息表,所以应该是没办法直接利用.
我能想到的办 ...

大佬,再请教个问题呗,如果输UCS改了一下坐标,entmake创建的图元就跑偏了,就不是点哪画哪了,这种情况咋处理呢?
举个例子,以下是一个画双线的小lisp,我输ucs,然后随便点两个点,把鼠标指针的坐标改歪了,然后我发现,这个时候用这个小lisp画出来的双线是跑偏的,

如何规避这种情况呢?就是正常ucs也能指哪画哪,歪了的UCS也能指哪画哪

(defun c:hsxa (/ L1 L2 KU PT1 PT2 PT3 PT4 ZX ENT13 ENT24)

(setq L1 (getpoint))
(setq L2 (getpoint L1))
(setq KU (angle L1 L2))
(setq PT1 (polar L1 (+ KU (* 0.5 pi)) 100))
(setq PT2 (polar L1 (+ KU (* 1.5 pi)) 100))
(setq PT3 (polar L2 (+ KU (* 0.5 pi)) 100))
(setq PT4 (polar L2 (+ KU (* 1.5 pi)) 100))

(setq
    ENT13 (entmakex (list '(0 . "LINE") (cons 10 pt1) (cons 11 pt3)))
)
(setq
    ENT24 (entmakex (list '(0 . "LINE") (cons 10 pt2) (cons 11 pt4)))
)

)

caocaosasd 发表于 2021-6-29 00:05:13

有没有什么办法实时查看图元的组码呢?

我也是无语,假设abc是一条两个端点的多段线,
(assoc 10 abc)得到的结果竟然是两遍起点么?

组码表里不是写着:
10
顶点坐标(在 OCS 中),多个条目;每个顶点一个条目

多段线有多个顶点时,assoc 10 不会把每个顶点都输出出来么?

start4444 发表于 2021-6-29 00:53:05

不能直接设abc,用entlast连接
(defun c:tta (/ abcstart edd )
(setq start (getpoint))
(setq edd (getpoint start))
(entmake (list '(0 . "LWPOLYLINE") '(100 . "AcDbEntity") '(100 . "AcDbPolyline") (cons 90 2) (cons 10 start) (cons 10 edd)))
(setq abc (entlast))
(princ (entget abc))
(princ)
)

caocaosasd 发表于 2021-6-29 01:12:11

本帖最后由 caocaosasd 于 2021-6-29 01:14 编辑

然后我打开了一个纯净的CAD,照着30集的那个lisp视频教程,一步一步操作如下

在命令行输入
命令: (setq e1 (entget(car(entsel))))

返回以下内容:
选择对象: ((-1 . <图元名: 7ff425c05d10>) (0 . "LWPOLYLINE") (330 . <图元名: 7ff425c039f0>) (5 . "249") (100 . "AcDbEntity") (67 . 0) (410 . "Model") (8 . "0") (100 . "AcDbPolyline") (90 . 2) (70 . 0) (43 . 0.0) (38 . 0.0) (39 . 0.0) (10 4012.48 1599.2) (40 . 0.0) (41 . 0.0) (42 . 0.0) (91 . 0) (10 4124.66 1819.59) (40 . 0.0) (41 . 0.0) (42 . 0.0) (91 . 0) (210 0.0 0.0 1.0))

命令: (setq e2 (assoc 10 e1))
返回以下内容:
(10 4012.48 1599.2)


也就是说,assoc 10 对于多个端点的多段线,只会返回第一个点,不会返回所有点,这么坑爹呢……

所以请教大神们,如何操作能返回多段线的各个顶点呢?如果不用vlax的话(我还没学到那呢……)

烟盒迷唇 发表于 2021-6-29 08:44:35

2个端点的话,用reverse倒置就可以提取另一个端点,多个端点的话就要遍历提取了。entmakeX可以直接取得图元,不用ENTLAST也可以。

masterlong 发表于 2021-6-29 10:09:41

多段线属于比较特殊的图元
不光是获取数据比较绕
生成和修改PL线也是比较麻烦

lxw320 发表于 2021-6-29 12:47:08

在本论坛里搜索能解决你90%的疑问

wyl219 发表于 2021-6-29 16:00:13

;纯lisp获取所有顶点
(setq ed(entget (setq en (car (entsel)))));获取关联表

(setq lst_tmp '()) ;初始化一个空表
(while         (setq ed         (member (assoc 10 ed ) ed)) ;找到下一个顶点,并把其后所有内容(包括这个顶点)重新赋值给ed,找不到时返回nil,结束循环
        (setq lst_tmp (cons (car ed ) lst_tmp)) ;把关联表中第一个元素记录下来
        (setq ed (cdr ed)) ;从ed中去除第一个元素,避免死循环
)
(print (reverse lst_tmp) );倒置列表并打印
(princ)

;纯lisp获取起点终点
(setq ed(entget (setq en (car (entsel)))));获取关联表

(setq start (assoc 10 ed)) ;获取第一个顶点
(setq end (assoc 10 (reverse ed)));倒置后获取第一个顶点,即原始的最后一个顶点

(print (list start end) );倒置列表并打印
(princ)

; 纯lisp获取到的点包含组码10,可用cdr去除
页: [1] 2
查看完整版本: 新人想不明白呀……怎么获得两点多段线的终点呢?