http://bbs.mjtd.com/forum.php?mod=viewthread&tid=182681&page=1#pid881384
;;;1.命令可以连续执行,中键(或ESC)结束命令。;;;2.不要调用offset命令。因为对于(直线,圆弧,圆)这些对象不能进行0值偏移,且新生成的图元不在当前层。(defun c:ERR();;计算多义线的各顶点的坐标值返回点表(pt_1 pt_2 falg);;参数plename----多段线图元名,ptj@----跟多段线某一段的交点或是ENTSEL在多段线上的选择点;;全局变量flag1---如果为Ture,表示是直线段,否则为圆弧段;;全局变量PTB#;pldata---存储多义线圆弧的一些参数(defun polyline_pt (plename ptj@ / ptz pts pte jd jd1 jd2 pt1## pt2## cnt pt_1 pt_2 flag pt_3 ptb### arcb# arcdata)(if (null ptb#)(progn(pline_pt plename);;rem---去余数 70组码代表多段线的标志,1代表封闭(if (= (rem (cdr (assoc '70 (entget plename))) 2) 1)(if (equal (car pt1##) (caar (reverse ptb#)) 0.0001)(setq ptb# (reverse (cons pt1## ptb#)))(setq ptb# (reverse (cons pt1## (reverse ptb#))))))))(setq cnt 1);;38组码代表标高(setq ptz (cdr (assoc '38 (entget plename))))(setq pts (caar ptb#)ptb### ptb#)(setq ptb# (cdr ptb#))(setq pt_1 nilpt_2 nil)(setq ptj@ (trans ptj@ 1 0));;通过交点跟各个点值的角度来判断交点在哪两点之间的直线上(while ptb#(cond;;当是多义线的直线段时((= (setq flag (cadar ptb###)) 0.0)(setq pte (caar ptb#))(setq jd (rem (angle pts pte) (* 2 pi)))(if (equal jd (* 2 pi) 0.0001)(setq jd 0))(setq jd1 (rem (angle pts ptj@) (* 2 pi)))(if (equal jd1 (* 2 pi) 0.0001)(setq jd1 0))(setq jd2 (rem (angle ptj@ pte) (* 2 pi)))(if (equal jd2 (* 2 pi) 0.0001)(setq jd2 0))(if (and (equal jd1 jd2 0.0001) (equal jd1 jd 0.0001))(setq pt_1 (list pts flag)pt_2 pte))(setq pts pte)(setq ptb# (cdr ptb#)ptb### (cdr ptb###))(setq cnt (1+ cnt)));;当时多义线的圆弧段时((/= (setq flag (cadar ptb###)) 0.0)(setq pte (caar ptb#))(if (setq arcdata (if-pointatarc flag pts pte ptj@))(if arcdata(setq pldata arcdatapt_1 (list pts flag)pt_2 pte)))(setq pts pte)(setq ptb# (cdr ptb#)ptb### (cdr ptb###))(setq cnt (1+ cnt)))));;取出交点所在段的两端点(if (and pt_1 pt_2)(progn(setq pt_3 pt_1pt_1 (list (caar pt_1) (cadr (car pt_1)) ptz)pt_2 (list (car pt_2) (car (cdr pt_2)) ptz)flag1 t)(list pt_1 pt_2 (cadr pt_3)))(progn(setq flag1 nil))));;;;ZDM2000;;;;寻找lwpolyline,polyline的各顶点并返回点表ptb#;;参数plname为图元名;;返回值:为(((100.0 100.0) 0.0) ((100.0 200.0) 0.0)((150.0 200.0) 0.423)...)的表,其中最后一项代表凸度(DEFUN PLINE_PT (plename / ssb ssb1 N PT PT_B arc_b arcbz ssn5 arcbz1)(setq SSB (ENTGET plename)N 1ssb1 ssb)(if (= (cdr (assoc '0 ssb)) "LWPOLYLINE")(progn (while (SETQ PT_B (assoc '10 SSB))(SETQ PT (CDR PT_B)arcbz1 (assoc 42 ssb)arcbz (cdr arcbz1)pt (list pt arcbz))(IF (= N 1)(SETQ PT1## PTPTB# (LIST PT))(SETQ PT2## PTPTB# (CONS PT PTB#)))(SETQ SSB (CDR (MEMBER arcbz1 SSB)))(SETQ N (+ N 1)));;; ;;;有些封闭的LWPOLYLINE末端多出一点,该点与第一点的差值为本0.001需除去;;;;;;在编译后的vlsp中LWPOLYLINE点位为三维点,而在Autocad中是二维点(if (and (= (rem (cdr (assoc '70 (entget plename))) 2) 1)(equal (car pt1##) (car pt2##) 0.002))(setq ptb# (reverse (cdr ptb#))pt2## (car ptb#)))(setq n 1ssb ssb1)(while (setq arc_b (assoc '42 ssb))(setq arcbz (cdr arc_b))(if (= n 1)(setq arcb# (list arcbz))(setq arcb# (cons arcbz arcb#)))(setq ssb (cdr (member arc_b ssb)))(setq n (+ n 1))))(progn ;;polyline(setq ssn5 (entnext plename))(setq pt (cdr (assoc '10 (entget ssn5))))(setq arcbz (cdr (assoc '42 (entget ssn5))))(setq ptb# (list pt)pt1## ptarcb# (list arcbz))(setq ssn5 (entnext ssn5))(while (/= (cdr (assoc '0 (entget ssn5))) "SEQEND")(setq pt (cdr (assoc '10 (entget ssn5))))(setq arcbz (cdr (assoc '42 (entget ssn5))))(setq ptb# (cons pt ptb#)pt2## ptarcb# (cons arcbz arcb#))(setq ssn5 (entnext ssn5)))))(setq arcb# (cons 0 (reverse arcb#)))(SETQ PTB# (REVERSE PTB#)));;函数:判断一个点是否在圆弧上;;参数:b---凸度=2h/d h---拱高 , d---弦长;pnt1---圆弧的起点;pnt2---圆弧的终点;pnt3---需要判断的点;;当b<0的时候,圆弧为顺时针旋转;;变量:r--圆弧的半径;acpnt--圆弧中心点(defun If-PointAtArc ( b pnt1 pnt2 pnt3 / d h r acpnt refang1 refang2 strang endang midang arcdata dist1 refpnt1)(setq d (distance pnt1 pnt2)h (abs (/ (* b d) 2.0))r (/ (+ (expt d 2.0) (* 4 (expt h 2.0))) (* 8.0 h))refang1 (rem (angle pnt1 pnt2) (* pi 2))refpnt1 (polar pnt1 refang1 (/ d 2.0)));;当圆弧是逆时针旋转时(if (> b 0)(setq refang2 (rem (+ refang1 (/ pi 2)) (* pi 2)))(setq refang2 (rem (- refang1 (/ pi 2)) (* pi 2))))(setq acpnt (polar refpnt1 refang2 (- r h))strang (rem (angle acpnt pnt1) (* pi 2))endang (rem (angle acpnt pnt2) (* pi 2))midang (rem (angle acpnt pnt3) (* pi 2))dist1 (distance pnt3 acpnt))(setq midang1 (- midang strang)endang1 (- endang strang))(if (< midang1 0.0)(setq midang1 (+ (* pi 2) midang1)))(if (< endang1 0)(setq endang1 (+ (* pi 2) endang1)))(if (< b 0)(setq strang1 (* pi 2))(setq strang1 0.0))(if (and(or (and (>= strang1 midang1) (<= endang1 midang1)) (and (<= strang1 midang1) (>= endang1 midang1)))(equal dist1 r 0.0001))(progn(setq arcdata (list (list acpnt))arcdata (append arcdata (list strang) (list endang) (list r))))));;计算在非世界坐标系时的点对应于世界坐标系的坐标值;;此函数是针对直线段的;;参数elist----用nselect、nselectp选择函数返回的表;;此处有2个全局变量p10a p11a(defun matrix_b(elist / ent ename bname matlist p10 p11 cnt p10x p11x)(setq ent elistename (car ent)bname (nth 3 ent)matlist (nth 2 ent)p10 (cdr (assoc 10 (entget ename)))cnt 0)(repeat 3(setq p10x (+ (* (car p10) (car (nth cnt matlist)))(* (cadr p10) (cadr (nth cnt matlist)))(* (caddr p10) (caddr (nth cnt matlist)))(cadddr (nth cnt matlist)))p10a (append p10a (list p10x))cnt (1+ cnt)))(if (= (cdr (assoc 0 (entget ename))) "LINE")(progn (setq p11 (cdr (assoc 11 (entget ename)))cnt 0)(repeat 3(setq p11x (+ (* (car p11) (car (nth cnt matlist)))(* (cadr p11) (cadr (nth cnt matlist)))(* (caddr p11) (caddr (nth cnt matlist)))(cadddr (nth cnt matlist)))p11a (append p11a (list p11x))cnt (1+ cnt))))));;针对点的模型坐标系和世界坐标系的转换;;参数entlist--通过entsel或nentselp选择的返回表,pt--选择的点坐标(defun matrix_b_pt(entlist pt / ent ename bname matlist p10 cnt p10x p10a)(setq ent entlistename (car ent)bname (nth 3 ent)matlist (nth 2 ent)p10 ptcnt 0)(repeat 3(setq p10x (+ (* (car p10) (car (nth cnt matlist)))(* (cadr p10) (cadr (nth cnt matlist)))(* (caddr p10) (caddr (nth cnt matlist)))(cadddr (nth cnt matlist)))p10a (append p10a (list p10x))cnt (1+ cnt)))p10a)(defun *error* (msg)(if old-osmode(setvar "osmode" old-osmode))(if old-ortho(setvar "orthomode" old-ortho))(if old-cmdecho(setvar "cmdecho" old-cmdecho))(if (member msg'("Function cancelled""quit / exit abort""console break""函数被取消"))(princ)(princ (strcat "Error: " msg)))(princ))(defun dtr (a)(if (numberp a)(* pi (/ a 180.0))(princ "\nError : Invalid datatype.")));;偏移复制函数(defun oneoffset (dist pldata / pnt refpnt intpnt ang acpnt r)(if pldata(setq acpnt (caar pldata)strang (cadr pldata)endang (caddr pldata)r (last pldata)))(initget 1)(setq pnt (getpoint "\n指定要偏移的那一侧的点:"))(cond((or (= ename "CIRCLE") (= ename "ARC"))(while (and(or(and (> (distance pt1 pnt) radius)(> (distance pnt selectpnt) (distance pt1 pnt)))(< (distance pt1 pnt) radius))(<= radius dist))(setq pnt (getpoint "无法偏移对象。指定要偏移的那一侧的点:"))(if (not pnt) (exit))))((and (or (= ename "LWPOLYLINE") (= ename "POLYLINE"))pldata)(while (and(or(and (> (distance acpnt (trans pnt 1 0)) r)(> (distance (trans pnt 1 0) (trans neapt 1 0)) (distance (trans pnt 1 0) acpnt)))(< (distance acpnt (trans pnt 1 0)) r))(<= r dist))(setq pnt (getpoint "无法偏移对象。指定要偏移的那一侧的点:"))(if (not pnt) (exit)))))(if pnt(cond;;第一种情况:选择的是直线,多义线的直线段时((and (or (= ename "LINE")(= ename "LWPOLYLINE")(= ename "POLYLINE"))(null pldata))(setq refpnt (polar pnt (+ (angle pt1 pt2) (dtr 90)) 10)intpnt (inters pnt refpnt pt1 pt2 nil)ang (angle intpnt pnt)pt1 (trans (polar pt1 ang dist) 1 0)pt2 (trans (polar pt2 ang dist) 1 0))(entmake (list '(0 . "LINE")'(100 . "AcDbEntity")'(100 . "AcDbLine")(cons 10 pt1)(cons 11 pt2))));;第二种情况:选择的是多义线的圆弧段((and (or (= ename "LWPOLYLINE") (= ename "POLYLINE"))pldata)(setq pnt (trans pnt 1 0)neapt (trans neapt 1 0))(if (or (and (> (distance acpnt pnt) r)(> (distance pnt neapt) (distance acpnt pnt)))(< (distance acpnt pnt) r))(setq radius (- r dist))(setq radius (+ r dist)))(if (> b 0)(entmake (list '(0 . "ARC")'(100 . "AcDbEntity")'(100 . "AcDbArc")(cons 10 acpnt)(cons 40 radius)(cons 50 strang)(cons 51 endang)))(entmake (list '(0 . "ARC")'(100 . "AcDbEntity")'(100 . "AcDbArc")(cons 10 acpnt)(cons 40 radius)(cons 50 endang)(cons 51 strang)))));;第三种情况:选择的是圆((= ename "CIRCLE")(if (< (distance pt1 pnt) radius)(setq radius (- radius dist))(setq radius (+ radius dist)))(setq pt1 (trans pt1 1 0))(entmake (list '(0 . "CIRCLE")'(100 . "AcDbEntity")'(100 . "AcDbCircle")(cons 10 pt1)(cons 40 radius))));;第四种情况:选择的是圆弧((= ename "ARC")(if (or (and (> (distance pt1 pnt) radius)(> (distance pnt selectpnt) (distance pt1 pnt)))(< (distance pt1 pnt) radius))(setq radius (- radius dist))(setq radius (+ radius dist)))(setq pt1 (trans pt1 1 0))(entmake (list '(0 . "ARC")'(100 . "AcDbEntity")'(100 . "AcDbArc")(cons 10 pt1)(cons 40 radius)strangendang))))))(defun main (/ selectlist ent ename etype old-dist jingdu1 sedpnt old-ortho old-osmode err nselectlist s42 s41 s70 s71selectpnt pt1 pt2 ptw ptws pts plpts ptb# old-error newent strang endpnt radius p10a p11a neapt pldataendang)(vl-load-com);(setsysvar)(setvar "cmdecho" 0);(chg_undo_push)(or *dist*(setq *dist* 10))(setvar "errno" 0)(Initget 128 "D")(while(=(setq selectlist (nentselp (strcat"\n选择需要偏移复制的对象,改距离按D键:< "(itoa *dist*)">")))"D")(setq jingdu1 (getint (Strcat "\n请输入要偏移的距离<" (itoa *dist*) ">:")))(if jingdu1 (setq *dist* jingdu1))(Initget 128 "D"))(setq selectpnt (cadr selectlist))(setq err (getvar "errno"))(if selectlist(setq ename (cdr (assoc 0 (entget (car selectlist))))));;如果用户用右键则退出,左键未选中则循环(if (= err 52)(exit))(while (= err 7)(setvar "errno" 0)(setq selectlist (nentselp "选择需要偏移复制的对象: "))(setq selectpnt (cadr selectlist))(setq err (getvar "errno"))(if selectlist(setq ename (cdr (assoc 0 (entget (car selectlist)))))))(if (= err 52)(exit));;如果是块,则查看是否是阵列、比例不一致的块(if (nth 3 selectlist)(progn(setq nselectlist (entget (car (last selectlist)))s41 (cdr (assoc 41 nselectlist))s42 (cdr (assoc 42 nselectlist))s70 (cdr (assoc 70 nselectlist))s71 (cdr (assoc 71 nselectlist)))(if (or (and (/= s41 -1.0) (/= s41 1.0))(and (/= s42 -1.0) (/= s42 1.0))(> s70 1)(> s71 1))(progn(princ"\n不支持阵列后或不一致比例的块。")(exit)))));;是否是块中的多段线,是,找出选择点两端的断点值(cond;;如果是块((nth 3 selectlist);;如果是块中的多段线(if (or (= ename "LWPOLYLINE") (= ename "POLYLINE"))(progn(setq neapt (osnap selectpnt "nea"))(setq plpts (pline_pt (car selectlist)));;先将块中的各端点值通过矩阵转换成世界坐标,然后再找出选择点两端的点值(while (caar plpts)(setq ptw (matrix_b_pt selectlist (append (caar plpts) '(0.0))))(setq ptw (append (list ptw) (cdar plpts)))(setq ptws (append ptws (list ptw)))(setq plpts (cdr plpts)))(setq ptws (append ptws (list (car ptws))))(setq ptb# ptwsptws nil);;如果是圆弧段,则提示并退出(if(or (/= (last (setq pts (polyline_pt (car selectlist) neapt)))0.0)(= flag1 nil))(progn(setq pt1 (trans (car pts) 0 1)pt2 (trans (cadr pts) 0 1)b (caddr pts))(oneoffset *dist* pldata));;如果是直段,则取出端点,并绘制成线(progn(setq pt1 (trans (car pts) 0 1 )pt2 (trans (cadr pts) 0 1))(oneoffset *dist* nil))));;结束多段线程序;;如果选中的不是块中的多段线(progn(cond;;当选中的是直线((= ename "LINE")(matrix_b selectlist)(setq pt1 (trans p10a 0 1)pt2 (trans p11a 0 1))(oneoffset *dist* nil));;当选中的是圆((= ename "CIRCLE")(setq pt1 (cdr (assoc 10 (entget (car selectlist)))))(setq pt1 (trans (matrix_b_pt selectlist pt1) 0 1))(setq radius (cdr (assoc 40 (entget (car selectlist)))))(oneoffset *dist* nil));;当选中的是圆弧((= ename "ARC")(setq pt1 (cdr (assoc 10 (entget (car selectlist)))))(setq pt1 (trans (matrix_b_pt selectlist pt1) 0 1))(setq radius (cdr (assoc 40 (entget (car selectlist))))strang (assoc 50 (entget (car selectlist)))endang (assoc 51 (entget (car selectlist))))(oneoffset *dist* nil))))));;非块的情况((not (nth 3 selectlist));;如果是多义线(if (or (= ename "LWPOLYLINE") (= ename "POLYLINE"))(progn(setq neapt (osnap selectpnt "nea"))(if(or (/= (last (setq pts (polyline_pt (car selectlist) neapt)))0.0)(= flag1 nil));;如果选择了圆弧段(progn(setq pt1 (trans (car pts) 0 1)pt2 (trans (cadr pts) 0 1)b (caddr pts))(oneoffset *dist* pldata));;如果选择了直段(progn(setq pt1 (trans (car pts) 0 1)pt2 (trans (cadr pts) 0 1))(oneoffset *dist* nil))));;如果是非多义线,则直接调用offset命令(progn(cond ((setq sss(equal *dist* 0.0 1.0e-4))(command "_COPY" selectlist "" "0" "0"))(t(princ "\n指定要偏移的那一侧的点:")(command "_offset" *dist* selectlist pause "")))(command "change" (entlast) "" "p" "la" (getvar "clayer") "c" "bylayer" "")))));(setvar "offsetdist" *dist*)(main);(setvar "cmdecho" 0);(chg_undo_pop);(setsysvar)(princ))(main)(princ))
