找回密码
 立即注册

QQ登录

只需一步,快速开始

扫一扫,访问微社区

查看: 2651|回复: 11

[求助] [求助]:能够创建类似多线的线型么(不平行)?

[复制链接]
发表于 2006-6-29 09:08:26 | 显示全部楼层 |阅读模式

马上注册,结交更多好友,享用更多功能,让你轻松玩转社区。

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

×
多线命令mline是否由autolisp编写?
如果是,源程序在哪个文件里?
想研究一下

具体问题在三楼
论坛插件加载方法
发帖求助前要善用【论坛搜索】功能,那里可能会有你要找的答案;
如果你在论坛求助问题,并且已经从坛友或者管理的回复中解决了问题,请把帖子标题加上【已解决】;
如何回报帮助你解决问题的坛友,一个好办法就是给对方加【D豆】,加分不会扣除自己的积分,做一个热心并受欢迎的人!

已领礼包: 10553个

财富等级: 富甲天下

发表于 2006-6-29 12:04:09 | 显示全部楼层
不是。有MLINE实体。
论坛插件加载方法
发帖求助前要善用【论坛搜索】功能,那里可能会有你要找的答案;
如果你在论坛求助问题,并且已经从坛友或者管理的回复中解决了问题,请把帖子标题加上【已解决】;
如何回报帮助你解决问题的坛友,一个好办法就是给对方加【D豆】,加分不会扣除自己的积分,做一个热心并受欢迎的人!
回复 支持 反对

使用道具 举报

 楼主| 发表于 2006-6-30 11:06:44 | 显示全部楼层
谢谢回答,但不懂,实体是什么意思?
我现在需要了解多线的实现过程,来编辑我需要的命令。
具体是:
目标:画一条线a的同时,并行自动生成另一条线b(但不一定平行,多线只能平行),接着转折继续画线到,仍有新的并行线,最后的结果是两条并行的折线。如上图。
麻烦:用lisp能够实现并行线的绘制,但转折后的麻烦就来了,新的并行线与转折前的要不分离要不交叉。如下图
实际如果能在lisp中实现自动fillet,也就解决了问题,但似乎fillet在lisp中很难使用,对于我这样的生手很成问题。
请指点。
论坛插件加载方法
发帖求助前要善用【论坛搜索】功能,那里可能会有你要找的答案;
如果你在论坛求助问题,并且已经从坛友或者管理的回复中解决了问题,请把帖子标题加上【已解决】;
如何回报帮助你解决问题的坛友,一个好办法就是给对方加【D豆】,加分不会扣除自己的积分,做一个热心并受欢迎的人!
回复 支持 反对

使用道具 举报

已领礼包: 3个

财富等级: 恭喜发财

发表于 2006-6-30 17:04:42 | 显示全部楼层
先用多义线带宽度绘出线段,再把此线段的轮廓勾绘出来
论坛插件加载方法
发帖求助前要善用【论坛搜索】功能,那里可能会有你要找的答案;
如果你在论坛求助问题,并且已经从坛友或者管理的回复中解决了问题,请把帖子标题加上【已解决】;
如何回报帮助你解决问题的坛友,一个好办法就是给对方加【D豆】,加分不会扣除自己的积分,做一个热心并受欢迎的人!
回复 支持 反对

使用道具 举报

发表于 2006-6-30 17:09:15 | 显示全部楼层
Autodesk早期版本的双线程序dline.lsp,假如看透的说不定可以写出需要的代码
[php]
;;;   DLINE.LSP
;;;   Copyright (C) 1990-1994 by Autodesk, Inc.
;;;      
;;;   Permission to use, copy, modify, and distribute this software
;;;   for any purpose and without fee is hereby granted, provided
;;;   that the above copyright notice appears in all copies and that
;;;   both that copyright notice and this permission notice appear in
;;;   all supporting documentation.
;;;
;;;   THIS SOFTWARE IS PROVIDED "AS IS" WITHOUT EXPRESS OR IMPLIED
;;;   WARRANTY.  ALL IMPLIED WARRANTIES OF FITNESS FOR ANY PARTICULAR
;;;   PURPOSE AND OF MERCHANTABILITY ARE HEREBY DISCLAIMED.
;;;
;;;   DESCRIPTION
;;;     
;;;     This is a general purpose "double-line/arc" generator.  It performs
;;;     automatic corner intersection cleanups, as well as a number of other
;;;     features described below.
;;;  
;;;     The user is prompted for a series of endpoints.  As they are picked
;;;     "DLINE"  segments are drawn on the current layer.  Options are
;;;     available for changing the Width of the DLINE, specifying whether
;;;     or not to Snap to existing lines or arcs, whether or not to
;;;     Break the lines or arcs when snapping to them, and which of the
;;;     following to do:  
;;;     
;;;     Set the global variable dl:ecp to the values listed below:
;;;  
;;;     Value  Meaning
;;;     ---------------------------
;;;       0    No end caps
;;;       1    Start end cap only
;;;       2    Ending end cap only
;;;       3    Both end caps
;;;       4    Auto ON -- Cap any end not on a line or arc.
;;;      
;;;     The user may choose to back up as far as the beginning of the command
;;;     by typing "U" or "Undo", both of which operate as AutoCAD's "UNDO 1"
;;;     does.
;;;     
;;;     Curved DLINE's are drawn using the AutoCAD ARC command and follow as
;;;     closely as possible its command structure for the various options.
;;;  
;;;----------------------------------------------------------------------------
;;;   OPERATION
;;;
;;;     The routine is executed, after loading, by typing either DL or DLINE
;;;     at which time you are presented with the opening line and menu of
;;;     choices:
;;;     
;;;       Dline, Version 1.12, (c) 1990-1994 by Autodesk, Inc.  
;;;       Break/Caps/Dragline/Offset/Snap/Undo/Width/<start point>:
;;;     
;;;     Typing Break allows you to set breaking of lines and arcs found at
;;;     the start and end points of any segment either ON or OFF.
;;;     
;;;       Break Dline's at start and end points?  OFF/<ON>:
;;;     
;;;     Typing Caps allows you to specify how the DLINE will be finished
;;;     off when exiting the routine, per the values listed above.
;;;     
;;;       Draw which endcaps?  Both/End/None/Start/<Auto>:
;;;      
;;;     The default of Auto caps an end only if you did not snap to an arc
;;;     or line.
;;;     
;;;     Typing Dragline allows you to set the location of the dragline
;;;     relative to the centerline of the two arcs or lines to any value
;;;     between - 1/2 of "tracewid" and + 1/2 of "tracewid".  (There is a
;;;     local variable you may set if you want to experiment with offsets
;;;     outside this range;  the results may not be correct, your choice.
;;;     See the function (dl_sao) for more information.)
;;;     
;;;       Set dragline position to Left/Center/Right/<Offset from center = 0.0>:
;;;     
;;;     Enter any real number or one of the keywords.  The value in the angle
;;;     brackets is the default value and changes as you change the dragline
;;;     position.
;;;     
;;;     Offset allows the first point you enter to be offset from a known
;;;     point.
;;;     
;;;       Offset from:  (enter a point)
;;;       Offset toward:    (enter a point)
;;;       Enter the offset distance:   (enter a distance or real number)
;;;  
;;;     Snap allows you to set the snapping size and turn snapping ON or OFF.
;;;     
;;;       Set snap size or snap On/Off.  Size/OFF/<ON>:
;;;       New snap size (1 - 10):
;;;     
;;;     The upper limit may be reset by changing the value of MAXSNP to a
;;;     value other than 10.  Higher values may be necessary for ADI display
;;;     drivers, but generally, you should keep this value somewhere in the
;;;     middle of the allowed range for snapping to work most effectively
;;;     in an uncluttered drawing, and toward the lower end for a more
;;;     cluttered drawing.  You may also use object snap to improve your
;;;     aim.
;;;     
;;;     This feature allows you to very quickly "snap" to another line or arc,
;;;     breaking it at the juncture and performing all of the intersection
;;;     cleanups at one time without having to be precisely on the line, i.e.,
;;;     you can be visually one the line and it will work, or you can use
;;;     object snap to be more precise.
;;;     
;;;     Undo backs you up one segment in the chain of segments you are drawing,
;;;     stopping when there are no more segments to be undone.  All of the
;;;     necessary points are saved in lists so that the DLINE will close, cap,
;;;     and continue correctly after any number of undo's.
;;;     
;;;     Width prompts you for a new width.
;;;     
;;;       New DLINE width <1.0000>:
;;;      
;;;     You may enter a new width and continue the DLINE in the same direction
;;;     you were drawing before;  if you do this, connecting lines from the
;;;     endpoints of the previous segment are drawn to the start points of
;;;     the new segment.
;;;     
;;;     If you press RETURN after closing a DLINE or before creating any
;;;     DLINE's, you will see this message:
;;;     
;;;       No continuation point -- please pick a point.  
;;;       Break/Caps/Dragline/Offset/Snap/Undo/Width/<start point>:  
;;;     
;;;     After you pick the first point, you will see this set of options:
;;;     
;;;       Arc/Break/CAps/CLose/Dragline/Snap/Undo/Width/<next point>:
;;;      
;;;     Picking more points will draw straight DLINE segments until either
;;;     RETURN is pressed or the CLose option is chosen.
;;;     
;;;     CLose will close the lines if you have drawn at least two segments.
;;;     
;;;     Selecting Arc presents you with another set of choices:
;;;     
;;;       Break/CAps/CEnter/CLose/Dragline/Endpoint/Line/Snap/Undo/Width/<second point>:
;;;     
;;;     All of the options here are the same as they are for drawing straight
;;;     DLINE's except CEnter, Endpoint, and Line.
;;;     
;;;     The default option, CEnter, and Endpoint are modeled after the ARC
;;;     command in AutoCAD and exactly mimic its operation including all of
;;;     the subprompts.  Refer to the AutoCAD reference manual for exact usage.
;;;     
;;;     The Line option returns you to drawing straight DLINE segments.
;;;     
;;;     Snapping to existing LINE's an ARC's accomplishes all of the trimming
;;;     and extending of lines and arcs necessary, including cases where arcs
;;;     and lines do not intersect.  In these cases a line is drawn from either;
;;;     a point on the arc at the perpendicular point from the center of the
;;;     arc to the line, to the line, or along the line from the centers of the
;;;     two arcs that do not intersect at the points where this line crosses
;;;     the two arcs.  In this way, we ensure that all DLINE's can be closed
;;;     visually.
;;;     
;;;     Breaking will not work unless Snapping is turned on.
;;;     
;;;----------------------------------------------------------------------------
;;;  GLOBALS:
;;;     dl:osd -- dragline alignment offset from center of two lines or arcs.
;;;     dl:snp -- T if snapping to existing lines and arcs.
;;;     dl:brk -- T if breaking existing lines and arcs.
;;;     dl:ecp -- Bitwise setting of caps when exiting.
;;;     v:stpt -- Continuation point.
;;;----------------------------------------------------------------------------
;;;
;;; ===========================================================================
;;; ===================== load-time error checking ============================
;;;

  (defun ai_abort (app msg)
;;LCA - COMMENT: *error* defun no longer evaluates as a list.
     (defun *error* (s)
        (if old_error (setq *error* old_error))
        (princ)
     )
     (if msg
       (alert (strcat " Application error: "
                      app
                      " \n\n  "
                      msg
                      "  \n"
              )
       )
     )
     (exit)
  )

