明经CAD社区

 找回密码
 注册

QQ登录

只需一步,快速开始

搜索
查看: 1441|回复: 4

依据平面四参数变换图形

  [复制链接]
发表于 2020-8-28 17:41:41 | 显示全部楼层 |阅读模式
本帖最后由 hothua2020 于 2020-8-28 22:06 编辑

最近写的一个图形变换程序,上传源码供大家参考和提出修改意见。因为我的应用目标主要是地形图方面的坐标变换,其拉扯缩放比例和角度都不大。对于图块插入点与块实际图形范围距离很大的情况,我的转换程序比CASS10.1效果好。借用网络上高手的一些函数,特别是Lee Mac的。

  1. ;; TRP
  2. ;; Transpose a matrix -Doug Wilson-
  3. (defun trp (m) (apply 'mapcar (cons 'list m)))
  4. ;; MXV
  5. ;; Apply a transformation matrix to a vector -Vladimir Nesterovsky-
  6. (defun mxv (m v)
  7.     (mapcar (function (lambda (r) (apply '+ (mapcar '* r v))))
  8.             m
  9.     )
  10. )
  11. ;; MXM
  12. ;; Multiply two matrices -Vladimir Nesterovsky-
  13. (defun mxm (m q)
  14.   (mapcar (function (lambda (r) (mxv (trp q) r))) m)
  15. )  
  16. ;;;
  17. ;;--------------------=={ Inverse Matrix }==------------------;;
  18. ;;                                                            ;;
  19. ;;  Implements the Gauss-Jordan Elimination algorithm to      ;;
  20. ;;  inverse a non-singular nxn matrix.                        ;;
  21. ;;------------------------------------------------------------;;
  22. ;;  Author: Lee Mac, Copyright ? 2011 - www.lee-mac.com       ;;
  23. ;;------------------------------------------------------------;;
  24. ;;  Arguments: m - nxn Matrix                                 ;;
  25. ;;------------------------------------------------------------;;
  26. ;;  Returns:  Matrix inverse, or nil if matrix is singular    ;;
  27. ;;------------------------------------------------------------;;
  28. (defun LM:InverseMatrix ( m / _identity _eliminate p r x )

  29.   (defun _identity ( n / i j l m ) (setq i 1)
  30.     (repeat n (setq j 0)
  31.       (repeat n
  32.         (setq l (cons (if (= i (setq j (1+ j))) 1. 0.) l))
  33.       )
  34.       (setq m (cons l m) l nil i (1+ i)) m
  35.     )
  36.   )

  37.   (defun _eliminate ( m p )
  38.     (mapcar
  39.       (function
  40.         (lambda ( x / d )
  41.           (setq d (car x)) (mapcar (function (lambda ( a b ) (- a (* d b)))) (cdr x) p)
  42.         )
  43.       )
  44.       m
  45.     )
  46.   )
  47.   (setq m (mapcar 'append m (_identity (length m))))
  48.   
  49.   (while m
  50.     (setq p (apply 'max (mapcar 'abs (mapcar 'car m))))
  51.     (while (not (equal p (abs (caar m)) 1e-14))
  52.       (setq m (append (cdr m) (list (car m))))
  53.     )
  54.     (if (equal 0.0 (caar m) 1e-14)
  55.       (setq m nil)
  56.       (setq p (/ 1. (caar m))
  57.             p (mapcar (function (lambda ( x ) (* p x))) (cdar m))
  58.             m (_eliminate (cdr m) p)
  59.             r (cons p (_eliminate r p))
  60.       )
  61.     )
  62.   )
  63.   (reverse r)
  64. )

  65. ;; 2D Projection: Unique with Fuzz  -  Lee Mac
  66. ;; Returns a list with all elements considered duplicate to a given tolerance removed.
  67. (defun 2dprojection:uniquefuzz ( lst fuz )
  68.     (if lst
  69.         (cons (car lst)
  70.             (2dprojection:uniquefuzz
  71.                 (vl-remove-if
  72.                     (function (lambda ( x ) (equal x (car lst) fuz)))
  73.                     (cdr lst)
  74.                 )
  75.                 fuz
  76.             )
  77.         )
  78.     )
  79. )

  80. ;; 2D Projection: Check Collinearity  -  Lee Mac
  81. ;; Returns T if any three points in a supplied list are collinear.

  82. (defun 2dprojection:checkcollinearity ( lst )
  83.     (and (caddr lst)
  84.         (or (   (lambda ( a b c )
  85.                     (or (equal (+ a b) c 1e-8)
  86.                         (equal (+ b c) a 1e-8)
  87.                         (equal (+ c a) b 1e-8)
  88.                     )
  89.                 )
  90.                 (distance (car  lst) (cadr  lst))
  91.                 (distance (cadr lst) (caddr lst))
  92.                 (distance (car  lst) (caddr lst))
  93.             )
  94.             (2dprojection:checkcollinearity (cdr lst))
  95.         )
  96.     )
  97. )

  98. ;; 2D Projection: Clockwise-p  -  Lee Mac
  99. ;; Returns T if the supplied point list is clockwise oriented.

  100. (defun 2dprojection:clockwise-p ( lst )
  101.     (minusp
  102.         (apply '+
  103.             (mapcar
  104.                 (function
  105.                     (lambda ( a b )
  106.                         (- (* (car b) (cadr a)) (* (car a) (cadr b)))
  107.                     )
  108.                 )
  109.                 lst (cons (last lst) lst)
  110.             )
  111.         )
  112.     )
  113. )
  114. ;; 2D Projection: Get Reference Frame  -  Lee Mac
  115. ;; Prompts the user to select a closed planar polyline with 4 vertices in
  116. ;; order to obtain 4 counter-clockwise oriented non-collinear points
  117. ;; defining a reference frame for the transformation.
  118. (defun 2dprojection:getreferenceframe ( msg / ent enx lst tmp )
  119.     (while
  120.         (progn (setvar 'errno 0) (setq ent (car (entsel msg)))
  121.             (cond
  122.                 (   (= 7 (getvar 'errno))
  123.                     (princ "\n错误,重试.")
  124.                 )
  125.                 (   (null ent) nil)
  126.                 (   (or (/= "LWPOLYLINE" (cdr (assoc 0 (setq enx (entget ent)))))
  127.                         (zerop (logand 1 (cdr (assoc 70 enx))))
  128.                         (/= 4 (cdr (assoc 90 enx)))
  129.                         (/= 4 (length (setq lst (2dprojection:uniquefuzz (mapcar 'cdr (vl-remove-if-not '(lambda ( x ) (= 10 (car x))) enx)) 1e-8))))
  130.                         (2dprojection:checkcollinearity (cons (last lst) lst))
  131.                     )
  132.                     (setq lst nil)
  133.                     (princ "\n请选择闭合的4点POLYLINE线.")
  134.                 )
  135.             )
  136.         )
  137.     )
  138.     (if lst
  139.         (progn
  140.             (if (2dprojection:clockwise-p lst)
  141.                 (setq lst (reverse lst))
  142.             )
  143.             (setq tmp (apply 'mapcar (cons 'min lst)))
  144.             (repeat (car (vl-sort-i lst '(lambda ( a b ) (< (distance a tmp) (distance b tmp)))))
  145.                 (setq lst (append (cdr lst) (list (car lst))))
  146.             )
  147.             lst
  148.         )
  149.     )
  150. )
  151. ;;------------=={ SelectionSet -> VLA Objects }==-------------;;
  152. ;;                                                            ;;
  153. ;;  Converts a SelectionSet to a list of VLA Objects          ;;
  154. ;;------------------------------------------------------------;;
  155. ;;  Author: Lee Mac, Copyright ? 2011 - www.lee-mac.com       ;;
  156. ;;------------------------------------------------------------;;
  157. ;;  Arguments:                                                ;;
  158. ;;  ss - Valid SelectionSet (Pickset)                         ;;
  159. ;;------------------------------------------------------------;;
  160. ;;  Returns:  List of VLA Objects, else nil                   ;;
  161. ;;------------------------------------------------------------;;
  162. (defun LM:ss->vla ( ss / i l )
  163.     (if ss
  164.         (repeat (setq i (sslength ss))
  165.             (setq l (cons (vlax-ename->vla-object (ssname ss (setq i (1- i)))) l))
  166.         )
  167.     )
  168. )
  169. ;;;
  170. ;;;主执行程序
  171. (defun c:2dTrans(/ FourParam->Matrix ss src des minx miny pt11 pt12 pt13 pt14 pt21 pt22 pt23 pt24 matL matB matBT matX dx dy a b dxys fdx fdy)
  172.     ;;;
  173.   ;;;平面四参数->CAD图形转换矩阵
  174.   ;;;本来应没有minx miny,但是我使用最小二乘法计算转换参数失真,测试降低坐标值结果较好,所以多了先将图形平移到0轴附近在计算参数的多于过程,变换矩阵也就多了minx,miny两个参数
  175.   (defun FourParam->Matrix(dx dy ang scl minx miny / )
  176.     (list (list (* (cos ang) scl) (* (sin ang) scl -1.) 0. (- (+ dx minx (* (sin ang) scl miny)) (* (cos ang) scl minx)))  
  177.            (list (* (sin ang) scl) (* (cos ang) scl) 0. (- (+ dy miny) (* (sin ang) scl minx) (* (cos ang) scl miny)))
  178.          (list 0. 0. scl 0.0)
  179.          '(0. 0. 0. 1.)
  180.       )
  181.   )
  182.   (print "请选择待变换图形")
  183.   (setq ss (ssget))
  184.   (if ss (progn
  185.      (setq src (2dprojection:getreferenceframe "\n请选择源边界: "))
  186.          (setq des (2dprojection:getreferenceframe "\n请选择目标边界: "))
  187.      ;(mapcar '(lambda(x) (print (strcat (rtos (car x) 2 20) "," (rtos (cadr x) 2 20)))) src)
  188.      ;(mapcar '(lambda(x) (print (strcat (rtos (car x) 2 20) "," (rtos (cadr x) 2 20)))) des)
  189.      ;;;矩阵运算数值较大结果失真,所以将坐标减去一个最小值
  190.     (setq minx (caar src) miny (cadar src))
  191.     (mapcar '(lambda(pt) (setq minx (min minx (car pt)) miny (min miny (cadr pt)))) src)
  192.     (mapcar '(lambda(pt) (setq minx (min minx (car pt)) miny (min miny (cadr pt)))) des)
  193.     (setq src (mapcar '(lambda(pt) (list (- (car pt) minx) (- (cadr pt) miny))) src))
  194.     (setq des (mapcar '(lambda(pt) (list (- (car pt) minx) (- (cadr pt) miny))) des))
  195.     ;;;太多的car或者nth太麻烦,试着用mapcar构造矩阵又没搞定,只好用变量
  196.     (mapcar 'set (list 'pt11 'pt12 'pt13 'pt14) src)
  197.     (mapcar 'set (list 'pt21 'pt22 'pt23 'pt24) des)
  198.   
  199.     (setq  matL    (list (list (- (car pt21)(car pt11))) (list (- (cadr pt21)(cadr pt11)))
  200.                   (list (- (car pt22)(car pt12))) (list (- (cadr pt22)(cadr pt12)))
  201.                   (list (- (car pt23)(car pt13))) (list (- (cadr pt23)(cadr pt13)))
  202.                   (list (- (car pt24)(car pt14))) (list (- (cadr pt24)(cadr pt14)))
  203.             )                           
  204.          matB      (list (list 1. 0. (car pt11) (- 0 (cadr pt11))) (list 0. 1. (cadr pt11) (car pt11))
  205.                           (list 1. 0. (car pt12) (- 0 (cadr pt12))) (list 0. 1. (cadr pt12) (car pt12))
  206.                   (list 1. 0. (car pt13) (- 0 (cadr pt13))) (list 0. 1. (cadr pt13) (car pt13))
  207.                   (list 1. 0. (car pt14) (- 0 (cadr pt14))) (list 0. 1. (cadr pt14) (car pt14))
  208.               )
  209.         matBT     (trp matB)
  210.         matX      (mxm (LM:InverseMatrix (mxm matBT matB)) (mxm matBT matL))      
  211.     )
  212.     (mapcar 'set (list 'dx 'dy 'a  'b) (mapcar '(lambda(x) (car x))  matX))  
  213.   
  214.     (setq   ang (atan (/ b (1+ a)))
  215.         k   (sqrt (+ (* (1+ a) (1+ a)) (* b b)))              
  216.         matX (vlax-tmatrix (FourParam->Matrix dx dy ang k minx miny))   
  217.     )   
  218.     (foreach obj (LM:ss->vla ss)      
  219.       (vla-transformby  obj  matX)  
  220.         )     
  221.   ))
  222. )
  223. (vl-load-com)
  224. (print "键入2dTrans命令运行")
  225. (princ)


本帖子中包含更多资源

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

x
发表于 2020-8-28 18:47:47 | 显示全部楼层
谢谢大神的分享,请问可不可以加一个演示方式呢,,小白看不懂代码,对字面意思也不太理解呢
 楼主| 发表于 2020-8-28 21:18:10 | 显示全部楼层
我也是一个学习的,最近这个程序也是学了highflybir很多帖子,也看了些LEE MAC的代码,写出来分享的。我学学如何录Gif再发
发表于 2020-9-7 14:41:35 | 显示全部楼层
感谢楼主分享下载试试!
发表于 2020-11-11 20:56:20 | 显示全部楼层
您需要登录后才可以回帖 登录 | 注册

本版积分规则

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

GMT+8, 2024-11-29 01:36 , Processed in 0.269228 second(s), 25 queries , Gzip On.

Powered by Discuz! X3.4

Copyright © 2001-2021, Tencent Cloud.

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