明经CAD社区

 找回密码
 注册

QQ登录

只需一步,快速开始

搜索
查看: 3138|回复: 7

急救

[复制链接]
发表于 2002-6-4 11:39:00 | 显示全部楼层 |阅读模式
我在用visuallisp编写绘制齿轮程序碰到两个棘手的问题,希望哪位高手能助一臂之力!
1.在引用cad倒角命令时,一直没成功,命令行提示"不能给自身倒角",而另外设计一个简单的给两条直线倒角程序能成功,齿轮倒角的两条直线我也是用"line"命令画,选线是用线上点.这到底怎么回事?想想好像没错的地方.
2.再一个是通过对直线和圆进行修剪来回键的侧视图,我是通过圆上点和直线上的点来选取对象的,为什么有时能修剪成功有时不行.修改系统选项的显示精度,对修剪也有影响!这是为何!
真心希望哪位高手能帮我 ,到底怎么解决上述问题(我有急用).万分感激!
e-mail:jincaot@163.net
发表于 2002-6-5 00:49:00 | 显示全部楼层

使用双元表来响应

对于几个需要提供选择的图元及图元上的点的命令提供,如果只提供点坐标,有时由于图形的显示精度及捕捉的设置不同,造成通过点坐标无法精确选择到对象或选错对象等问题,这时你可以使用双元表来响应:
如(setq ent(entsel))中,ent就是一个双元表,其中包括了选定的对象及选择时的坐标,我们也可以使用list来组合形成双元表,如:
obj为对象,pnt为点坐标,则双元表为:
(setq objpnt(list obj pnt))
这样就可以解决你的问题。
发表于 2002-6-5 09:49:00 | 显示全部楼层

解决方案...

您真的应当买一本《Visual LISP for AutoCAD2000程序设计——从学会到用好》,这样,基础技术方法和常见问题的解决方案就有了。
以下摘自这本书的第五章:

