明经CAD社区

 找回密码
 注册

QQ登录

只需一步,快速开始

搜索
查看: 1601|回复: 16

[函数] 求一个可以渐变分段工具

[复制链接]
发表于 2018-7-20 17:26 | 显示全部楼层 |阅读模式
本帖最后由 tony1435 于 2018-7-25 22:02 编辑

如下图:左边红线长度已知为a,右边绿线长度已知为b,中间这段黄线已知长度为x,现想把x递增分成n段,n是输入整数,每一段的长度是递增的,每段长度都在a~b之间。比如
a=1,b=1.3,黄线为2.3,输入n=2的时候,黄线分2段,长度分别是1.1、1.2;
a=1,b=1.4,黄线为3.6,输入n=3的时候,黄线分3段,长度分别是1.1、1.2、1.3;
a=1,b=1.5,黄线为5,输入n=4的时候,黄线分4段,长度分别是1.1、1.2、1.3、1.4;
...

最后,n应该是有个取值范围,在x/b至x/a之间。。。假设a=1,b=2,x=100,输入n=2时,那就是无解了。








本帖子中包含更多资源

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

x
发表于 2018-7-26 14:52 | 显示全部楼层
本帖最后由 namezg 于 2018-7-27 14:43 编辑

你这种己知a,b,n本身就是不正确的,因为根据已知条件可推出中间段长度x=0.5*n*(a+b)
取不同的n值,x都对应一个固定值,而你画的直线中的lz不一定和这个固定值一样,所有已知条件过定义了。也能写出程序,但意义不大。程序如下:
;渐变分段--不推荐
(defun c:tt1 ( / en a b obj L x nx nd n d i x1 dist pt)
        (vl-load-com)
        (setvar "cmdecho" 0)
        (command "_undo" "be")
        (if (and
                        (setq en (car (entsel "\n请选择要分断的对象: ")))
                        (setq a (getreal "\n请输入第一段的长度: "))
                        (setq b (getreal "\n请输入最后一段的长度: "))
                )
                (progn
                        (setq obj (vlax-ename->vla-object en))
                        (setq L (vlax-curve-getDistAtParam obj (vlax-curve-getEndParam obj)));对象总长
                        (setq x (- L a b));中间段长度
                        ;根据已知条件可推出
                        ;等式① d=(b-a)/(n+1)
                        ;等式② x=(a+d)+...(a+n*d)=n*a+(1+...n)*d=n*a+0.5*(n+1)*n*d
                        ;将等式①代入等式②,x=n*a+0.5*(n+1)*n*(b-a)/(n+1)=n*a+0.5*n*(b-a)=n*a+0.5*n*b-0.5*n*a=0.5*n*a+0.5*n*b=0.5*n*(a+b)
                        ;即x=0.5*n*(a+b)
                        (setq nx (/ x b))
                        (setq nd (/ x a))
                        (while (not (< nx (setq n (getint (strcat "\n请输入中间段的段数n (" (vl-princ-to-string nx) "<n<" (vl-princ-to-string nd) "): "))) nd))
                                (princ "\n段数n超出范围,请重新输入!")
                        )
                        (setq d (/ (- b a) (+ n 1)));等差数列的公差
                        (setq x1 (+ (* n a) (* 0.5 (+ n 1) n d)))
                        (setq i 0)
                        (if (= x x1)
                                (repeat (+ n 1)
                                        (setq dist (+ a (* i d)))
                                        (setq pt (vlax-curve-getPointAtDist obj dist))
                                        (command "_.break" en "_non" (trans pt 0 1) "_non" "@")
                                        (setq en (entlast))
                                        (setq obj (vlax-ename->vla-object en))
                                        (setq i (+ i 1))
                                )
                                (princ "\n无法分段,请重新输入段数n!")
                        )
                )
        )
        (command "_undo" "e")
        (setvar "cmdecho" 1)
        (princ)
)
我建议改为已知直线总长度为L,第一段长度为a,直线分段段数为n(注意这个n不是指的中间段段数,而且指定直线被分段的总段数,n≥3),然后根据计算可得出等差数列的公差d=2*(L-n*a)/(n*(n-1)),然后程序获得各分段点进行分段。(b无需做为已知条件,这里b=a+(n-1)*d)
程序如下:
;渐变分段--推荐
(defun c:tt ( / en a n obj L d i dist pt)
        (vl-load-com)
        (setvar "cmdecho" 0)
        (command "_undo" "be")
        (if (and
                        (setq en (car (entsel "\n请选择要分断的对象: ")))
                        (setq a (getreal "\n请输入第一段的长度: "))
                )
                (progn
                        (while (not (>= (setq n (getint "\n请输入段数n(n≥3): ")) 3))
                                (princ "\n段数n超出范围,请重新输入!")
                        )
                        (setq obj (vlax-ename->vla-object en))
                        (setq L (vlax-curve-getDistAtParam obj (vlax-curve-getEndParam obj)));对象总长
                        ;根据已知条件可推出
                        ;L=a+(a+d)+......+(a+(n-1)*d)=n*a+(1+.....+(n-1))*d=n*a+0.5*(1+n-1)*(n-1)*d=n*a+0.5*n*(n-1)*d
                        ;推出d=2*(L-n*a)/(n*(n-1))
                        (setq d (/ (* 2.0 (- L (* n a))) (* n (- n 1))));等差数列的公差
                        (setq i 0)
                        (repeat (- n 1)
                                (setq dist (+ a (* i d)))
                                (setq pt (vlax-curve-getPointAtDist obj dist))
                                (command "_.break" en "_non" (trans pt 0 1) "_non" "@")
                                (setq en (entlast))
                                (setq obj (vlax-ename->vla-object en))
                                (setq i (+ i 1))
                        )
                )
        )
        (command "_undo" "e")
        (setvar "cmdecho" 1)
        (princ)
)
回复 支持 1 反对 0

