明经CAD社区

 找回密码
 注册

QQ登录

只需一步,快速开始

搜索
查看: 4254|回复: 17

[讨论] 关于多个点是否共直线

[复制链接]
发表于 2013-12-9 03:36:24 | 显示全部楼层 |阅读模式
本帖最后由 llsheng_73 于 2014-11-8 04:20 编辑

关于三个点是否共直线有很多种算法,我能想到的有以下几种
1。角度比较:由于三个点p1,p2,p3不一定按顺序,所以可以比较p1p2,p1p3计算出的角度是否相等或者相差180度
2。夹角比较:以中间一点为起点求出夹角看它是否等于180度或者不找中间一点直接计算出两个角度来计算夹角不管它是0还是180都共线,不过比较第一个方法来,总之这个减法计算是多余的,还得对负数进行处理或者判断里边再加上-180度
3。长度比较:计算出三个边长排好序,是否两边和等于第三边
4。计算1个点到另两个点的垂距,看它是否等于0
5。计算它们的面积是否等于0
6。把这三个点交给CAD让它绘圆,如果绘制不出来就共直线(这个办法是临时想到的)

由三个点是否共线想到多于3个点怎么判断它们是否共线?
对于这个我想到的办法就少了
1。角度比较好象也比较直观
2。夹角比较
3.长度比较,要防止所用来计算距离的点跨越点
4.计算面积,虽然点太多了这个计算量会很大,但可以交给CAD,把这些点绘制成一根最短的不闭合多线段,如果面积为0就共线
5.还是把问题交给CAD,用POINT绘制出所有的点,找出距离最大的两个点(或者直接计算两个足够远点更快些也可能,点比较多的话)用它们进行ssget"F"看能否选中所有点
6.用最大距离的两个点绘制一条线段(其实要不要绘制出来都不影响),计算其余点到这条线的距离
以上是我能想到的办法,至于哪个最快最有效还不得而知,个人觉得第5个办法最简单也最奇特,但是如果点太多可能就不太合适了,最后一个办法可能更有用,第3、4两个办法都需要对点先进行排序(比如按到长度最大的两个点的其中之一距离进行排序),总之比较麻烦

