QQ登录

只需一步,快速开始

登录 | 注册 | 找回密码

三维网

 找回密码
 注册

QQ登录

只需一步,快速开始

展开

通知     

全站
4天前
全站
goto3d 说: 版主微信号:caivin811031;还未入三维微信群的小伙伴,速度加
2022-07-04
楼主: mimimao383
收起左侧

[讨论] 用什么方法使曲柄连杆机构转动?

[复制链接]
 楼主| 发表于 2008-9-7 12:18:05 | 显示全部楼层
此时滑块的运动方向是X方向,见笑了。我将细品22#教诲。
发表于 2008-9-7 15:44:41 | 显示全部楼层

回复 24# 的帖子

用vbaman命令或者在工具菜单下打开VBA管理器,其中的“工程”列表框中就有你的宏,选择它使其高亮,再点右面一排按钮中的“嵌入”,程序就和文件“绑”到一起了。
 楼主| 发表于 2008-9-8 01:31:11 | 显示全部楼层
加载完,不知道能否运行。

加载了VBA程序的曲柄连杆机构.dwg

275.69 KB, 下载次数: 48

发表于 2008-9-8 06:43:41 | 显示全部楼层

回复 27# 的帖子

你的文件中没有嵌入程序。
8 G8 [- Z) R$ W5 w! N: N0 @" n, m根据你这个帖子的图形,我把你在24楼帖的程序稍做修改嵌入进去了,你看一下,和你的是否有区别。见附件1。; y& Y( m8 s" a( N' ?, o9 ~
! g8 x% [0 `. l/ r8 g! K' i! a
加载了VBA程序的曲柄连杆机构[1].dwg (97.08 KB, 下载次数: 42)
 楼主| 发表于 2008-9-8 09:02:27 | 显示全部楼层
本帖最后由 woaishuijia 于 2012-3-30 20:14 编辑
1 @3 i* ~9 I) Q4 S! k# [( [
! S+ W5 H" A' ?+ Q$ d2 V$ q- E是两种赋值方法,还是存在优劣?
8 c$ D! o; |' q! V; H# D/ z5 ^4 _2 |  m$ V& U
  1. For Each Obj In SS" E% b, ~% g$ c- W% k4 ~7 J
  2. '        Obj.Delete7 Z( t6 G9 O. e* S9 L
  3.             Select Case Obj.Name '用多重条件语句select case挑选被选中的块参照并赋值8 Q3 @1 S4 x: K
  4.                 Case Is = "l" '如果块参照的名字是l
    ' T  ]- }& o% o  ?$ E
  5.                     Set Bl = Obj '把该块参照赋值给Bl
    0 R4 M$ N0 K0 h9 X) b# v
  6.                 Case Is = "m" '如果该块参照的名字是m
    . o8 c  g- K$ @, I- t  s+ b% \
  7.                     Set Bm = Obj '把该块参照赋值给Bm" _4 }6 Z& [# N
  8.                 Case Is = "n" '如果该块参照的名字是n
    7 n( L3 x  `( E  K& F; D" f0 H
  9.                     Set Bn = Obj '把该块参照赋值给Bn" s! ?; W( [! r* ?9 A8 t# v/ L
  10.             End Select '结束select case语句7 [+ K% R2 v  _8 Y3 b9 I5 {. ^2 S
  11.         Next/ R1 K, |' }9 ]$ v5 M
  12.         SS.Delete" @1 g. t* u! |% m. e1 A9 `
  13. '        .SendCommand "ucs w "$ t1 y- ~& ]" @8 \$ u: W% H
  14. '        Set Bl = .ModelSpace.InsertBlock(P1, "L", 1, 1, 1, 0)6 y. k+ @  Z& Y6 V" v: H4 \
  15. '        P1(2) = 501 U) W. ~  R/ a- J8 E
  16. '        Set Bm = .ModelSpace.InsertBlock(P1, "M", 1, 1, 1, 0)
    : S' k+ ]# ^6 O" s2 L- z
  17. '        Set Bn = .ModelSpace.InsertBlock(P2, "N", 1, 1, 1, 0)
复制代码
 楼主| 发表于 2008-9-8 09:10:48 | 显示全部楼层

重新加载,存在一个直线运动的问题。

我又加载了一次,试一试。
8 r9 V: a. P* r0 l, h! ^
0 z5 g/ l% o; c, F在滑块上加两个沿Z轴运动的圆柱,但我在帮助中搜索,没有找到相关命令。' e" y6 b. F3 D  X' n9 S/ a" Q- S) C5 b
这应该是一个牵连运动,是否应该加子程序呢?8 w# u+ Z  h9 d  Y

+ r; n+ k. d$ k" X7 ^3 P& q[ 本帖最后由 mimimao383 于 2008-9-8 09:40 编辑 ]

加载了VBA程序的曲柄连杆机构.dwg

175.16 KB, 下载次数: 28

 楼主| 发表于 2008-9-8 09:31:17 | 显示全部楼层
可能还是没有加载上
 楼主| 发表于 2008-9-8 09:38:13 | 显示全部楼层
滑块上面的孔,就是期望沿Z轴的运动体位置。它应该是P2(1)的函数还是应该是Ag的函数,实在弄不清楚。# q9 `* L5 j- d- |0 w! \

6 a( ~5 q; _7 N: z! Y. _0 G[ 本帖最后由 mimimao383 于 2008-9-8 09:44 编辑 ]
录象 10两个重复,体积小了不少3少了末注册标志.gif
发表于 2008-9-8 10:11:38 | 显示全部楼层
SOLIDWORK&UG&PROE&INVENTOR&CATIA都可以吧
发表于 2008-9-8 11:17:09 | 显示全部楼层
你在27楼上传的文件没有嵌入VBA工程; a2 T  h& N' o, q# f+ t* U, B
30楼的文件嵌有VBA工程(有声明的模块级变量),但没有宏(就是没有sub...end sub过程),应该是你误删除了。* I* _5 _$ @, c8 t5 C4 c  A
子程序的用途是在需要重复使用某一段代码时,把这段代码写成子程序由其它程序反复调用(也可以自己调用自己,这在编程上叫做递归调用),以减少编程工作量,同时也减少错误的发生。就这个程序而言,用子程序的意义似乎不大。
% u5 X/ B* p! H+ {. R" z我不知道你的圆柱体的运动规律具体与什么有关,但从你的问题分析应该也与主动轮的转动角度(Ag)及滑块的位置(P2)有关,而P2(0)又是Ag的函数,所以,具体是用Ag做自变量还是是P2(0)做自变量计算圆柱的位置只取决于用哪个更方便。就是一个数学关系式,怎么算简单就怎么算。
7 b5 z" ~0 J6 t, l; W/ ]比如在你的程序中9 ?. `1 N4 c4 Y# }
P1(0) = 200# * Cos(Ag)5 k. E  P0 @4 Q5 h. Z: H
P1(1) = 200# * Sin(Ag)
2 W) }2 w) w% I( r9 FP2(0) = P1(0) + Sqr(500# ^ 2 - P1(1) ^ 2)/ ]4 H* d5 W+ {$ n9 e
其实P2(0)也是Ag的函数,但我们并没有写成P2(0) = 200# * Cos(Ag) + Sqr(500# ^ 2 - (200# * Sin(Ag)) ^ 2)
发表于 2008-9-8 13:23:38 | 显示全部楼层
还有两种赋值方法的问题。
. u1 o. C! h9 a2 ?! W第一方法用来对新添加的图元赋值,第二种方法是对现有的图元赋值。并没有明确的优劣之分,看在什么情况下使用。
, ]8 U4 e# Q: ~4 `3 F4 P这两种都是直接用赋值语句,还有一种方法是利用过程或函数的参数传递。比如用鼠标在屏幕上选择一个对象并对其赋值:, d& O& k; A- U( ^1 B$ Q
Dim Obj as acadEntity,P as Variant+ a# e0 g' I5 ?
ThisDrawing.Utility.GetEntity Obj,P
2 \3 ~0 P5 [+ l0 h& M运行上述代码后屏幕上十字光标会变成拾取框,等待使用者选择一个对象。选择后变量Obj就被赋值为被选择的对象,变量P就是拾取点的坐标数组
 楼主| 发表于 2008-9-9 09:09:20 | 显示全部楼层
能否给我指点一本VBA的教材,我应该系统的去努力了。
; a1 ^3 v1 M" T) i+ z) B网上的一个练习:# m, J7 x9 L9 F2 s+ J" T
“选择一个要移动的对象,然后定位起点和终点,程序会慢慢地把对象移动。
0 B- k) t$ t% g2 ^. o3 o1 {移动方法:object.move 起点坐标,端点坐标
8 U( |0 M& E% \/ B, j$ {Sub testmove()
1 I. {) U1 \1 {  V4 P2 RDim p0 As Variant'起点坐标,po p1 pc pe movx movy getobj都是变量命
# C8 A' U# z5 g4 T3 BDim p1 As Variant'终点坐标Variant是数据类型,最普通的一种
1 Z! A! @) n6 C% P. H9 ~  ZDim pc As Variant'移动时起点坐标, J7 [& O4 t. j# x  ^+ w9 `) H
Dim pe As Variant'移动时终点坐标8 Y1 z' S2 Z5 i9 f4 b, U
Dim movx As Variant'x轴增量
* N' R" X' x' V2 a5 Z6 }Dim movy As Variant'y轴增量
! _  S: v, L2 q& qDim getobj As Object'移动对象9 _8 _3 B8 e( b' s- }$ b
Dim movtimes As Integer '移动次数  不知道integer 是整数变量?不能用Variant型吗?3 O1 z1 y4 w# l; J3 u- T' t6 @
ThisDrawing.Utility.GetEntity getobj, po, "请选择移动对象"“获得实体,怎么是这么复杂的语句”,还是不知道从哪获得实体。
9 Z3 T" M$ b, c  V" n/ k$ vp0 = ThisDrawing.Utility.GetPoint(, "起点:")
& U" ]$ ^& u( m1 J1 cp1 = ThisDrawing.Utility.GetPoint(p0, "终点:")
" }& C! q* |4 f7 v3 H9 K* spe = p0& _" I3 L* s1 `% D4 {) ?# B' U
pc = p0  {4 r: L, l0 l- S/ L
motimes = 3000‘运动次数?( R6 O8 ~, e& F3 X, r% Z3 H2 S
movx = (p1(0) - p0(0)) / motimesX方向每次的运动量?/ k, f$ o  o( C3 X5 I
movy = (p1(1) - p0(1)) / motimesY方向,motimes的数值决定速度?
4 q' m! E$ R1 ~6 F- I( P3 wFor i = 1 To motimes
! {9 d5 q" K* k; @$ g5 o$ d: dpe(0) = pc(0) + movx
" b# W& ?0 U+ K" P) @
pe(1) = pc(1) + movy8 f/ g  P0 `8 @" ?& ^& S, C
getobj.Move pc, pe'移动一段
; S0 E( R) N2 ?0 o+ _getobj.Update'更新对象   运动结束不再返回?
! {* c# o; u! @0 INext7 I6 q  }' C2 i3 ^' v3 r: ]  k
End Sub# B9 w/ `$ D* m7 I+ x
结束”
, X% |& u9 e+ c  n) i7 o8 R
8 ^! l0 {0 b8 G  ?4 a+ @
7 {) w8 ^; y: x+ r" I$ i1 h' K: i; i. M7 V4 r
[ 本帖最后由 mimimao383 于 2008-9-9 09:11 编辑 ]
 楼主| 发表于 2008-9-9 09:22:14 | 显示全部楼层
如果运行这段代码,则指出变量未定义,这是为什么呢?, o  X, O! @3 o: i! f( g5 ~
Sub testmove()) o# C" q7 L2 n, d9 D
Dim p0 As Variant       '起点坐标
1 n3 E4 F  P% o2 V5 K& b. x' VDim p1 As Variant       '终点坐标
$ i7 }" A6 c! @# {+ s0 ~Dim pc As Variant       '移动时起点坐标
' g) X  B4 f' ?8 IDim pe As Variant       '移动时终点坐标( e" y9 H5 g; P- T$ h& y3 p  s
Dim movx As Variant     'x轴增量1 p0 f2 H5 N# I% ^
Dim movy As Variant     'y轴增量
1 G' Y/ U1 p9 p( ]8 p4 VDim getobj As Object    '移动对象. i# _0 d  q, x) F% ^3 x) v7 a$ a
Dim movtimes As Integer '移动次数2 p7 f! w2 o# v! W
ThisDrawing.Utility.GetEntity getobj, po, "请选择移动对象"2 E) o* K0 Y+ u2 |
p0 = ThisDrawing.Utility.GetPoint(, "起点:")
, v* i2 J2 p4 ^; `: bp1 = ThisDrawing.Utility.GetPoint(p0, "终点:")1 O$ c3 X7 `1 W9 c5 \: d
pe = p05 d- `2 I, t6 C0 z# ^
pc = p0
5 ~' p. ~% n0 S/ N0 Dmotimes = 3000
) |& W# M- m$ }; `7 umovx = (p1(0) - p0(0)) / motimes
% g" X8 c1 @5 H) t) f& o6 \movy = (p1(1) - p0(1)) / motimes! h5 `. h# A4 i& ]) E6 q" L
For i = 1 To motimes
" z1 Z7 ~0 [9 x4 |& m' n, `2 \, z  pe(0) = pc(0) + movx
: [+ y! S0 e% v  pe(1) = pc(1) + movy
) m/ }5 p0 v0 |! N! Y  getobj.Move pc, pe    '移动一段
* [  R5 ~) e+ F7 y- W  getobj.Update         '更新对象
+ \$ K+ p* M9 `/ Z% b, `3 tNext1 b/ s8 N& E& a: k# R
End Sub
: C* S$ G! Y, o. Q4 s" Z, L8 i0 ]: R1 p8 T8 o1 A0 ?) q6 C$ N
[ 本帖最后由 mimimao383 于 2008-9-9 09:23 编辑 ]
发表于 2008-9-9 13:08:59 | 显示全部楼层

回复 36# 的帖子

Dim movtimes As Integer '移动次数  不知道integer 是整数变量?不能用Variant型吗?
/ `" y8 \" ?& n! xVariant型是变体变量,是能够根据首次使用自动适应数据类型的,在这里使用完全可以。不支持使用的理由是影响运行速度,支持的理由是这个小程序没关系。5 W, E! b" i1 `3 u7 z
ThisDrawing.Utility.GetEntity getobj, po, "请选择移动对象"“获得实体,怎么是这么复杂的语句”,还是不知道从哪获得实体。$ t( W3 h" H& d8 ~4 t6 \1 u0 ?
我在35楼恰巧提到了这个方法,不同之处在于我的帖子里省略了它的第三个参数--命令行提示。对照我35楼的文字说明看看。) J5 D9 E7 W' G: M% }
movx = (p1(0) - p0(0)) / motimes‘X方向每次的运动量?: A$ ]0 Y/ r: n% {
是的。5 c: t9 d  L1 u) \; y5 I$ k: A8 U
movy = (p1(1) - p0(1)) / motimes‘Y方向,motimes的数值决定速度?
9 U/ g, e4 f) L3 c) u. u严格说motimes是移动的次数而不管P0和P1之间的距离有多远。是它们共同决定了运动速度。- n. D9 }& h* H' x5 o% z
getobj.Update'更新对象   运动结束不再返回?
, f# t8 o, ]; S. R) U; p' s1 }) ~这下面还有个Next,它和前面的For i = 1 To motimes构成了固定循环次数的循环语句。这个语句的完整格式是  L  c6 D8 M2 H' F
For 循环变量=初始值 To 结束值 Step 步长6 i$ g( A# G9 I
    在循环中执行的代码% H7 F! K% w! k
Next 循环变量
+ j1 m) x' h: D5 A) S" c9 t4 ~其中,步长可以是正数和负数,不能是0。程序首次运行到循环语句时,循环变量=初始值,运行完中间的代码来到Next 这一行,循环变量=循环变量+步长,然后检查循环变量是否大于结束值(如果步长为正。若步长为负,就看是否小于结束值),如果不是,返回重新执行中间的代码;如果是,不再返回,转向执行后面的语句。4 ?6 N, k" H: t
这个循环语句中,Next这一行的循环变量可以省略;如果步长为1,For那一行的“Step 步长”也可以省略。2 ?: v) c1 o- t) D0 E* q
For i = 1 To motimes. G4 E* L4 |- p/ \+ |, O
Next) t) m8 M4 G! L3 J1 e5 L4 `3 A
这段代码要执行3000次,首次进入时i=1,到Next这一行时i变成2,小于motimes(3000),回去重新执行中间的代码,再来到Next这一行时i变成3,还是小于motimes,再回去......直到第3000次来到Next这一行,i变成3001,大于motimes,不再返回,向下执行End Sub
" I7 R: ^: o" h, F' y* P, L) e" v7 f. t! k! \
回复 37# 的帖子
4 t* k* Z. D( `4 j% l8 h5 cThisDrawing.Utility.GetEntity getobj, po, "请选择移动对象"4 N0 }3 i% z, |4 C. a1 n* ~% ]
这句中的po没有声明0 W7 _" h) U* R) q1 x( Y$ o& w4 v
Dim movtimes As Integer '移动次数
1 U/ d7 J# ^0 U" Q4 M. ]$ t这句声明的movtimes变量在后面代码中成了motimes,少了个v
! e, @$ t9 |7 m: FFor i = 1 To motimes; O8 D. O' E& i" E0 _
For...Next循环语句的循环变量i没有声明
发表于 2008-9-9 13:31:31 | 显示全部楼层
对于初学CAD的VBA的朋友来说,目前较好的入门教材主要有Autocad VBA初级教程Autocad vbA 初级教程(13) 块操作AutoCAD VBA从入门到精通AutoCADVBA开发精彩实例教程+源代码。特别是Autocad VBA初级教程是网上目前最热的入门教材。可以从这里起步,基本入门后再去找些VB的书(比如《中文VisualBasic 6.0傻瓜书》、《vb6.0开发宝典》等)看,结合学习CAD帮助文件中的《ActiveX 和 VBA 开发人员手册》,加宽、加深知识面。! g1 {" o  I- ~/ v, E2 K( h
主要的工具手册一个是Visual Basic 语言参考-函数速查,再一个就是CAD帮助文件的《ActiveX and VBA Reference》。后者是英文版。网上有一个翻译成中文的版本,但人家说明不让传播,我也就不好意思往三维网上传。如果你需要,我可以单独给你。3 b' S$ S  K& Z1 T0 o" @9 K7 q
还有一个学习CAD的VBA的非常好的工具,一个高手编的“宏记录器”,适合2004(或2005)以前版本,可以自动把画图过程记录为VBA代码,就像在Word和Excel软件中录制宏一样。我在本版块上传过,在一个别人的求助帖里,我现在找不到了,我时间有限,你可以先自己找找看。6 {6 H  L( Q0 q, d6 `4 w8 N3 |) D
最后一本书是成为高手的必经之路,《windows32API函数大全》+ W- V/ y: S$ T% r" n8 u

& D$ ]. x& _4 B- B4 B3 z& [[ 本帖最后由 woaishuijia 于 2008-9-9 14:02 编辑 ]
 楼主| 发表于 2008-9-10 09:30:23 | 显示全部楼层
我先去买相关的VB6.0傻瓜书,入门的,基础的是现在所需要的。但每次买的计算机方面的书都沙漠的感觉,收获不多,前两天买了一本美国人编著的“AUTO CAD2007宝典” 108元,涉及到VBA的内容十分空泛,令人失望。
, Q% I6 N2 z5 \' D+ S; ]' O; ?我上边拷的程序就出自“Autocad VBA初级教程”感觉它有些粗糙,我根据你上面指出的错误进行了修改,目前可以移动了,但感觉很别扭,肯定不是最佳。
 楼主| 发表于 2008-9-10 09:53:37 | 显示全部楼层
移动代码理解:) M- F$ u8 t( z6 ]* w- J
Sub testmove()
5 F3 B, @+ x; l  \* E  @, w: T Dim po As AcadBlockReference '增加了块的定义7 e0 R6 |  @1 z: I! [3 ^7 |
  Dim p As AcadBlockReference'相对于运动对象的块
, ^# ]) Y: \: i4 n1 C+ D
Dim p0 As Variant       '起点坐标
: M8 f- J  a# l) A6 Q9 t+ ?% oDim p1 As Variant       '终点坐标. ~% E# J+ G. z6 W$ n6 {
Dim pc As Variant       '移动时起点坐标
  z! g2 a. I1 }Dim pe As Variant       '移动时终点坐标2 N, ~( F$ X# [, p" k
Dim movx As Variant     'x轴增量
' A) X% x  A, ?! ^Dim movy As Variant     'y轴增量
; Y4 Y( U* [; p5 |6 @: CDim getobj As Object    '移动对象( s/ H( b/ i2 U$ y9 e
Dim movtimes As Integer '移动次数* v  `+ O4 _; p. P
Dim i As Integer+ q4 ?% C- J- K" f2 A" Z
ThisDrawing.Utility.GetEntity getobj, po, "请选择移动对象"    不明白这里,为什么不能在这里直接选,期望直接选择PO,* b, X7 W+ d! k6 m$ {( R) j- E
p0 = ThisDrawing.Utility.GetPoint(, "起点:")          '起点和终点要人工选择,如何靠条件触发?
& p* e! {. P- B1 m
p1 = ThisDrawing.Utility.GetPoint(p0, "终点:")
- H) J( G0 j: G! Y) [% g9 `pe = p01 E/ ?" ]8 T4 |* Y/ u; x% K
pc = p0, l5 D" |. b( r6 O
movtimes = 100   改变数值,使运动通畅
9 X; }- m' D) e' j# [: }. w5 b( Hmovx = (p1(0) - p0(0)) / movtimes' Y2 y6 y9 j: e4 V" [
movy = (p1(1) - p0(1)) / movtimes$ a: o; f5 ]) k7 f
For i = 1 To movtimes
: b! z: Z9 E1 y/ i0 D6 N+ b  pe(0) = pc(0) + movx
4 m0 J( S8 ]# A( u4 k5 y  pe(1) = pc(1) + movy  '如果需Z轴移动,语句是否为  movz=(p1(2)-p0(2))/movtimes,      Pe(2)=Pc(2)+movy+ z" w  |. [. y. v
  getobj.Move pc, pe    '移动一段
1 c) O& r' J3 l9 y' s7 {  getobj.Update         '更新对象     '如果没有这一句,移动后将有拖影
2 k  \: f, R6 C' W0 _* [Next
+ \" t; q$ M6 O7 ~End Sub6 d: r" c3 Y' @0 @+ T" b
我目前思索的问题,
: k# O+ h+ f9 O" C$ Y5 p1\移动的对象在语句中确定,我们就可以将这段程序移植到我们先前调节好的程序中
, y# b0 s# \+ _; L" U2\触发移动根据条件,不要人去干预.4 |2 ?' J7 r- Y+ A/ B8 q9 K
3\起点和终点在程序中确定) h+ j) e' H3 f$ R  L, ]; o
4\我想返回的过程应该也可在这段程序中完成
发表于 2008-9-10 13:05:32 | 显示全部楼层
Dim po As AcadBlockReference '增加了块的定义
" Z" T: z' _. n+ g9 x错了,后面使用的po是一个点而不是块参照。这里应该用dim po as variant) t% Q) `' }3 i5 d0 P5 ~4 n* @0 K
/ y/ J4 R7 j  I! V; N$ ~
ThisDrawing.Utility.GetEntity getobj, po, "请选择移动对象"$ n! {6 k& K/ j& g8 K
这行中,getobj是对象型变量,就是在屏幕上用鼠标选的对象,在楼上程序中是在第十行用dim getobj as object声明的;而po是一个点坐标变量,就是选择对象时鼠标所在的点,在原来的程序中没有声明,我们修改原来的程序,应该用dim po as variant。  X* o* n# g& T, l: l, X
有以前我们讨论的程序中,点坐标都是用dim po(2) as double声明的,而这次是用dim po as variant声明,这是因为以前我们在程序中都是从一开始就用常数或算式分别给点的三维坐标赋值,必须让电脑知道这是个有三个元素的数组。而这个程序中是在屏幕上用鼠标选点,要用变体变量,这是规定。还有,如果把一条直线的端点坐标赋值给一个变量,也是用变体变量。总之,只要是用CAD对象的方法、属性给点坐标变量赋值,就要用变体变量。变体变量的点坐标被赋值后,就自动变成数组,这时就可以用常数或算式分别给点的三维坐标赋值,就象用dim po(2) as double声明的一样。
7 q+ ]  H, \- [; F7 {3 ^/ q$ R: v7 l: ?  `6 i, W# G+ |
dim ** as acadblocdreference 是声明一个块参照对象变量,dim ** as acadline 是声明一个直线对象变量,dim ** as acadlayer 是声明一个图层对象变量。。。。。。这些都是对象型变量,它们是有层级结构的。比如块参照和直线都是图元(也叫实体,但不一定是三维的),都是acadentity对象,也就是说,可以把一个准备用到的块参照变量这样声明:dim ** as acadentity,直线、圆、三维实体等图元(实体)对象变量都可以这样声明。图元对象和非图元对象(包括图层、颜色、线型以及CAD文档等)都是object对象。object是对象的总称,任何对象型变量都可以声明为object,这个程序中,作者就是把下一步准备移动的图元对象变量声明为object。
# A5 ?) M# H. G如果你能够确定下步要用到的变量具体是什么类型,还是用具体的类型声明为好。你可以在VBA编辑器中试一下,如果你是用dim ** as acadblocdreference 声明的变量,在编写代码时输入“**.”,界面上就会弹出下拉列表,提示块参照对象可供选择的属性和方法。如果你是用dim ** as acadentity声明,就提示图元对象共有的属性和方法,而用dim ** as object声明,就没有提示,因为电脑只知道它是个对象,而不知道具体是什么对象,都有哪些可用的方法、属性。
! D6 n9 Q$ k4 k9 J7 j在这个程序中,合理的对象变量声明应该是dim getobj as acadentity,而不是Dim getobj As Object ,你总不至于试图用鼠标选择并移动一个颜色吧?呵呵。. G$ f# X! v( @" g- J$ T
0 ^% w- o# L; R* v
ThisDrawing.Utility.GetEntity getobj, po, "请选择移动对象"4 q' K3 A) ~+ n, w9 K0 y4 A( ?' v
这个方法是用鼠标选择一个对象。它的赋值方法和你刚刚学到的用赋值语句赋值不一样。这个方法叫参数传递。其中有三个参数,第一个是准备赋值的对象型变量,第二个是选择对象时鼠标左键按下时的点坐标变量,第三个是命令行提示字符串(可有可无的)。当程序运行到这一行的时候,程序会停下来等待用户选择对象,选择后会同时给两个变量赋值,把被选择的对象赋值给对象型变量,把点坐标变体型变量变成含有三个元素的数组,并把鼠标位置赋值给数组。- `4 w8 T$ Q( x5 A
! U9 P/ ~2 s. Q5 y
到目前为止,我们共讨论了三种选择运动对象的方法:第一种是删除图元,重新插入块参照并顺便给变量赋值;第二种是用选择集选择现有图元,再根据被选择对象不同的特点(包括使用过滤器使选择时只选择块参照对象和根据块名称的不同区分块参照)分别向不同的变量赋值;第三种就是这种,在屏幕上选择单个对象并向变量赋值。还有其它方法,就是第二种方法的变种。在前面的讨论中,我们向选择集添加对象用的是“全选”,其实也可以用鼠标或不用鼠标在屏幕上选择部分对象,这涉及到选择集对象的多种选择方法,以后你会逐渐遇到并掌握。
1 \7 b, ?) Q, {4 Y8 u1 N- C
8 v& M7 O& M3 W% m# Y# up0 = ThisDrawing.Utility.GetPoint(, "起点:" )          '起点和终点要人工选择,如何靠条件触发?/ c; F; {( O$ }5 E6 {! O/ ~- h9 o
这是由用户在屏幕上指定点的方法。向点坐标变量赋值不一定要由用户在屏幕上选,我们前几天的讨论就没用这种方法而是分别用常数或算式向坐标数组赋值,还有我在这个帖子前面提到的,用图元特定的点向点坐标赋值。具体用什么方法根据需要而定。8 D9 R7 u! i5 g6 S8 \. n% G

- {, ~. K; D$ a/ K: y# o, g% pDim p As AcadBlockReference'相对于运动对象的块; u/ x% x$ N7 K4 O: G0 H. |
这一行不知道你要做什么用,后面的程序中也没有用到p变量。5 y% J7 L. `, @" W" i

* v" g+ t0 U0 J- q; i其它你对原来程序的修改都是对的,包括沿Z轴移动的方法。- K$ H9 h& R' v# ]8 T* t
8 V3 p# m+ g* B) V5 T# F6 I
这段程序和我们以前讨论的不同的是,它用了for i=1 to movtimes......next循环。这是一个固定循环次数的循环语句。而我们以前用的是do......loop循环语句,如果不按下esc键就会无休止地运动下去。# h" h5 \8 Q) X- I9 c' {7 o) I3 H# ^
( p/ x  J/ i- X/ v
以前的程序完全可以改成用for......next语句
6 G: o3 l7 ], l- j  g2 J! X
; g' M/ X( o9 W1 m. D; cfor ag=0 to 总转动角度 step 每循环一次转动的角度
% \. S) W4 ^. X2 @    P1(0) = 200# * Cos(Ag)
4 C! I4 \( {# K% }+ k- W    P1(1) = 200# * Sin(Ag)5 S4 O9 A8 B- I- M$ ]6 I
    P2(0) = P1(0) + Sqr(500# ^ 2 - P1(1) ^ 2)
2 Y- h3 q) N9 N! _* G    Bl.Rotation = Ag: k( d8 M: A& H5 A6 h
    Bm.InsertionPoint = P1
7 h" f# m( {2 P. Q/ D/ D8 U) h    Bm.Rotation = .Utility.AngleFromXAxis(P1, P2)
3 d0 l5 |0 f+ E/ C" @    Bn.InsertionPoint = P2
9 z* z4 p% E9 I4 v* Q1 U    Bl.Update
/ l* N/ ?1 {2 C$ x) M. b/ {, w    Bm.Update
: T0 A  T# v+ @- T- U    Bn.Update
( G- d; _2 H* k    If GetAsyncKeyState(27) = -32767 Then Exit for
4 p4 B. s5 P! u/ w9 \2 d6 e    DoEvents/ k3 C+ }- B! n( Q7 ?
next
5 x1 \5 D# m, S1 U& ^( s
1 U  c7 j0 y1 {- v这样这个运动部分就成了指定循环次数、转动总角度后会自动停止的循环形式。每循环一次,角度ag增加一个步长,直到ag等于总角度。在这段程序中,检测esc键的API函数和DoEvents可有可无了,反正它运动一段时间后自己会停下来。
5 X0 L( I0 N! T( o6 ]' n$ R9 c; u4 t# S# c& W0 ]8 G: k( s$ B/ m
如果不想让它自己停止,也可以把两种循环一起用
  m9 p6 A9 p3 C# i
9 R; q- Q1 r) u( J2 z- U6 V+ K* ?do% e# u8 s0 x8 H' C! k' u
    for ag=0 to 总转动角度 step 每循环一次转动的角度6 H6 O! [, e- I( A6 P+ \, u
        P1(0) = 200# * Cos(Ag)* m9 b) b$ m" k4 b8 y! @" }3 S
        P1(1) = 200# * Sin(Ag)3 Y8 g+ g3 w4 @, n% i, B& `
        P2(0) = P1(0) + Sqr(500# ^ 2 - P1(1) ^ 2)  W, k' ^6 w9 w- j5 F
        Bl.Rotation = Ag# J) P$ z- [6 X! w1 t2 G
        Bm.InsertionPoint = P1
* @7 x+ t' S/ f: w0 Z  l        Bm.Rotation = .Utility.AngleFromXAxis(P1, P2)
( A- ~1 k' M: o2 s4 ]        Bn.InsertionPoint = P29 A% ^; S! ?; l5 k
        Bl.Update! n# {3 \) H/ ?$ f: G
        Bm.Update
, \6 k' F# p3 j# ^# H        Bn.Update
: k4 ], E- U4 y/ a5 j; Y9 Q        If GetAsyncKeyState(27) = -32767 Then Exit do9 r- Q2 n& N, c8 \  C, B- n8 @0 r% i
        DoEvents
) {# j6 T+ y5 }( C5 W2 y6 w$ E. R    next
$ @3 U- X. U7 {loop2 R2 C4 P, Q. b0 }7 C; l8 C/ r. w

& f1 p  A8 B% b# h进入do循环后又进入for循环,for循环执行指定的次数后出来还是在do循环里面,回去再重新for循环。。。。。。直到esc键被按下,直接退出两层循环。

评分

参与人数 1三维币 +30 收起 理由
wsj249201 + 30 技术讨论!合并奖励!

查看全部评分

 楼主| 发表于 2008-9-14 10:08:05 | 显示全部楼层
我在考虑滑块上的圆柱体的Z轴方向运动,但不得要领。圆柱体现在跟随滑快运动,期望在弧度等于2时,圆柱体开始向上运动200,怎样设计语句一筹莫展,大师有时间时请指点。下图显示圆柱体的位置,两个圆柱体是一个块。
曲柄圆柱体1.gif
 楼主| 发表于 2008-9-14 10:28:34 | 显示全部楼层
这是修改后的程序,我已经找到“函数速查”手册,但是我对函数的理解总是和在程序使用的情况出入很大,弄来弄去头都大了。
4 ]1 J* s5 z' w- G& n3 a7 `( C6 T/ C" P# i8 B. Q+ Z! J
Option Explicit
2 f  F* i( Z& D* P! y0 D+ y
8 Z0 p, Z! F7 i. m' M; I& d: mPrivate Declare Function GetAsyncKeyState Lib "user32" (ByVal vKey As Long) As Integer& ~/ y6 \' }* |% L+ j& @9 C1 u
Dim V As Double, Ag As Double
9 _2 j  C! u/ E3 F7 [Sub qubingliangan()6 n: ]) H9 w3 r& y: B: o
    Dim SS As AcadSelectionSet, Obj As Object! P" G1 ?* ?3 F8 x  I
    Dim Bl As AcadBlockReference, Bm As AcadBlockReference, Bn As AcadBlockReference, Bo As AcadBlockReference$ Z8 W7 D) y4 J0 d
    Dim P1(2) As Double, P2(2) As Double, P3(2) As Double
% W2 @5 H2 Z" [: \: l    Dim P4(2) As Double'滑块上圆柱体的终点坐标/ {2 G5 g& P5 S" W
    Dim Bq As AcadBlockReference'滑块上的圆柱体块参照7 c4 \; @9 u4 n. s! `
    Dim movtimes As Integer'滑块上圆柱体的移动次数
3 J) w7 N3 W7 h  f% [    Dim movz As Variant'在Z轴方向上移动3 I& B# ?2 X" g: ]5 @
    Dim i As Double'声明变量; C! g* ]. ?+ B: F& [
    V = 20'暂时关掉速度选择
, z# }9 M0 t1 t  `$ q  w' n    'If V < 1# Then V = 10#
, D! E2 m8 A1 T4 L, B* ~    'V = Val(InputBox("输入速度1~100", "autoCAD", V))
2 W9 C: n0 @% x    'If V > 100# Then V = 100#
4 I7 R# l! B( Z    'If V < 1# Then V = 1#
& R9 I+ t, Y: a& g    With ThisDrawing. f3 y9 j3 O$ C
    Set SS = .SelectionSets.Add("SS")# q3 U7 ?/ a1 x, b
    SS.Select acSelectionSetAll
' k8 ~2 J4 [+ H% [0 c0 Y    For Each Obj In SS
& Z' q% c4 n, h9 I9 V: i' F    Obj.Delete5 s0 v) P$ u1 K. y  b7 E5 p
    Next& t% T+ ~1 _, W$ N( F' W9 _
    SS.Delete
) g  @! D, b8 A8 t6 o    '.SendCommand "ucs w "
1 C" v. h! o0 X; l! M, b( p% A    Set Bl = .ModelSpace.InsertBlock(P1, "L", 1, 1, 1, 0)# n  F2 A7 M1 P& T4 [% S* A( y
   ' P2(0) = 1005 k# _) D2 d; H) a8 t& k% t
    Set Bm = .ModelSpace.InsertBlock(P1, "M", 1, 1, 1, 0)
9 ^, g2 |  L. E$ O2 s0 k: e    Set Bn = .ModelSpace.InsertBlock(P2, "N", 1, 1, 1, 0)& _2 g8 E8 F: S+ ~
    P1(0) = 200
! U& R3 p7 s* C$ V9 T9 Q    Set Bo = .ModelSpace.InsertBlock(P1, "O", 1, 1, 1, 0)
0 w' k9 Y) n2 r2 E( [# E9 u    P3(0) = 1000'滑块上圆柱体的初始相对坐标
1 |0 ^7 N' Q, r' a4 T5 w$ I    Set Bq = .ModelSpace.InsertBlock(P3, "q", 1, 1, 1, 0); j8 i  }9 N7 X; |2 q$ ?0 \" C
    'P3(2) = 0
+ A" L3 i8 Z- Q! ~5 P5 c    P4(2) = 200'圆柱体的终点坐标
( K' D& }  Y, w4 |: `6 ~    Do- l% g2 ]/ z0 i9 z0 d9 z6 j
    P1(0) = 200# * Cos(Ag)6 a8 f. u9 N) K, o/ e) ?  B
    P1(1) = 200# * Sin(Ag)
# v" a, {% b6 W, h    P2(0) = P1(0) + Sqr(500# ^ 2 - P1(1) ^ 2)
/ w& y/ }4 c' b. j    Bl.Rotation = Ag
5 d6 L1 A$ V: j6 t+ W. i    Bm.InsertionPoint = P1
+ l4 ~: t  Q1 D. Z2 L3 u/ f& C1 K2 |    Bm.Rotation = .Utility.AngleFromXAxis(P1, P2)' D! ?9 I9 q( F8 L
    Bn.InsertionPoint = P2' ]5 P+ u- ?% K, w; F9 D
    P3(0) = P2(0) + 300
: Z2 p. n* @, i2 m- x& c5 J: Q
& x- }, T1 o: ]$ N    Bq.InsertionPoint = P30 R1 N& X4 r1 ~. Z& x% z# G
    P2(2)=200'圆柱体的高度坐标
8 P) o0 z( ]0 j- A9 N& v! `    If Ag = 2 Then'期望在AG等于2时触发圆柱体运动,这个语句问题很大
1 q$ p. \. Q4 V' {9 |    'For i = 1 To movtimes'循环* ]" K# F: C& B! `2 u& j
    movtimes = 100'通过100次运动结束$ u3 d" O4 i0 y
    movz = (P4(2) - P3(2)) / movtimes'每次平均位移+ ?3 z8 ^/ ^* A8 r8 t1 M9 Q
    P4(2) = P3(2) + movz
! P- m2 X& F' O* n1 m7 l% _    Next! s# {( f# H+ ]$ C8 N
    (这一段应该怎么考虑:不知道如何下手,不知道用什么语句,不知道该将其插到什么地方。
8 T1 ~+ ~7 x  m* ^2 v   Bl.Update$ P' {1 G1 l, K9 j1 x* [
    Bm.Update
' G$ d+ b. p  G    Bn.Update/ a" q* s$ h7 D+ ]0 j% q
    Bq.Update
' a; Q. U/ p9 T( o: G4 Z    If GetAsyncKeyState(27) = -32767 Then Exit Do; W+ d; d+ v3 l* D. m( n
    DoEvents* w+ k8 h, Q0 j+ X! l
    Ag = ((Ag * 500# / V + 1#) Mod Int(3.14159265358979 * 1000# / V)) / 500# * V  h$ K7 z# ^, B
                                   '为什么选择500这些参数,mod和前面的运算关系如何?
( D& p. L# J& g, P+ C8 u
+ P5 M" t, m# y. m  Loop. Q, e+ v* N7 [3 i  j# U
     End with
2 i% W  a$ y( t( v- W- X     end sub
发表于 2008-9-15 12:41:05 | 显示全部楼层
Option Explicit
: v; Z. g3 W4 _" i
1 A9 L( ]7 _* y3 p" HPrivate Declare Function GetAsyncKeyState Lib "user32" (ByVal vKey As Long) As Integer+ q. \" c# z7 B; j, Q
Dim V As Double, Ag As Double' P' n4 J  g2 e

% Q+ O; |: E! g6 b. a# YSub qubingliangan()' a3 z% Z+ y$ D/ A0 R+ O% {* ~4 k
    Dim SS As AcadSelectionSet, Obj As Object
) u, K4 [& H, ]: i) {7 m! U2 z4 `    Dim Bl As AcadBlockReference, Bm As AcadBlockReference, Bn As AcadBlockReference, Bo As AcadBlockReference9 d9 C0 z; v9 q
    Dim P1(2) As Double, P2(2) As Double, P3(2) As Double$ |3 u8 q% b, p6 I) u  Y$ b$ t
    Dim Bq As AcadBlockReference '滑块上的圆柱体块参照; ^0 T* J% u4 @3 c( E: Z
    Dim P4(2) As Double '滑块上圆柱体的终点坐标
! b2 m" v! o, }& \4 n+ P    Dim deltaV As Double '每次循环Ag的增量
7 r$ J. g! d1 c7 @    Dim V2 As Double '圆柱体相对于主动轮转速的垂直运动速度,即Ag每增加或减少1弧度时圆柱体的运动距离5 u% _/ U! s. f; u1 ~) i& t
    Dim deltaV2 '每次循环圆柱体Z轴增量
5 z9 d+ n; k, u) d    ; a2 U8 s+ A& O. p# T  x, Y
    'If V < 1# Then V = 10#7 I, d" i2 _7 [- g5 v, V& U, w
    'V = Val(InputBox("输入速度1~100", "autoCAD", V))
/ P, F% P4 X# w2 n    'If V > 100# Then V = 100#
2 Y2 @6 i8 E7 u0 k3 Z    'If V < 1# Then V = 1#+ Z/ E, |1 A6 ~9 ~6 _
    V = 10 '暂时关掉速度选择% V% c6 u. e8 P$ v
    deltaV = 3.14159265358979 * 2 / 1000 * V '每次循环主动轮转动圆周的1/1000*V
7 l* N4 A/ `0 T% D; w5 L' E) j    V2 = 200" z0 U5 I3 `- o' m% E
    deltaV2 = deltaV * V2. _6 I# h4 k2 {6 ~; S, }
    P4(2) = 200 '圆柱体的终点坐标& |" S% r* F: r& M+ N+ Y* |, t
   
& S7 a0 l, z4 `9 ^, E5 P    With ThisDrawing
) u- p2 k; J3 e/ }; F$ y  t+ H        Set SS = .SelectionSets.Add("SS" )% N. B, G+ ]" D7 |$ H& C
        SS.Select acSelectionSetAll
) e9 A  |  ]/ r: ?; Z7 w! Z        For Each Obj In SS7 s+ u6 G/ m+ J# n
            Obj.Delete
  c% W" ~) o* w( W1 A        Next
5 ~& N  ~" Q8 O) M' d$ k% v  w        SS.Delete
4 R' M" ?. W& A- \        3 r, P1 X% O6 j% n" P& A
        '.SendCommand "ucs w "
) q- r* }7 O( X8 M; d9 M; H4 u        Set Bl = .ModelSpace.InsertBlock(P1, "L", 1, 1, 1, 0)4 T9 e- I! d4 g
        Set Bm = .ModelSpace.InsertBlock(P1, "M", 1, 1, 1, 0)) e/ G8 n0 s0 Z- b3 g+ T
        Set Bn = .ModelSpace.InsertBlock(P2, "N", 1, 1, 1, 0)
( j' v# i; g+ c& \) a( ?" Q        P1(0) = 200
0 }) ^( _/ ~& w) x; @        Set Bo = .ModelSpace.InsertBlock(P1, "O", 1, 1, 1, 0)( r6 u" v" Q* q! t; H
        P3(0) = 1000 '滑块上圆柱体的初始相对坐标
/ V7 T; `8 b3 P5 P1 W; w        Set Bq = .ModelSpace.InsertBlock(P3, "q", 1, 1, 1, 0)( A6 e: m' B0 C" _7 j. S$ P- J8 D
        7 a$ T0 }% Q2 W+ W% o2 r  Q
        Do8 c+ [# P; C/ t) G1 Z' y
            P1(0) = 200# * Cos(Ag)
8 l$ P+ U* [' m$ Q9 b            P1(1) = 200# * Sin(Ag), x: h2 p$ [  a
            P2(0) = P1(0) + Sqr(500# ^ 2 - P1(1) ^ 2)# e2 e3 @& r, [. _9 _* [
            P3(0) = P2(0) + 300. k, Z& t& B" d: b; N4 e' P
            If Ag >= 2 And Ag < 4 Then
' v0 Z) T4 H/ Y7 @! ]% x                If P3(2) < P4(2) Then  ^1 t/ J7 A! o- s
                    P3(2) = P3(2) + deltaV2
2 f* g5 W% H( S                Else# [; p3 x  t- M
                    P3(2) = P4(2)- _: F5 h, N  _) w; J
                End If) I! ]+ ~! b3 @  a/ j
            Else
  M) n; t) i/ x$ f9 Z                If P3(2) > 0 Then
" A/ U2 a! n; c# J( g/ T# j) ]                    P3(2) = P3(2) - deltaV27 p+ ?+ N2 \& U: v4 H" ~
                Else
* u- A8 }% P! O4 g3 O) e3 V                    P3(2) = 0, Z/ m1 C$ F; V. H: O& O
                End If9 T, U1 h7 l# S% ]) x
            End If$ F4 I1 f: s7 A% W- j0 [
            Bl.Rotation = Ag
% @4 W- I; E  R, q            Bm.InsertionPoint = P1
/ m! F8 v/ z1 X  E            Bm.Rotation = .Utility.AngleFromXAxis(P1, P2)
7 i+ n8 T5 m7 Q7 G/ o5 X, ]            Bn.InsertionPoint = P21 N. j3 r! D( u, H8 ~: G
            Bq.InsertionPoint = P3
* n8 M* _3 R, l' Q% y            Bl.Update" ^3 E4 y4 X1 P9 N
            Bm.Update/ L, j1 L7 l4 |1 x$ ?
            Bn.Update
0 `. o+ R3 ?3 \# X            Bq.Update2 a* V/ E, P8 Y' A1 B8 ]% Y
            DoEvents
6 v$ ~: H1 o: R'            Ag = ((Ag * 500# / V + 1#) Mod Int(3.14159265358979 * 1000# / V)) / 500# * V
5 a, S( w5 D7 L! l0 Y% j+ L'                                       为什么选择500这些参数,mod和前面的运算关系如何?8 @' e4 r% l1 W* m
'这个式子看起来复杂,其实核心就是Ag=Ag+增量,就是每次循环让Ag增加一点点。4 d9 {0 j  W6 \7 v+ ]
'但这个式子有个问题,就是如果用户不停止,Ag将无限制地增大,这可能造成数据溢出(尽管对于本程序恐怕直到地球毁灭也不会溢出,但不能那样编程)
" e: t" U$ M4 ?7 @' a) R'于是我要限制Ag在0到2π范围内变化
* }1 Z$ F0 e5 H* D3 k'方法通常有两种:一是取余运算,二是条件判断。先说取余运算Mod
& a- Q2 x# }# }0 d5 j7 l'取余运算是整数运算,前面是被除数,后面是除数,结果是余数,都是整数8 d& O4 c9 J- R/ u4 C
'取余运算的优先级高于加、减、乘、除、乘方,被除数和除数要用括号括起来) k4 z- X- J6 l. A6 S6 h6 _
'现在我们尝试用取余运算来限制Ag的大小: Ag = (Ag + 增量) Mod (3.14159265358979 * 2)& C7 ]& }! |6 U/ l2 t
'这个式子在计算的时候,除数将被化为整数,也就是6;被除数也将被化为整数,由于首次进入循环时Ag=0,而增量肯定会小于0.5
+ @1 }, Y% f9 Z3 ^( w* F) g'所以被除数会被化为0,结果余数是0。无论循环多少次,Ag永远等于0。失败。
4 }, _, Q# E. c" V/ D: T' R' @% B'假设增量为0.01,我们把除数和被除数都乘以100,式子变成:Ag = ((Ag + 0.01)*100) Mod (3.14159265358979 * 2*100)
: U7 }) r# b0 p" W'化简一下: Ag = (Ag * 100 + 1) Mod (3.14159265358979 * 2 * 100)
3 ~' @0 s9 I4 d1 r, i'运算时除数会化为整数628,首次循环时被除数化为整数1,余数为1,下一次为2,以此类推,直到627,再下一次归0* X$ ^- b+ Y+ z
'我们把除数、被除数都乘以100,实际上是把余数乘100了,所以还要被100除一下才是我们要的在0到2π范围内变化的Ag
# c! K  ]) \; |, e'式子变成Ag = ((Ag * 100 + 1) Mod (3.14159265358979 * 2 * 100)) / 100- g" \' f0 A+ S
'进入循环时Ag=0,首次循环后Ag=0.01,下一次为0.02,以此类推,直到6.27,再下一次归0
5 w6 G0 `3 X" }2 C/ C( P) I- `'这个式子是针对增量为0.01的,当增量不是0.01时我们可以扩展一下8 Z1 H4 @# m) S% }+ p) W
'Ag = ((Ag / 增量 + 1) Mod (3.14159265358979 * 2 / 增量)) * 增量: j" z' f! L7 s- J3 L: F( t! K/ q
'我不打算让使用者在输入框中输入一个小数来决定角度增量,因为输入正整数形式的速度会让人更舒服# _+ C; y3 w5 Z* b5 W; s4 \
'把使用者输入的速度化为小数增量的工作由我在程序中完成: 增量 = 速度 / 常数& J  d; z+ {+ w6 O& \& s7 Z+ d% B$ @7 J  o
'于是式子变成了: Ag = ((Ag / (速度 / 常数) + 1) Mod (3.14159265358979 * 2 / (速度 / 常数))) * (速度 / 常数)+ d0 M  e5 C2 O$ E. h8 e
'在程序调试中认为常数=500比较合适,所以式子最终变成了; g& k9 ^1 ?8 v  y+ P0 c
'Ag = ((Ag * 500# / V + 1#) Mod Int(3.14159265358979 * 1000# / V)) / 500# * V
- c0 o$ A6 C5 y7 }* e8 U, j* G$ g# A0 V- `6 B/ s% ]' H. a
'第二个方法是条件判断,下面的两行代码就是; ~% Q  {7 M% i0 r
            Ag = Ag + deltaV0 ~- |% ?$ R* y. P
            If Ag > 3.14159265358979 * 2 Then Ag = 0 '当Ag>2π时归0
4 e0 X8 k1 I1 |: d% l, i# U4 x        Loop Until GetAsyncKeyState(27) = -32767
7 L4 R1 W& p4 F! h" ~- d) w    End With
0 @* h2 h% w+ u7 i3 p: B4 s# Q% xEnd Sub
 楼主| 发表于 2008-9-15 15:54:35 | 显示全部楼层
1、关于 Ag = ((Ag * 500# / V + 1#) Mod Int(3.14159265358979 * 1000# / V)) / 500# * V
8 [$ K6 R8 n$ I2 z7 Q您讲的很清楚。通过观察Ag的增量为0.02,在(0,2π)之间循环。为了构成这样一种运动,需要做的工作太有创造性了,也太复杂了。; C. r1 P5 m- b
2、随着Ag的不断增大,最终使得除数和被除数相等,余数等于零,则Ag等于零,循环重新开始。这里的方法太巧妙。) e0 D7 _0 k# N! D4 g! W; C
3、为什么对其Int(3.14159265358979 * 1000# / V),又为什么PI的小数位这么多?# u" j7 ?, Z9 d. F" `+ d
4、在VBA中有没有这样的语句或命令,它可以直接使某物体旋转,呵呵。
; s; ?8 \* [" |6 ?2 b  ~5、如果最初你给定的程序是Ag=Ag+0.02,也可能完成旋转,但却少了精彩。
) N# f5 l+ c2 \  s3 C6、过程太曲折了,看起来完成圆柱体沿Z轴这样一个看似简单的运动,起编程可能比较复杂。
发表于 2008-9-15 16:23:31 | 显示全部楼层
3、这里的INT()可有可不用。用,就是我主动把它变成整数;不用,反正用MOD运算它会自己变整数,还省了输入的麻烦。但为了提高程序的可读性,也为了避免意外错误,还是写上比较好。其实我的程序中有些地方写得比较简略,别人看着就费劲。# g7 m8 M4 @$ r5 Q3 w0 z% L& N; j$ c4 [
PI是我在windows计算器中复制,在VBA编辑器中粘贴的,习惯了。如果不是双精度数的位数有限,电脑自动删掉了后面的,要有几十位呢,呵呵。
: J. g2 {/ X/ l* \5 k* H5 ]4、有啊。所有的图元对象都有Rotate(旋转)方法,就像画图一样,只要指定基点和要旋转的角度就行了。比如
* v3 S# R1 J' V7 O2 k7 UDim P0(2) as Double
; b1 F8 ~' i0 H& N! t$ TBl.Rotate P0,Ag
: A# d  M( R: Z6、我说其实不复杂,只是你刚刚开始接触这东西,还没有真正入门,或者说还没有学会用电脑的方式去思维。多练习,熟能生巧。
 楼主| 发表于 2008-9-15 16:39:25 | 显示全部楼层

谢谢

正如你所说,的确不易进入到VBA的思维方式中去。
( i* q6 Y' c# d' V比如:8 I$ g5 ]& y) ~5 \8 E5 K0 p
      Ag = Ag + Δ
) c& f) m: ?+ d! X1 l& z& f* `' M            If Ag > 2PI  Then Ag = 0      ''当Ag>2π时归0
9 m8 |+ z9 Y  b0 n这种形式就比较好理解。
 楼主| 发表于 2008-9-16 15:30:44 | 显示全部楼层
这不是期望的直线运动
旋转加直线运动.gif
发表回复
您需要登录后才可以回帖 登录 | 注册

本版积分规则

Licensed Copyright © 2016-2020 http://www.3dportal.cn/ All Rights Reserved 京 ICP备13008828号

小黑屋|手机版|Archiver|三维网 ( 京ICP备13008828号-1 )

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