使用道具 举报

 楼主| 发表于 2018-7-28 16:47 | 显示全部楼层
namezg 发表于 2018-7-26 14:52
你这种己知a,b,n本身就是不正确的,因为根据已知条件可推出中间段长度x=0.5*n*(a+b)
取不同的n值,x都对应 ...

试了一下,改后的lsp完全可以使用,满足使用要求,感谢您~
表达的不清楚,烧了大神们不少脑细胞了,哈哈~
发表于 2018-7-21 10:31 | 显示全部楼层
玩什么花样
 楼主| 发表于 2018-7-23 17:00 | 显示全部楼层

分段摆东西~距离渐变~
发表于 2018-7-24 09:49 | 显示全部楼层
本帖最后由 namezg 于 2018-7-24 09:54 编辑

已知条件是什么,要的结果是什么,什么是距离渐变也没说明白,等差数列吗。是己知a b n吗,还是己知只有n
比如说直线长度是20,你多给几个不同段数,分段结果是多少的例子。
问题都没表达清楚,让人怎么帮助你。
 楼主| 发表于 2018-7-25 17:15 | 显示全部楼层
namezg 发表于 2018-7-24 09:49
已知条件是什么,要的结果是什么,什么是距离渐变也没说明白,等差数列吗。是己知a b n吗,还是己知只有n
...

不好意思,语文是体育老师教的~现已重新编辑,麻烦看看有没有工具咯,谢谢~

发表于 2018-7-25 17:29 | 显示全部楼层
tony1435 发表于 2018-7-25 17:15
不好意思,语文是体育老师教的~现已重新编辑,麻烦看看有没有工具咯,谢谢~

既然a跟b跟黄线是已知的,那n也是确定的啊,根本不用输入n啊
发表于 2018-7-25 17:37 | 显示全部楼层
tony1435 发表于 2018-7-25 17:15
不好意思,语文是体育老师教的~现已重新编辑,麻烦看看有没有工具咯,谢谢~

确定是等差数列,问题就简单了。
 楼主| 发表于 2018-7-25 18:35 | 显示全部楼层
tryhi 发表于 2018-7-25 17:29
既然a跟b跟黄线是已知的,那n也是确定的啊,根本不用输入n啊

N是要输入的~就像系统那个等分命令(DIVIDE)的那样~~
发表于 2018-7-25 21:55 | 显示全部楼层
tony1435 发表于 2018-7-25 18:35
N是要输入的~就像系统那个等分命令(DIVIDE)的那样~~

a=1,b=1.3,黄线为2.3,输入n=10的时候,要怎么分?
 楼主| 发表于 2018-7-25 22:00 | 显示全部楼层
tryhi 发表于 2018-7-25 21:55
a=1,b=1.3,黄线为2.3,输入n=10的时候,要怎么分?

是的,刚才跟一同行在讨论的时候就发现问题了~n是有取值范围的~贴子又重写了一下
您需要登录后才可以回帖 登录 | 注册

本版积分规则

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

GMT+8, 2024-3-28 19:50 , Processed in 0.267868 second(s), 28 queries , Gzip On.

Powered by Discuz! X3.4

Copyright © 2001-2021, Tencent Cloud.

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