不知道各位高手的更好的招数舍不舍得分享出来,就算不想分享你的高招也请选出你认为最可行或者最有效的方法并说明你的理由先谢谢各位了哈

  1. (defun CK:ColineP(ptlst / a);;ptlst坐标点表(第二维以后被忽略,可以所有点坐标相同也可以前几个点相同
  2.   (if(and(=(type ptlst)'list)
  3.            (=(type(car ptlst))'list)
  4.            (apply'and(apply'append(mapcar'(lambda(x)(cons(>(length x)1)(mapcar'(lambda(x)(member(type x)'(real int)))x)))ptlst))))
  5.     ;;;最后一项检查的后边很大程度上不是必须的,因为坐标点通常直接根据图元提取或者屏幕点击,这里只是顺便写出来
  6.     ;;;前两项检查是必须的,不然(CK:ColineP nil)也会返回真,一个点说它共线勉强可以说得过去,但空表共线这说不通,所以加上这两项检查
  7.     (setq a(car ptlst)
  8.     ptlst(vl-remove a ptlst)
  9.     a(mapcar'- a(car ptlst))
  10.     a(apply'and(mapcar'(lambda(x)(equal(cadr(trans x 0 a))0 1e-8))ptlst)))
  11.     )
  12.   )


此问题讨论了近一年,得到众多坛友的关注,Gu_xl版主 、vormittagedataxyp1964 院长、wowan1314自贡黄明儒 等众多高手提供思路和算法,最终采用了vormittag 构建直线坐标系的方法,加入数据检查后完成该函数,在此贴出对众多坛友的关注表示感谢
当然,此算法由于取前两个不同的点构建直线坐标系,有可能因为这两个点距离过小产生计算误差,导致同样的坐标点因为点的顺序而产生二义性,因此最终版本应该取最远的两个点来构建直线坐标系,这个等有了时间再加上



"觉得好,就打赏"
还没有人打赏,支持一下
 楼主| 发表于 2013-12-9 05:00:10 | 显示全部楼层
本帖最后由 llsheng_73 于 2013-12-9 05:01 编辑

泡杯茶坐点支烟在沙发上等你的见解哟

点评

15楼 我写了个,请测试看看是否通用!  发表于 2014-11-7 18:52
发表于 2013-12-9 08:15:02 | 显示全部楼层
解决问题是关键,三点没有交点,不就在一条直线上了?这个有讨论的必要吗?
发表于 2013-12-9 09:19:53 | 显示全部楼层
任选两点计算向量,把所有点坐标trans 到以该向量为法向量的对象坐标系,如果trans后的所有点 x y 坐标在允许的误差之内均一致,n点共线,否则不共线。
发表于 2013-12-9 09:24:09 | 显示全部楼层
代码如下:
  1. (defun CK:ColineP (ptlst / linenormal templst firstpt)
  2.         (setq linenormal (mapcar '- (car ptlst) (cadr ptlst))
  3.                 templst (mapcar '(lambda(x) (mapcar '+ '(0.0 0.0) (trans x 0 linenormal))) ptlst)
  4.                 firstpt (car templst)
  5.                 templst (apply 'append (mapcar '(lambda(x) (mapcar '- x firstpt)) templst)))
  6.         (apply 'and (mapcar '(lambda(x) (equal 0.0 x 1e-8)) templst)))

点评

现在才看懂(mapcar'+'(0 0)....)的目的是取坐标的前两维....学习了  发表于 2014-11-8 02:48
感觉很不错的一个办法,晕,这里不能加分的么?  发表于 2013-12-9 09:56

评分

参与人数 2明经币 +2 金钱 +10 收起 理由
llsheng_73 + 1 + 10 学习了
edata + 1 很给力!

查看全部评分

发表于 2013-12-9 09:30:58 | 显示全部楼层
vormittag 发表于 2013-12-9 09:24
代码如下:

代码太长、太复杂
发表于 2013-12-9 21:41:08 | 显示全部楼层
,三角形法则应该适用。另外有这个
计算几何算法概览
http://bbs.mjtd.com/forum.php?mo ... &fromuid=338795

 
发表于 2013-12-9 23:01:38 | 显示全部楼层
直接转换坐标,用前2个点定义x轴,查看第点的y坐标,r如果是0就表示共线
(command "ucs" pt1 (trans pt2 0 1) "@0,1")
(if (= (nth 1 (trans pt3 0 1)) 0)

点评

和5楼的办法是一样的  发表于 2013-12-10 08:47
发表于 2013-12-10 00:36:47 | 显示全部楼层
  1. (defun aaa (ptn / s1 mode i pt)
  2.   (entmake (list '(0 . "line")(cons 10 (car ptn))(cons 11 (cadr ptn))))
  3.   (setq s1   (entlast)
  4.         mode t
  5.         i    0
  6.   )
  7.   (while (and mode (setq pt (nth i ptn)))
  8.     (if (> (distance (vlax-curve-getclosestpointto s1 pt t) pt) 0)
  9.       (setq mode nil)
  10.       (setq i (1+ i))
  11.     )
  12.   )
  13.   (entdel s1)
  14.   mode
  15. )

点评

感谢院长的关注,我说院长能不能把排序32式放出来,看了那个32式再也不想弄排序了,只想等院长大人开放它  发表于 2013-12-10 08:38
发表于 2013-12-10 10:42:52 | 显示全部楼层
  1. (defun ListColinear-p  (lst / ColinearP)
  2.   (defun ColinearP  (p1 p2 p3)
  3.     (
  4.      (lambda (a b c)
  5.        (or
  6.          (equal (+ a b) c 1e-8)
  7.          (equal (+ b c) a 1e-8)
  8.          (equal (+ c a) b 1e-8)
  9.          )
  10.        )
  11.       (distance p1 p2)
  12.       (distance p2 p3)
  13.       (distance p1 p3)
  14.       )
  15.     )
  16.   (or (null (cddr lst))
  17.       (not
  18.         (vl-some
  19.           '(lambda (a) (not (ColinearP (car lst) (cadr lst) a)))
  20.           (cddr lst)
  21.           )
  22.         )
  23.       )
  24.   )
您需要登录后才可以回帖 登录 | 注册

本版积分规则

小黑屋|手机版|CAD论坛|CAD教程|CAD下载|联系我们|关于明经|明经通道 ( 粤ICP备05003914号 )  
©2000-2023 明经通道 版权所有 本站代码,在未取得本站及作者授权的情况下,不得用于商业用途

GMT+8, 2025-5-23 21:08 , Processed in 0.208342 second(s), 28 queries , Gzip On.

Powered by Discuz! X3.4

Copyright © 2001-2021, Tencent Cloud.

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