hb198075 发表于 2012-3-31 13:53:46

如何在多点之间绘制最短的不交叉连线(附一个用于植物图块标注的程序源码)

本帖最后由 hb198075 于 2012-3-31 13:57 编辑

对选择的图块进行连线,要求获得最短的一种自身不交叉的连线方式。
已完成如下代码,感觉不理想,图块少时还不错,图块多了就乱了。望高手们赐教!

;;;测试程序
(defun c:tt1 ( / e10 ent itm n na ptlst ss)
(if (setq ss (ssget '((0 . "INSERT"))))
    (progn
      (setq n 0)
      (repeat (sslength ss)
(setq na    (ssname ss n)
       ent   (entget na)
       e10   (cdr (assoc 10 ent))
       ptlst (cons e10 ptlst)
       n   (1+ n)
)
      )
      (setq ptlst (bz-dianjuLst ptlst))
      (command "_.PLINE")
      (foreach itm ptlst
(command itm)
      )
      (command "")
    )
)
(princ)
)
;;;获得最短的总点距
(defun bz-dianjuLst (lst / a all b jd jl n pt tglst)
(setq n 0)
(while (< n (length lst))
    (setq pt (nth n lst)
   tglst (bz-getNextPoint pt lst)
   jl (HB_GETdist tglst)
   )
    (setq jd(bz-getPlistInsert tglst)
   jl(* jl jd)
   );_根据交点数设置优先级,每多一个交点,则距加一倍
    (setq all (cons (cons jl tglst) all)
   n (1+ n)
    )
)
(setq all(vl-sort all '(LAMBDA (a b)(< (car a)(car b)))))
(cdar all)
)
;;;获得离当前点最近的下一点
(defun bz-getNextPoint (pt lst / a b rel tmplst)
(setq tmplst lst)
(while tmplst
    (setq tmplst (vl-sort tmplst
   '(LAMBDA (a b) (< (DISTANCE pt a) (DISTANCE pt b)))
   )
   pt(car tmplst)
    )
    (setq rel(cons pt rel)
   tmplst (cdr tmplst)
    )
)
(REVERSE rel)
)
;;;判断当前连线自身的交点数
(defun bz-getPlistInsert (lst / jd len m n p1 p2 pt1 pt2 rel)
(setq n   0
len (length lst)
rel 1
)
(repeat (- len 2)
    (setq p1 (nth n lst)
   p2 (nth (1+ n) lst)
   n(1+ n)
   m(1+ n)
    )
    (repeat (- len n 2)
      (setq pt1 (nth m lst)
   pt2 (nth (1+ m) lst)
   jd (INTERS p1 p2 pt1 pt2)
   m (1+ m)
      )
      (if jd
(setq rel (1+ rel))
      )
    )
)
rel
)
;;;获得点连线的总长度
(defun HB_GETdist (lst / rel n p1 p2 tmp)
(setq rel 0.0)
(if (> (length lst) 1)
    (progn
      (setq n 0)
      (repeat (1- (length lst))
(setq p1(nth n lst)
       p2(nth (1+ n) lst)
       n   (1+ n)
       tmp (DISTANCE p1 p2)
       rel (+ tmp rel)
)
      )
    )
)
rel
)

下面是测试图


hb198075 发表于 2012-3-31 14:06:06

下面是自己使用多年的一个用于植物图块标注与统计的程序,先附图:

命令执行方式:ZW


灬北方狼灬 发表于 2014-8-11 09:05:27

学习了,谢谢分享.

flowerson 发表于 2018-6-27 23:53:20

为什么看不到了?显示“提示: 作者被禁止或删除 内容自动屏蔽”

yoyoho 发表于 2018-2-9 10:20:18

感谢诸位高手分享程序!!!!

SYTDD 发表于 2018-2-8 23:45:30

谢谢楼主和各位高手,学习中

guankuiwu 发表于 2019-11-14 12:39:04

hb198075 发表于 2012-3-31 14:06
下面是自己使用多年的一个用于植物图块标注与统计的程序,先附图:

命令执行方式:ZW

楼主还在么?那个植物的lsp。好像还有个CAD样板文件吧.

smartstar 发表于 2012-6-27 08:43:16

学习学习。

hb198075 发表于 2012-4-2 09:08:48

Gu_xl 发表于 2012-4-1 23:33 static/image/common/back.gif
发个动态串线程序:




看起来很好用的,速度应该比我那个快多了,不知道G版能不提供源码让我学习一下,我想加上自动计算最佳连线方式的功能,而不是由人来判断。

hb198075 发表于 2019-11-26 11:14:59

这个是应用公司制图标准自动设置的标注,你手动建一个名称为“yD10"的标注样式就可以了。(后面的数字表示标注样式的比例)

Gu_xl 发表于 2012-3-31 14:10:19

参考帖子
http://bbs.mjtd.com/forum.php?mod=viewthread&tid=88065&page=1&extra=#pid472441pid472441
6楼代码:

xiaxiang 发表于 2012-3-31 14:12:38

hb198075 发表于 2012-3-31 14:06 static/image/common/back.gif
下面是自己使用多年的一个用于植物图块标注与统计的程序,先附图:

命令执行方式:ZW

很多的个人函数哦,收下了

hb198075 发表于 2012-3-31 14:18:03

感谢G版的热情,我先去看看~

hb198075 发表于 2012-3-31 14:33:20

本帖最后由 hb198075 于 2012-3-31 14:34 编辑

Gu_xl 发表于 2012-3-31 14:10 http://bbs.mjtd.com/static/image/common/back.gif
参考帖子
http://bbs.mjtd.com/forum.php?mod=viewthread&tid=88065&page=1&extra=#pid472441pid472441
6 ...

G版你那个程序的思路比我灵活多了,不过也是在图块稍多些时连线就不大如意。只实现了不交叉,但没有实现最短连线,希望能有个更完美的算法了。

hb198075 发表于 2012-4-1 17:34:52

本帖最后由 hb198075 于 2012-4-1 17:36 编辑

想了一天总算搞出来了,虽然法子比较笨,运算也有些慢,不过在处理100个图块以下时速度还是能忍受的,关键是连线比较完美的。先附个图

把源码也奉上,。。。循环用得比较多,速度有点慢,希望有朋友能帮着也优化一下~


;;;测试程序
(defun c:tt1 ( / e10 ent itm n na ptlst ss oldvar)
(setq oldvar(getvar "OSMODE"))
(setvar "OSMODE" 0)
(if (setq ss (ssget '((0 . "INSERT"))))
    (progn
      (setq n 0)
      (repeat (sslength ss)
(setq na    (ssname ss n)
       ent   (entget na)
       e10   (cdr (assoc 10 ent))
       ptlst (cons e10 ptlst)
       n   (1+ n)
)
      )
      (setq ptlst (bz-dianjuLst ptlst))
      (command "_.PLINE")
      (foreach itm ptlst
(command itm)
      )
      (command "")
    )
)
(setvar "OSMODE" oldvar)
(princ)
)
;;;获得最短的总点距
(defun bz-dianjuLst
       (lst / a all b jd jl n n_sd newlst pt tglst)
(setq n 0
n_sd 0
)
(while (< n (length lst))
    (setq pt (nth n lst)
   tglst (bz-getNextPoint pt lst)
    )
    (setq newlst (bz-getPlistInsert tglst)
   tglst(cadr newlst)
   jl(HB_GETdist tglst)
    )
    (setq all (cons (cons jl tglst) all)
   n   (1+ n)
    )
)
(setq all (vl-sort all '(LAMBDA (a b) (< (car a) (car b)))))
(cdar all)
)
;;;获得离当前点最近的下一点
(defun bz-getNextPoint (pt lst / a b rel tmplst)
(setq tmplst lst)
(while tmplst
    (setq tmplst (vl-sort tmplst
   '(LAMBDA (a b) (< (DISTANCE pt a) (DISTANCE pt b)))
   )
   pt(car tmplst)
    )
    (setq rel(cons pt rel)
   tmplst (cdr tmplst)
    )
)
(REVERSE rel)
)
;;;判断当前连线自身的交点数
(defun bz-getPlistInsert (lst / 1lst 2lst leftitm len mjd n num p1 p2 pt1 pt2 rellst)
(setq n      0
len    (length lst)
num    1
rellst (list (car lst))
1lst   lst
)
(while (and (setq p1 (car 1lst))
       (setq p2 (cadr 1lst))
)
    (setq mjdnil
   1lst (cdr 1lst)
   2lst (cdr 1lst)
    )
    (while (and (null mjd)
(setq pt1 (car 2lst))
(setq pt2 (cadr 2lst))
(setq 2lst (cdr 2lst))
    )
      (if (INTERS p1 p2 pt1 pt2)
(setq mjd pt1)
      )
    )
    (if mjd
      (setq num(1+ num)
   leftitm (HB_LIST_LEFTITEM mjd 1lst)
   1lst (cdr (member mjd 1lst))
   1lst (append (list p1 mjd) (REVERSE leftitm) 1lst)
      )
      (setq rellst (cons p2 rellst))
    )
)
(list num (REVERSE rellst))
)
;;;获得点连线的总长度
(defun HB_GETdist (lst / rel n p1 p2 tmp)
(setq rel 0.0)
(if (> (length lst) 1)
    (progn
      (setq n 0)
      (repeat (1- (length lst))
(setq p1(nth n lst)
       p2(nth (1+ n) lst)
       n   (1+ n)
       tmp (DISTANCE p1 p2)
       rel (+ tmp rel)
)
      )
    )
)
rel
)
;;;返回列表中某元素之前的列表
(defun hb_list_leftItem (itm lst / tmplst rel)
(setq tmplst (REVERSE lst))
(while (setq tmplst (cdr (member itm tmplst)))
    (setq rel tmplst)
)
(REVERSE rel)
)


Gu_xl 发表于 2012-4-1 23:33:42

本帖最后由 Gu_xl 于 2013-4-10 14:55 编辑

发个动态串线程序:


程序文件下载:



tm20038175 发表于 2012-4-2 12:19:15

学习一下~~~~~
页: [1] 2 3 4 5 6 7 8 9
查看完整版本: 如何在多点之间绘制最短的不交叉连线(附一个用于植物图块标注的程序源码)