乐筑天下

搜索
欢迎各位开发者和用户入驻本平台 尊重版权,从我做起,拒绝盗版,拒绝倒卖 签到、发布资源、邀请好友注册,可以获得银币 请注意保管好自己的密码,避免账户资金被盗
查看: 26|回复: 19

[编程交流] 由质心偏移-需要帮助

[复制链接]

11

主题

35

帖子

28

银币

初露锋芒

Rank: 3Rank: 3Rank: 3

铜币
53
发表于 2022-7-6 12:21:14 | 显示全部楼层 |阅读模式
我试图在用户选择的一组多条直线内自动创建多段线(注意:直线始终在端点相交,因此此处不包含错误检查,但应在某个点添加错误检查)。
 
它调用了我在这里找到的get centroid函数(以获取要偏移的边):
问题是,它会提示我选择要作为中心的多段线(在get-centroid函数中应该这样做),但我希望将变量“last”传递给它,而不是提示。不管我做什么,我都不能让它工作。如果我实际键入“l”,它将选择创建的多段线并继续,但我希望在选择初始线后自动执行。有什么想法吗?
回复

使用道具 举报

54

主题

3755

帖子

3583

银币

后起之秀

Rank: 20Rank: 20Rank: 20Rank: 20

铜币
438
发表于 2022-7-6 12:25:26 | 显示全部楼层
未经测试,但请尝试替换此行:
  1. (vla-getentity util 'plineObj 'pickPt "\nSelect a polyline:\n")

有了这个:
  1. (setq plineObj (vlax-ename->vla-object (entlast)))

 
我强烈建议您在质心子例程中定位变量。
回复

使用道具 举报

11

主题

35

帖子

28

银币

初露锋芒

Rank: 3Rank: 3Rank: 3

铜币
53
发表于 2022-7-6 12:28:53 | 显示全部楼层
非常好,谢谢。我不擅长vla命令,不知道该怎么办。再次感谢。
回复

使用道具 举报

15

主题

687

帖子

169

银币

中流砥柱

Rank: 25

铜币
582
发表于 2022-7-6 12:33:51 | 显示全部楼层
你好
 