;;; Check to see if AI_UTILS is loaded, If not, try to find it,
;;; and then try to load it.
;;;
;;; If it can't be found or it can't be loaded, then abort the
;;; loading of this file immediately, preserving the (autoload)
;;; stub function.

  (cond
     (  (and ai_dcl (listp ai_dcl)))          ; it's already loaded.

     (  (not (findfile "ai_utils.lsp"))                     ; find it
        (ai_abort "DLINE"
                  (strcat "Can't locate file AI_UTILS.LSP."
                          "\n Check support directory.")))

     (  (eq "failed" (load "ai_utils" "failed"))            ; load it
        (ai_abort "DLINE" "Can't load file AI_UTILS.LSP"))
  )

  (if (not (ai_acadapp))               ; defined in AI_UTILS.LSP
      (ai_abort "DLINE" nil)         ; a Nil <msg> supresses
  )                                    ; ai_abort's alert box dialog.

;;; ==================== end load-time operations ===========================
;;; Main function

(defun dline  (/ strtpt nextpt pt1    pt2    spts   wnames elast
                 uctr   pr     prnum  temp   ans    dir    ipt
                 v      lst    dist   cpt    rad    orad   ftmp
                 spt    ept    pt     en1    en2    npt    cpt1
                 flg    cont   flg2   flgn   ang    tmp    undo_setting
                 brk_e1 brk_e2 bent1  bent2  nn     nnn   
                 dl_osm dl_oem dl_oce dl_opb dl_obm dl_ver
                 dl_err dl_oer dl_arc fang   MAXSNP ange   
                 savpt1 savpt2 savpt3 savpt4 savpts
              )

  ;; Version number.  Reset this local if you make a change.
  (setq dl_ver "1.12")  
  
  ;; Reset this value higher for ADI drivers.
  (setq MAXSNP 10)              

  (setq dl_osm (getvar "osmode")
        dl_oce (getvar "cmdecho")
        dl_opb (getvar "pickbox")
  )

  ;;
  ;; Internal error handler defined locally
  ;;

  (defun dl_err (s)                   ; If an error (such as CTRL-C) occurs
                                      ; while this command is active...
    (if (/= s "Function cancelled")
      (if (= s "quit / exit abort")
        (princ)
        (princ (strcat "\nError: " s))
      )
    )
    (command "_.UNDO" "_EN")
    (ai_undo_off)
    (if dl_oer                        ; If an old error routine exists
      (setq *error* dl_oer)           ; then, reset it
    )
;;LCA - WARNING: The OSMODE sysvar has changed.
    (if dl_osm (setvar "osmode" dl_osm))
    (if dl_opb (setvar "pickbox" dl_opb))
   
    ;; Reset command echoing on error
    (if dl_oce (setvar "cmdecho" dl_oce))      
    (princ)
  )
  
  ;; Set our new error handler
  (if (not *DEBUG*)
    (if *error*
      (setq dl_oer *error* *error* dl_err)
      (setq *error* dl_err)
    )
  )

  (setvar "cmdecho" 0)
  (ai_undo_on)                       ; Turn on UNDO
  (command "_.UNDO" "_GROUP")
;;LCA - WARNING: The OSMODE sysvar has changed.
  (setvar "osmode" 0)
  (if (null dl:opb) (setq dl:opb (getvar "pickbox")))

  
  (setq nextpt "Straight")

  ;; Get the first segment's start point

  (menucmd "s=dline1")
  (graphscr)
  (princ (strcat "\nDline, Version " dl_ver ", (c) 1990-1994 by Autodesk, Inc. "))
  
  (setq cont T)
  (while cont
    (dl_m1)

    ;; Ready to draw successive DLINE segments

    (dl_m2)
  )
  
;;LCA - WARNING: The OSMODE sysvar has changed.
  (if dl_osm (setvar "osmode" dl_osm))
  (if dl_opb (setvar "pickbox" dl_opb))

  (ai_undo_off)                      ; Return UNDO to initial state

  ;; Reset command echoing
  (if dl_oce (setvar "cmdecho" dl_oce))      
  (menucmd "s=s")
  (princ)
)
;;;
;;; Main function subsection 1.
;;;
;;; dl_m1 == DLine_Main_1
;;;
(defun dl_m1 ()
  (setq temp T
        uctr nil
  )
  (if dl_arc
    (setq nextpt "Arc")
    (setq nextpt "Line")
  )
  ;; temp set to nil when a valid point is entered.
  (while temp
    (initget "Break Caps Dragline Offset Snap Undo Width")
    (setq strtpt (getpoint
      "\nBreak/Caps/Dragline/Offset/Snap/Undo/Width/<start point>: "))
    (cond
      ((= strtpt "Dragline")
        (dl_sao)
      )
      ((= strtpt "Break")
        (initget "ON OFf")
        (setq dl:brk (getkword
          "\nBreak Dline's at start and end points?  OFf/<ON>: "))
        (setq dl:brk (if (= dl:brk "OFf") nil T))   
      )
      ((= strtpt "Offset")
        (dl_ofs)
      )
      ((= strtpt "Snap")
        (dl_sso)
      )
      ((= strtpt "Undo")
        (princ "\nAll segments already undone. ")
        (setq temp T)
      )
      ((= strtpt "Width")
        (initget 6)
        (dl_snw)
        (setq temp T)
      )
      ((null strtpt)
        (if v:stpt
          (setq strtpt v:stpt
                temp   nil
          )
          (progn
            (princ "\nNo continuation point -- please pick a point. ")
          )
        )
      )
      ((= strtpt "Caps")
        (endcap)   
      )
      ;; If none of the above, it must be OK to continue - a point has been
      ;; picked or entered from the keyboard.
      (T
        (setq v:stpt strtpt
              temp   nil
        )
      )
    )
  )
)
;;;
;;; Main function subsection 2.
;;;
;;; dl_m3 == DLine_Main_2
;;;
(defun dl_m2 (/ temp)
  (setq spts (list strtpt)
        uctr 0
  )
  (if dl:snp
    (dl_ved "brk_e1" strtpt)
  )
  ;; Make sure that the offset is not greater than 1/2 of "tracewid", even
  ;; if the user transparently resets it while the command is running.
  (setq temp (/ (getvar "tracewid") 2.0))
  (if (< dl:osd (- temp))
    (setq dl:osd (- temp))
  )
  (if (> dl:osd temp)
    (setq dl:osd temp)
  )
   
  (while (and nextpt (/= nextpt "CLose"))
    (if (/= nextpt "Quit")
      (if dl_arc
        (progn
          (menucmd "s=dline2")
          (initget
            "Break CAps CEnter CLose Dragline Endpoint Line Snap Undo Width")
          (setq nextpt (getpoint strtpt (strcat
            "\nBreak/CAps/CEnter/CLose/Dragline/Endpoint/"
            "Line/Snap/Undo/Width/<second point>: "))
          )
        )
        (progn
          (menucmd "s=dline3")
          (initget "Arc Break CAps CLose Dragline Snap Undo Width")
          (setq nextpt (getpoint strtpt
            "\nArc/Break/CAps/CLose/Dragline/Snap/Undo/Width/<next point>: ")
          )
          (grdraw nextpt strtpt 1)
        )
      )
    )
    (setq v:stpt (last spts))
    (cond
      ((= nextpt "Dragline")
        (dl_sao)
      )
      ((= nextpt "Width")
        (dl_snw)
        
      )
      ((= nextpt "Undo")
        (cond
          ;;((= uctr 0) (princ "\nNothing to undo. ") )
          ((= uctr 0) (setq nextpt nil) )
          ((> uctr 0)
            (command "_.U")
            (setq spts   (dl_lsu spts 1))
            (setq savpts (dl_lsu savpts 2))
            (setq wnames (dl_lsu wnames 2))
            (setq uctr (- uctr 2))
            (setq strtpt (last spts))
          )
        )
        (if dl:snp
          (if (= uctr 0)
            (dl_ved "brk_e1" strtpt)
          )
        )
      )
      ((= nextpt "Break")
        (initget "ON OFf")
        (setq dl:brk (getkword
          "\nBreak Dline's at start and end points?  OFF/<ON>: "))
        (setq dl:brk (if (= dl:brk "OFf") nil T))   
        
        (if dl:snp
          (dl_ved "brk_e1" strtpt)
        )
        (if dl_arc
          (setq nextpt "Arc")
          (setq nextpt "Line")
        )
      )
      ((= nextpt "Snap")
        (dl_sso)
      )
      ((= nextpt "Arc")
        (setq dl_arc T)               ; Change to Arc segment prompt.
      )
      ((= nextpt "Line")
        (setq dl_arc nil)             ; Change to Line segment prompt.
      )
      ((= nextpt "CLose")
        (dl_cls)
      )
      ((= (type nextpt) 'LIST)
        (dl_ds)
      )
      ((= nextpt "CEnter")
        (dl_ceo)
      )
      ((= nextpt "Endpoint")
        (dl_epo)
      )
      ((= nextpt "CAps")
        (endcap)                      ; Set which caps to draw when exiting.
      )
      (T
        (setq nextpt nil cont nil)
        (if (> uctr 1)
          (if (= (logand 4 dl:ecp) 4)
            (progn
              (if (null brk_e1) (command "_.LINE" savpt1 savpt2 ""))
              (dl_ssp)
              (if (null brk_e2) (command "_.LINE" savpt3 savpt4 ""))
            )
            (progn
              (if (= (logand 1 dl:ecp) 1)
                (command "_.LINE" savpt1 savpt2 "")
              )
              (if (= (logand 2 dl:ecp) 2)
                (progn
                  (dl_ssp)
                  (command "_.LINE" savpt3 savpt4 "")
                )
              )
            )
          )
        )
        (if brk_e1 (setq brk_e1 nil))
        (if brk_e2 (setq brk_e2 nil))
        (command "_.UNDO" "_EN")
      )                               ; end of inner cond  
    )                                 ; end of outer cond  
  )                                   ; end of while
)
;;; ------------------ End Main Functions ---------------------------
;;; ---------------- Begin Support Functions ------------------------


;;;
;;; Close the DLINE with either straight or arc segments.  
;;; If closing with arcs, the minimum number of segments already drawn
;;; is 1, otherwise it is 2.
;;;
;;; dl_cls == DLine_CLose_Segments
;;;
(defun dl_cls ()
  (if (or (and (null dl_arc) (< uctr 4)
               (if (> uctr 1)
                 (/= (dl_val 0 (entlast)) "ARC")
                 (not (> uctr 1))
               )
          )
          (and dl_arc (< uctr 2)))
    (progn
      (princ "\nCannot close -- too few segments. ")
      (if dl_arc
        (setq nextpt "Arc")
        (setq nextpt "Line")
      )
    )
    (progn
      (command "_.UNDO" "_GROUP")
      (setq nextpt (nth 0 spts))
      (if (null dl_arc)
        ;; Close with line segments
        (dl_mlf 3)
        (progn
          (setq tmp (last wnames)
                ange (trans '(1 0 0) (dl_val -1 tmp) 1)
                ange (angle '(0 0 0) ange)
                dir (if (= (dl_val 0 tmp) "LINE")
                      (angle (trans (dl_val 10 tmp) 0 1)
                             (trans (dl_val 11 tmp) 0 1))
                      (progn
                        (setq dir (+ (dl_val 50 tmp) ange)
                              dir (if (> dir (* 2 pi))
                                    (- dir (* 2 pi))
                                    dir
                                  )
                        )
                        (if (equal dir
                                   (setq dir (angle (trans (dl_val 10 tmp)
                                                           (dl_val -1 tmp)
                                                           1)
                                                    strtpt
                                             )
                                   )
                                   0.01)
                          (- dir (/ pi 2))
                          (+ dir (/ pi 2))
                        )
                      )
                    )
          )
          (command "_.ARC"
                   strtpt
                   "_E"
                   nextpt
                   "_D"
                   (* dir (/ 180 pi))
          )
          ;; Close with arc segments
          (dl_mlf 4)
        )
      )
      ;; set nextpt to "CLose" which will cause an exit.
      (setq nextpt "CLose"
            v:stpt nil
            cont   nil
      )
    )
  )
)
;;;
;;; A point was entered, do either an arc or line segment.
;;;
;;; dl_ds == DLine_Do_Segment
;;;
(defun dl_ds ()
  (if (equal strtpt nextpt 0.0001)
    (progn
      (princ "\nCoincident point -- please try again. ")
      (if dl_arc
        (setq nextpt "Arc")
        (setq nextpt "Line")
      )
    )
    (progn
      (command "_.UNDO" "_GROUP")
      (setq nextpt (list (car nextpt) (cadr nextpt) (caddr strtpt)))
      (if dl_arc
        (progn
          (command "_.ARC" strtpt nextpt)
          (prompt "\nEndpoint: ")
          (command pause)
          (setq nextpt (getvar "lastpoint")
                v:stpt nextpt)
          (setq temp (entlast))
          ;; Delete the last arc segment so we can find the line or
          ;; arc under it.
          (entdel temp)
          (if dl:snp
            (dl_ved "brk_e2" nextpt)
          )
          ;; Restore the arc previously deleted.
          (entdel temp)
          ;; Draw the arc segments.
          (dl_mlf 2)
        )
        (progn
          (setq v:stpt nextpt)
          (if dl:snp
            (dl_ved "brk_e2" nextpt)
          )
          (if (and brk_e1 (eq brk_e1 brk_e2) (= (dl_val 0 brk_e1) "LINE"))
            (progn
              (princ "\nSecond point cannot be on the same line segment. ")
              (setq brk_e2 nil)
            )
            ;; Draw the line segments.
            (dl_mlf 1)
          )
        )
      )
      (if brk_e2 (setq nextpt "Quit"))
    )
  )
)
;;;
;;; The CEnter option for drawing arc segments was selected.
;;;
;;; dl_ceo == DLine_CEnter_Option
;;;
(defun dl_ceo ()
  (command "_.UNDO" "_GROUP")
  (setq temp T)
  (while temp
    (initget 1)
    (setq cpt (getpoint strtpt "\nCenter point: "))
    (if (<= (distance cpt strtpt) (- (/ (getvar "tracewid") 2.0) dl:osd))
      (progn
        (princ
        "\nThe radius defined by the selected center point is too small ")
        (princ "\nfor the current Dline width.  ")
        (princ "Please select another point.")
      )
      (setq temp nil)
    )
  )
  ;; Start the ARC command so that we can get visual dragging.
  (command "_.ARC" strtpt "_C" cpt)
  (initget "Angle Length Endpoint")
  (setq nextpt (getkword "\nAngle/Length of chord/<Endpoint>: "))
  (cond
    ((= nextpt "Angle")
      (prompt "\nIncluded angle: ")
      (command "_A" pause)
      (setq nextpt (dl_vnp)
            v:stpt nextpt
      )
      ;; Draw the arc segments.
      (dl_mlf 2)
    )
    ((= nextpt "Length")
      (prompt "\nChord length: ")
      (command "_L" pause)
      (setq nextpt (dl_vnp)
            v:stpt nextpt
      )
      ;; Draw the arc segments.
      (dl_mlf 2)
    )
    (T
      (prompt "\nEndpoint: ")
      (command pause)
      (setq nextpt (dl_vnp)
            v:stpt nextpt
      )
      ;; Draw the arc segments.
      (dl_mlf 2)
    )
  )
)
;;;
;;; Endpoint option was selected.
;;;
;;; dl_epo == DLine_End_Point_Option
;;;
(defun dl_epo ()
  (command "_.UNDO" "_GROUP")
  (initget 1)
  (setq cpt (getpoint "\nEndpoint: "))
  ;; Start the ARC command so that we can get visual dragging.
  (command "_.ARC" strtpt "_E" cpt)
  (initget "Angle Direction Radius Center")
  (setq nextpt (getkword "\nAngle/Direction/Radius/<Center>: "))
  (cond
    ((= nextpt "Angle")
      (prompt "\nIncluded angle: ")
      (command "_A" pause)
      (setq nextpt (dl_vnp)
            v:stpt nextpt
      )
      ;; Draw the arc segments.
      (dl_mlf 2)
    )
    ((= nextpt "Direction")
      (prompt "\nTangent direction: ")
      (command "_D" pause)
      (setq nextpt (dl_vnp)
            v:stpt nextpt
      )
      ;; Draw the arc segments.
      (dl_mlf 2)
    )         
    ((= nextpt "Radius")
      (setq temp T)
      (while temp
        (initget 1)
        (setq rad (getdist cpt "\nRadius: "))
        
        (if (or (<= rad (/ (getvar "tracewid") 2.0))
                (< rad (/ (distance strtpt cpt) 2.0)))
          (progn
            (princ "\nThe radius entered is less than 1/2 ")
            (princ "of the Dline width or is invalid")
            (princ "\nfor the selected endpoints.  ")
            (princ "Please enter a radius greater than ")
            (if (< (/ (getvar "tracewid") 2.0)
                   (/ (distance strtpt cpt) 2.0))
              (princ (rtos (/ (distance strtpt cpt) 2.0)))
              (princ (rtos (/ (getvar "tracewid") 2.0)))
            )
            (princ ". ")
          )
          (setq temp nil)
        )
      )
      (command "_R" rad)
      (setq nextpt (dl_vnp)
            v:stpt nextpt
      )
      ;; Draw the arc segments.
      (dl_mlf 2)
    )
    (T
      (prompt "\nCenter: ")
      (command pause)
      (setq nextpt (dl_vnp)
            v:stpt nextpt
      )
      ;; Draw the arc segments.
      (dl_mlf 2)
    )
  )
)
;;;
;;; Set the ending save points for capping the DLINE.
;;;
;;; dl_ssp == DLine_Set_Save_Points
;;;
(defun dl_ssp ( / temp)
  (setq temp (length savpts))
  (if (> temp 1)
    (progn
      (setq savpt3 (nth (- temp 2) savpts)
            savpt4 (nth (- temp 1) savpts)
      )
    )
  )
)
;;;
;;; Set the alignment of the "ghost" line to one of the following values:
;;;   
;;;   Left   == -1/2 of width (Real number)
;;;           > -1/2 of width (Real number)
;;;   Center == 0.0
;;;           < +1/2 of width (Real number)
;;;   Right  == +1/2 of width (Real number)
;;;
;;; All of the alignment options are taken as if you are standing at the
;;; start point of the line or arc looking toward the end point, with
;;; left and negative values being on the left, center or 0.0 being
;;; directly in line, and right or positive on the right.
;;;
;;; Entering a real number equal to 1/2 of the width sets an absolute offset
;;; distance from the centerline, while specifying the same offset distance
;;; with the keywords tells the routine to change the offset distance to
;;; match 1/2 of the width, whenever it is changed.
;;;
;;; NOTE:  If you wish to allow the dragline to be positioned outside
;;;      of the two arcs or lines being created, you may set the local
;;;      variable "dragos" = T, on the 4th line of the defun, which  
;;;      checks that the offset value entered is not greater or less
;;;      than + or - TRACEWID / 2.
;;;      
;;;      You should be aware that the results of allowing this to occur
;;;      may not be obvious or necessarily correct.  Specifically, when
;;;      drawing lines with a width of 1 and an offset of 4, if you draw
;;;      segments as follows, the lines will cross back on themselves.
;;;      
;;;      dl 0,0,0 10,0,0 10,5 then 5,5
;;;      
;;;      However, this can be quite useful for creating parallel DLINE's.
;;;      
;;; dl_sao == DLine_Set_Alignment_Option
;;;
(defun dl_sao (/ temp dragos)
  (initget "Left Center Right")
  (setq temp dl:osd)
  ;;(setq dragos T)                   ; See note above.
  (setq dl:osd (getreal (strcat
    "\nSet dragline position to Left/Center/Right/<Offset from center = "
    (rtos dl:osd) ">: ")))
  (cond
    ((= dl:osd "Left")
      (setq dl:aln 1
            dl:osd (- (/ (getvar "tracewid") 2.0))
      )
    )
    ((= dl:osd "Center")
      (setq dl:aln 0
            dl:osd 0.0
      )
    )
    ((= dl:osd "Right")
      (setq dl:aln 2
            dl:osd (/ (getvar "tracewid") 2.0)
      )
    )
    ((= (type dl:osd) 'REAL)
      (if dragos
        (setq dl:aln nil)
        (progn
          (setq dl:aln nil)
          (if (> dl:osd (/ (getvar "tracewid") 2.0))
            (progn
              (princ "\nValue entered is out of range.  Reset to ")
              (princ (/ (getvar "tracewid") 2.0))
              (setq dl:osd (/ (getvar "tracewid") 2.0))
            )
          )
          (if (< dl:osd (- (/ (getvar "tracewid") 2.0)))
            (progn
              (princ "\nValue entered is out of range.  Reset to ")
              (princ (- (/ (getvar "tracewid") 2.0)))
              (setq dl:osd (- (/ (getvar "tracewid") 2.0)))
            )
          )
        )
      )
    )
    (T
      (setq dl:osd temp)
    )
  )
)
;;;
;;; Set a new DLINE width.
;;;
;;; dl_snw == DLine_Set_New_Width
;;;
(defun dl_snw ()
  (initget 6)
  (setvar "tracewid"
    (if (setq temp (getdist (strcat
      "\nNew DLINE width <" (rtos (getvar "tracewid")) ">: ")))
      temp
      (getvar "tracewid")
    )
  )
  (if dl:aln
    (cond
      ((= dl:aln 1) ; left aligned
        (setq dl:osd (- (/ (getvar "tracewid") 2.0)))
      )
      ((= dl:aln 2) ; right aligned
        (setq dl:osd (/ (getvar "tracewid") 2.0))
      )
      (T
        (princ)     ; center aligned
      )
    )
  )
)
;;;
;;; Get an offset from a given point to the start point toward a second
;;; point.  The distance between the two points is the default, but any
;;; positive distance may be entered.  If a negative number is entered,
;;; it is used as a percentage distance from the "Offset from" point
;;; toward the "Offset toward" point, i.e., if -75 is entered, a point
;;; 75% of the distance between the two points listed above is returned.
;;;
;;;
;;; dl_ofs == DLine_OFfset_Startpoint
;;;
(defun dl_ofs ()
  (menucmd "s=osnapb")
  (initget 1)
  (setq strtpt (getpoint "\nOffset from: "))
  (initget 1)
  (setq nextpt (getpoint strtpt "\nOffset toward: "))
  
  (setq dist (getdist strtpt (strcat
    "\nEnter the offset distance <" (rtos (distance strtpt nextpt))
    ">: ")))
  (setq dist (if (or (= dist "") (null dist))
               (distance strtpt nextpt)
               (if (< dist 0)
                 (* (distance strtpt nextpt) (/ (abs dist) 100.0))
                 dist
               )
             )
  )              
  (setq strtpt (polar strtpt
                      (angle strtpt nextpt)
                      dist
               )
  )
  (setq temp nil)
  (command "_.UNDO" "_GROUP")
)
;;;
;;; Set snap options to ON, OFF or set the size of the area to be searched
;;; by (ssget point) via "pickbox".  This value is being limited for built-
;;; in display drivers at 10 pixels.  For ADI drivers it may be necessary
;;; to bump up this number by adjusting "MAXSNP" at the top of this file.
;;;
;;; dl_sso == DLine_Set_Snap_Options
;;;
(defun dl_sso ()
  (initget "ON OFf Size")
  (setq ans (getkword
    "\nSet snap size or snap On/Off.  Size/OFF/<ON>: "))
  (if (= ans "OFf")
    (progn
      (setq dl:snp nil)
      (setvar "pickbox" 0)
    )
    (if (= ans "Size")
      (progn
        (setq dl:snp T ans 0)
        (while (or (< ans 1) (> ans MAXSNP))
          (setq ans (getint (strcat
            "\nNew snap size (1 - " (itoa MAXSNP) ") <" (itoa dl:opb) ">: ")))

          (if (or (= ans "") (null ans))
            (setq ans dl:opb)
          )
        )
        (setvar "pickbox" ans)
        (setq dl:opb ans)
      )
      (progn
        (setq dl:snp T)
        (setvar "pickbox" dl:opb)
      )  
    )
  )
  (if dl:snp
    (if (= uctr 0)
      (dl_ved "brk_e1" strtpt)
    )
  )
  (if dl_arc
    (setq nextpt "Arc")
    (setq nextpt "Line")
  )

)
;;;
;;; Obtain and verify the extrusion direction of an entity at the
;;; start point or endpoint of the line or arc we are drawing.
;;;
;;; dl_ved == DLine_Verify_Extrusion_Direction
;;;
(defun dl_ved (vent pt)
  ;; Get entity to break if the user snapped to a DLINE.
  ;; Make sure that it is a line or arc and that its extrusion
  ;; direction is parallel to the current UCS.
  (if (set (read vent) (ssget pt))
    (progn
      (set (read vent) (ssname (eval (read vent)) 0))
      (if (and
            (or (= (dl_val 0 (eval (read vent))) "ARC")
                (= (dl_val 0 (eval (read vent))) "LINE")
            )
            (equal (caddr(dl_val 210 (eval (read vent))))
                   (caddr(trans '(0 0 1) 1 0)) 0.001)
          )
        (princ)
        (progn
          (princ (strcat
            "\nEntity found is not an arc or line, "
            "or is not parallel to the current UCS. "))
          (set (read vent) nil)
        )
      )
    )
  )
  (eval (read vent))
)
;;;
;;; Verify nextpt.
;;; Get the point on the arc at the opposite
;;; end from the start point (strtpt).
;;;
;;; dl_vnp == DLine_Verify_NextPt
;;;
(defun dl_vnp (/ temp cpt ang rad)

  (setq temp (entlast))
  (if (= (dl_val 0 temp) "LINE")
    (setq nextpt (if (equal strtpt (dl_val 10 temp) 0.001)
                   (dl_val 11 temp)
                   (dl_val 10 temp)
                 )
    )
    ;; Then it must be an arc...
    (progn
      ;; get its center point
      (setq cpt  (trans (dl_val 10 temp) (dl_val -1 temp) 1)
            ang  (dl_val 50 temp)     ; starting angle
            rad  (dl_val 40 temp)     ; radius
      )
      (setq ange (trans '(1 0 0) (dl_val -1 temp) 1)
            ange (angle '(0 0 0) ange)
            ang (+ ang ange)
      )
      (if (> ang (* 2 pi))
        (setq ang (- ang (* 2 pi)))
      )
      (setq nextpt (if (equal strtpt (polar cpt ang rad) 0.01)
                     (polar cpt (dl_val 51 temp) rad)
                     (polar cpt ang rad)
                   )
      )
    )
  )
)
;;; ----------------- Main Line Drawing Function -------------------
;;;
;;; Draw the lines.
;;;
;;; dl_mlf == DLine_Main_Line_Function
;;;
(defun dl_mlf (flg / temp1 temp2 newang ang1 ang2
                     ent cpt ang rad1 rad2 sent1 sent2
                     tmpt1 tmpt2 tmpt3 tmpt4)

  ;; Verify nextpt
  (if (null nextpt) (setq nextpt (dl_vnp)))
  
  (if (equal nextpt (nth 0 spts) 0.01)
    (if dl_arc
      (setq flg 4)
      (setq flg 3)
    )
  )
   
  (setq temp1  (+ (/ (getvar "tracewid") 2.0) dl:osd)
        temp2  (- (getvar "tracewid") temp1)
        newang (angle strtpt nextpt)
        ang1   (+ (angle strtpt nextpt) (/ pi 2))
        ang2   (- (angle strtpt nextpt) (/ pi 2))
  )
  (cond
    ((= flg 1)                        ; if drawing lines
      (dl_dls nil ang1 temp1)         ; Draw line segment 1
      (dl_dls nil ang2 temp2)         ; Draw line segment 2
    )
    ((or (= flg 2) (= flg 4))         ; else drawing arcs...
      (setq tmp (entlast)             ; get the last arc entity
            ent  (entget tmp)         ; (i.e., the guideline)
            ;; get its center point
            cpt  (trans (dl_val 10 tmp) (dl_val -1 tmp) 1)
            ang  (dl_val 50 tmp)      ; starting angle
      )
      (setq ange (trans '(1 0 0) (dl_val -1 tmp) 1)
            ange (angle '(0 0 0) ange)
            ang (+ ang ange)
      )
      (if (> ang (* 2 pi))
        (setq ang (- ang (* 2 pi)))
      )
     
      ;; if start angle needs revision
      (if (equal (angle cpt strtpt) ang 0.01)   
        (progn
          ;; Start angle needs revision.
          (setq strt_a T
                rad1  (+ (dl_val 40 tmp) temp2) ; outer radius
                rad2  (- (dl_val 40 tmp) temp1) ; inner radius
          )
          (setq ent (subst (cons 40 rad2) ; modify its radius
                           (assoc 40 ent)
                           ent))
          (entmod ent)
          (dl_atl)                    ; Add ename to list
          (setq save_1 ent)
          (setq sent1 (dl_val -1 tmp))                           
          (if (= flg 4)
            (if (> uctr 2)
              (dl_das 0 rad2 50)      ; modify arc endpt and close
            )
            (dl_das nil rad2 50)      ; else modify arc endpt
          )
          ;; Create the "parallel" arc
          (command "_.OFFSET" (getvar "tracewid") ; offset the arc
                              (list tmp '(0 0 0))
                              (polar cpt ang (+ 1 rad1 rad2))
                              "")
          (setq tmp (entlast)         ; get the offset arc
                ent  (entget tmp))
          (dl_atl)                    ; Add ename to list
          (setq save_2 ent)
          (setq sent2 tmp)
          (if (= flg 4)
            (if (> uctr 3)
              (progn
                (dl_das 1 rad1 50)    ; modify arc endpt and close

                ;; set nextpt to "CLose" which will cause an exit.
                (setq nextpt "CLose"
                      v:stpt nil
                      cont   nil
                )
              )
            )
            (dl_das nil rad1 50)      ; else modify arc endpt
          )

        )
        (progn                        ; if end angle needs revision
          ;; End angle needs revision.
          (setq strt_a nil
                rad1  (+ (dl_val 40 tmp) temp1) ; outer radius
                rad2  (- (dl_val 40 tmp) temp2) ; inner radius
          )
          (setq ent (subst (cons 40 rad1) ; modify its radius
                           (assoc 40 ent)
                           ent))
          (entmod ent)                             
          (dl_atl)                    ; Add ename to list
          (setq save_1 ent)
          (setq sent1 (dl_val -1 tmp))                           
          (if (= flg 4)
            (if (> uctr 2)
              (dl_das 0 rad1 51)      ; modify arc endpt and close
            )
            (dl_das nil rad1 51)      ; else modify arc endpt
          )
          ;; Create the "parallel" arc
          (command "_.OFFSET" (getvar "tracewid")   
                            (list tmp '(0 0 0))
                            cpt
                            "")
          (setq tmp (entlast)         ; get the last arc entity
                ent  (entget tmp))
          (dl_atl)                    ; Add ename to list
          (setq save_2 ent)
          (setq sent2 tmp)
          (if (= flg 4)
            (if (> uctr 3)
              (progn
                (dl_das 1 rad2 51)    ; modify arc endpt and close

                ;; set nextpt to "CLose" which will cause an exit.
                (setq nextpt "CLose"
                      v:stpt nil
                      cont   nil
                )
              )
            )
            (dl_das nil rad2 51)      ; else modify arc endpt
          )
        )
      )

    )
    ((= flg 3)                        ; if straight closing
      (setq nextpt (nth 0 spts)
            ang1   (+ (angle strtpt nextpt) (/ pi 2))
            ang2   (- (angle strtpt nextpt) (/ pi 2))
      )
      (dl_dls 0 ang1 temp1)
      (dl_dls 1 ang2 temp2)

      ;; set nextpt to "CLose" which will cause an exit.
      (setq nextpt "CLose"
            v:stpt nil
            cont   nil
      )
    )
    (T
      (princ "\nERROR:  Value out of range. ")
      (exit)
    )
  )
  (setq strtpt nextpt   
        spts   (append spts (list strtpt))
        savpts (append savpts (list savpt3))
        savpts (append savpts (list savpt4))
  )
  (command "_.UNDO" "_E")                ; only end when DLINE's have been drawn
)
;;; ------------------- End Support Functions -----------------------
;;; ---------------- Begin Line Drawing Functions -------------------
;;;
;;; Straight DLINE function
;;;
;;; dl_dls == DLine_Draw_Line_Segment
;;;
(defun dl_dls (flgn ang temp / j k pt1 pt2 tmp1 ent1 p1 p2)

  (mapcar                             ; get endpoints of the offset line
    '(lambda (j k)
       (set j (polar (eval k) ang temp))
     )      
     '(pt1 pt2)
     '(strtpt nextpt)
  )
  (cond
    ((= uctr 0)
      ;; Set points 1 and 2 for segment 1.
      (setq p1 (if (dl_l01 brk_e1 "1" pt1 pt2 strtpt) ipt savpt1))
      (setq pt2 (if (dl_l01 brk_e2 "3" pt2 pt1 nextpt) ipt savpt3))
      (setq pt1 p1)
    )
    ((= uctr 1)
      ;; Set points 1 and 2 for segment 2.
      (setq p1 (if (dl_l01 brk_e1 "2" pt1 pt2 strtpt) ipt savpt2))
      (setq pt2 (if (dl_l01 brk_e2 "4" pt2 pt1 nextpt) ipt savpt4))
      (setq pt1 p1)
      
      ;; Now break the line or arc found at the start point
      ;; if there is one, and we are in a breaking mood.
      (if (and dl:brk brk_e1)
        (progn
          (command "_.BREAK" brk_e1 savpt1 savpt2)
        )
      )
      ;; Now break the line or arc found at the end point
      ;; if there is one, and we are in a breaking mood.
      (if (and dl:brk brk_e2)
        (progn
          (if (eq brk_e1 brk_e2)
            (progn
              ;; Delete first line so we can find the arc or line that
              ;; we found previously.
              (entdel (nth 0 wnames))  
              (dl_ved "brk_e2" nextpt)
              ;; Restore first line
              (entdel (nth 0 wnames))
            )
          )
          (command "_.BREAK" brk_e2 savpt3 savpt4)
        )
      )
      ;; Do not set brk_e2 nil... it will be set later.
    )
    ((= (rem uctr 2.0) 0)   
      (setq fang nil)
      (setq p1 (dl_dl2 pt1))          ; Draw line part 2
      (setq pt2 (if (dl_l01 brk_e2 "3" pt2 pt1 strtpt)
                  ipt
                  savpt3
                )
      )
      (setq pt1 p1)
      (if flgn                        ; if closing
        (progn
          (setq tmp1 (nth flgn wnames)
                ent1 (entget tmp1)    ; get the corresponding prev. entity
          )
          (if (= (dl_val 0 tmp1) "LINE")
            ;; if it's a line
            (setq pt2 (dl_mls nil 10))           
            ;; if it's an arc
            (setq pt2 (dl_mas T nil pt2 pt1 nil))  
          )
        )                             
      )
    )
    (T
      (setq p1 (dl_dl2 pt1))              ; Draw line part 2
      (setq pt2 (if (dl_l01 brk_e2 "4" pt2 pt1 nextpt)
                  ipt
                  savpt4
                )
      )
      (setq pt1 p1)
      (if flgn                        ; if closing
        (progn
          (setq tmp1 (nth flgn wnames)
                ent1 (entget tmp1)    ; get the corresponding prev. entity
                brk_e1 nil
                brk_e2 nil
          )
          (if (= (dl_val 0 tmp1) "LINE")
            ;; if it's a line
            (setq pt2 (dl_mls nil 10))           
            ;; if it's an arc
            (setq pt2 (dl_mas T nil pt2 pt1 nil))  
          )
        )                             
      )
      ;; Now break the line or arc found at the end point
      ;; if there is one, and we are in a breaking mood.
      (if (and dl:brk brk_e2)
        (progn
          (command "_.BREAK" brk_e2 savpt3 savpt4)
        )
      )
      ;; Do not set brk_e2 nil... it will be set later.
    )
  )
  (command "_.LINE" pt1 pt2 "")         ; draw the line
  (setq wnames (if (null wnames)
                 (list (setq elast (entlast)) )
                 (append wnames (list (setq elast (entlast)))))
        uctr   (1+ uctr)
  )
  wnames
)
;;;
;;; Set pt1 or pt2 based on whether there is an arc or line to be broken.
;;;
;;; dl_l01 == DLine_draw_Lines_0_and_1
;;;
(defun dl_l01 (bent1 n p1 p2 pt / temp)
  (setq n (strcat "savpt" n))
  (setq spt nil)
  (if bent1
    (if (= (dl_val 0 bent1) "LINE")
      (progn
        (setq temp (inters (trans (dl_val 10 bent1) 0 1)
                            (trans (dl_val 11 bent1) 0 1)
                            p1
                            p2
                            nil
                    )
        )
        (if temp
          (set (read n) temp)
          (progn
            (set (read n) p1)
            (setq brk_e1 nil)
          )
        )
      )
      (progn
        (set (read n) (dl_ial bent1 p1 p2 pt))
        ;; Spt is set only if there was no intersection point.
        (if spt
          (progn
            (setq ipt (eval (read n)))
            (set (read n) spt)
          )
        )
      )
    )
    (set (read n) p1)
  )
  (if spt
    T
    nil
  )
)
;;;
;;; Do more of the line drawing stuff.  This is where we call the modify
;;; functions for the previous arc or line segment.  The line end being
;;; modified is always the group 11 end, but we have to test the start
;;; and end angle of an arc to tell which end to modify.
;;;
;;; dl_dl2 == DLine_Draw_Line_segment_part_2
;;;
(defun dl_dl2 (npt)
  (setq tmp1 (nth (- uctr 2) wnames)
        ent1 (entget tmp1))           ; get the corresponding prev. entity
   
  (if (= (dl_val 0 tmp1) "LINE")  
    ;; Check angles 0 180, -180  and 360...   
    (if (or  (equal (angle strtpt nextpt)
                   (angle (trans (dl_val 10 tmp1) 0 1)
                          (trans (dl_val 11 tmp1) 0 1)) 0.001)
             (equal (angle strtpt nextpt)
                   (angle (trans (dl_val 11 tmp1) 0 1)
                          (trans (dl_val 10 tmp1) 0 1)) 0.001)
             (equal (+ (* 2 pi) (angle strtpt nextpt))
                   (angle (trans (dl_val 10 tmp1) 0 1)
                          (trans (dl_val 11 tmp1) 0 1)) 0.001)
        )
      ;; if it's a line
      (progn
        (setq brk_e2 nil)
        (command "_.LINE" (trans (dl_val 11 tmp1) 0 1) pt1 "")
        pt1
      )
      ;; else, if it's an arc
      (progn
        (dl_mls nil 11)
      )
    )
    ;; if it's an arc
    (dl_mas nil nil pt1 pt2 strtpt)  
  )
)
;;;
;;; Modify line endpoint
;;;
;;; dl_mls == DLine_Modify_Line_Segment
;;;
(defun dl_mls (flg2 nn / spt ept pt)  ; flg2 = nil if line to line
                                      ;      = T   if line to arc

  ;; This is the previous entity; a line
  (setq spt (trans (dl_val 10 tmp1) 0 1)   
        ept (trans (dl_val 11 tmp1) 0 1)
  )
  (if flg2
    ;; find intersection with arc; tmp == ename of arc
    (progn
      ;; Find arc intersection with line; tmp == ename of arc.
      (setq pt (dl_ial tmp spt ept (if flgn nextpt strtpt)))
    )

    ;; find intersection with line
    (setq pt (inters spt ept pt1 pt2 nil))
  )
  ;; modify the previous line
  (if pt
    (entmod (subst (cons nn (trans pt 1 0))
                   (assoc nn ent1)
                   ent1))
    (setq pt pt2)
  )
  pt
)
;;;
;;; This routine does a variety of tasks: it calculate the distance from
;;; the center of the arc (or congruent circle) to a line, then it
;;; calculates up to two intersection points of a line and the arc,
;;; then it attempts to determine which of the points serves as a
;;; best-fit to the following criteria:
;;;
;;;   1) One end of the arc must lie "on" the line, or
;;;      one end of the line must lie on the arc.
;;;   2) Given that the point given in 1 above is p1,
;;;      and that the other point is p2, then if the arc crosses over
;;;      the line then use p2, otherwise the arc does not cross over
;;;      the line so use p1.
;;;      
;;; If the line and the arc do not intersect, then a line will be drawn
;;; from the point of intersection of the arc and the perpendicular from
;;; the line to the arc centerpoint, and the line;  The line and arc will be
;;; trimmed or extended as needed to meet these points.
;;;
;;; If the line and arc are tangent, then the arc and line are
;;; trimmed/extended to this point.
;;;
;;; p1 and p2 are two points on a line
;;; ename  == entity name of arc
;;; flg == T when the segment being drawn ends on an arc,
;;; flg == nil when the segment being drawn starts on an arc.
;;;
;;; dl_ial == DLine_Intersect_Arc_with_Line
;;;
(defun dl_ial (arc pt_1 pt_2 npt / d pi2 rad ang nang temp ipt)

  (setq cpt  (trans (dl_val 10 arc) (dl_val -1 arc) 1)  
        pi2  (/ pi 2)                 ; 1/2 pi
        ang  (angle pt_1 pt_2)                  
        nang (+ ang pi2)              ; Normal to "ang"
        temp (inters pt_1 pt_2 cpt (polar cpt nang 1) nil)
        nang (angle cpt temp)
  )
  ;; Get the perpendicular distance from the center of the arc to the line.
  (setq d (distance cpt temp))

  (cond
    ((equal (setq rad (dl_val 40 arc)) d 0.01)
      ;; One intersection.
      (setq ipt temp)
    )
    ((< rad d)                       
      ;; No intersection.
      (setq spt (polar cpt nang rad)
            ipt temp
      )
      (command "_.LINE" spt ipt "")
      ipt
    )
    (T
      ;; Two intersections. Now...
      ;; If drawing arcs, fang is set, we're past the first segment...
      ;; Reset the `near' point based on the previous ipt.  This can be
      ;; quite different and necessary from the `npt' passed in.
      (if (and dl_arc fang (> uctr 1))
        (setq npt (polar cpt fang rad))
      )
      (dl_g2p npt)
      (setq ipt (dl_bp arc pt_1 pt_2 ipt1 ipt2))
      ;; If `fang' is not set, set it, otherwise set it to nil.
      (if fang
        (setq fang nil)
        (if dl_arc (setq fang (angle cpt ipt)))
      )
      ipt
    )
  )
)
;;;
;;; Get two intersection points, ordering them such that ipt1
;;; is the closer of the two points to the passed-in point "npt".
;;;
;;; dl_g2p == DLine_Get_2_Points
;;;
(defun dl_g2p (npt / temp l theta)
  (if (equal d 0.0 0.01)
    (setq theta pi2
          nang (+ ang pi2)            ; Normal to "ang"
    )
    (setq l     (sqrt (abs (- (expt rad 2) (expt d 2))))
          theta (abs (atan (/ l d)))
    )
  )
  ;; Get the two angles to the infinite intersection points of the
  ;; congruent circle to the arc, and the line, then get the two
  ;; intersection points.
  (setq ipt1 (polar cpt (- nang theta) rad))
  (setq ipt2 (polar cpt (+ nang theta) rad))
  ;; Set the closer of the two points to npt to be ipt1.
  (if (< (distance ipt2 npt) (distance ipt1 npt))
    ;; Swap points
    (setq temp ipt1
          ipt1 ipt2
          ipt2 temp
    )
    (if (equal (distance ipt2 npt) (distance ipt1 npt) 0.01)
      (exit)
    )
  )
  ipt1
)
;;;
;;; Test a point `pt' to see if it is on the line `sp--ep'.
;;;
;;; dl_onl == DLine_ON_Line_segment
;;;
(defun dl_onl (sp ep pt / cpt sa ea ang)
  (if (inters sp ep pt
              (polar pt (+ (angle sp ep) (/ pi 2))
                     (/ (getvar "tracewid") 10)
              )
              T)
    T
    nil
  )
)
;;;
;;; Test a point `pt' to see if it is on the arc `arc'.
;;;
;;; dl_ona == DLine_ON_Arc_segment
;;;
(defun dl_ona (arc pt / cpt sa ea ang)
  (setq cpt (trans (dl_val 10 arc) (dl_val -1 arc) 1)
        sa  (dl_val 50 arc)           ; angle of current ent start point
        ea  (dl_val 51 arc)           ; angle of current ent end point
        ang (angle cpt pt)            ; angle to pt.
  )
  (if (> sa ea)
    (if (or (and (> ang sa) (< ang (+ ea (* 2 pi))))
            (and (> ang (- ea (* 2 pi))) (< ang ea))
        )
      T
      nil
    )
    (if (and (> ang sa) (< ang ea)) T nil)
  )
)
;;;
;;; Get the best intersection point of an arc and a line.  The criteria
;;; are as follows:
;;;
;;;   1) The best point will lie on both the arc and the line.
;;;   2) It will be the point which causes the shortest arc to be created
;;;      such that (1) is satisfied.
;;;   3) If closing, then always use the point closest to nextpt.  Unless,
;;;      the points are equidistant, then use 1 and 2 above to tiebreak.
;;;   4) If breaking an arc with a line, always use the points nearest the
;;;      break point.
;;;
;;; dl_bp == DLine_Best_Point_of_arc_and_line
;;;
(defun dl_bp (en1 p1 p2 pp1 pp2 / temp temp1 temp2)
  (setq temp1 (dl_onl p1 p2 pp2)
        temp2 (dl_ona en1 pp2)
        temp  (if (or (= flg 1) (= flg 3)) T nil)
  )
  (if (and temp1 temp2)
    (if (and (< uctr 2)
             (and brk_e1 brk_e2))
      pp1
      (if (and temp (not fang)) pp1 pp2)
    )
    pp1
  )
)
;;; ----------------- End Line Drawing Functions --------------------
;;; ---------------- Begin Arc  Drawing Functions -------------------
;;;
;;; Draw curved DLINE
;;;
;;; dl_das == DLine_Draw_Arc_Segment
;;;
(defun dl_das (flgn orad nn / tmp1 ent1 pt ang )
  (cond
    ((= uctr 0)
      (setq sent1 tmp)
      (dl_a01 brk_e1 "1" strtpt nil)  ; DLine_draw_Arc_0_and_1
      (dl_a01 brk_e2 "3" nextpt T)    ; DLine_draw_Arc_0_and_1
    )
    ((= uctr 1)
      (setq sent1 tmp)
      (dl_a01 brk_e1 "2" strtpt nil)  ; DLine_draw_Arc_0_and_1
      (dl_a01 brk_e2 "4" nextpt T)    ; DLine_draw_Arc_0_and_1
      (dl_mae nil T)
      (dl_mae nil nil)
      ;; Now break the line or arc found at the start point
      ;; if there is one, and we are in a breaking mood.
      (if (and dl:brk brk_e1)
        (progn
          (dl_mae T T)
          (dl_mae T nil)
          (command "_.BREAK" brk_e1 savpt1 savpt2)
        )
      )
      ;; Do not set brk_e1 nil... it will be set later.
      ;; Now break the line or arc found at the end point
      ;; if there is one, and we are in a breaking mood.
      (if (and dl:brk brk_e2)
        (progn
          (if (eq brk_e1 brk_e2)
            (progn
              ;; Delete both arcs so we can find the arc or line that
              ;; we found previously.
              (entdel (nth 0 wnames))  
              (entdel (nth 1 wnames))  
              (dl_ved "brk_e2" nextpt)
              ;; Restore first line
              (entdel (nth 0 wnames))
              (entdel (nth 1 wnames))
            )
          )
          (if (null brk_e1)
            (progn
              (dl_mae T T)
              (dl_mae T nil)
            )
          )
          (command "_.BREAK" brk_e2 savpt3 savpt4)
        )
      )
      ;; Do not set brk_e2 nil... it will be set later.
    )
    ((= (rem uctr 2.0) 0)
      (setq fang nil)
      (dl_da2)                        ; Draw arc part 2
      (if fang
        (setq ftmp fang
              fang nil
        )
      )
      (setq save_1 ent)
      (setq sent1 (cdr(assoc -1 ent)))
      (setq pt2 (dl_a01 brk_e2 "3" nextpt T)) ; DLine_draw_Arc_0_and_1
      (if ftmp
        (setq fang ftmp
              ftmp nil
        )
      )
    )
    (T
      (dl_da2)                        ; Draw arc part 2
      (if fang
        (setq ftmp fang
              fang nil
        )
      )
      (setq save_2 ent)
      (setq sent1 (cdr(assoc -1 ent)))
      (setq pt2 (dl_a01 brk_e2 "4" nextpt T)) ; DLine_draw_Arc_0_and_1
      (if ftmp
        (setq fang fang
              ftmp nil
        )
      )

      ;; Now break the line or arc found at the end point
      ;; if there is one, and we are in a breaking mood.
      (if (and dl:brk brk_e2)
        (progn
          (dl_mae T T)
          (dl_mae T nil)
          (command "_.BREAK" brk_e2 savpt3 savpt4)
        )
      )
      ;; Do not set brk_e2 nil... it will be set later.
    )
  )
  (setq uctr   (1+ uctr))
)
;;;
;;; Set pt1 or pt2 based on whether there is an arc or line to be broken.
;;;
;;; dl_a01 == DLine_draw_Arcs_0_and_1
;;;
(defun dl_a01 (bent1 n pt flg / pt1 pt2 ang1 ang2 anga angb)
  ;; "n" is the point to save for end capping
  (setq n (strcat "savpt" n))
  ;; "tmp" is the arc just created.
  ;; "bent1" is the line or arc to be broken, if there is one...
  (if bent1
    (if (= (dl_val 0 bent1) "LINE")
      (progn
        (set (read n) (dl_ial tmp (trans (dl_val 10 bent1) 0 1)
                                  (trans (dl_val 11 bent1) 0 1) pt))
      )
      (progn
        (setq curcpt (trans (dl_val 10 sent1) (dl_val -1 sent1) 1)
              prvcpt (trans (dl_val 10 bent1) (dl_val -1 bent1) 1)
              pt1    (polar prvcpt (dl_val 50 bent1) (dl_val 40 bent1))
              pt2    (polar curcpt (dl_val nn sent1) (dl_val 40 sent1))
              ang1   (angle prvcpt pt1)
        )
        (if (not (equal ang1 (angle prvcpt strtpt) 0.01))
          (setq pt1  (polar prvcpt (dl_val 51 bent1) (dl_val 40 bent1))
                ang1 (angle prvcpt pt1)
                ang2 (angle curcpt pt2)
                anga (- ang1 ang2)
                angb (- ang2 ang1)
          )
        )
        (if (or (and (< anga 0.0872665)
                     (> anga -0.0872665))
                (and (< angb 0.0872665)
                     (> angb -0.0872665))
            )
          (progn
            (set (read n) pt)
            (if (= bent1 brk_e1)
              (setq brk_e1 nil)
              (setq brk_e2 nil)
            )
          )
          (set (read n) (dl_iaa sent1 bent1 pt flg))
        )
      )
    )
    (progn
      (setq cpt (trans (dl_val 10 tmp) (dl_val -1 tmp) 1))
      (set (read n) (polar cpt (angle cpt pt) orad))
    )
  )
  (eval (read n))
)
;;;
;;; Do more of the arc drawing stuff.  This is where we call the modify
;;; functions for the previous arc or line segment.  The line end being
;;; modified is always the group 11 end, but we have to test the start
;;; and end angle of an arc to tell which end to modify.
;;;
;;; dl_da2 == DLine_Draw_Arc_segment_part_2
;;;
(defun dl_da2 (/ pt)
  ;; get the corresponding previous entity
  (setq tmp1 (nth (- uctr 2) wnames)
        ent1 (entget tmp1))
  (if (= (dl_val 0 tmp1) "LINE")     
    ;; if it's a line
    (setq pt (dl_mls T 11))            
    ;; if it's an arc
    (setq pt (dl_mas nil T nil nil strtpt))
  )
  ;; pt is a point in the current UCS, not ECS
  (if pt
    (progn
      (setq ang (- (angle cpt pt) ange))
      (entmod (setq ent (subst (cons nn ang)
                       (assoc nn ent)
                       ent)))         ; modify arc endpt
    )
  )
  (if flgn                            ; if closing
    (progn
      (setq tmp1 (nth flgn wnames)     
            ent1  (entget tmp1))  ; get the flagged entity
      (if (= (dl_val 0 tmp1) "LINE")     
        ;; if it's a line
        (setq pt (dl_mls T 10))   
        ;; if it's an arc
        (setq pt (dl_mas T T nil nil nextpt))
      )
      (if pt
        (progn
          (setq ang (- (angle cpt pt) ange))
          (setq nn (if (= nn 50) 51 50))
          (entmod (setq ent (subst (cons nn ang)
                         (assoc nn ent)
                         ent)))       ; modify arc endpt
        )                             
      )
    )                             
  )
)
;;;
;;; Modify the endpoints of an arc by changing the start and end angles.
;;;
;;; dl_mae == DLine_Modify_Arc_Endpoints
;;;
(defun dl_mae (eflg sflg / nn1 nn2)
  (if (= nn 50)
    (setq nn1 50 nn2 51)
    (setq nn1 51 nn2 50)
  )
  (if sflg
    (if eflg
      (setq save_1 (subst (cons nn2
                                (angle
                                  (trans cpt    1 (cdr(assoc -1 save_1)))
                                  (trans savpt3 1 (cdr(assoc -1 save_1)))
                                )
                          )
                          (assoc nn2 save_1) save_1)
      )
      (setq save_1 (subst (cons nn1
                                (angle
                                  (trans cpt    1 (cdr(assoc -1 save_1)))
                                  (trans savpt1 1 (cdr(assoc -1 save_1)))
                                )
                          )
                          (assoc nn1 save_1) save_1)
      )
    )
    (if eflg
      (setq save_2 (subst (cons nn2
                                (angle
                                  (trans cpt    1 (cdr(assoc -1 save_1)))
                                  (trans savpt4 1 (cdr(assoc -1 save_2)))
                                )
                          )
                          (assoc nn2 save_2) save_2)
      )
      (setq save_2 (subst (cons nn1
                                (angle
                                  (trans cpt    1 (cdr(assoc -1 save_1)))
                                  (trans savpt2 1 (cdr(assoc -1 save_2)))
                                )
                          )
                          (assoc nn1 save_2) save_2)
      )
    )
  )
  (if sflg
    (entmod save_1)
    (entmod save_2)
  )
)
;;;
;;; Modify arc                        ; flg2 = nil if arc to line
;;;                                   ;      = T   if arc to arc
;;;
;;; dl_mas == DLine_Modify_Arc_Segment
;;;
(defun dl_mas (flg3 flg2 spt ept pt / nnn pt1 pt2 rad1 ange)
  ;; get some stuff
  (setq cpt1   (trans (dl_val 10 tmp1) (dl_val -1 tmp1) 1)           
        rad1   (dl_val 40 tmp1)
        ang1   (dl_val 50 tmp1)
  )
  (if (null pt)                       ; if a point is not passed in:
    (setq pt (nth 0 spts))            ; set to initial saved start point.
  )               
  (setq ange (trans '(1 0 0) (dl_val -1 tmp1) 1)
        ange (angle '(0 0 0) ange)
        ang1 (+ ang1 ange)
  )
  (if (> ang1 (* 2 pi))
    (setq ang1 (- ang1 (* 2 pi)))
  )
  (if (equal (angle cpt1 pt) ang1 0.01) ; figure out if we're looking
    (setq nnn 50)                     ; for the start or end point of
    (setq nnn 51)                     ; the beginning arc, then
  )                                   ; get the intersection point
  ;; if arc to arc
  (if flg2
    ;; then
    (progn
      ;; find intersection with arc
      (setq pt1 (dl_iaa tmp tmp1 (if flg3 nextpt strtpt) flg2))   
      (if pt1
        (progn
          (setq ang1 (- (angle cpt1 pt1) ange))
          (setq ent1 (subst (cons nnn ang1)
                            (assoc nnn ent1)
                            ent1))                 
          (entmod ent1)               ; modify arc endpt
        )
      )
    )
    ;; else
    (progn
      ;; find arc intersection with line from spt to ept
      (setq pt1 (dl_ial tmp1 spt ept pt))
      (setq ang1 (- (angle cpt1 pt1) ange))
      (setq ent1 (subst (cons nnn ang1)
                        (assoc nnn ent1)
                        ent1))                 
      (entmod ent1)                   ; modify arc endpt
    )
  )
  pt1
)
;;; ---------------- Begin Arc to Arc Functions ---------------------
;;;
;;; This routine does a variety of tasks: it calculate up to two
;;; intersection points of two arcs,
;;; then it attempts to determine which of the points serves as a
;;; best-fit to the following criteria:
;;;
;;;   1) One end of the arc must lie "on" the arc.
;;;   2) Given that the point given in 1 above is pt1,
;;;      and that the other point is pt2, then if the arc crosses over
;;;      the other arc then use pt2, otherwise the arc does not cross over
;;;      the other arc so use pt1.
;;;      
;;; If the two arcs do not intersect, then a line will be drawn
;;; from the point of intersection of the arc and the perpendicular from
;;; the line of the two arc centerpoints;  The arcs will be
;;; trimmed or extended as needed to meet these points.
;;;
;;; If the two arcs are tangent, then they are
;;; trimmed/extended to this point.
;;;
;;; Intersection point of two arcs or circles
;;; a    = radius of ename 1
;;; b    = distance from curcpt to prvcpt
;;; c    = radius of ename 2
;;; curcpt = center point of first circle or arc  -- bent1, bent2, tmp
;;; prvcpt = center point of second circle or arc -- sent1, sent2, tmp1
;;; npt  = near point for nearest test
;;;
;;; dl_iaa == DLine_Intersect_Arc_and_Arc
;;;
(defun dl_iaa  (en1 en2 npt flga / a b c s ang alpha alph ipt
                                   curcpt prvcpt temp temp1 temp2)
  (setq curcpt  (trans (dl_val 10 en1) (dl_val -1 en1) 1) ; the "last" entity
        prvcpt  (trans (dl_val 10 en2) (dl_val -1 en2) 1) ; the previous entity
        a       (dl_val 40 en2)
        b       (distance curcpt prvcpt)
        c       (dl_val 40 en1)
        s       (/ (+ a b c) 2.0)
        ang     (angle curcpt prvcpt)
  )
  (cond
    ;; circles are tangent
    ;; If (- s a) == 0, this would cause a divide by zero below...
    ((or (= (- s a) 0) (equal b (+ a c) 0.001) (equal b (abs (- a c)) 0.001))
      ;; Circles are tangent.
      (setq ipt nil)
    )
    ;; circles do not intersect
    ((and (or (> b (+ a c)) (if (> c a) (< (+ a b) c) (< (+ c b) a)))                 
          (not (equal (+ a b ) c (/ (+ a b c) 1000000))))
      ;; No intersection.
      (if (= flg 4)
        (progn
          (setq ipt (polar curcpt (angle curcpt prvcpt) c))
          (command "_.LINE" (polar prvcpt (angle prvcpt ipt) a) ipt "")
        )
        (progn
          (setq ipt (polar curcpt (angle curcpt prvcpt) c))
          (command "_.LINE" (polar prvcpt (angle prvcpt ipt) a) ipt "")
        )
      )
    )
    (T
      ;; general law of cosines formula -- (- s a) != 0
      (setq alpha (* 2.0 (atan (sqrt (abs (/ (* (- s b) (- s c))
                                             (* s (- s a)))))))
      )
      
      (setq tpt1 (polar curcpt (+ ang alpha) c)
            tpt2 (polar curcpt (- ang alpha) c)
            anga  (angle curcpt npt)
            angb  (angle prvcpt npt)
      )
      ;; Two intersections. Now...
      ;; If drawing arcs, fang is set, we're past the first segment...
      ;; Reset the `near' point based on the previous ipt.  This can be
      ;; quite different and necessary from the `npt' passed in.
      (if (and dl_arc fang (> uctr 1))
        (setq npt (polar prvcpt fang c))
      )
      (if (< (distance tpt1 npt) (distance tpt2 npt))
        (setq temp tpt1
              tpt1 tpt2
              tpt2 temp
        )
      )
      (setq temp (angle prvcpt curcpt)) ; angle from prev ent to this ent
      (setq ipt (dl_bap en1 en2 tpt2 tpt1 nil))
      (if fang
        (setq fang nil)
        (if dl_arc (setq fang (angle cpt ipt)))
      )
    )
  )
  (setq cpt curcpt)
  (setq cpt1 prvcpt)
  ipt                                 ; return point
)
;;;
;;; Get the best point for the arc/arc intersection.
;;;
;;; dl_bap == DLine_Best_Point_to_Arc
;;;
(defun dl_bap (en1 en2 pp1 pp2 flg / temp1 temp2)
  (setq temp1 (dl_ona en1 pp2)
        temp2 (dl_ona en2 pp2)
  )
  (if temp2
    (if (and (< uctr 2)
             (and brk_e1 brk_e2))
      pp1
      (if temp1
        (if (< uctr 2)
          pp2
          (if (not fang) pp2 pp1)
        )
        pp1
      )
    )
    pp1
  )        
)
;;; ----------------- End Arc  Drawing Functions --------------------
;;; -------------------- Begin Misc Functions -----------------------
;;;
;;; Add the entity name to the list in wnames.
;;;
;;; dl_atl == DLine_Add_To_List
;;;
(defun dl_atl ()
  (setq wnames (if (null wnames)
                 (list (entlast))
                 (append wnames (list tmp)))
  )
  wnames
)
;;;
;;; The value of the assoc number of <ename>
;;;
(defun dl_val (v temp)
  (cdr(assoc v (entget temp)))
)
;;;
;;; List stripper : strips the last "v" members from the list
;;;
(defun dl_lsu (lst v / m)
  (setq m 0 temp '())
  (repeat (- (length lst) v)
    (progn
      (setq temp (append temp (list (nth m lst))))
      (setq m (1+ m))
  ) )
  temp
)
;;;
;;; Bitwise DLINE endcap setting function.
;;;
(defun endcap ()
  (initget "Auto Both End None Start")
  (setq dl:ecp (getkword
    "\nDraw which endcaps?  Both/End/None/Start/<Auto>: "))
  (cond
    ((= dl:ecp "None")
      (setq dl:ecp 0)
    )
    ((= dl:ecp "Start")
      (setq dl:ecp 1)
    )
    ((= dl:ecp "End")
      (setq dl:ecp 2)
    )
    ((= dl:ecp "Both")
      (setq dl:ecp 3)
    )
    (T  ; Auto
      (setq dl:ecp 4)
    )
  )
)
;;;
;;; Set these defaults when loading the routine.
;;;
(if (null dl:ecp) (setq dl:ecp 4))    ; default to auto endcaps
(if (null dl:snp) (setq dl:snp T))    ; default to snapping ON
(if (null dl:brk) (setq dl:brk T))    ; default to breaking ON
(if (null dl:osd) (setq dl:osd 0))    ; default to center alignment
;;;
;;; These are the c: functions.
;;;
(defun c:dl()
  (if (ai_notrans) (dline))           ; DLINE can't be used transparently
)
(defun c:dline()
  (if (ai_notrans) (dline))           ; DLINE can't be used transparently
)

(princ "  DLINE loaded.")
(princ)

[/php]
论坛插件加载方法
发帖求助前要善用【论坛搜索】功能,那里可能会有你要找的答案;
如果你在论坛求助问题,并且已经从坛友或者管理的回复中解决了问题,请把帖子标题加上【已解决】;
如何回报帮助你解决问题的坛友,一个好办法就是给对方加【D豆】,加分不会扣除自己的积分,做一个热心并受欢迎的人!
回复 支持 反对

使用道具 举报

已领礼包: 3个

财富等级: 恭喜发财

发表于 2006-6-30 17:27:28 | 显示全部楼层
看得头都晕了!着急是不懂E文。其实我在4楼说的方法可以一试,还可以绘出带凸度的多线
论坛插件加载方法
发帖求助前要善用【论坛搜索】功能,那里可能会有你要找的答案;
如果你在论坛求助问题,并且已经从坛友或者管理的回复中解决了问题,请把帖子标题加上【已解决】;
如何回报帮助你解决问题的坛友,一个好办法就是给对方加【D豆】,加分不会扣除自己的积分,做一个热心并受欢迎的人!
回复 支持 反对

使用道具 举报

发表于 2006-6-30 17:44:37 | 显示全部楼层
你的另一条线,难度跟你绘的线没有任何联系吗?说出这二条线之间的关系,这样才有可能帮到你啊。
论坛插件加载方法
发帖求助前要善用【论坛搜索】功能,那里可能会有你要找的答案;
如果你在论坛求助问题,并且已经从坛友或者管理的回复中解决了问题,请把帖子标题加上【已解决】;
如何回报帮助你解决问题的坛友,一个好办法就是给对方加【D豆】,加分不会扣除自己的积分,做一个热心并受欢迎的人!
回复 支持 反对

使用道具 举报

发表于 2006-6-30 19:13:07 | 显示全部楼层
有点乱,不容易理解楼主的意思
论坛插件加载方法
发帖求助前要善用【论坛搜索】功能,那里可能会有你要找的答案;
如果你在论坛求助问题,并且已经从坛友或者管理的回复中解决了问题,请把帖子标题加上【已解决】;
如何回报帮助你解决问题的坛友,一个好办法就是给对方加【D豆】,加分不会扣除自己的积分,做一个热心并受欢迎的人!
回复 支持 反对

使用道具 举报

发表于 2006-7-1 08:17:14 | 显示全部楼层
简单问题复杂化,你的问题好像和多线没什么关系:)
或者你的表述有问题?
论坛插件加载方法
发帖求助前要善用【论坛搜索】功能,那里可能会有你要找的答案;
如果你在论坛求助问题,并且已经从坛友或者管理的回复中解决了问题,请把帖子标题加上【已解决】;
如何回报帮助你解决问题的坛友,一个好办法就是给对方加【D豆】,加分不会扣除自己的积分,做一个热心并受欢迎的人!
回复 支持 反对

使用道具 举报

 楼主| 发表于 2006-7-3 09:48:21 | 显示全部楼层
最初由 Dream.Fei 发布
[B]你的另一条线,难度跟你绘的线没有任何联系吗?说出这二条线之间的关系,这样才有可能帮到你啊。 [/B]


我说的不清,是要有联系。但这个联系是要有变化,或说主观可以选择的。楼上有同学说和多线没什么关系,其实我也不知道和多线的实质有多大关系,只是要求绘制过程类似多线,但又有不同:
1。假设我绘制多线,我需要定制一下,比如偏移距离是10;然后我绘制一条线,随之会有一条偏移距离为10的平行线同时绘制出来,随着转折,平行线也跟着转折,直到绘制完毕
2。我要的,和这个类似,但重要的不同点,是我要的随之生成的线不一定平行,比如a1与b1距离是10,画到a2点时,b2与a2的距离要求是20——这个可以是事先定制,也可能是在绘制过程输入,然后的a3和b3的间距是20或30或10(根据需求)。

谢谢4楼,你的思路很巧妙,我想想

谢谢5楼,非常好的资料,谢谢
论坛插件加载方法
发帖求助前要善用【论坛搜索】功能,那里可能会有你要找的答案;
如果你在论坛求助问题,并且已经从坛友或者管理的回复中解决了问题,请把帖子标题加上【已解决】;
如何回报帮助你解决问题的坛友,一个好办法就是给对方加【D豆】,加分不会扣除自己的积分,做一个热心并受欢迎的人!
回复 支持 反对

使用道具 举报

已领礼包: 3个

财富等级: 恭喜发财

发表于 2006-7-3 12:30:38 | 显示全部楼层
就按我在4楼说的方法完全可以达到你的目的
论坛插件加载方法
发帖求助前要善用【论坛搜索】功能,那里可能会有你要找的答案;
如果你在论坛求助问题,并且已经从坛友或者管理的回复中解决了问题,请把帖子标题加上【已解决】;
如何回报帮助你解决问题的坛友,一个好办法就是给对方加【D豆】,加分不会扣除自己的积分,做一个热心并受欢迎的人!
回复 支持 反对

使用道具 举报

发表于 2006-7-6 11:19:23 | 显示全部楼层
写了一段可以变宽度的双线画法
过程:
1)取点
2)根据变化的宽度得到每条线向两边offset的距离
(其中,w1是线左边的起点和终点宽度,w1是起点宽度,w1a是终点宽度,
w2是线左边的起点和终点宽度,w2是起点宽度,w2a是终点宽度,W1和W2中,假如起始终点一样,就是普通的双线了)
在这个程序中,采用了某种模式来构建全线长的宽度
比如给了w1=2 w1a=8
那么就构建了一种(2 8 8 2 2 8 8 2),奇数段用2为起始宽度,8为终点宽度,偶数段取8,2 为起终点宽度的做法,函数是makew,假如自己建立一个宽度列表也是可以的,本程序中的做法只是为了显示效果,便于求交而已。
3)得到偏移线之后,求交,得到修剪线型
4)构建pline

程序没有什么难度和技巧,也有不少地方不足,比如采用grdraw,在缩放时这些临时画的线会丢失等等,不过说真的,我不知道变化线宽有什么必要呢,至少我自己没有遇到过。

图片不知道为什么不能显示
传到这里看看
http://autolisper.googlepages.co ... idthchange-full.jpg



  1. ;;;=============================================
  2. ;;;Most of the following codes are writen by   ;
  3. ;;; CHEN QING JUN                              ;
  4. ;;; Civil engineering Department,              ;
  5. ;;; South China University of Technology       ;
  6. ;;; [url]http://autolisper.googlepages.com[/url]          ;
  7. ;;; [url]http://autolisper.googlepages.com[/url]          ;
  8. ;;; Purpose:Draw different width double line   ;
  9. ;;; 2006.07.02                                 ;
  10. ;;; Version:0.1                                ;
  11. ;;; ============================================

  12. ;;;Main function
  13. (defun c:test (/ p1 plist w1 w1a w2 w2a w1lst w2lst anglist seglist
  14. seg1list seg2list)
  15. (setq w1 2
  16.         w1a 10
  17.         w2 8
  18.         w2a 15
  19.   )
  20.   (setq w1lst (makew w1 w1a 100))
  21.   (setq w2lst (makew w2 w2a 100))
  22.   (setq plist (getpointlst w1lst w2lst))
  23.   (setq anglist (mapcar
  24.                   '(lambda (x y)
  25.                      (angle x y)
  26.                    )
  27.                   (1ton_1 plist)
  28.                   (cdr plist)
  29.                 )
  30.   )
  31.   (setq seglist (mapcar
  32.                   '(lambda (x y)
  33.                      (cons x (list y))
  34.                    )
  35.                   (1ton_1 plist)
  36.                   (cdr plist)
  37.                 )
  38.   )
  39.   (setq w1lst (makew w1 w1a (length seglist)))
  40.   (setq w2lst (makew w2 w2a (length seglist)))
  41.   (setq seg1list (segxlist seglist anglist 1 w1lst))
  42.   (setq seg2list (segxlist seglist anglist (- 1) w2lst))
  43.   (setq seg1list (intlst seg1list))
  44.   (setq seg2list (intlst seg2list))
  45.   (entmakepolyline seg1list)
  46.   (entmakepolyline seg2list)
  47. )
  48. ;;;getpointlist
  49. (defun getpointlst (w1lst w2lst / plist p1 p i)
  50.   (setq p1 (getpoint))
  51.   (setq plist (append
  52.                 plist
  53.                 (list p1)
  54.               )
  55.   )
  56.   (setq i 0)
  57.   (while (setq p (getpoint p1))
  58.     (grdraw p1 p 9)
  59.     (tempgrdraw p1 p i w1lst w2lst)
  60.     (setq plist (append
  61.                   plist
  62.                   (list p)
  63.                 )
  64.     )
  65.     (setq p1 p)
  66.     (setq i (1+ i))
  67.   )
  68.   plist
  69. )
  70. ;;;tempdraw
  71. (defun tempgrdraw (p1 p2 n lst1 lst2 / ang)
  72.   (setq ang (angle p1 p2))
  73.   (grdraw (polar p1 (+ ang (* pi 0.5)) (1- (nth (* n 2) lst1)))
  74.           (polar p2 (+ ang (* pi 0.5)) (1- (nth (1+ (* n 2)) lst1))) 251
  75.   )
  76.   (grdraw (polar p1 (+ ang (* pi 1.5)) (1- (nth (* n 2) lst2)))
  77.           (polar p2 (+ ang (* pi 1.5)) (1- (nth (1+ (* n 2)) lst2))) 251
  78.   )
  79. )

  80. ;; get the 1 to (n-1) element of a list
  81. (defun 1ton_1 (lst)
  82.   (reverse (cdr (reverse lst)))
  83. )
  84. ;;;to get the offset segment of two side line
  85. (defun segxlist (lst lst1 direction wlst / i res xa xb x1a x1b)
  86.   (setq i 0)
  87.   (if (= direction 1)
  88.     (setq ang (* pi 0.5))
  89.     (setq ang (* pi 1.5))
  90.   )
  91.   (foreach x lst
  92.     (setq xa (car x)
  93.           xb (cadr x)
  94.     )
  95.     (setq x1a (polar xa (+ ang (nth i lst1)) (nth (* i 2) wlst)))
  96.     (setq x1b (polar xb (+ ang (nth i lst1)) (nth (1+ (* i 2)) wlst)))
  97.     (setq res (append
  98.                 res
  99.                 (list x1a x1b)
  100.               )
  101.     )
  102.     (setq i (1+ i))
  103.   )
  104.   res
  105. )
  106. ;;;;find the inter intersections of a list of points
  107. (defun intlst (lst / i res p1 p2 p3 p4)
  108.   (setq i 0)
  109.   (setq res (list (car lst)))
  110.   (repeat (- (/ (length lst) 2) 1)
  111.     (setq p1 (nth i lst))
  112.     (setq i (1+ i))
  113.     (setq p2 (nth i lst))
  114.     (setq i (1+ i))
  115.     (setq p3 (nth i lst))
  116.     (setq p4 (nth (1+ i) lst))
  117.     (setq res (append
  118.                 res
  119.                 (list (inter p1 p2 p3 p4))
  120.               )
  121.     )
  122.   )
  123.   (setq res (append
  124.               res
  125.               (list (last lst))
  126.             )
  127.   )
  128.   res
  129. )
  130. (defun inter (a b c d / res)
  131.   (if (equal b c)
  132.     b
  133.     (inters
  134.       a
  135.       b
  136.       c
  137.       d
  138.       nil
  139.     )
  140.   )
  141. )
  142. ;;;function of entmake lwpolyline,by ElpanovEvgeniy at

  143. [url]www.theswamp.org[/url]
  144. (defun entmakepolyline (lst)
  145.   (entmakex (append
  146.               (list '(0 . "LWPOLYLINE") '(100 . "AcDbEntity") '(100 .

  147. "AcDbPolyline")
  148.                     (cons 90 (length lst)) '(70 . 0) ;;;1 is closed
  149.               ) ;_  list
  150.               (mapcar
  151.                 '(lambda (x)
  152.                    (cons 10 x)
  153.                  )
  154.                 lst
  155.               )
  156.             ) ;_  append
  157.   )
  158. )
  159. ;;;;make width list
  160. (defun makew (w1 w2 n / res i)
  161.   (setq i 1)
  162.   (repeat n
  163.     (if (odd i)
  164.       (setq res (append
  165.                   res
  166.                   (list w1 w2)
  167.                 )
  168.       )
  169.       (setq res (append
  170.                   res
  171.                   (list w2 w1)
  172.                 )
  173.       )
  174.     )
  175.     (setq i (1+ i))
  176.   )
  177.   res
  178. )
  179. ;;;judge whether a number is an odd number
  180. (defun odd (x)
  181.   (/= (/ x 2) (* 0.5 x))
  182. )
论坛插件加载方法
发帖求助前要善用【论坛搜索】功能,那里可能会有你要找的答案;
如果你在论坛求助问题,并且已经从坛友或者管理的回复中解决了问题,请把帖子标题加上【已解决】;
如何回报帮助你解决问题的坛友,一个好办法就是给对方加【D豆】,加分不会扣除自己的积分,做一个热心并受欢迎的人!
回复 支持 反对

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

QQ|申请友链|Archiver|手机版|小黑屋|辽公网安备|晓东CAD家园 ( 辽ICP备15016793号 )

GMT+8, 2025-1-10 10:41 , Processed in 0.392419 second(s), 54 queries , Gzip On.

Powered by Discuz! X3.5

© 2001-2025 Discuz! Team.

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