重慶崽兒 发表于 2015-9-26 16:52:27

用插密多段线替换圆弧

本帖最后由 重慶崽兒 于 2015-9-26 16:54 编辑

前些天看见同事用PL线在圆弧上一点点的画,于心不忍,于是便有了:
(defun c:tt( / aname bj hc_1 huchang i jsd ksd l name ss bc huchang_1 yxj ii lst pt)
(setq *error*_bak *error*)
(setq *error* *error*_non)
(setq osmode_bak (getvar "osmode"))
(setvar "osmode" 0)
(setq Gridmode_bak (getvar "Gridmode"))
(setvar "Gridmode" 0)
(setq ss (ssget '((0 . "ARC"))))
(setq l (getreal "\n请输入点间距:"))
(setq i 0)
(if (> l 0)
    (repeat (sslength ss)
      (setq name (ssname ss i))
      (setq bj (cdr (assoc 40 (entget name))))
      (setq aname (vlax-ename->vla-object name))
      (setq ksd (vlax-curve-getStartPoint aname))
      (setq jsd (vlax-curve-getEndPoint aname))
      (setq huchang (vlax-curve-getDistAtParam aname (vlax-curve-getendparam aname)))
      (if (>= (/ l 2.0) bj)
      (entmake (list '(0 . "LWPOLYLINE") '(100 . "AcDbEntity") '(100 . "AcDbPolyline") (cons 90 2) (cons 10 ksd) (cons 10 jsd)))
      (progn
          (setq hc_1 (shc l bj))
          (huaxian hc_1 huchang aname ksd jsd)
      )
      )
      (setq i (1+ i))
    )
    (progn
      (alert "输入有误!")
      (exit)
    )
)
(setvar "osmode" osmode_bak)
(setvar "Gridmode" Gridmode_bak)
(setq *error* *error*_bak)
(princ)
)



(defun shc (l bj / )
(setq bc (sqrt (- (expt bj 2) (expt (/ l 2.0) 2))))
(setq yxj (* (/ (* (atan (/ l 2.0) bc) 180) pi) 2.0))
(setq huchang_1 (/ (* yxj pi bj) 180.0))
)


(defun huaxian (hc_1 huchang en ksd jsd / )
(if (< hc_1 huchang)
    (progn
      (setq ii 0 lst nil)
      (while (< ii huchang)
      (setq pt (vlax-curve-getPointAtDist en ii))
      (setq lst (append lst (list pt)))
      (setq ii (+ ii hc_1))
      )
      (setq lst (append lst (list jsd)))
      (entmake (append (list '(0 . "LWPOLYLINE") '(100 . "AcDbEntity") '(100 . "AcDbPolyline") (cons 90 (length lst))) (mapcar '(lambda (x) (cons 10 x)) lst)))
    )
   
    (entmake (list '(0 . "LWPOLYLINE") '(100 . "AcDbEntity") '(100 . "AcDbPolyline") (cons 90 2) (cons 10 ksd) (cons 10 jsd)))
)
)



(defun *error*_non (msg)
(command)
(setvar "osmode" osmode_bak)
(setvar "Gridmode" Gridmode_bak)
(setq *error* *error*_bak)
(princ)
)


写的不好,各位莫笑

lysygyy 发表于 2017-12-18 11:35:24

重慶崽兒 发表于 2015-9-29 21:50
额,你是定数等分吧,我也写过,但我这边用不到,要是和多段线面积差不多的话,估计点很密吧,好思路,要 ...

lisp不懂哦,现在都是用C++实现的

yangchao2005090 发表于 2018-1-3 11:16:45

edata 发表于 2015-9-28 22:16
没细看你做的是定距弦长,修改如下。

能否改成带有记忆功能的呀,不用每次都输入间距

依然小小鸟 发表于 2023-6-1 12:46:07

土木燃 发表于 2018-10-18 16:00
我也觉得,要再有一个多段线转圆弧就完美了。需要用到

同求 多段线转圆弧

ttmc 发表于 2015-9-26 17:16:35

实用最好。

yoyoho 发表于 2015-9-26 22:22:37

感谢 重庆崽儿 分享程序!!!

edata 发表于 2015-9-27 08:47:49

定距等分,没有用command命令的情况下,不建议更改捕捉值,格栅模式这里没什么意义吧程序有3处生成多段线,其实可以合在一处即可,没必要分开,尝试生成定距点表,最后生成多段线即可。

重慶崽兒 发表于 2015-9-27 17:00:26

edata 发表于 2015-9-27 08:47 static/image/common/back.gif
定距等分,没有用command命令的情况下,不建议更改捕捉值,格栅模式这里没什么意义吧程序有3处生成多段线, ...

首先谢谢E大
我想说下我为什么要这样写:
更改捕捉模式的话的是为了保险起见,怕出错
栅格模式我觉得是必要的,有时候图纸很大,平移缩放的时候会提示:“栅格太密,无法显示”整个人感觉都不好了。
至于三处生成多段线,其实每个圆弧都只会用到一个,我通过判断来决定使用哪一个的
这个程序确实还要很多可以优化的地方
不知道E大有没有什么更好的思路,谢谢

edata 发表于 2015-9-27 19:37:58

本帖最后由 edata 于 2015-9-27 20:29 编辑

;圆弧转PL线
;code by edata @mjtd.com 2015-9-27 19:37:27
(defun c:tt(/ ss en ds lst x)
(if(and (setq ss(ssget '((0 . "arc"))))
          (setq ds(getreal "\n输入等分间距:")))
    (while(setq en(ssname ss 0))
      (setq lst(sk_div_pts en ds))
      (and lst
         (entmake (append (list '(0 . "LWPOLYLINE")
                                  '(100 . "AcDbEntity")
                                  '(100 . "AcDbPolyline")
                                  (cons 90 (length lst))
                            )
                            (mapcar '(lambda (x) (cons 10 x)) lst)
                  )
         )
      )
      (setq ss(ssdel en ss))
      )
    )
(princ)
)
;;arc定距等分函数
(defun sk_div_pts(en ds / obj arc_len lst i reptime)
(if en
    (progn
      (setq obj(vlax-ename->vla-object en)
            arc_len(vla-get-arclength obj)
            )
      (cond
      ((>= ds arc_len)
         (setq lst(list(vlax-curve-getStartPoint obj)(vlax-curve-getEndPoint obj)))
         )
      ((< ds arc_len)
         (setq reptime(1+ (fix (/ arc_len ds))))
         (setq i -1)
         (repeat reptime
         (setq lst(cons (vlax-curve-getPointAtDist obj (* ds (setq i(1+ i)))) lst))
         )
         (if (not(equal (vlax-curve-getEndPoint obj) (car lst) 1e-8))
         (setq lst(cons (vlax-curve-getEndPoint obj) lst))
         )
         )
      )
      )
    )
)

重慶崽兒 发表于 2015-9-27 22:28:21

edata 发表于 2015-9-27 19:37 static/image/common/back.gif


谢谢E大的代码,刚才看了下,程序效率很高
但是我觉得这样的算法不是很好,因为这样创建的多段线的点间距并不是用户输入的点间距,而是那一段子弧的长度,比如:

这里我输入的是20,得到的点间距却是19.9489,而子弧的长度是20,我觉得应该将用户输入的长度当成是那一段子弧的弦长,然后算子圆弧的圆心角,半径不变,这样来得到子圆弧的弧长,然后再创建多段线!
小子随性妄语,E大看看笑笑就是

edata 发表于 2015-9-28 22:16:15

没细看你做的是定距弦长,修改如下。
;圆弧转PL线弦长定距版
;code by edata @mjtd.com 2015-9-28 22:14:47
(defun c:tt(/ ss en ds lst x)
(if(and (setq ss(ssget '((0 . "arc"))))
          (setq ds(getreal "\n输入等分弦长间距:")))
    (while(setq en(ssname ss 0))
      (setq lst(sk_div_pts en ds))
      (and lst
         (entmake (append (list '(0 . "LWPOLYLINE")
                                  '(100 . "AcDbEntity")
                                  '(100 . "AcDbPolyline")
                                  (cons 90 (length lst))
                            )
                            (mapcar '(lambda (x) (cons 10 x)) lst)
                  )
         )
      )
      (setq ss(ssdel en ss))
      )
    )
(princ)
)
;;arc定距弦长等分函数
(defun sk_div_pts(en ds / obj arc_len lst i reptime cen pt rad xian_len)
(if en
    (progn
      (setq obj(vlax-ename->vla-object en)
            arc_len(vla-get-arclength obj)
          xian_len(distance (vlax-curve-getStartPoint obj)(vlax-curve-getEndPoint obj))          
            )
      (cond
      ((or (>= ds xian_len) (>= ds arc_len))
         (setq lst(list(vlax-curve-getStartPoint obj)(vlax-curve-getEndPoint obj)))
         )
      ((< ds arc_len)
         (setq reptime (fix (/ arc_len ds)))
         (setq i -1
             pt (vlax-curve-getStartPoint obj)
             rad(vla-get-radius obj)
             cen(cdr(assoc 10 (entget en)))
             lst(list pt))
         (repeat reptime
           (setq pt(polar cen (+ (angle cen pt) (sk_atan (* ds 0.5) rad)) rad))
         (setq lst(cons pt lst))
         )
         (if (not(equal (vlax-curve-getEndPoint obj) (car lst) 1e-8))
         (setq lst(cons (vlax-curve-getEndPoint obj) lst))
         )
         )
      )
      )
    )
)
;;已知弦长半径求圆心角
(defun sk_atan(a c / b)
(if(and a c)
    (progn
      (setq b(sqrt(abs(-(* c c)(* a a)))))
      (* (atan (/ (* a 1.0) b)) 2.0)
      )
    )
)

culiang10086 发表于 2015-9-29 13:06:05

牛逼的高手啊,

culiang10086 发表于 2015-9-29 13:30:54

程序只能从弧的右侧到左侧吗
页: [1] 2 3
查看完整版本: 用插密多段线替换圆弧