这里有另一种获取多段线质心的方法(接受带弧段的多段线)。
根据我做的基准测试,它的运行速度大约是需要建模器的“区域声明”的3倍。
 
  1. ;; ALGEB-AREA
  2. ;; Returns the algebraic area of the triangle defined by three 2d points
  3. ;; the area is negative if points are clockwise
  4. (defun algeb-area (p1 p2 p3)
  5. (/ (-        (* (- (car p2) (car p1))
  6.    (- (cadr p3) (cadr p1))
  7. )
  8. (* (- (car p3) (car p1))
  9.    (- (cadr p2) (cadr p1))
  10. )
  11.     )
  12.     2.0
  13. )
  14. )
  15. ;; TRIANGLE-CENTROID
  16. ;; Returns the centroid of a triangle defined by 3 points
  17. (defun triangle-centroid (p1 p2 p3)
  18. (mapcar '(lambda (x1 x2 x3)
  19.      (/ (+ x1 x2 x3) 3.0)
  20.    )
  21.   p1
  22.   p2
  23.   p3
  24. )
  25. )
  26. ;; POLYARC-CENTROID
  27. ;; Returns a list which first item is the centroid of a 'polyarc'
  28. ;; and the second its algeraic area
  29. ;;
  30. ;; Arguments
  31. ;; bu : polyarc bulge
  32. ;; p1 : start point
  33. ;; p2 : end point
  34. (defun polyarc-centroid        (bu p1 p2 / ang rad cen area dist cg)
  35. (setq        ang  (* 2 (atan bu))
  36. rad  (/        (distance p1 p2)
  37.         (* 2 (sin ang))
  38.      )
  39. cen  (polar p1
  40.             (+ (angle p1 p2) (- (/ pi 2) ang))
  41.             rad
  42.      )
  43. area (/ (* rad rad (- (* 2 ang) (sin (* 2 ang)))) 2.0)
  44. dist (/ (expt (distance p1 p2) 3) (* 12 area))
  45. cg   (polar cen
  46.             (- (angle p1 p2) (/ pi 2))
  47.             dist
  48.      )
  49. )
  50. (list cg area)
  51. )
  52. ;; PLINE-CENTROID
  53. ;; Returns the WCS coordinates of a lwpolyline centroid
  54. ;;
  55. ;; Argument
  56. ;; pl : the lwpolyline ename
  57. (defun pline-centroid (pl / elst lst tot cen p0 area cen)
  58. (setq elst (entget pl))
  59. (while (setq elst (member (assoc 10 elst) elst))
  60.    (setq lst  (cons (cons (cdar elst) (cdr (assoc 42 elst))) lst)
  61.   elst (cdr elst)
  62.    )
  63. )
  64. (setq        lst (reverse lst)
  65. tot 0.0
  66. cen '(0.0 0.0)
  67. p0  (caar lst)
  68. )
  69. (if (/= 0 (cdar lst))
  70.    (setq p-c (polyarc-centroid (cdar lst) p0 (caadr lst))
  71.   cen (mapcar '(lambda (x) (* x (cadr p-c))) (car p-c))
  72.   tot (cadr p-c)
  73.    )
  74. )
  75. (setq lst (cdr lst))
  76. (if (equal (car (last lst)) p0 1e-9)
  77.    (setq lst (reverse (cdr (reverse lst))))
  78. )
  79. (while (cadr lst)
  80.    (setq area (algeb-area p0 (caar lst) (caadr lst))
  81.   cen  (mapcar '(lambda (x1 x2) (+ x1 (* x2 area)))
  82.                cen
  83.                (triangle-centroid p0 (caar lst) (caadr lst))
  84.        )
  85.   tot  (+ area tot)
  86.    )
  87.    (if        (/= 0 (cdar lst))
  88.      (setq p-c        (polyarc-centroid (cdar lst) (caar lst) (caadr lst))
  89.     cen        (mapcar        '(lambda (x1 x2) (+ x1 (* x2 (cadr p-c))))
  90.                 cen
  91.                 (car p-c)
  92.         )
  93.     tot        (+ tot (cadr p-c))
  94.      )
  95.    )
  96.    (setq lst (cdr lst))
  97. )
  98. (if (/= 0 (cdar lst))
  99.    (setq p-c (polyarc-centroid (cdar lst) (caar lst) p0)
  100.   cen (mapcar '(lambda (x1 x2) (+ x1 (* x2 (cadr p-c))))
  101.               cen
  102.               (car p-c)
  103.       )
  104.   tot (+ tot (cadr p-c))
  105.    )
  106. )
  107. (trans (list (/ (car cen) tot)
  108.        (/ (cadr cen) tot)
  109.        (cdr (assoc 38 (entget pl)))
  110. )
  111. pl
  112. 0
  113. )
  114. )
回复

使用道具 举报

11

主题

35

帖子

28

银币

初露锋芒

Rank: 3Rank: 3Rank: 3

铜币
53
发表于 2022-7-6 12:36:37 | 显示全部楼层
好吧,它又不起作用了。我不得不做一些调整,因为我发现如果您选择的原始线已经是多段线,该程序无法工作,因为它不会选择正确的最后一个图元(除非连接的多段线来自直线,否则它不会将连接的多段线视为最后一个)。
 
因此,我试图修改它,根本不使用last(而是将线发送到一个新层,由其属性选择)。出于某种原因,get centroid函数不接受我试图传递给它的值。
 
 
吉尔-我试过你的,但根本不起作用。我甚至注释掉了entget部分并将其编码为ssget,在手动选择后,它没有正常工作。
回复

使用道具 举报

15

主题

687

帖子

169

银币

中流砥柱

Rank: 25

铜币
582
发表于 2022-7-6 12:40:02 | 显示全部楼层
 
例行程序确实有效,您可以尝试以下方法:
但使用pline质心并不能确保在多段线内偏移。
多段线质心可能位于多段线之外:
132119ird33q1ognxn6xnf.png
回复

使用道具 举报

15

主题

687

帖子

169

银币

中流砥柱

Rank: 25

铜币
582
发表于 2022-7-6 12:41:26 | 显示全部楼层
使用闭合多段线的vla偏移功能可以确保“insde偏移”。
 
vla偏移函数的帮助文件说:
偏移对象的距离。偏移量可以是正数或负数,但不能等于零。如果偏移量为负数,则将其解释为生成“较小”曲线的偏移量。
 
对于闭合多段线,如果多段线为逆时针方向,则为真;如果多段线为顺时针方向,则为逆时针方向。
一种知道pline是否顺时针或逆时针的方法是计算其代数面积:负面积表示pline是顺时针的。
 
InsideOffset例程需要两个参数:多段线(ename或vla对象)和偏移距离(正实数)。
 
您可以使用:(InsideOffset(car(enstel)))进行测试
 
  1. ;; PLINE-ALGEBRAIC-AREA (gile)
  2. ;; Returns the algebraic area of the polyline
  3. ;; the area is negative if the polyline is clockwise
  4. ;;
  5. ;; Argument: a polyline ename
  6. (defun Pline-Algebraic-Area (pl / elst lst tot)
  7. (setq elst (entget pl))
  8. (while (setq elst (member (assoc 10 elst) elst))
  9.    (setq lst  (cons (cons (cdar elst) (cdr (assoc 42 elst))) lst)
  10.      elst (cdr elst)
  11.    )
  12. )
  13. (setq    lst (reverse lst)
  14.    tot 0.0
  15.    p0  (caar lst)
  16. )
  17. (if (/= 0 (cdar lst))
  18.    (setq tot (polyarc-algeb-area (cdar lst) p0 (caadr lst))
  19.    )
  20. )
  21. (setq lst (cdr lst))
  22. (if (equal (car (last lst)) p0 1e-9)
  23.    (setq lst (reverse (cdr (reverse lst))))
  24. )
  25. (while (cadr lst)
  26.    (setq tot  (+ (triangle-algeb-area p0 (caar lst) (caadr lst)) tot))
  27.    (if    (/= 0 (cdar lst))
  28.      (setq tot    (+ tot (polyarc-algeb-area (cdar lst) (caar lst) (caadr lst))))
  29.    )
  30.    (setq lst (cdr lst))
  31. )
  32. (if (/= 0 (cdar lst))
  33.    (setq tot (+ tot (polyarc-algeb-area (cdar lst) (caar lst) p0)))
  34. )
  35. tot
  36. )
  37. ;; TRIANGLE-ALGEB-AREA (gile)
  38. ;; Returns the algebraic area of the triangle defined by three 2d points
  39. ;; the area is negative if points are clockwise
  40. ;;
  41. ;; Arguments: three 2d points
  42. (defun triangle-algeb-area (p1 p2 p3)
  43. (/ (-    (* (- (car p2) (car p1))
  44.       (- (cadr p3) (cadr p1))
  45.    )
  46.    (* (- (car p3) (car p1))
  47.       (- (cadr p2) (cadr p1))
  48.    )
  49.     )
  50.     2.0
  51. )
  52. )
  53. ;; POLYARC-ALGEB-AREA (gile)
  54. ;; Returns the algeraic area of a 'polyarc'
  55. ;;
  56. ;; Arguments
  57. ;; bu : polyarc bulge
  58. ;; p1 : start point
  59. ;; p2 : end point
  60. (defun polyarc-algeb-area    (bu p1 p2 / ang rad)
  61. (setq    ang  (* 2 (atan bu))
  62.    rad  (/    (distance p1 p2)
  63.        (* 2 (sin ang))
  64.         )
  65. )
  66. (/ (* rad rad (- (* 2 ang) (sin (* 2 ang)))) 2.0)
  67. )
  68. ;; InsideOffset (gile)
  69. ;; Offset inside a closed polyline
  70. ;;
  71. ;; Arguments
  72. ;; pl: a polyline (ename or vla-object)
  73. ;; dist: offset distance
  74. ;;
  75. ;; Returns a variant
  76. ;; (an array of the newly created objects resulting from the offset).
  77. (defun InsideOffset (pl dist / obj)
  78. (vl-load-com)
  79. (if (= (type pl) 'ENAME)
  80.    (setq obj (vlax-ename->vla-object pl))
  81.    (setq obj pl
  82.          pl  (vlax-vla-object->ename obj)
  83.    )
  84. )
  85. (vla-offset obj
  86.              (if (minusp (Pline-Algebraic-Area pl))
  87.                dist
  88.                (- dist)
  89.              )
  90. )
  91. )
回复

使用道具 举报

54

主题

3755

帖子

3583

银币

后起之秀

Rank: 20Rank: 20Rank: 20Rank: 20

铜币
438
发表于 2022-7-6 12:45:21 | 显示全部楼层
我只是好奇你是否可以完成这个不计算代数面积的任务。这只是一个概念证明;想玩一会儿。
  1. ;;; Offset inside of selected objects
  2. ;;; Alan J. Thompson, 09.12.09
  3. (defun c:OffIn (/ #Dist #SSGet #Pline #Offset)
  4. (vl-load-com)
  5. (initget 6)
  6. (cond
  7.    ((and (setq #Dist (getdist "\nSpecify offset distance: "))
  8.          (setq #SSGet (ssget ":L" '((0 . "LINE,LWPOLYLINE,ARC"))))
  9.     ) ;_ and
  10.     (if (zerop (getvar "peditaccept"))
  11.       (vl-cmdf "_.pedit" "_m" #SSGet "" "_y" "_j" "" "")
  12.       (vl-cmdf "_.pedit" "_m" #SSGet "" "_j" "" "")
  13.     ) ;_ if
  14.     (if (not (vl-catch-all-error-p
  15.                (setq
  16.                  #Offset
  17.                   (vl-catch-all-apply
  18.                     'vla-offset
  19.                     (list (setq
  20.                             #Pline (vlax-ename->vla-object (entlast))
  21.                           ) ;_ setq
  22.                           (abs #Dist)
  23.                     ) ;_ list
  24.                   ) ;_ vl-catch-all-apply
  25.                ) ;_ setq
  26.              ) ;_ vl-catch-all-error-p
  27.         ) ;_ not
  28.       (if (> (vla-get-area
  29.                (setq #Offset (car (vlax-safearray->list
  30.                                     (vlax-variant-value #Offset)
  31.                                   ) ;_ vlax-safearray->list
  32.                              ) ;_ car
  33.                ) ;_ setq
  34.              ) ;_ vla-get-area
  35.              (vla-get-area #Pline)
  36.           ) ;_ >
  37.         (progn
  38.           (vla-delete #Offset)
  39.           (if (not (vl-catch-all-error-p
  40.                      (setq #Offset (vl-catch-all-apply
  41.                                      'vla-offset
  42.                                      (list #Pline (- (abs #Dist)))
  43.                                    ) ;_ vl-catch-all-apply
  44.                      ) ;_ setq
  45.                    ) ;_ vl-catch-all-error-p
  46.               ) ;_ not
  47.             (setq #Offset (car (vlax-safearray->list
  48.                                  (vlax-variant-value #Offset)
  49.                                ) ;_ vlax-safearray->list
  50.                           ) ;_ car
  51.             ) ;_ setq
  52.             (setq #Offset nil)
  53.           ) ;_ if
  54.         ) ;_ progn
  55.       ) ;_ if
  56.       (alert "Item cannot be offset.")
  57.     ) ;_ if
  58.     (and #Pline (vla-explode #Pline))
  59.    )
  60. ) ;_ cond
  61. (princ)
  62. ) ;_ defun
回复

使用道具 举报

0

主题

3

帖子

3

银币

初来乍到

Rank: 1

铜币
0
发表于 2022-7-6 12:46:59 | 显示全部楼层
尊敬的alanjt,
 
你能解释一下获取偏移多段线的内部点的步骤或基本思想吗?你的lisp很好,但我不明白它是怎么工作的?
回复

使用道具 举报

54

主题

3755

帖子

3583

银币

后起之秀

Rank: 20Rank: 20Rank: 20Rank: 20

铜币
438
发表于 2022-7-6 12:51:11 | 显示全部楼层
没问题。
它所做的只是将pline偏移非常小的距离。如果偏移pline的面积大于原始pline的面积,则删除新pline,并在另一个方向偏移原始pline。这是为了在原稿中得到一条普林线。一旦完成,它只需从新普林线坐标中提取第一个点。从而返回原始pline内的点。
回复

使用道具 举报

发表回复

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

本版积分规则

  • 微信公众平台

  • 扫描访问手机版

  • 点击图片下载手机App

QQ|关于我们|小黑屋|乐筑天下 繁体中文

GMT+8, 2025-3-5 06:19 , Processed in 0.332451 second(s), 74 queries .

© 2020-2025 乐筑天下

联系客服 关注微信 帮助中心 下载APP 返回顶部 返回列表