找回密码
 立即注册

QQ登录

只需一步,快速开始

扫一扫,访问微社区

查看: 3429|回复: 23

[研讨] 删除点集中的重复点

[复制链接]

已领礼包: 3941个

财富等级: 富可敌国

发表于 2013-6-6 22:31:49 | 显示全部楼层 |阅读模式

马上注册,结交更多好友,享用更多功能,让你轻松玩转社区。

您需要 登录 才可以下载或查看,没有账号?立即注册

×
本帖最后由 dnbcgrass 于 2013-6-6 23:41 编辑

下面是一个删除点集中重复点的函数,当点集的点数一万以上时耗用时间太多,大家有没有什么更快的方法?

  1. ;删除点集中重复的点
  2. ;用法:(del-pt 点集pts 判定点相同的限差eps)
  3. ;eps取1e-3
  4. (defun del-pt (pts eps / fhz pt)
  5.   (setq fhz nil)
  6.   (while pts
  7.     (setq pt (car pts)
  8.           fhz (cons pt fhz)
  9.           pts (cdr pts)
  10.           pts (vl-remove-if '(lambda (x)
  11.                                (equal x pt eps)
  12.                              ) pts
  13.               )
  14.     )
  15.   )
  16.   (setq fhz (reverse fhz))
  17. )

删除点集内重复点测试图.rar

338.6 KB, 下载次数: 9, 下载积分: D豆 -1 , 活跃度 1

论坛插件加载方法
发帖求助前要善用【论坛搜索】功能,那里可能会有你要找的答案;
如果你在论坛求助问题,并且已经从坛友或者管理的回复中解决了问题,请把帖子标题加上【已解决】;
如何回报帮助你解决问题的坛友,一个好办法就是给对方加【D豆】,加分不会扣除自己的积分,做一个热心并受欢迎的人!

已领礼包: 8125个

财富等级: 富甲天下