5.3  对象描述双元表及其使用
“双元表”,是AutoLISP特有的表数据类型之一,是一种针对AutoCAD数据库所特有的检索指针,就像是 (EntSel) 函数的返回值那样的数据结构。实际上也可以用 (List) 函数,按这种格式组成自定义的双元表。这种特有的数据结构,是在程序中使用CAGD技术的关键之一。
对于一些编辑命令,在指目标时,所指点位与处理的结果有关,就要在AutoLISP 中应当用双元表来“精确响应”要目标的提示,这也是AutoLISP特有的、相当有实用价值的技巧。这类命令有:DIM、EXTEND、TRIM、FILLET、CHAMFER、DIVIDE、MEASURE等等。下面有几个例子来说明双元表的使用技术:
例I:
如用 AutoLISP 制作的功能绘制较大图幅的图形时,一般是在全图幅显示下自动绘图,以便全面查看生成过程。在画机械图时,标尺寸是基本要求。但多数情况下要标尺寸的图线比较密集,其近旁还有不少其它对象,用指定点位来指目标,即使把目标选择框设置得相当小,也会一下子套住好几个目标,造成标注失败。如果为了能唯一地选中目标在程序中使用了 'ZOOM-W,又会加长运行时间。
较好的处理是使用双元表来响应关于DIM中“选择标注对象: ”的提示。用指定对象双元表的方法比指两个点标尺寸更方便和准确,而且能够标注各种尺寸。
如果EN是想要标注尺寸的图线的对象名(一般条件下可以在画好该对象后,紧接着用 (SetQ en (EntLast)) 得到),而 PT 是该对象上的,或对象近旁的一个点的点位表。一般直接使用生成该对象时的所用的点位。更详细的内容在下一个题目中讨论。
例II  :
除了标尺寸之外,双元表还有许多用法。例如,一个生成齿条图形的工具程序(使用Tools.DWG,参见Tools.LSP):
(Defun C:CT ()
        (SetQ m (GetReal "模数: ")
             p0 (GetPoint "\n基点: ") x0 (Car p0) y0 (Cadr p0)
             l (GetDist p0 "\n总长度: ")
            ll 0
       )
       (While (> (+ m l) ll)
                (Command "insert" "*c" (List x0 y0) m 0)
               (SetQ x0 (+ x0 (* m Pi)) ll (+ ll (* m Pi)))
      )
       (Command "pedit" (EntLast) "j" (SsGet "x" '((62 . 2))) "" "")
      (SetQ ctn (EntLast) x0 (Car p0) y0 (Cadr p0))
       (Command "color" 9
                "line" (List x0 (+ y0 m)) (List x0 (- y0 m m)) ""
                "trim" (EntLast) "" ;; 左端修整
                           (List ctn (Polar p0 Pi (+ (* Pi m) 10))) ""
      )
      (Command "color" 9
                   "line" (List (+ l x0) (+ y0 m))
(List (+ l x0) (- y0 m m))
                       ""
                  "trim" (EntLast) "" ;;右端修整
                           (List ctn (Polar p0 0 (+ (* Pi m) l 10))) ""       
                  "erase" (SsGet "x" '((62 . 9))) ""
                  "color" 7
                 "line" (List (- x0 m) y0) (List (+ x0 m l) y0) ""
                  "change" (EntLast) "" "p" "lt" "DHX" ""
      )
      (PrinC)
)
为能使齿条图形的长度尺寸符合要求,又要避开复杂的点位解析描述,在程序中用了TRIM命令处理左右两端的齿条修整,这又是CAGD功能的典型用法。左、右端的长度修整是用双元表响应TRIM命令,为了计算简便,所指点没有落在齿条轮廓线之上,其实本来也没有必要落在图线上,这个点的作用仅仅是指示方向。
对于LWPolyLine,修剪之后的对象名称不变,可以接着继续使用它。如果是老的多段线(PolyLine),因为它是一种复杂对象,在修剪之后将会重新生成图元名,必须用 (EntLast) 重新取出当前对象名称。
例III:
用等分对象之后的生成的点位,加上对象原来的始末两端点作为基础,“描绘”成与这个对象类型不同、几何形状很相同的图线。例如将样条线 (SPline) 转换成多段线 (PpolyLine) 的程序 (T502.LSP):
   
    (Defun C:ASpline ()
       (Defun SEPoint (sen)
               (SetQ sel (EntGet sen) snn 0 spl '())
               (While (SetQ spp (Nth snn sel))
                           (If (= 10 (Car spp))(SetQ spl (Cons (Cdr spp) spl)))
                           (SetQ snn (1+ snn))
               )
               (List (Last spl)(Car spl))
       )
       (SetQ se (Car (EntSel "\nA SPline: "))
                 sn (GetDist "\nLength of lines: ")
                 sp (SEPoint se)
                 sc (GetVar "cecolor")
       )
       (Command "color" 123
                     "measure" (List se (Cdr (Car sp))) sn
       )
       (SetQ ss (SSGet "x" '((62 . 123)(0 . "OINT")))
                  sn (SSLength ss) snn (1- sn)
       )
       (Command "color" sc "3dpoly" (Car sp))
       (Repeat sn
               (SetQ spn (SSName ss snn))
               (SetQ sdp (Cdr (Assoc 10 (EntGet spn))))
               (SetQ snn (1- snn))
               (EntDel spn)
               (Command sdp)
       )
       (Command (Cadr sp) "")
       (EntDel se)
       (PrinC)
)
首先,我们用 (SEPoint) 函数遍历这条样条线的所有控制点,返回始末两点的数据表:’(起点点位 末点点位),然后按照用户的期望进行定距等分,并取出这些点,与原线始末两点配合,生成新的多段线。
        Measure将从这条线上,距所指点较近的端点开始等分。如果用了 (EntSel) 函数接受的用户指定样条线时的结果,很难保证一定会在起点处开始等分,这样的确定与不确定之间就难以形成必然的规则。最好就是Measure的方向与原线始末点的方向一致。于是,有下面的表达式:
(Command "measure" (List se (Car sp)) sn)
这样,双元表的对象名沿用了用户指定的、而点位则强令使用原线的起点点位。这就保证了上边的要求,使程序顺畅、简洁。

注意:
尽量不要在 VL-CmdF 函数中用双元表数据结构,否则可能提示:
应用程序错误: 发送到 ads_cmd 的类型无效
发表于 2002-6-5 12:49:00 | 显示全部楼层

要连续标注圆弧,双元表又无效,可有解决方法。

要连续标注圆弧,有时由于图形的显示精度及捕捉的设置不同,会有抓错或抓不到圆弧,双元表又无效,可有解决方法。

(defun DIM_ARC_CIRCLE (NT / HOLDOSMODE HOLDBLIP        HOLDECHO A N AA        AA10
                       AA40 LL AA50 AA51 PT1 PT2 PT3 DIST DIST1        ANG
                      )
  (setq HOLDECHO (getvar "cmdecho"))
  (setq HOLDBLIP (getvar "blipmode"))
  (setq HOLDOSMODE (getvar "osmode"))
  (setvar "cmdecho" 0)
  (setvar "blipmode" 0)
  (command "_.undo" "_group")
  (command "_.ucs" "world")
  (while (= A NIL)
    (cond
      ((= NT 0)
       (prompt "\n选取圆孔或圆弧: ")
       (setq A (ssget '((0 . "ARC,CIRCLE"))))
      )
      ((= NT 1)
       (prompt "\n选取圆孔: ")
       (setq A (ssget '((0 . "CIRCLE"))))
      )
      ((= NT 2)
       (prompt "\n选取圆弧: ")
       (setq A (ssget '((0 . "ARC"))))
      )
    )
  )
  (setvar "osmode" 0)
  (setq N 0)
  (repeat (sslength A)
    (setq AA10 (cdr (assoc 10 (entget (ssname A N)))))
    (setq AA40 (cdr (assoc 40 (entget (ssname A N)))))
    (if        (= (cdr (assoc 0 (entget (ssname A N)))) "ARC")
      (progn
        (setq AA50 (cdr (assoc 50 (entget (ssname A N)))))
        (setq AA51 (cdr (assoc 51 (entget (ssname A N)))))
        (setq PT1 (polar AA10 AA51 AA40))
        (setq PT2 (polar AA10 AA50 AA40))
        (setq ANG (angle PT2 PT1))
        (setq DIST (distance PT1 PT2))
        (setq PT3 (polar PT2 ANG (/ DIST 2)))
        (setq DIST1 (- AA40 (distance AA10 PT3)))
        (if (> (abs (- AA50 AA51)) pi)
          (setq AA (polar PT3 (- ANG (/ pi 2)) DIST1))
          (setq AA (polar AA10 (- ANG (/ pi 2)) AA40))
        )
        (command "_dimradius" AA PAUSE)
      )
      (progn
        (setq AA (polar AA10 0 AA40))
        (command "_dimdiameter" AA PAUSE)
      )
    )
    (setq N (1+ N))
  )
  (command "_.ucs" "p")
  (command "_.undo" "_end")
  (setvar "blipmode" HOLDBLIP)
  (setvar "osmode" HOLDOSMODE)
  (setvar "cmdecho" HOLDECHO)
  (princ)
)
(defun C:DIM_ARC_CIRCLE0 () (DIM_ARC_CIRCLE 0))
(defun C:DIM_ARC_CIRCLE1 () (DIM_ARC_CIRCLE 1))
(defun C:DIM_ARC_CIRCLE2 () (DIM_ARC_CIRCLE 2))
(prompt "\nType DIM_ARC_CIRCLE0 for 连续标注圆孔或圆弧")
(prompt
  "\nType DIM_ARC_CIRCLE1 for 连续标注圆孔,Type DIM_ARC_CIRCLE2 for 连续标注圆弧"
)
(princ)
发表于 2002-6-5 21:34:00 | 显示全部楼层

龙弟,下面的内容也许对您有用...

5.4  利用绘图时建立的条件进行尺寸标注
为了讨论时简单,生成某图线的程序的模拟程序如下:
(SetQ p1 '(0 0) p2 '(0 50) p3 '(30 50) p4 '(45 35)
       p5 '(45 10) p6 '(55 0)
)
(Command "pline" p1 p2 p3 "a" p4 "l" p5 p6 "")

(1)直接利用绘图生成的控制点作为尺寸界线的原点
这样的使用方法比较直观(结果参见图 5-4-1):
(SetQ p1 '(0 0) p2 '(0 50) p3 '(30 50)
       p4 '(45 35) p5 '(45 10) p6 '(55 0)
)
(Command "pline" p1 p2 p3 "a" p4 "l" p5 p6 "")
(Command "dim" "ver" p1 p2 "@-10,0" ""
                 "ali" p5 p6 "@10,0" ""
                 "rad" p4 "" "@10,10"
           "exi"
)

标注线性尺寸与交互操作的过程相同,这样做没有问题。标注直径或半径尺寸时,虽然所指点P4是直线和圆弧片段的公共端点,但是我们的标注子命令是“Radiu”,因此也没有问题。
这种方法适用于所有显示比例比较大,有关片段“显露”在图形窗口中的,而且所指点附近没有其它图线的条件下。否则执行结果可能不稳定。
(2)使用双元表响应标注命令的提示
实际的绘图程序在图线生成时,会由于显示的比例较小,而对象选择框相对较大,所套中的图线可能除了弧片段之外还有其它的片段,造成AutoCAD不能正确标注半径。上述程序在 Zoom-0.01x显示操作之后,执行出错。跟踪命令执行结果如下:
标注: rad
选择圆弧或圆:       
所选对象不是圆弧或圆。
选择圆弧或圆:
标注: @10,10
标注: 键入 EXIT,返回“命令”提示。
标注: exi

上述现象在生成装配图或者较大的零件图时,时常会发生。如果为了解决这个问题,在标注尺寸之前进行局部显示放大,又会影响程序的速度。较好的解决方法是使用“双元表”。双元表中的图元名取自这条线的第三个片段。具体程序如下(T526.LSP):
(SetQ p1 '(0 0) p2 '(0 50) p3 '(30 50) p4 '(45 35)
       p5 '(45 10) p6 '(55 0)
)
(SetQ pt (GetVar "plinetype"))
(SetVar "plinetype" 0)
(Command "pline" p1 p2 p3 "a" p4 "l" p5 p6 "")
(SetQ ren (EntNext (EntNext (EntNext (EntLast)))))
(Command "dim" "ver" p1 p2 "@-10,0" ""
                            "ali" p5 p6 "@10,0" ""
                      "rad" (List ren (Polar p4 1 20)) "" ""
           "exi"
)
(SetVar "plinetype" pt)

t  点评
·  程序中将PlineType系统变量设置成0,是要使用老的PolyLine。这是因为如果使用了新的LWPolyLine,就无法这样解决问题了,LWPolyLine是一种与Line/Circle一样的简单对象,不能分出各个片段,虽然实际上它是多个片段组成的一个复杂对象。可见,LWPoliLine这种对象的数据结构在被“轻装”之后,数据的可再用性也同时被“轻装”了。祥见5.25
·  程序中标半径用了 (List ren (Polar p4 1 20)) 表达式,显然这个双元表中的点位并没有落在所标的弧片段上,也没有必要必须落在所标的弧片段上,因为这个点所起的作用只是确定半径尺寸线的方向。这一点与手工交互操作过程有所不同。这种方法对于所有的图线(除了LWPolyLine之外),在各种条件下都有效。
·  在AutoCAD中标注尺寸,还有一个“意外”的功能:如果当前UCS与对象的ECS并不重合,所标的尺寸将生成在当前UCS的XY面上。如果是线性尺寸,将标出这条线在当前UCS的XY面上投影的长度;如果是角度尺寸,将标出这两条线当前UCS的XY面上投影的夹角;如果是直径或半径,标注值保持正常,而尺寸线和箭头位置则按照这条线在当前UCS的XY面上投影的位置生成。这显然是十分有用的功能,尤其是对于空间几何数据分析。

摘自《Visual LISP for AutoCAD2000程序设计——从学会到用好》第五章
发表于 2002-6-6 09:03:00 | 显示全部楼层

可否再說明”半径尺寸线的方向”是甚麼??......

我就是欠了这样的一本好书《Visual LISP for AutoCAD2000程序设计——从学会到用好》
陳老師請問汇款账号多少???我要那本书,帮我想想办法,我7月6日回香港。
发表于 2002-6-6 09:48:00 | 显示全部楼层

説明...

因爲圓弧不是一週,尺寸標註時,尺寸線的方向會相關地受到限制。
爲了保證尺寸線不至於落在弧綫外邊,就要確認可能的方向。例如30度、45度...
至於書,我手頭也只剩下一本。
建議您以我的名字在Yahoo中搜索,肯定會找到辦理這本書郵購的商店。
发表于 2002-6-7 09:51:00 | 显示全部楼层

但我在双元表中的点位(用中心点时好像都没有限制)...

本帖最后由 作者 于 2002-6-7 9:51:16 编辑

但我在双元表中的点位(用中心点时好像都没有限制)
(defun DIM_ARC_CIRCLE (NT / HOLDOSMODE HOLDBLIP HOLDECHO A N AA10)
  (setq HOLDECHO (getvar "cmdecho"))
  (setq HOLDBLIP (getvar "blipmode"))
  (setq HOLDOSMODE (getvar "osmode"))
  (setvar "cmdecho" 0)
  (setvar "blipmode" 0)
  (command "_.undo" "_group")
  (while (= A NIL)
    (cond
      ((= NT 0)
       (prompt "\n选取圆孔或圆弧: ")
       (setq A (ssget '((0 . "ARC,CIRCLE"))))
      )
      ((= NT 1)
       (prompt "\n选取圆孔: ")
       (setq A (ssget '((0 . "CIRCLE"))))
      )
      ((= NT 2)
       (prompt "\n选取圆弧: ")
       (setq A (ssget '((0 . "ARC"))))
      )
    )
  )
  (command "_.ucs" "_world")
  (setvar "osmode" 0)
  (setq N 0)
  (repeat (sslength A)
    (setq AA10 (cdr (assoc 10 (entget (ssname A N)))))
    (if        (= (cdr (assoc 0 (entget (ssname A N)))) "ARC")
      (command "_.dimradius"
               (list (ssname A N) AA10); (polar AA10 0 0.01))
               PAUSE
      )
      (command "_.dimdiameter"
               (list (ssname A N) AA10); (polar AA10 0 0.01))
               PAUSE
      )
    )
    (setq N (1+ N))
  )
  (command "_.ucs" "_p")
  (command "_.undo" "_end")
  (setvar "blipmode" HOLDBLIP)
  (setvar "osmode" HOLDOSMODE)
  (setvar "cmdecho" HOLDECHO)
  (princ)
)
(defun C:DIM_ARC_CIRCLE0 () (DIM_ARC_CIRCLE 0))
(defun C:DIM_ARC_CIRCLE1 () (DIM_ARC_CIRCLE 1))
(defun C:DIM_ARC_CIRCLE2 () (DIM_ARC_CIRCLE 2))
(prompt "\nType DIM_ARC_CIRCLE0 for 连续标注圆孔或圆弧")
(prompt
  "\nType DIM_ARC_CIRCLE1 for 连续标注圆孔,Type DIM_ARC_CIRCLE2 for 连续标注圆弧"
)
(princ)
您需要登录后才可以回帖 登录 | 注册

本版积分规则

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

GMT+8, 2024-11-25 15:30 , Processed in 0.214434 second(s), 31 queries , Gzip On.

Powered by Discuz! X3.4

Copyright © 2001-2021, Tencent Cloud.

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