本帖最后由 dtucad 于 2023-9-11 23:13 编辑

利用向量求点到直线垂足的坐标,可用于三维
没啥技术含量,向量入门知识,希望对新手有用。
水平有限,如有错误,请不吝指正。

  1. ;利用向量求点到直线垂足的坐标
  2. ;参数1:直线起点、终点
  3. ;参数2:直线外一点
  4. ;返回值:点到直线垂足的坐标
  5. (defun footcoord (p1 p2 cp / dis dot-product foot projection v-p v-w)
  6.   (setq v-w (mapcar '- p2 p1));向量p1-p2
  7.   (setq v-p (mapcar '- cp p1));向量p1-cp
  8.   ;计算点到直线的投影比例
  9.   (setq dot-product (+ (* (car v-p) (car v-w)) (* (cadr v-p) (cadr v-w)) (* (caddr v-p) (caddr v-w))));点乘
  10.   (setq dis (distance p1 p2))
  11.   (setq projection (/ dot-product (expt dis 2)))
  12.   (setq foot (list (+ (car p1) (* (car v-w) projection)) (+ (cadr p1) (* (cadr v-w) projection)) (+ (caddr p1) (* (caddr v-w) projection))));求垂足的坐标
  13. )

  14. ;测试用
  15. (defun c:tt (/ cp dis p1 p2 pt)
  16.   (if (and
  17.         (setq p1 (getpoint "\n指定直线起点"))
  18.         (setq p2 (getpoint p1 "\n指定直线终点"))
  19.         (setq cp (getpoint "\n指定直线外一点"))
  20.       )
  21.     (progn
  22.       (setq pt (footcoord p1 p2 cp))
  23.       (princ "\n点到直线的垂足坐标为:")(princ pt)
  24.     )
  25.   )
  26.   (princ)
  27. )




网友答: ;; 获取点到直线的垂足
(defun FootPoint (P P1 P2 / V)
  (setq V  (mapcar '- P2 P1)
        P1 (trans P1 0 V)
  )
  (trans (vl-list* (car P1) (cadr P1) (cddr (trans P 0 V))) V 0)
)

网友答: 本帖最后由 dtucad 于 2023-9-12 13:14 编辑

谢谢大佬的优化建议,下次手动优化一下(gpt的码确实不够简洁,但是整体流程还是非常清晰),谢谢大佬

  1. ;利用向量求点到直线垂足的坐标
  2. ;参数1:直线起点、终点
  3. ;参数2:直线外一点
  4. ;返回值:点到直线垂足的坐标
  5. (defun footcoord (p1 p2 cp / dis dot-product foot projection v-p v-w)
  6.   (setq v-w (mapcar '- p2 p1));向量p1-p2
  7.   (setq v-p (mapcar '- cp p1));向量p1-cp
  8.   ;计算点到直线的投影比例
  9.   
  10.   ;(setq dot-product (+ (* (car v-p) (car v-w)) (* (cadr v-p) (cadr v-w)) (* (caddr v-p) (caddr v-w))));点乘
  11.   (setq dot-product (apply '+ (mapcar '* v-w v-p)));点乘
  12.   (setq dis (distance p1 p2))
  13.   (setq projection (/ dot-product (expt dis 2)))
  14.   ;(setq foot (list (+ (car p1) (* (car v-w) projection)) (+ (cadr p1) (* (cadr v-w) projection)) (+ (caddr p1) (* (caddr v-w) projection))));求垂足的坐标
  15.   (mapcar '(lambda (x y)(+ x (* y projection))) p1 v-w);求垂足的坐标
  16. )





网友答:
vormittag 发表于 2023-9-17 19:40
如果垂足不在曲线上,找到的就是曲线比较近的端点。比如直线两点是 (-1,0) 和 (1,0),点 P 是 (5,3),得 ...

(vlax-curve-getClosestPointTo curve givenPnt [extend])

功能
    返回曲线上离指定点最近的点(在 WCS 上)。

说明
1)参数 curve为要测量的对象。
2)参数 givenPnt 为点(在 WCS 上),寻找曲线上距该点最近的点。
3)参数 extend 若指定该参数且其值不为 nil,那么 vlax-curve-getClosestPointTo  在搜索最近点时扩展曲线。

网友答: 代码太复杂了

网友答: 本帖最后由 xyp1964 于 2023-9-17 21:03 编辑

  1. (defun PtPer2Pt (p0 p1 p2 / s1 pt)
  2.   "点到两点的垂足"
  3.   (command "line" "non" p1 "non" p2 "")
  4.   (setq pt (vlax-curve-getclosestpointto (setq s1 (entlast)) p0 t)); 参数 t 在搜索最近点时扩展曲线
  5.   (entdel s1)
  6.   pt
  7. )


网友答: 院长 这样最快(getdist)

网友答:
dtucad 发表于 2023-9-12 22:29
院长 这样最快(getdist)

(getdist)完全两码事

网友答: 本帖最后由 dtucad 于 2023-9-12 22:46 编辑

vlax-curve-getclosestpointto的实现原理倒是可以研究一下
大量程序运算 为了节省代码 还去画线 本末倒置了
可能一会又有人说用trans了 好吧好吧 轮子最香 我爱轮子


网友答: 另一个思路
  1. (defun get-perp_pt (pt p1 p2 / vec);
  2.   (setq vec (mapcar '- p2 p1))
  3.   (inters pt (mapcar '+ pt (vl-list* (- (cadr vec)) (car vec) (cddr vec))) p1 p2 nil)
  4. )


网友答: vlax-curve-getclosestpointto 在很多情况下得到的不是垂足,说不定是一个端点。

网友答:
vormittag 发表于 2023-9-14 17:11
vlax-curve-getclosestpointto 在很多情况下得到的不是垂足,说不定是一个端点。

如果垂足不在曲线上,找到的就是曲线比较近的端点。比如直线两点是 (-1,0) 和 (1,0),点 P 是 (5,3),得到的点不是(5,0) 而是 (1,0)
  • 上一篇:自动打包、编译、备份、加密lisp源码!
  • 下一篇:没有了