发表于 2013-6-6 23:07:27 | 显示全部楼层
试试这个:  
  1. ;;;参数 Lst----点集
  2. ;;;     tol----容差
  3. (defun RemoveDup (lst Tol / L n)
  4.   (setq
  5.     lst
  6.     (vl-sort
  7.       lst
  8.       (function
  9.         (lambda (pt1 pt2)
  10.           (if (equal (car pt1) (car pt2) tol)
  11.             (if (equal (cadr pt1) (cadr pt2) tol)
  12.               (< (caddr pt1) (caddr pt2))
  13.               (< (cadr pt1) (cadr pt2))
  14.             )
  15.             (< (car pt1) (car pt2))
  16.           )
  17.         )
  18.       )
  19.     )
  20.   )
  21.   (while lst
  22.     (setq n (car lst))
  23.     (setq L (cons n L))
  24.     (while
  25.       (and
  26.         (cadr lst)
  27.         (equal (car lst) (cadr lst) tol)
  28.       )
  29.       (setq lst (cdr lst))
  30.     )
  31.     (setq lst (cdr lst))
  32.   )
  33.   (reverse L)
  34. )

  35. ;;;example:
  36. ;;;(setq lst '((1235 255 140) (1258 230 150) (1258 230 150) (1263 262 160)))
  37. ;;;(setq lst (removeDup lst 0.))

点评

==> 改成这样,可以少运算几次  详情 回复 发表于 2013-6-7 08:43
点集数量多的时候一定要对点排序,不然效率不高。 正如你所说,谢谢!  发表于 2013-6-7 00:08

评分

参与人数 1D豆 +5 收起 理由
炫翔 + 5 技术引导讨论和指点奖!

查看全部评分

论坛插件加载方法
发帖求助前要善用【论坛搜索】功能,那里可能会有你要找的答案;
如果你在论坛求助问题,并且已经从坛友或者管理的回复中解决了问题,请把帖子标题加上【已解决】;
如何回报帮助你解决问题的坛友,一个好办法就是给对方加【D豆】,加分不会扣除自己的积分,做一个热心并受欢迎的人!
回复 支持 1 反对 0

使用道具 举报

发表于 2013-6-6 22:46:31 | 显示全部楼层
你用这个测试下,看下要多长时间
http://www.xdcad.net/forum/thread-668673-1-1.html
论坛插件加载方法
发帖求助前要善用【论坛搜索】功能,那里可能会有你要找的答案;
如果你在论坛求助问题,并且已经从坛友或者管理的回复中解决了问题,请把帖子标题加上【已解决】;
如何回报帮助你解决问题的坛友,一个好办法就是给对方加【D豆】,加分不会扣除自己的积分,做一个热心并受欢迎的人!
回复 支持 反对

使用道具 举报

已领礼包: 8125个

财富等级: 富甲天下

发表于 2013-6-6 23:08:54 | 显示全部楼层
点集数量多的时候一定要对点排序,不然效率不高。

点评

的确是这样,无序表判断是 n*(n-1)*(n-2)* .... 1 排序以后只有极端情况下才是上述情况,一般就是比较 car cadr  详情 回复 发表于 2013-6-6 23:46
论坛插件加载方法
发帖求助前要善用【论坛搜索】功能,那里可能会有你要找的答案;
如果你在论坛求助问题,并且已经从坛友或者管理的回复中解决了问题,请把帖子标题加上【已解决】;
如何回报帮助你解决问题的坛友,一个好办法就是给对方加【D豆】,加分不会扣除自己的积分,做一个热心并受欢迎的人!
回复 支持 反对

使用道具 举报

已领礼包: 145个

财富等级: 日进斗金

发表于 2013-6-6 23:14:44 | 显示全部楼层
楼主先给大家做个生成随机点的函数吧,然后根据这个函数随机生成1万个,然后大家测试下每个函数的效率。
论坛插件加载方法
发帖求助前要善用【论坛搜索】功能,那里可能会有你要找的答案;
如果你在论坛求助问题,并且已经从坛友或者管理的回复中解决了问题,请把帖子标题加上【已解决】;
如何回报帮助你解决问题的坛友,一个好办法就是给对方加【D豆】,加分不会扣除自己的积分,做一个热心并受欢迎的人!
回复 支持 反对

使用道具 举报

发表于 2013-6-6 23:46:04 | 显示全部楼层
Highflybird 发表于 2013-6-6 23:08
点集数量多的时候一定要对点排序,不然效率不高。

的确是这样,无序表判断是 n*(n-1)*(n-2)* .... 1
排序以后只有极端情况下才是上述情况,一般就是比较 car cadr
论坛插件加载方法
发帖求助前要善用【论坛搜索】功能,那里可能会有你要找的答案;
如果你在论坛求助问题,并且已经从坛友或者管理的回复中解决了问题,请把帖子标题加上【已解决】;
如何回报帮助你解决问题的坛友,一个好办法就是给对方加【D豆】,加分不会扣除自己的积分,做一个热心并受欢迎的人!
回复 支持 反对

使用道具 举报

已领礼包: 3941个

财富等级: 富可敌国

 楼主| 发表于 2013-6-7 00:06:05 | 显示全部楼层
谢谢Highflybird,对于测试图,用你那个函数,快了几万倍!!!

点评

这么夸张!把测试数据贴上来看看  详情 回复 发表于 2013-6-7 00:23
论坛插件加载方法
发帖求助前要善用【论坛搜索】功能,那里可能会有你要找的答案;
如果你在论坛求助问题,并且已经从坛友或者管理的回复中解决了问题,请把帖子标题加上【已解决】;
如何回报帮助你解决问题的坛友,一个好办法就是给对方加【D豆】,加分不会扣除自己的积分,做一个热心并受欢迎的人!
回复 支持 反对

使用道具 举报

已领礼包: 593个

财富等级: 财运亨通

发表于 2013-6-7 00:23:31 | 显示全部楼层
dnbcgrass 发表于 2013-6-7 00:06
谢谢Highflybird,对于测试图,用你那个函数,快了几万倍!!!

这么夸张!把测试数据贴上来看看
论坛插件加载方法
发帖求助前要善用【论坛搜索】功能,那里可能会有你要找的答案;
如果你在论坛求助问题,并且已经从坛友或者管理的回复中解决了问题,请把帖子标题加上【已解决】;
如何回报帮助你解决问题的坛友,一个好办法就是给对方加【D豆】,加分不会扣除自己的积分,做一个热心并受欢迎的人!
回复 支持 反对

使用道具 举报

已领礼包: 8125个

财富等级: 富甲天下

发表于 2013-6-7 00:57:50 | 显示全部楼层
本帖最后由 Highflybird 于 2013-6-7 11:29 编辑

我这里提供了一个lsp文件:
能创建大数量的随机点,并进行效率测试:
请点击此处下载

查看状态:需购买或无权限

您的用户组是:游客

文件名称:rem-dup.LSP 
下载次数:26  文件大小:4.58 KB 
下载权限: 不限 以上  [免费赚D豆]


里面已经包含了两位网友的方法。可以做比较。
论坛插件加载方法
发帖求助前要善用【论坛搜索】功能,那里可能会有你要找的答案;
如果你在论坛求助问题,并且已经从坛友或者管理的回复中解决了问题,请把帖子标题加上【已解决】;
如何回报帮助你解决问题的坛友,一个好办法就是给对方加【D豆】,加分不会扣除自己的积分,做一个热心并受欢迎的人!
回复 支持 反对

使用道具 举报

已领礼包: 3884个

财富等级: 富可敌国

发表于 2013-6-7 01:09:52 | 显示全部楼层
这基本上就不用测试了

评分

参与人数 1D豆 -4 收起 理由
XDSoft -4 影响不好!

查看全部评分

论坛插件加载方法
发帖求助前要善用【论坛搜索】功能,那里可能会有你要找的答案;
如果你在论坛求助问题,并且已经从坛友或者管理的回复中解决了问题,请把帖子标题加上【已解决】;
如何回报帮助你解决问题的坛友,一个好办法就是给对方加【D豆】,加分不会扣除自己的积分,做一个热心并受欢迎的人!
回复 支持 反对

使用道具 举报

已领礼包: 5679个

财富等级: 富甲天下

发表于 2013-6-7 08:15:39 | 显示全部楼层
判断点PT1与点PT2、误差精度为FUZZ(一个实数)是否相等,可用:
(equal pt1 pt2 fuzz)
如:(equal '(1.01 2.01 3.01) '(1.02 2.02 3.02) 0.5)   返回T
论坛插件加载方法
发帖求助前要善用【论坛搜索】功能,那里可能会有你要找的答案;
如果你在论坛求助问题,并且已经从坛友或者管理的回复中解决了问题,请把帖子标题加上【已解决】;
如何回报帮助你解决问题的坛友,一个好办法就是给对方加【D豆】,加分不会扣除自己的积分,做一个热心并受欢迎的人!
回复 支持 反对

使用道具 举报

发表于 2013-6-7 08:43:37 | 显示全部楼层

  1. ...
  2. (while lst
  3.     (setq n (car lst))
  4.     (setq L (cons n L))
  5.     (while
  6.       (and
  7.         (cadr lst)
  8.         (equal (car lst) (cadr lst) tol)
  9.       )
  10.       (setq lst (cdr lst))
  11.     )
  12.     (setq lst (cdr lst))
  13.   )
  14. ...

==>
改成这样,可以少运算几次
  1. ...
  2. (while lst
  3.   (setq L   (cons (setq n (car lst)) L)
  4.         lst (cdr lst)
  5.         )
  6.   (while
  7.     (and
  8.       lst
  9.       (equal (car lst) n tol)
  10.       )
  11.      (setq lst (cdr lst))
  12.      )
  13.   )
  14. ...

点评

虽然是很小的改进(能提高一点点效率),但这种精益求精的态度很好。  发表于 2013-6-7 10:04
论坛插件加载方法
发帖求助前要善用【论坛搜索】功能,那里可能会有你要找的答案;
如果你在论坛求助问题,并且已经从坛友或者管理的回复中解决了问题,请把帖子标题加上【已解决】;
如何回报帮助你解决问题的坛友,一个好办法就是给对方加【D豆】,加分不会扣除自己的积分,做一个热心并受欢迎的人!
回复 支持 反对

使用道具 举报

发表于 2013-6-7 09:37:17 | 显示全部楼层
本帖最后由 wowan1314 于 2013-6-7 09:43 编辑

我原来是这么写的!
  1. (defun YY:PTSCF (PTS ZZ / A B)
  2.   (SETQ A NIL)
  3.   (foreach B PTS
  4.     (if (vl-member-if '(lambda(x) (equal X B ZZ)) A)
  5.       NIL
  6.       (setq A (CONS B A))
  7.     )
  8.   )
  9.   A
  10. )
改成mapcar的
  1. (defun PTSCF (PTS ZZ / A B)
  2.   (SETQ A NIL)
  3.   (mapcar '(lambda(b)
  4.     (if (vl-member-if '(lambda(x) (equal X B ZZ)) A)
  5.       NIL
  6.       (setq A (CONS B A))
  7.     )
  8.   )
  9. pts)
  10.   A
  11. )
论坛插件加载方法
发帖求助前要善用【论坛搜索】功能,那里可能会有你要找的答案;
如果你在论坛求助问题,并且已经从坛友或者管理的回复中解决了问题,请把帖子标题加上【已解决】;
如何回报帮助你解决问题的坛友,一个好办法就是给对方加【D豆】,加分不会扣除自己的积分,做一个热心并受欢迎的人!
回复 支持 反对

使用道具 举报

发表于 2013-6-7 10:07:30 | 显示全部楼层
本帖最后由 wowan1314 于 2013-6-7 10:11 编辑

还是按楼主给的样本来测试好些。 避免样本上的差别.1的测试时间24.3秒。2的测试时间0.28秒。    时间差将近百倍。
  1. ;;测试
  2. (DEFUN C:1 ( / SS PTS T1 T2 LST)
  3. (SETQ SS (SSGET) LST (YY:SS2LST SS))
  4. (setq pts (mapcar '(lambda(x) (dxf_read 10 x)) lst))
  5. (SETQ T1 (get-utime))
  6. (DEL-CF1 PTS 0.01)
  7. (SETQ T2 (get-utime))
  8. (PRINC "\nmapcar方法:")
  9. (PRINC (- T2 T1))
  10. (PRINC "S")
  11. (PRINC)
  12. )
  13. ;;测试
  14. (DEFUN C:2 ( / SS PTS T1 T2 LST)
  15. (SETQ SS (SSGET) LST (YY:SS2LST SS))
  16. (setq pts (mapcar '(lambda(x) (dxf_read 10 x)) lst))
  17. (SETQ T1 (get-utime))
  18. (RemoveDup PTS 0.01)
  19. (SETQ T2 (get-utime))
  20. (PRINC "\n高飞鸟-方法:")
  21. (PRINC (- T2 T1))
  22. (PRINC "S")
  23. (PRINC)
  24. )

点评

所以说, 算法是基础,数据结构是桥梁。  详情 回复 发表于 2013-6-7 11:06
论坛插件加载方法
发帖求助前要善用【论坛搜索】功能,那里可能会有你要找的答案;
如果你在论坛求助问题,并且已经从坛友或者管理的回复中解决了问题,请把帖子标题加上【已解决】;
如何回报帮助你解决问题的坛友,一个好办法就是给对方加【D豆】,加分不会扣除自己的积分,做一个热心并受欢迎的人!
回复 支持 反对

使用道具 举报

已领礼包: 8125个

财富等级: 富甲天下

发表于 2013-6-7 10:11:30 | 显示全部楼层
如果点只是平面上的点,可以进一步改进改进,在排序的时候,少作一次比较。
[pcode=lisp,true];;;参数 Lst----点集
;;;     tol----容差
;;;example:
;;;(setq lst '((1235 255 140) (1258 230 150) (1258 230 150) (1263 262 160)))
;;;(setq lst (removeDup lst 0.))
(defun RemoveDup (lst Tol / Ret n)
  (setq
    lst
    (vl-sort
      lst
      (function
        (lambda (pt1 pt2)
          (if (equal (car pt1) (car pt2) tol)
            (< (cadr pt1) (cadr pt2))
            (< (car pt1) (car pt2))
          )
        )
      )
    )
  )
  (while lst
    (setq Ret (cons (setq n (car lst)) Ret)
          lst (cdr lst)
    )
    (while (and lst (equal (car lst) n tol))
      (setq lst (cdr lst))
    )
  )
  (reverse Ret)
)[/pcode]

点评

你第一次给出的函数就是快!  发表于 2013-6-8 22:16
经测试,还是第一次给出的快![b]  发表于 2013-6-8 22:14
论坛插件加载方法
发帖求助前要善用【论坛搜索】功能,那里可能会有你要找的答案;
如果你在论坛求助问题,并且已经从坛友或者管理的回复中解决了问题,请把帖子标题加上【已解决】;
如何回报帮助你解决问题的坛友,一个好办法就是给对方加【D豆】,加分不会扣除自己的积分,做一个热心并受欢迎的人!
回复 支持 反对

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

QQ|申请友链|Archiver|手机版|小黑屋|辽公网安备|晓东CAD家园 ( 辽ICP备15016793号 )

GMT+8, 2025-9-28 12:58 , Processed in 0.388553 second(s), 73 queries , Gzip On.

Powered by Discuz! X3.5

© 2001-2025 Discuz! Team.

快速回复 返回顶部 返回列表