home *** CD-ROM | disk | FTP | other *** search
/ CD Actual 9 / CDACTUAL9.iso / share / Dos / VARIOS / acad / DLINE.LSP < prev    next >
Encoding:
Text File  |  1993-07-19  |  67.7 KB  |  2,143 lines

  1. ;;;   TRANSREV  08/05/92  By: Jose M. Calahorra
  2. ;;;   DLINE.LSP
  3. ;;;   Copyright (C) 1990-1992 by Autodesk, Inc.
  4. ;;;      
  5. ;;;   Este programa es propiedad intelectual de Autodesk siendo
  6. ;;;   licenciado para su uso bajo los siguientes condiciones:
  7. ;;;   - La distribución o publicación del código fuente del programa
  8. ;;;   queda totalmente prohibida.
  9. ;;;   - La incorporación del código objeto de este programa en sus
  10. ;;;   trabajos esta permitida siempre que se cumplan las siguientes
  11. ;;;   condiciones:  a) sean diseñados y vayan a ser empleados
  12. ;;;   exclusivamente con productos de Autodesk;  b) aparezca la marca
  13. ;;;   de propiedad intelectual de Autodesk  ((C) Copyright 1988-1992
  14. ;;;   by Autodesk, Inc).
  15. ;;;
  16. ;;;   AUTODESK SUMINISTRA ESTOS MATERIALES "TAL COMO ESTAN", 
  17. ;;;   ES DECIR QUE SU SUMINISTRO NO IMPLICA NINGUN TIPO DE GARANTIA,
  18. ;;;   NI EXPRESA NI IMPLICITA, INCLUYENDO -PERO SIN LIMITARSE
  19. ;;;   A ELLAS- LAS RELATIVAS AL CUMPLIMIENTO DE CRITERIOS COMERCIALES
  20. ;;;   Y A LA ADECUACION DE PROPOSITOS PARTICULARES.
  21. ;;;
  22. ;;;   DESCRIPTION
  23. ;;;     
  24. ;;;     This is a general purpose "double-line/arc" generator.  It performs 
  25. ;;;     automatic corner intersection cleanups, as well as a number of other 
  26. ;;;     features described below.
  27. ;;;  
  28. ;;;     The user is prompted for a series of endpoints.  As they are picked 
  29. ;;;     "DLINE"  segments are drawn on the current layer.  Options are 
  30. ;;;     available for changing the Width of the DLINE, specifying whether
  31. ;;;     or not to Snap to existing lines or arcs, whether or not to 
  32. ;;;     Break the lines or arcs when snapping to them, and which of the 
  33. ;;;     following to do:  
  34. ;;;     
  35. ;;;     Set the global variable dl:ecp to the values listed below:
  36. ;;;  
  37. ;;;     Value  Meaning
  38. ;;;     ---------------------------
  39. ;;;       0    No end caps
  40. ;;;       1    Start end cap only
  41. ;;;       2    Ending end cap only
  42. ;;;       3    Both end caps
  43. ;;;       4    Auto ON -- Cap any end not on a line or arc.
  44. ;;;       
  45. ;;;     The user may choose to back up as far as the beginning of the command 
  46. ;;;     by typing "U" or "Undo", both of which operate as AutoCAD's "UNDO 1" 
  47. ;;;     does.
  48. ;;;     
  49. ;;;     Curved DLINE's are drawn using the AutoCAD ARC command and follow as 
  50. ;;;     closely as possible its command structure for the various options.
  51. ;;;  
  52. ;;;----------------------------------------------------------------------------
  53. ;;;   OPERATION
  54. ;;;
  55. ;;;     The routine is executed, after loading, by typing either DL or DLINE
  56. ;;;     at which time you are presented with the opening line and menu of
  57. ;;;     choices:
  58. ;;;     
  59. ;;;       Dline, Version 1.11, (c) 1990-1992 by Autodesk, Inc.  
  60. ;;;       Break/Caps/Dragline/Offset/Snap/Undo/Width/<start point>: 
  61. ;;;     
  62. ;;;     Typing Break allows you to set breaking of lines and arcs found at
  63. ;;;     the start and end points of any segment either ON or OFF.
  64. ;;;     
  65. ;;;       Break Dline's at start and end points?  OFF/<ON>:
  66. ;;;     
  67. ;;;     Typing Caps allows you to specify how the DLINE will be finished 
  68. ;;;     off when exiting the routine, per the values listed above.
  69. ;;;     
  70. ;;;       Draw which endcaps?  Both/End/None/Start/<Auto>:
  71. ;;;       
  72. ;;;     The default of Auto caps an end only if you did not snap to an arc
  73. ;;;     or line.
  74. ;;;     
  75. ;;;     Typing Dragline allows you to set the location of the dragline
  76. ;;;     relative to the centerline of the two arcs or lines to any value
  77. ;;;     between - 1/2 of "tracewid" and + 1/2 of "tracewid".  (There is a
  78. ;;;     local variable you may set if you want to experiment with offsets
  79. ;;;     outside this range;  the results may not be correct, your choice.
  80. ;;;     See the function (dl_sao) for more information.)
  81. ;;;     
  82. ;;;       Set dragline position to Left/Center/Right/<Offset from center = 0.0>:
  83. ;;;     
  84. ;;;     Enter any real number or one of the keywords.  The value in the angle
  85. ;;;     brackets is the default value and changes as you change the dragline
  86. ;;;     position.
  87. ;;;     
  88. ;;;     Offset allows the first point you enter to be offset from a known
  89. ;;;     point.
  90. ;;;     
  91. ;;;       Offset from:  (enter a point)
  92. ;;;       Offset toward:    (enter a point)
  93. ;;;       Enter the offset distance:   (enter a distance or real number)
  94. ;;;  
  95. ;;;     Snap allows you to set the snapping size and turn snapping ON or OFF.
  96. ;;;     
  97. ;;;       Set snap size or snap On/Off.  Size/OFF/<ON>:
  98. ;;;       New snap size (1 - 10):
  99. ;;;     
  100. ;;;     The upper limit may be reset by changing the value of MAXSNP to a 
  101. ;;;     value other than 10.  Higher values may be necessary for ADI display
  102. ;;;     drivers, but generally, you should keep this value somewhere in the 
  103. ;;;     middle of the allowed range for snapping to work most effectively 
  104. ;;;     in an uncluttered drawing, and toward the lower end for a more 
  105. ;;;     cluttered drawing.  You may also use object snap to improve your 
  106. ;;;     aim.
  107. ;;;     
  108. ;;;     This feature allows you to very quickly "snap" to another line or arc, 
  109. ;;;     breaking it at the juncture and performing all of the intersection 
  110. ;;;     cleanups at one time without having to be precisely on the line, i.e., 
  111. ;;;     you can be visually one the line and it will work, or you can use 
  112. ;;;     object snap to be more precise.
  113. ;;;     
  114. ;;;     Undo backs you up one segment in the chain of segments you are drawing,
  115. ;;;     stopping when there are no more segments to be undone.  All of the 
  116. ;;;     necessary points are saved in lists so that the DLINE will close, cap,
  117. ;;;     and continue correctly after any number of undo's.
  118. ;;;     
  119. ;;;     Width prompts you for a new width.
  120. ;;;     
  121. ;;;       New DLINE width <1.0000>:
  122. ;;;       
  123. ;;;     You may enter a new width and continue the DLINE in the same direction
  124. ;;;     you were drawing before;  if you do this, connecting lines from the
  125. ;;;     endpoints of the previous segment are drawn to the start points of 
  126. ;;;     the new segment.
  127. ;;;     
  128. ;;;     If you press RETURN after closing a DLINE or before creating any
  129. ;;;     DLINE's, you will see this message:
  130. ;;;     
  131. ;;;       No continuation point -- please pick a point.  
  132. ;;;       Break/Caps/Dragline/Offset/Snap/Undo/Width/<start point>:  
  133. ;;;     
  134. ;;;     After you pick the first point, you will see this set of options:
  135. ;;;     
  136. ;;;       Arc/Break/CAps/CLose/Dragline/Snap/Undo/Width/<next point>:
  137. ;;;       
  138. ;;;     Picking more points will draw straight DLINE segments until either 
  139. ;;;     RETURN is pressed or the CLose option is chosen.
  140. ;;;     
  141. ;;;     CLose will close the lines if you have drawn at least two segments.
  142. ;;;     
  143. ;;;     Selecting Arc presents you with another set of choices:
  144. ;;;     
  145. ;;;       Break/CAps/CEnter/CLose/Dragline/Endpoint/Line/Snap/Undo/Width/<second point>:
  146. ;;;     
  147. ;;;     All of the options here are the same as they are for drawing straight
  148. ;;;     DLINE's except CEnter, Endpoint, and Line.
  149. ;;;     
  150. ;;;     The default option, CEnter, and Endpoint are modeled after the ARC
  151. ;;;     command in AutoCAD and exactly mimic its operation including all of
  152. ;;;     the subprompts.  Refer to the AutoCAD reference manual for exact usage.
  153. ;;;     
  154. ;;;     The Line option returns you to drawing straight DLINE segments.
  155. ;;;     
  156. ;;;     Snapping to existing LINE's an ARC's accomplishes all of the trimming 
  157. ;;;     and extending of lines and arcs necessary, including cases where arcs 
  158. ;;;     and lines do not intersect.  In these cases a line is drawn from either;
  159. ;;;     a point on the arc at the perpendicular point from the center of the 
  160. ;;;     arc to the line, to the line, or along the line from the centers of the
  161. ;;;     two arcs that do not intersect at the points where this line crosses
  162. ;;;     the two arcs.  In this way, we ensure that all DLINE's can be closed
  163. ;;;     visually.
  164. ;;;     
  165. ;;;     Breaking will not work unless Snapping is turned on.
  166. ;;;     
  167. ;;;----------------------------------------------------------------------------
  168. ;;;  GLOBALS:
  169. ;;;     dl:osd -- dragline alignment offset from center of two lines or arcs.
  170. ;;;     dl:snp -- T if snapping to existing lines and arcs.
  171. ;;;     dl:brk -- T if breaking existing lines and arcs.
  172. ;;;     dl:ecp -- Bitwise setting of caps when exiting.
  173. ;;;     v:stpt -- Continuation point.
  174. ;;;----------------------------------------------------------------------------
  175. ;;;
  176. ;;; ===========================================================================
  177. ;;; ===================== load-time error checking ============================
  178. ;;;
  179.  
  180.   (defun ai_abort (app msg)
  181.      (defun *error* (s)
  182.         (if old_error (setq *error* old_error))
  183.         (princ)
  184.      )
  185.      (if msg
  186.        (alert (strcat " Error de la aplicación: "
  187.                       app
  188.                       " \n\n  "
  189.                       msg
  190.                       "  \n"
  191.               )
  192.        )
  193.      )
  194.      (exit)
  195.   )
  196.  
  197. ;;; Check to see if AI_UTILS is loaded, If not, try to find it,
  198. ;;; and then try to load it.
  199. ;;;
  200. ;;; If it can't be found or it can't be loaded, then abort the
  201. ;;; loading of this file immediately, preserving the (autoload)
  202. ;;; stub function.
  203.  
  204.   (cond
  205.      (  (and ai_dcl (listp ai_dcl)))          ; it's already loaded.
  206.  
  207.      (  (not (findfile "ai_utils.lsp"))                     ; find it
  208.         (ai_abort "DLINE"
  209.                   (strcat "No encuentro el fichero AI_UTILS.LSP."
  210.                           "\n Verifique el directorio support.")))
  211.  
  212.      (  (eq "failed" (load "ai_utils" "failed"))            ; load it
  213.         (ai_abort "DLINE" "No puedo cargar el fichero AI_UTILS.LSP"))
  214.   )
  215.  
  216.   (if (not (ai_acadapp))               ; defined in AI_UTILS.LSP
  217.       (ai_abort "DLINE" nil)         ; a Nil <msg> supresses
  218.   )                                    ; ai_abort's alert box dialog.
  219.  
  220. ;;; ==================== end load-time operations ===========================
  221. ;;; Main function
  222.  
  223. (defun dline  (/ strtpt nextpt pt1    pt2    spts   wnames elast
  224.                  uctr   pr     prnum  temp   ans    dir    ipt
  225.                  v      lst    dist   cpt    rad    orad   ftmp
  226.                  spt    ept    pt     en1    en2    npt    cpt1
  227.                  flg    cont   flg2   flgn   ang    tmp    undo_setting
  228.                  brk_e1 brk_e2 bent1  bent2  nn     nnn    
  229.                  dl_osm dl_oem dl_oce dl_opb dl_obm dl_ver 
  230.                  dl_err dl_oer dl_arc fang   MAXSNP ange   
  231.                  savpt1 savpt2 savpt3 savpt4 savpts 
  232.               )
  233.  
  234.   ;; Version number.  Reset this local if you make a change.
  235.   (setq dl_ver "1.11")  
  236.   
  237.   ;; Reset this value higher for ADI drivers.
  238.   (setq MAXSNP 10)              
  239.  
  240.   (setq dl_osm (getvar "osmode")
  241.         dl_oce (getvar "cmdecho")
  242.         dl_opb (getvar "pickbox")
  243.   )
  244.   ;; poner grosor en 0.25
  245.   (if (= (getvar "tracewid") 1) (setvar "tracewid" 0.25))
  246.  
  247.   ;;
  248.   ;; Internal error handler defined locally
  249.   ;;
  250.  
  251.   (defun dl_err (s)                   ; If an error (such as CTRL-C) occurs
  252.                                       ; while this command is active...
  253.     (if (/= s "Función cancelada")
  254.       (if (= s "quit / exit abort")
  255.         (princ)
  256.         (princ (strcat "\nError: " s))
  257.       )
  258.     )
  259.     (command "_.UNDO" "_EN")
  260.     (ai_undo_off)
  261.     (if dl_oer                        ; If an old error routine exists
  262.       (setq *error* dl_oer)           ; then, reset it 
  263.     )
  264.     (if dl_osm (setvar "osmode" dl_osm))
  265.     (if dl_opb (setvar "pickbox" dl_opb))
  266.     
  267.     ;; Reset command echoing on error
  268.     (if dl_oce (setvar "cmdecho" dl_oce))      
  269.     (princ)
  270.   )
  271.   
  272.   ;; Set our new error handler
  273.   (if (not *DEBUG*)
  274.     (if *error*
  275.       (setq dl_oer *error* *error* dl_err)
  276.       (setq *error* dl_err)
  277.     )
  278.   )
  279.  
  280.   (setvar "cmdecho" 0)
  281.   (ai_undo_on)                       ; Turn on UNDO
  282.   (command "_.UNDO" "_GROUP")
  283.   (setvar "osmode" 0)
  284.   (if (null dl:opb) (setq dl:opb (getvar "pickbox")))
  285.  
  286.   
  287.   (setq nextpt "Straight")
  288.  
  289.   ;; Get the first segment's start point
  290.  
  291.   (menucmd "s=dline1")
  292.   (graphscr)
  293.   (princ (strcat "\nDline, Versión " dl_ver ", (c) 1990-1992 por Autodesk, Inc. "))
  294.   
  295.   (setq cont T)
  296.   (while cont
  297.     (dl_m1)
  298.  
  299.     ;; Ready to draw successive DLINE segments
  300.  
  301.     (dl_m2)
  302.   )
  303.   
  304.   (if dl_osm (setvar "osmode" dl_osm))
  305.   (if dl_opb (setvar "pickbox" dl_opb))
  306.  
  307.   (ai_undo_off)                      ; Return UNDO to initial state
  308.  
  309.   ;; Reset command echoing
  310.   (if dl_oce (setvar "cmdecho" dl_oce))      
  311.   (menucmd "s=s")
  312.   (princ)
  313. )
  314. ;;;
  315. ;;; Main function subsection 1.
  316. ;;;
  317. ;;; dl_m1 == DLine_Main_1
  318. ;;;
  319. (defun dl_m1 ()
  320.   (setq temp T
  321.         uctr nil 
  322.   )
  323.   (if dl_arc
  324.     (setq nextpt "Arco")
  325.     (setq nextpt "Línea")
  326.   )
  327.   ;; temp set to nil when a valid point is entered.
  328.   (while temp
  329.     (initget "Parte reMates arraStre Desplaza Forzcoor Revoca Grosor")
  330.     (setq strtpt (getpoint 
  331.       "\nParte/reMates/arraStre/Desplaza/Forzcoor/Revoca/Grosor/<punto inicial>: "))
  332.     (cond
  333.       ((= strtpt "arraStre")
  334.         (dl_sao)
  335.       )
  336.       ((= strtpt "Parte")
  337.         (initget "ACT DES")
  338.         (setq dl:brk (getkword 
  339.           "\n¿Partir Dline en los puntos inicial y final?  DES/<ACT>: "))
  340.         (setq dl:brk (if (= dl:brk "DES") nil T))    
  341.       )
  342.       ((= strtpt "Desplaza")
  343.         (dl_ofs)
  344.       )
  345.       ((= strtpt "Forzcoor")
  346.         (dl_sso)
  347.       )
  348.       ((= strtpt "Revoca")
  349.         (princ "\nTodos los segmentos ya revocados. ")
  350.         (setq temp T)
  351.       )
  352.       ((= strtpt "Grosor")
  353.         (initget 6)
  354.         (dl_snw)
  355.         (setq temp T)
  356.       )
  357.       ((null strtpt)
  358.         (if v:stpt
  359.           (setq strtpt v:stpt
  360.                 temp   nil
  361.           )
  362.           (progn
  363.             (princ "\nNo hay punto de continuación -- designar un punto. ")
  364.           )
  365.         )
  366.       )
  367.       ((= strtpt "reMates")
  368.         (endcap)    
  369.       )
  370.       ;; If none of the above, it must be OK to continue - a point has been 
  371.       ;; picked or entered from the keyboard.
  372.       (T
  373.         (setq v:stpt strtpt
  374.               temp   nil
  375.         )
  376.       )
  377.     )
  378.   )
  379. )
  380. ;;;
  381. ;;; Main function subsection 2.
  382. ;;;
  383. ;;; dl_m3 == DLine_Main_2
  384. ;;;
  385. (defun dl_m2 (/ temp)
  386.   (setq spts (list strtpt)
  387.         uctr 0 
  388.   )
  389.   (if dl:snp
  390.     (dl_ved "brk_e1" strtpt)
  391.   )
  392.   ;; Make sure that the offset is not greater than 1/2 of "tracewid", even
  393.   ;; if the user transparently resets it while the command is running.
  394.   (setq temp (/ (getvar "tracewid") 2.0))
  395.   (if (< dl:osd (- temp))
  396.     (setq dl:osd (- temp))
  397.   )
  398.   (if (> dl:osd temp)
  399.     (setq dl:osd temp)
  400.   )
  401.     
  402.   (while (and nextpt (/= nextpt "CIerra"))
  403.     (if (/= nextpt "Quita")
  404.       (if dl_arc 
  405.         (progn
  406.           (menucmd "s=dline2")
  407.           (initget 
  408.             "Parte reMates CEntro CIerra arraStre pTofinal Línea Forzcoor Revoca Grosor")
  409.           (setq nextpt (getpoint strtpt (strcat
  410.             "\nParte/reMates/CEntro/CIerra/arraStre/pTofinal/"
  411.             "Línea/Forzcoor/Revoca/Grosor/<segundo punto>: "))
  412.           )
  413.         )
  414.         (progn
  415.           (menucmd "s=dline3")
  416.           (initget "Arco Parte reMates CIerra arraStre Forzcoor Revoca Grosor")
  417.           (setq nextpt (getpoint strtpt
  418.             "\nArco/Parte/reMates/CIerra/arraStre/Forzcoor/Revoca/Grosor/<Siguiente punto>: ")
  419.           )
  420.         )
  421.       )
  422.     )
  423.     (setq v:stpt (last spts))
  424.     (cond
  425.       ((= nextpt "arraStre")
  426.         (dl_sao)
  427.       )
  428.       ((= nextpt "Grosor")
  429.         (dl_snw)
  430.         
  431.       )
  432.       ((= nextpt "Revoca")
  433.         (cond
  434.           ;;((= uctr 0) (princ "\nNothing to undo. ") )
  435.           ((= uctr 0) (setq nextpt nil) )
  436.           ((> uctr 0) 
  437.             (command "_.U")
  438.             (setq spts   (dl_lsu spts 1))
  439.             (setq savpts (dl_lsu savpts 2))
  440.             (setq wnames (dl_lsu wnames 2))
  441.             (setq uctr (- uctr 2))
  442.             (setq strtpt (last spts))
  443.           )
  444.         ) 
  445.         (if dl:snp
  446.           (if (= uctr 0)
  447.             (dl_ved "brk_e1" strtpt)
  448.           ) 
  449.         ) 
  450.       )
  451.       ((= nextpt "Parte")
  452.         (initget "ACT DES")
  453.         (setq dl:brk (getkword 
  454.           "\n¿Partir Dline en los puntos inicial y final?  DES/<ACT>: "))
  455.         (setq dl:brk (if (= dl:brk "DES") nil T))    
  456.         
  457.         (if dl:snp
  458.           (dl_ved "brk_e1" strtpt)
  459.         )
  460.         (if dl_arc
  461.           (setq nextpt "Arco")
  462.           (setq nextpt "Línea")
  463.         )
  464.       )
  465.       ((= nextpt "Forzcoor")
  466.         (dl_sso)
  467.       )
  468.       ((= nextpt "Arco")
  469.         (setq dl_arc T)               ; Change to Arc segment prompt.
  470.       )
  471.       ((= nextpt "Línea")
  472.         (setq dl_arc nil)             ; Change to Line segment prompt.
  473.       )
  474.       ((= nextpt "CIerra")
  475.         (dl_cls)
  476.       )
  477.       ((= (type nextpt) 'LIST)
  478.         (dl_ds)
  479.       )
  480.       ((= nextpt "CEntro")
  481.         (dl_ceo)
  482.       )
  483.       ((= nextpt "pTofinal")
  484.         (dl_epo)
  485.       )
  486.       ((= nextpt "reMates")
  487.         (endcap)                      ; Set which caps to draw when exiting.
  488.       )
  489.       (T
  490.         (setq nextpt nil cont nil)
  491.         (if (> uctr 1)
  492.           (if (= (logand 4 dl:ecp) 4)
  493.             (progn
  494.               (if (null brk_e1) (command "_.LINE" savpt1 savpt2 ""))
  495.               (dl_ssp)
  496.               (if (null brk_e2) (command "_.LINE" savpt3 savpt4 ""))
  497.             )
  498.             (progn
  499.               (if (= (logand 1 dl:ecp) 1)
  500.                 (command "_.LINE" savpt1 savpt2 "")
  501.               )
  502.               (if (= (logand 2 dl:ecp) 2)
  503.                 (progn
  504.                   (dl_ssp)
  505.                   (command "_.LINE" savpt3 savpt4 "")
  506.                 )
  507.               )
  508.             )
  509.           )
  510.         )
  511.         (if brk_e1 (setq brk_e1 nil))
  512.         (if brk_e2 (setq brk_e2 nil))
  513.         (command "_.UNDO" "_EN")
  514.       )                               ; end of inner cond  
  515.     )                                 ; end of outer cond  
  516.   )                                   ; end of while
  517. )
  518. ;;; ------------------ End Main Functions ---------------------------
  519. ;;; ---------------- Begin Support Functions ------------------------
  520.  
  521.  
  522. ;;;
  523. ;;; Close the DLINE with either straight or arc segments.  
  524. ;;; If closing with arcs, the minimum number of segments already drawn
  525. ;;; is 1, otherwise it is 2.
  526. ;;;
  527. ;;; dl_cls == DLine_CLose_Segments
  528. ;;;
  529. (defun dl_cls ()
  530.   (if (or (and (null dl_arc) (< uctr 4)
  531.                (if (> uctr 1)
  532.                  (/= (dl_val 0 (entlast)) "ARC")
  533.                  (not (> uctr 1))
  534.                )
  535.           )
  536.           (and dl_arc (< uctr 2)))
  537.     (progn 
  538.       (princ "\nImposible cerrar -- pocos segmentos. ")
  539.       (if dl_arc
  540.         (setq nextpt "Arc")
  541.         (setq nextpt "Line")
  542.       )
  543.     )
  544.     (progn
  545.       (command "_.UNDO" "_GROUP")
  546.       (setq nextpt (nth 0 spts))
  547.       (if (null dl_arc)
  548.         ;; Close with line segments
  549.         (dl_mlf 3)
  550.         (progn
  551.           (setq tmp (last wnames)
  552.                 ange (trans '(1 0 0) (dl_val -1 tmp) 1)
  553.                 ange (angle '(0 0 0) ange)
  554.                 dir (if (= (dl_val 0 tmp) "LINE")
  555.                       (angle (trans (dl_val 10 tmp) 0 1) 
  556.                              (trans (dl_val 11 tmp) 0 1))
  557.                       (progn
  558.                         (setq dir (+ (dl_val 50 tmp) ange)
  559.                               dir (if (> dir (* 2 pi))
  560.                                     (- dir (* 2 pi))
  561.                                     dir
  562.                                   )
  563.                         )
  564.                         (if (equal dir
  565.                                    (setq dir (angle (trans (dl_val 10 tmp) 
  566.                                                            (dl_val -1 tmp) 
  567.                                                            1)
  568.                                                     strtpt
  569.                                              ) 
  570.                                    )
  571.                                    0.01)
  572.                           (- dir (/ pi 2))
  573.                           (+ dir (/ pi 2))
  574.                         )
  575.                       )
  576.                     )
  577.           )
  578.           (command "_.ARC" 
  579.                    strtpt 
  580.                    "_E" 
  581.                    nextpt 
  582.                    "_D"
  583.                    (* dir (/ 180 pi))
  584.           )
  585.           ;; Close with arc segments
  586.           (dl_mlf 4)
  587.         )
  588.       )
  589.       ;; set nextpt to "CLose" which will cause an exit.
  590.       (setq nextpt "CIerra"
  591.             v:stpt nil
  592.             cont   nil
  593.       )
  594.     )
  595.   )
  596. )
  597. ;;;
  598. ;;; A point was entered, do either an arc or line segment.
  599. ;;;
  600. ;;; dl_ds == DLine_Do_Segment
  601. ;;;
  602. (defun dl_ds ()
  603.   (if (equal strtpt nextpt 0.0001)
  604.     (progn
  605.       (princ "\nLos puntos coinciden -- intentar de nuevo. ")
  606.       (if dl_arc
  607.         (setq nextpt "Arc")
  608.         (setq nextpt "Line")
  609.       )
  610.     )
  611.     (progn
  612.       (command "_.UNDO" "_GROUP")
  613.       (setq nextpt (list (car nextpt) (cadr nextpt) (caddr strtpt)))
  614.       (if dl_arc
  615.         (progn
  616.           (command "_.ARC" strtpt nextpt)
  617.           (prompt "\nPunto final: ")
  618.           (command pause)
  619.           (setq nextpt (getvar "lastpoint")
  620.                 v:stpt nextpt)
  621.           (setq temp (entlast))
  622.           ;; Delete the last arc segment so we can find the line or 
  623.           ;; arc under it.
  624.           (entdel temp)
  625.           (if dl:snp
  626.             (dl_ved "brk_e2" nextpt)
  627.           )
  628.           ;; Restore the arc previously deleted.
  629.           (entdel temp)
  630.           ;; Draw the arc segments.
  631.           (dl_mlf 2)
  632.         )
  633.         (progn
  634.           (setq v:stpt nextpt)
  635.           (if dl:snp
  636.             (dl_ved "brk_e2" nextpt)
  637.           )
  638.           (if (and brk_e1 (eq brk_e1 brk_e2) (= (dl_val 0 brk_e1) "LINE"))
  639.             (progn
  640.               (princ "\nEl segundo punto no puede estar en el mismo segmento de línea. ")
  641.               (setq brk_e2 nil)
  642.             )
  643.             ;; Draw the line segments.
  644.             (dl_mlf 1)
  645.           )
  646.         )
  647.       )
  648.       (if brk_e2 (setq nextpt "Quit"))
  649.     )
  650.   )
  651. )
  652. ;;;
  653. ;;; The CEnter option for drawing arc segments was selected.
  654. ;;;
  655. ;;; dl_ceo == DLine_CEnter_Option
  656. ;;;
  657. (defun dl_ceo ()
  658.   (command "_.UNDO" "_GROUP")
  659.   (setq temp T)
  660.   (while temp
  661.     (initget 1)
  662.     (setq cpt (getpoint strtpt "\nCEntro: "))
  663.     (if (<= (distance cpt strtpt) (- (/ (getvar "tracewid") 2.0) dl:osd))
  664.       (progn
  665.         (princ 
  666.         "\nEl radio definido por el centro designado es damasiado pequeño ")
  667.         (princ "\npara el grosor actual de Dline.  ")
  668.         (princ "Designar otro punto.")
  669.       )
  670.       (setq temp nil)
  671.     )
  672.   )
  673.   ;; Start the ARC command so that we can get visual dragging.
  674.   (command "_.ARC" strtpt "_C" cpt)
  675.   (initget "Angulo Longitud punto Final")
  676.   (setq nextpt (getkword "\nAngulo/Longitud de cuerda/<punto Final>: "))
  677.   (cond 
  678.     ((= nextpt "Angulo")
  679.       (prompt "\nAngulo incluido: ")
  680.       (command "_A" pause)
  681.       (setq nextpt (dl_vnp)
  682.             v:stpt nextpt
  683.       )
  684.       ;; Draw the arc segments.
  685.       (dl_mlf 2) 
  686.     )
  687.     ((= nextpt "Longitud")
  688.       (prompt "\nLongitud de cuerda: ")
  689.       (command "_L" pause)
  690.       (setq nextpt (dl_vnp)
  691.             v:stpt nextpt
  692.       )
  693.       ;; Draw the arc segments.
  694.       (dl_mlf 2) 
  695.     )
  696.     (T
  697.       (prompt "\nPunto final: ")
  698.       (command pause)
  699.       (setq nextpt (dl_vnp)
  700.             v:stpt nextpt
  701.       )
  702.       ;; Draw the arc segments.
  703.       (dl_mlf 2) 
  704.     )
  705.   )
  706. )
  707. ;;;
  708. ;;; Endpoint option was selected.
  709. ;;;
  710. ;;; dl_epo == DLine_End_Point_Option
  711. ;;;
  712. (defun dl_epo ()
  713.   (command "_.UNDO" "_GROUP")
  714.   (initget 1)
  715.   (setq cpt (getpoint "\nPunto final: "))
  716.   ;; Start the ARC command so that we can get visual dragging.
  717.   (command "_.ARC" strtpt "_E" cpt)
  718.   (initget "Angulo Dirección Radio Centro")
  719.   (setq nextpt (getkword "\nAngulo/Dirección/Radio/<Centro>: "))
  720.   (cond 
  721.     ((= nextpt "Angulo")
  722.       (prompt "\nAngulo incluido: ")
  723.       (command "_A" pause)
  724.       (setq nextpt (dl_vnp)
  725.             v:stpt nextpt
  726.       )
  727.       ;; Draw the arc segments.
  728.       (dl_mlf 2) 
  729.     )
  730.     ((= nextpt "Dirección")
  731.       (prompt "\nDirección de tangente: ")
  732.       (command "_D" pause)
  733.       (setq nextpt (dl_vnp)
  734.             v:stpt nextpt
  735.       )
  736.       ;; Draw the arc segments.
  737.       (dl_mlf 2) 
  738.     )          
  739.     ((= nextpt "Radio")
  740.       (setq temp T)
  741.       (while temp
  742.         (initget 1)
  743.         (setq rad (getdist cpt "\nRadio: "))
  744.         
  745.         (if (or (<= rad (/ (getvar "tracewid") 2.0))
  746.                 (< rad (/ (distance strtpt cpt) 2.0)))
  747.           (progn
  748.             (princ "\nRadio introducido menor que la 1/2 ")
  749.             (princ "del grosor de Dline o no es válido")
  750.             (princ "\npara los extremos designados.  ")
  751.             (princ "Introducir un radio mayor que ")
  752.             (if (< (/ (getvar "tracewid") 2.0) 
  753.                    (/ (distance strtpt cpt) 2.0))
  754.               (princ (rtos (/ (distance strtpt cpt) 2.0)))
  755.               (princ (rtos (/ (getvar "tracewid") 2.0)))
  756.             )
  757.             (princ ". ")
  758.           )
  759.           (setq temp nil)
  760.         )
  761.       )
  762.       (command "_R" rad)
  763.       (setq nextpt (dl_vnp)
  764.             v:stpt nextpt
  765.       )
  766.       ;; Draw the arc segments.
  767.       (dl_mlf 2) 
  768.     )
  769.     (T
  770.       (prompt "\nCentro: ")
  771.       (command pause)
  772.       (setq nextpt (dl_vnp)
  773.             v:stpt nextpt
  774.       )
  775.       ;; Draw the arc segments.
  776.       (dl_mlf 2) 
  777.     )
  778.   )
  779. )
  780. ;;;
  781. ;;; Set the ending save points for capping the DLINE.
  782. ;;;
  783. ;;; dl_ssp == DLine_Set_Save_Points
  784. ;;;
  785. (defun dl_ssp ( / temp)
  786.   (setq temp (length savpts))
  787.   (if (> temp 1)
  788.     (progn
  789.       (setq savpt3 (nth (- temp 2) savpts)
  790.             savpt4 (nth (- temp 1) savpts)
  791.       )
  792.     )
  793.   )
  794. )
  795. ;;;
  796. ;;; Set the alignment of the "ghost" line to one of the following values:
  797. ;;;   
  798. ;;;   Left   == -1/2 of width (Real number)
  799. ;;;           > -1/2 of width (Real number)
  800. ;;;   Center == 0.0
  801. ;;;           < +1/2 of width (Real number)
  802. ;;;   Right  == +1/2 of width (Real number)
  803. ;;;
  804. ;;; All of the alignment options are taken as if you are standing at the
  805. ;;; start point of the line or arc looking toward the end point, with 
  806. ;;; left and negative values being on the left, center or 0.0 being
  807. ;;; directly in line, and right or positive on the right.
  808. ;;; 
  809. ;;; Entering a real number equal to 1/2 of the width sets an absolute offset
  810. ;;; distance from the centerline, while specifying the same offset distance
  811. ;;; with the keywords tells the routine to change the offset distance to 
  812. ;;; match 1/2 of the width, whenever it is changed.
  813. ;;;
  814. ;;; NOTE:  If you wish to allow the dragline to be positioned outside
  815. ;;;      of the two arcs or lines being created, you may set the local 
  816. ;;;      variable "dragos" = T, on the 4th line of the defun, which  
  817. ;;;      checks that the offset value entered is not greater or less 
  818. ;;;      than + or - TRACEWID / 2.
  819. ;;;      
  820. ;;;      You should be aware that the results of allowing this to occur
  821. ;;;      may not be obvious or necessarily correct.  Specifically, when
  822. ;;;      drawing lines with a width of 1 and an offset of 4, if you draw
  823. ;;;      segments as follows, the lines will cross back on themselves.
  824. ;;;      
  825. ;;;      dl 0,0,0 10,0,0 10,5 then 5,5
  826. ;;;      
  827. ;;;      However, this can be quite useful for creating parallel DLINE's.
  828. ;;;      
  829. ;;; dl_sao == DLine_Set_Alignment_Option
  830. ;;;
  831. (defun dl_sao (/ temp dragos)
  832.   (initget "Izquierda Centro Derecha")
  833.   (setq temp dl:osd)
  834.   ;;(setq dragos T)                   ; See note above.
  835.   (setq dl:osd (getreal (strcat
  836.     "\nEstablecer posición de arrastre Izquierda/Centro/Derecha/<Distancia del centro = "
  837.     (rtos dl:osd) ">: ")))
  838.   (cond
  839.     ((= dl:osd "Izquierda")
  840.       (setq dl:aln 1
  841.             dl:osd (- (/ (getvar "tracewid") 2.0))
  842.       )
  843.     )
  844.     ((= dl:osd "Centro")
  845.       (setq dl:aln 0
  846.             dl:osd 0.0
  847.       )
  848.     )
  849.     ((= dl:osd "Derecha")
  850.       (setq dl:aln 2
  851.             dl:osd (/ (getvar "tracewid") 2.0)
  852.       )
  853.     )
  854.     ((= (type dl:osd) 'REAL)
  855.       (if dragos
  856.         (setq dl:aln nil)
  857.         (progn
  858.           (setq dl:aln nil)
  859.           (if (> dl:osd (/ (getvar "tracewid") 2.0))
  860.             (progn
  861.               (princ "\nEl valor se encuentra fuera de rango.  Redefinir en ")
  862.               (princ (/ (getvar "tracewid") 2.0))
  863.               (setq dl:osd (/ (getvar "tracewid") 2.0))
  864.             )
  865.           )
  866.           (if (< dl:osd (- (/ (getvar "tracewid") 2.0)))
  867.             (progn
  868.               (princ "\nEl valor se encuentra fuera de rango.  Redefinir en ")
  869.               (princ (- (/ (getvar "tracewid") 2.0)))
  870.               (setq dl:osd (- (/ (getvar "tracewid") 2.0)))
  871.             )
  872.           )
  873.         )
  874.       )
  875.     )
  876.     (T
  877.       (setq dl:osd temp)
  878.     )
  879.   )
  880. )
  881. ;;;
  882. ;;; Set a new DLINE width.
  883. ;;;
  884. ;;; dl_snw == DLine_Set_New_Width
  885. ;;;
  886. (defun dl_snw ()
  887.   (initget 6)
  888.   (setvar "tracewid"
  889.     (if (setq temp (getdist (strcat 
  890.       "\nNuevo grosor de DLINE <" (rtos (getvar "tracewid")) ">: ")))
  891.       temp
  892.       (getvar "tracewid") 
  893.     ) 
  894.   )
  895.   (if dl:aln
  896.     (cond
  897.       ((= dl:aln 1) ; left aligned
  898.         (setq dl:osd (- (/ (getvar "tracewid") 2.0)))
  899.       )
  900.       ((= dl:aln 2) ; right aligned
  901.         (setq dl:osd (/ (getvar "tracewid") 2.0))
  902.       )
  903.       (T
  904.         (princ)     ; center aligned
  905.       )
  906.     )
  907.   )
  908. )
  909. ;;;
  910. ;;; Get an offset from a given point to the start point toward a second
  911. ;;; point.  The distance between the two points is the default, but any
  912. ;;; positive distance may be entered.  If a negative number is entered,
  913. ;;; it is used as a percentage distance from the "Offset from" point 
  914. ;;; toward the "Offset toward" point, i.e., if -75 is entered, a point
  915. ;;; 75% of the distance between the two points listed above is returned.
  916. ;;; 
  917. ;;;
  918. ;;; dl_ofs == DLine_OFfset_Startpoint
  919. ;;;
  920. (defun dl_ofs ()
  921.   (menucmd "s=osnapb")
  922.   (initget 1)
  923.   (setq strtpt (getpoint "\nDesplaza de: "))
  924.   (initget 1)
  925.   (setq nextpt (getpoint strtpt "\nDesplaza hacia: "))
  926.   
  927.   (setq dist (getdist strtpt (strcat
  928.     "\nDistancia de desplazamiento <" (rtos (distance strtpt nextpt)) 
  929.     ">: ")))
  930.   (setq dist (if (or (= dist "") (null dist))
  931.                (distance strtpt nextpt)
  932.                (if (< dist 0)
  933.                  (* (distance strtpt nextpt) (/ (abs dist) 100.0))
  934.                  dist
  935.                )
  936.              )
  937.   )              
  938.   (setq strtpt (polar strtpt
  939.                       (angle strtpt nextpt)
  940.                       dist
  941.                ) 
  942.   )
  943.   (setq temp nil)
  944.   (command "_.UNDO" "_GROUP")
  945. )
  946. ;;;
  947. ;;; Set snap options to ON, OFF or set the size of the area to be searched
  948. ;;; by (ssget point) via "pickbox".  This value is being limited for built-
  949. ;;; in display drivers at 10 pixels.  For ADI drivers it may be necessary 
  950. ;;; to bump up this number by adjusting "MAXSNP" at the top of this file.
  951. ;;;
  952. ;;; dl_sso == DLine_Set_Snap_Options
  953. ;;;
  954. (defun dl_sso ()
  955.   (initget "ACT DES Intérvalo")
  956.   (setq ans (getkword
  957.     "\nDefinir Intérvalo de forzcoor o forzcoor ACT/DES.  Intérvalo/DES/<ACT>: "))
  958.   (if (= ans "DES") 
  959.     (progn
  960.       (setq dl:snp nil)
  961.       (setvar "pickbox" 0) 
  962.     )
  963.     (if (= ans "Intérvalo") 
  964.       (progn
  965.         (setq dl:snp T ans 0)
  966.         (while (or (< ans 1) (> ans MAXSNP))
  967.           (setq ans (getint (strcat
  968.             "\nNuevo intérvalo (1 - " (itoa MAXSNP) ") <" (itoa dl:opb) ">: ")))
  969.  
  970.           (if (or (= ans "") (null ans))
  971.             (setq ans dl:opb)
  972.           )
  973.         )
  974.         (setvar "pickbox" ans)
  975.         (setq dl:opb ans)
  976.       )
  977.       (progn
  978.         (setq dl:snp T)
  979.         (setvar "pickbox" dl:opb)
  980.       )  
  981.     ) 
  982.   )
  983.   (if dl:snp
  984.     (if (= uctr 0)
  985.       (dl_ved "brk_e1" strtpt)
  986.     ) 
  987.   ) 
  988.   (if dl_arc
  989.     (setq nextpt "Arc")
  990.     (setq nextpt "Line")
  991.   )
  992.  
  993. )
  994. ;;;
  995. ;;; Obtain and verify the extrusion direction of an entity at the 
  996. ;;; start point or endpoint of the line or arc we are drawing.
  997. ;;;
  998. ;;; dl_ved == DLine_Verify_Extrusion_Direction
  999. ;;;
  1000. (defun dl_ved (vent pt)
  1001.   ;; Get entity to break if the user snapped to a DLINE.
  1002.   ;; Make sure that it is a line or arc and that its extrusion
  1003.   ;; direction is parallel to the current UCS.
  1004.   (if (set (read vent) (ssget pt))
  1005.     (progn
  1006.       (set (read vent) (ssname (eval (read vent)) 0))
  1007.       (if (and 
  1008.             (or (= (dl_val 0 (eval (read vent))) "ARC")
  1009.                 (= (dl_val 0 (eval (read vent))) "LINE")
  1010.             )
  1011.             (equal (caddr(dl_val 210 (eval (read vent))))
  1012.                    (caddr(trans '(0 0 1) 1 0)) 0.001)
  1013.           )
  1014.         (princ)
  1015.         (progn
  1016.           (princ (strcat
  1017.             "\nEntity found is not an arc or line, "
  1018.             "or is not parallel to the current UCS. "))
  1019.           (set (read vent) nil)
  1020.         )
  1021.       )
  1022.     )
  1023.   )
  1024.   (eval (read vent))
  1025. )
  1026. ;;;
  1027. ;;; Verify nextpt.
  1028. ;;; Get the point on the arc at the opposite 
  1029. ;;; end from the start point (strtpt).
  1030. ;;;
  1031. ;;; dl_vnp == DLine_Verify_NextPt
  1032. ;;;
  1033. (defun dl_vnp (/ temp cpt ang rad)
  1034.  
  1035.   (setq temp (entlast))
  1036.   (if (= (dl_val 0 temp) "LINE")
  1037.     (setq nextpt (if (equal strtpt (dl_val 10 temp) 0.001)
  1038.                    (dl_val 11 temp)
  1039.                    (dl_val 10 temp)
  1040.                  )
  1041.     )
  1042.     ;; Then it must be an arc...
  1043.     (progn
  1044.       ;; get its center point
  1045.       (setq cpt  (trans (dl_val 10 temp) (dl_val -1 temp) 1)
  1046.             ang  (dl_val 50 temp)     ; starting angle
  1047.             rad  (dl_val 40 temp)     ; radius
  1048.       )
  1049.       (setq ange (trans '(1 0 0) (dl_val -1 temp) 1)
  1050.             ange (angle '(0 0 0) ange)
  1051.             ang (+ ang ange)
  1052.       )
  1053.       (if (> ang (* 2 pi))
  1054.         (setq ang (- ang (* 2 pi)))
  1055.       )
  1056.       (setq nextpt (if (equal strtpt (polar cpt ang rad) 0.01)
  1057.                      (polar cpt (dl_val 51 temp) rad)
  1058.                      (polar cpt ang rad)
  1059.                    )
  1060.       )
  1061.     )
  1062.   )
  1063. )
  1064. ;;; ----------------- Main Line Drawing Function -------------------
  1065. ;;;
  1066. ;;; Draw the lines.
  1067. ;;;
  1068. ;;; dl_mlf == DLine_Main_Line_Function
  1069. ;;;
  1070. (defun dl_mlf (flg / temp1 temp2 newang ang1 ang2 
  1071.                      ent cpt ang rad1 rad2 sent1 sent2
  1072.                      tmpt1 tmpt2 tmpt3 tmpt4)
  1073.  
  1074.   ;; Verify nextpt
  1075.   (if (null nextpt) (setq nextpt (dl_vnp)))
  1076.   
  1077.   (if (equal nextpt (nth 0 spts) 0.01)
  1078.     (if dl_arc
  1079.       (setq flg 4)
  1080.       (setq flg 3)
  1081.     )
  1082.   )
  1083.    
  1084.   (setq temp1  (+ (/ (getvar "tracewid") 2.0) dl:osd)
  1085.         temp2  (- (getvar "tracewid") temp1)
  1086.         newang (angle strtpt nextpt)
  1087.         ang1   (+ (angle strtpt nextpt) (/ pi 2))
  1088.         ang2   (- (angle strtpt nextpt) (/ pi 2))
  1089.   )
  1090.   (cond
  1091.     ((= flg 1)                        ; if drawing lines
  1092.       (dl_dls nil ang1 temp1)         ; Draw line segment 1
  1093.       (dl_dls nil ang2 temp2)         ; Draw line segment 2
  1094.     )
  1095.     ((or (= flg 2) (= flg 4))         ; else drawing arcs...
  1096.       (setq tmp (entlast)             ; get the last arc entity
  1097.             ent  (entget tmp)         ; (i.e., the guideline)
  1098.             ;; get its center point
  1099.             cpt  (trans (dl_val 10 tmp) (dl_val -1 tmp) 1) 
  1100.             ang  (dl_val 50 tmp)      ; starting angle
  1101.       )
  1102.       (setq ange (trans '(1 0 0) (dl_val -1 tmp) 1)
  1103.             ange (angle '(0 0 0) ange)
  1104.             ang (+ ang ange)
  1105.       )
  1106.       (if (> ang (* 2 pi))
  1107.         (setq ang (- ang (* 2 pi)))
  1108.       )
  1109.      
  1110.       ;; if start angle needs revision
  1111.       (if (equal (angle cpt strtpt) ang 0.01)   
  1112.         (progn
  1113.           ;; Start angle needs revision.
  1114.           (setq strt_a T
  1115.                 rad1  (+ (dl_val 40 tmp) temp2) ; outer radius
  1116.                 rad2  (- (dl_val 40 tmp) temp1) ; inner radius
  1117.           )
  1118.           (setq ent (subst (cons 40 rad2) ; modify its radius
  1119.                            (assoc 40 ent) 
  1120.                            ent))
  1121.           (entmod ent) 
  1122.           (dl_atl)                    ; Add ename to list
  1123.           (setq save_1 ent)
  1124.           (setq sent1 (dl_val -1 tmp))                            
  1125.           (if (= flg 4)
  1126.             (if (> uctr 2)
  1127.               (dl_das 0 rad2 50)      ; modify arc endpt and close
  1128.             )
  1129.             (dl_das nil rad2 50)      ; else modify arc endpt
  1130.           )
  1131.           ;; Create the "parallel" arc
  1132.           (command "_.OFFSET" (getvar "tracewid") ; offset the arc
  1133.                               (list tmp '(0 0 0)) 
  1134.                               (polar cpt ang (+ 1 rad1 rad2))
  1135.                               "")
  1136.           (setq tmp (entlast)         ; get the offset arc
  1137.                 ent  (entget tmp))
  1138.           (dl_atl)                    ; Add ename to list
  1139.           (setq save_2 ent)
  1140.           (setq sent2 tmp) 
  1141.           (if (= flg 4)
  1142.             (if (> uctr 3)
  1143.               (progn
  1144.                 (dl_das 1 rad1 50)    ; modify arc endpt and close
  1145.  
  1146.                 ;; set nextpt to "CLose" which will cause an exit.
  1147.                 (setq nextpt "CIerra"
  1148.                       v:stpt nil
  1149.                       cont   nil
  1150.                 )
  1151.               )
  1152.             )
  1153.             (dl_das nil rad1 50)      ; else modify arc endpt
  1154.           )
  1155.  
  1156.         )
  1157.         (progn                        ; if end angle needs revision
  1158.           ;; End angle needs revision.
  1159.           (setq strt_a nil
  1160.                 rad1  (+ (dl_val 40 tmp) temp1) ; outer radius
  1161.                 rad2  (- (dl_val 40 tmp) temp2) ; inner radius
  1162.           )
  1163.           (setq ent (subst (cons 40 rad1) ; modify its radius
  1164.                            (assoc 40 ent) 
  1165.                            ent))
  1166.           (entmod ent)                             
  1167.           (dl_atl)                    ; Add ename to list
  1168.           (setq save_1 ent)
  1169.           (setq sent1 (dl_val -1 tmp))                            
  1170.           (if (= flg 4)
  1171.             (if (> uctr 2)
  1172.               (dl_das 0 rad1 51)      ; modify arc endpt and close
  1173.             )
  1174.             (dl_das nil rad1 51)      ; else modify arc endpt
  1175.           )
  1176.           ;; Create the "parallel" arc
  1177.           (command "_.OFFSET" (getvar "tracewid")    
  1178.                             (list tmp '(0 0 0)) 
  1179.                             cpt 
  1180.                             "")
  1181.           (setq tmp (entlast)         ; get the last arc entity
  1182.                 ent  (entget tmp))
  1183.           (dl_atl)                    ; Add ename to list
  1184.           (setq save_2 ent)
  1185.           (setq sent2 tmp)
  1186.           (if (= flg 4)
  1187.             (if (> uctr 3)
  1188.               (progn
  1189.                 (dl_das 1 rad2 51)    ; modify arc endpt and close
  1190.  
  1191.                 ;; set nextpt to "CLose" which will cause an exit.
  1192.                 (setq nextpt "CIerra"
  1193.                       v:stpt nil
  1194.                       cont   nil
  1195.                 )
  1196.               )
  1197.             )
  1198.             (dl_das nil rad2 51)      ; else modify arc endpt
  1199.           )
  1200.         )
  1201.       )
  1202.  
  1203.     )
  1204.     ((= flg 3)                        ; if straight closing
  1205.       (setq nextpt (nth 0 spts)
  1206.             ang1   (+ (angle strtpt nextpt) (/ pi 2))
  1207.             ang2   (- (angle strtpt nextpt) (/ pi 2))
  1208.       )
  1209.       (dl_dls 0 ang1 temp1)
  1210.       (dl_dls 1 ang2 temp2)
  1211.  
  1212.       ;; set nextpt to "CLose" which will cause an exit.
  1213.       (setq nextpt "CIerra"
  1214.             v:stpt nil
  1215.             cont   nil
  1216.       )
  1217.     )
  1218.     (T
  1219.       (princ "\nERROR:  Valor fuera de rango. ")
  1220.       (exit)
  1221.     )
  1222.   )
  1223.   (setq strtpt nextpt   
  1224.         spts   (append spts (list strtpt))
  1225.         savpts (append savpts (list savpt3))
  1226.         savpts (append savpts (list savpt4))
  1227.   )
  1228.   (command "_.UNDO" "_E")                ; only end when DLINE's have been drawn
  1229. )
  1230. ;;; ------------------- End Support Functions -----------------------
  1231. ;;; ---------------- Begin Line Drawing Functions -------------------
  1232. ;;;
  1233. ;;; Straight DLINE function
  1234. ;;;
  1235. ;;; dl_dls == DLine_Draw_Line_Segment
  1236. ;;;
  1237. (defun dl_dls (flgn ang temp / j k pt1 pt2 tmp1 ent1 p1 p2)
  1238.  
  1239.   (mapcar                             ; get endpoints of the offset line
  1240.     '(lambda (j k)
  1241.        (set j (polar (eval k) ang temp))
  1242.      )      
  1243.      '(pt1 pt2)
  1244.      '(strtpt nextpt)
  1245.   )
  1246.   (cond
  1247.     ((= uctr 0)
  1248.       ;; Set points 1 and 2 for segment 1.
  1249.       (setq p1 (if (dl_l01 brk_e1 "1" pt1 pt2 strtpt) ipt savpt1)) 
  1250.       (setq pt2 (if (dl_l01 brk_e2 "3" pt2 pt1 nextpt) ipt savpt3))
  1251.       (setq pt1 p1)
  1252.     )
  1253.     ((= uctr 1)
  1254.       ;; Set points 1 and 2 for segment 2.
  1255.       (setq p1 (if (dl_l01 brk_e1 "2" pt1 pt2 strtpt) ipt savpt2))
  1256.       (setq pt2 (if (dl_l01 brk_e2 "4" pt2 pt1 nextpt) ipt savpt4))
  1257.       (setq pt1 p1)
  1258.       
  1259.       ;; Now break the line or arc found at the start point 
  1260.       ;; if there is one, and we are in a breaking mood.
  1261.       (if (and dl:brk brk_e1)
  1262.         (progn
  1263.           (command "_.BREAK" brk_e1 savpt1 savpt2)
  1264.         )
  1265.       )
  1266.       ;; Now break the line or arc found at the end point 
  1267.       ;; if there is one, and we are in a breaking mood.
  1268.       (if (and dl:brk brk_e2)
  1269.         (progn
  1270.           (if (eq brk_e1 brk_e2)
  1271.             (progn
  1272.               ;; Delete first line so we can find the arc or line that
  1273.               ;; we found previously.
  1274.               (entdel (nth 0 wnames))  
  1275.               (dl_ved "brk_e2" nextpt)
  1276.               ;; Restore first line
  1277.               (entdel (nth 0 wnames))
  1278.             )
  1279.           )
  1280.           (command "_.BREAK" brk_e2 savpt3 savpt4)
  1281.         )
  1282.       )
  1283.       ;; Do not set brk_e2 nil... it will be set later.
  1284.     )
  1285.     ((= (rem uctr 2.0) 0)    
  1286.       (setq fang nil)
  1287.       (setq p1 (dl_dl2 pt1))          ; Draw line part 2
  1288.       (setq pt2 (if (dl_l01 brk_e2 "3" pt2 pt1 strtpt) 
  1289.                   ipt
  1290.                   savpt3
  1291.                 )
  1292.       )
  1293.       (setq pt1 p1)
  1294.       (if flgn                        ; if closing
  1295.         (progn
  1296.           (setq tmp1 (nth flgn wnames)
  1297.                 ent1 (entget tmp1)    ; get the corresponding prev. entity
  1298.           )
  1299.           (if (= (dl_val 0 tmp1) "LINE")
  1300.             ;; if it's a line
  1301.             (setq pt2 (dl_mls nil 10))           
  1302.             ;; if it's an arc
  1303.             (setq pt2 (dl_mas T nil pt2 pt1 nil))  
  1304.           )
  1305.         )                             
  1306.       )
  1307.     )
  1308.     (T
  1309.       (setq p1 (dl_dl2 pt1))              ; Draw line part 2
  1310.       (setq pt2 (if (dl_l01 brk_e2 "4" pt2 pt1 nextpt) 
  1311.                   ipt
  1312.                   savpt4
  1313.                 )
  1314.       )
  1315.       (setq pt1 p1)
  1316.       (if flgn                        ; if closing
  1317.         (progn
  1318.           (setq tmp1 (nth flgn wnames)
  1319.                 ent1 (entget tmp1)    ; get the corresponding prev. entity
  1320.                 brk_e1 nil
  1321.                 brk_e2 nil
  1322.           )
  1323.           (if (= (dl_val 0 tmp1) "LINE")
  1324.             ;; if it's a line
  1325.             (setq pt2 (dl_mls nil 10))           
  1326.             ;; if it's an arc
  1327.             (setq pt2 (dl_mas T nil pt2 pt1 nil))  
  1328.           )
  1329.         )                             
  1330.       )
  1331.       ;; Now break the line or arc found at the end point 
  1332.       ;; if there is one, and we are in a breaking mood.
  1333.       (if (and dl:brk brk_e2)
  1334.         (progn
  1335.           (command "_.BREAK" brk_e2 savpt3 savpt4)
  1336.         )
  1337.       )
  1338.       ;; Do not set brk_e2 nil... it will be set later.
  1339.     )
  1340.   )
  1341.   (command "_.LINE" pt1 pt2 "")         ; draw the line
  1342.   (setq wnames (if (null wnames) 
  1343.                  (list (setq elast (entlast)) )
  1344.                  (append wnames (list (setq elast (entlast)))))
  1345.         uctr   (1+ uctr)
  1346.   )
  1347.   wnames
  1348. )
  1349. ;;;
  1350. ;;; Set pt1 or pt2 based on whether there is an arc or line to be broken.
  1351. ;;;
  1352. ;;; dl_l01 == DLine_draw_Lines_0_and_1
  1353. ;;;
  1354. (defun dl_l01 (bent1 n p1 p2 pt / temp)
  1355.   (setq n (strcat "savpt" n))
  1356.   (setq spt nil)
  1357.   (if bent1
  1358.     (if (= (dl_val 0 bent1) "LINE")
  1359.       (progn
  1360.         (setq temp (inters (trans (dl_val 10 bent1) 0 1)
  1361.                             (trans (dl_val 11 bent1) 0 1)
  1362.                             p1
  1363.                             p2
  1364.                             nil
  1365.                     )
  1366.         ) 
  1367.         (if temp
  1368.           (set (read n) temp)
  1369.           (progn
  1370.             (set (read n) p1)
  1371.             (setq brk_e1 nil)
  1372.           )
  1373.         )
  1374.       )
  1375.       (progn
  1376.         (set (read n) (dl_ial bent1 p1 p2 pt))
  1377.         ;; Spt is set only if there was no intersection point.
  1378.         (if spt
  1379.           (progn
  1380.             (setq ipt (eval (read n)))
  1381.             (set (read n) spt)
  1382.           )
  1383.         )
  1384.       )
  1385.     )
  1386.     (set (read n) p1)
  1387.   )
  1388.   (if spt
  1389.     T
  1390.     nil
  1391.   )
  1392. )
  1393. ;;;
  1394. ;;; Do more of the line drawing stuff.  This is where we call the modify 
  1395. ;;; functions for the previous arc or line segment.  The line end being
  1396. ;;; modified is always the group 11 end, but we have to test the start
  1397. ;;; and end angle of an arc to tell which end to modify.
  1398. ;;;
  1399. ;;; dl_dl2 == DLine_Draw_Line_segment_part_2
  1400. ;;;
  1401. (defun dl_dl2 (npt)
  1402.   (setq tmp1 (nth (- uctr 2) wnames)
  1403.         ent1 (entget tmp1))           ; get the corresponding prev. entity
  1404.    
  1405.   (if (= (dl_val 0 tmp1) "LINE")  
  1406.     ;; Check angles 0 180, -180  and 360...   
  1407.     (if (or  (equal (angle strtpt nextpt)
  1408.                    (angle (trans (dl_val 10 tmp1) 0 1)
  1409.                           (trans (dl_val 11 tmp1) 0 1)) 0.001)
  1410.              (equal (angle strtpt nextpt)
  1411.                    (angle (trans (dl_val 11 tmp1) 0 1)
  1412.                           (trans (dl_val 10 tmp1) 0 1)) 0.001)
  1413.              (equal (+ (* 2 pi) (angle strtpt nextpt))
  1414.                    (angle (trans (dl_val 10 tmp1) 0 1)
  1415.                           (trans (dl_val 11 tmp1) 0 1)) 0.001)
  1416.         )
  1417.       ;; if it's a line
  1418.       (progn
  1419.         (setq brk_e2 nil)
  1420.         (command "_.LINE" (trans (dl_val 11 tmp1) 0 1) pt1 "") 
  1421.         pt1 
  1422.       )
  1423.       ;; else, if it's an arc
  1424.       (progn
  1425.         (dl_mls nil 11)
  1426.       )
  1427.     )
  1428.     ;; if it's an arc
  1429.     (dl_mas nil nil pt1 pt2 strtpt)  
  1430.   )
  1431. )
  1432. ;;;
  1433. ;;; Modify line endpoint
  1434. ;;;
  1435. ;;; dl_mls == DLine_Modify_Line_Segment
  1436. ;;;
  1437. (defun dl_mls (flg2 nn / spt ept pt)  ; flg2 = nil if line to line
  1438.                                       ;      = T   if line to arc
  1439.  
  1440.   ;; This is the previous entity; a line
  1441.   (setq spt (trans (dl_val 10 tmp1) 0 1)   
  1442.         ept (trans (dl_val 11 tmp1) 0 1)
  1443.   )
  1444.   (if flg2
  1445.     ;; find intersection with arc; tmp == ename of arc
  1446.     (progn
  1447.       ;; Find arc intersection with line; tmp == ename of arc.
  1448.       (setq pt (dl_ial tmp spt ept (if flgn nextpt strtpt)))
  1449.     )
  1450.  
  1451.     ;; find intersection with line
  1452.     (setq pt (inters spt ept pt1 pt2 nil)) 
  1453.   )
  1454.   ;; modify the previous line
  1455.   (if pt 
  1456.     (entmod (subst (cons nn (trans pt 1 0)) 
  1457.                    (assoc nn ent1) 
  1458.                    ent1))
  1459.     (setq pt pt2)
  1460.   )
  1461.   pt
  1462. )
  1463. ;;; 
  1464. ;;; This routine does a variety of tasks: it calculate the distance from
  1465. ;;; the center of the arc (or congruent circle) to a line, then it
  1466. ;;; calculates up to two intersection points of a line and the arc,
  1467. ;;; then it attempts to determine which of the points serves as a 
  1468. ;;; best-fit to the following criteria:
  1469. ;;; 
  1470. ;;;   1) One end of the arc must lie "on" the line, or
  1471. ;;;      one end of the line must lie on the arc. 
  1472. ;;;   2) Given that the point given in 1 above is p1,
  1473. ;;;      and that the other point is p2, then if the arc crosses over
  1474. ;;;      the line then use p2, otherwise the arc does not cross over
  1475. ;;;      the line so use p1.
  1476. ;;;      
  1477. ;;; If the line and the arc do not intersect, then a line will be drawn
  1478. ;;; from the point of intersection of the arc and the perpendicular from
  1479. ;;; the line to the arc centerpoint, and the line;  The line and arc will be 
  1480. ;;; trimmed or extended as needed to meet these points.
  1481. ;;; 
  1482. ;;; If the line and arc are tangent, then the arc and line are
  1483. ;;; trimmed/extended to this point. 
  1484. ;;;
  1485. ;;; p1 and p2 are two points on a line
  1486. ;;; ename  == entity name of arc
  1487. ;;; flg == T when the segment being drawn ends on an arc, 
  1488. ;;; flg == nil when the segment being drawn starts on an arc.
  1489. ;;;
  1490. ;;; dl_ial == DLine_Intersect_Arc_with_Line
  1491. ;;;
  1492. (defun dl_ial (arc pt_1 pt_2 npt / d pi2 rad ang nang temp ipt)
  1493.  
  1494.   (setq cpt  (trans (dl_val 10 arc) (dl_val -1 arc) 1)  
  1495.         pi2  (/ pi 2)                 ; 1/2 pi
  1496.         ang  (angle pt_1 pt_2)                   
  1497.         nang (+ ang pi2)              ; Normal to "ang"
  1498.         temp (inters pt_1 pt_2 cpt (polar cpt nang 1) nil)
  1499.         nang (angle cpt temp)
  1500.   )
  1501.   ;; Get the perpendicular distance from the center of the arc to the line.
  1502.   (setq d (distance cpt temp))
  1503.  
  1504.   (cond
  1505.     ((equal (setq rad (dl_val 40 arc)) d 0.01)
  1506.       ;; One intersection.
  1507.       (setq ipt temp)
  1508.     )
  1509.     ((< rad d)                       
  1510.       ;; No intersection.
  1511.       (setq spt (polar cpt nang rad)
  1512.             ipt temp
  1513.       )
  1514.       (command "_.LINE" spt ipt "")
  1515.       ipt
  1516.     )
  1517.     (T
  1518.       ;; Two intersections. Now...
  1519.       ;; If drawing arcs, fang is set, we're past the first segment...
  1520.       ;; Reset the `near' point based on the previous ipt.  This can be
  1521.       ;; quite different and necessary from the `npt' passed in.
  1522.       (if (and dl_arc fang (> uctr 1)) 
  1523.         (setq npt (polar cpt fang rad))
  1524.       )
  1525.       (dl_g2p npt)
  1526.       (setq ipt (dl_bp arc pt_1 pt_2 ipt1 ipt2))
  1527.       ;; If `fang' is not set, set it, otherwise set it to nil.
  1528.       (if fang 
  1529.         (setq fang nil)
  1530.         (if dl_arc (setq fang (angle cpt ipt)))
  1531.       )
  1532.       ipt
  1533.     )
  1534.   )
  1535. )
  1536. ;;;
  1537. ;;; Get two intersection points, ordering them such that ipt1
  1538. ;;; is the closer of the two points to the passed-in point "npt".
  1539. ;;;
  1540. ;;; dl_g2p == DLine_Get_2_Points
  1541. ;;;
  1542. (defun dl_g2p (npt / temp l theta)
  1543.   (if (equal d 0.0 0.01)
  1544.     (setq theta pi2
  1545.           nang (+ ang pi2)            ; Normal to "ang"
  1546.     )
  1547.     (setq l     (sqrt (abs (- (expt rad 2) (expt d 2))))
  1548.           theta (abs (atan (/ l d)))
  1549.     )
  1550.   )
  1551.   ;; Get the two angles to the infinite intersection points of the 
  1552.   ;; congruent circle to the arc, and the line, then get the two 
  1553.   ;; intersection points.
  1554.   (setq ipt1 (polar cpt (- nang theta) rad))
  1555.   (setq ipt2 (polar cpt (+ nang theta) rad))
  1556.   ;; Set the closer of the two points to npt to be ipt1.
  1557.   (if (< (distance ipt2 npt) (distance ipt1 npt))
  1558.     ;; Swap points
  1559.     (setq temp ipt1
  1560.           ipt1 ipt2
  1561.           ipt2 temp
  1562.     )
  1563.     (if (equal (distance ipt2 npt) (distance ipt1 npt) 0.01)
  1564.       (exit)
  1565.     )
  1566.   )
  1567.   ipt1
  1568. )
  1569. ;;;
  1570. ;;; Test a point `pt' to see if it is on the line `sp--ep'.
  1571. ;;;
  1572. ;;; dl_onl == DLine_ON_Line_segment
  1573. ;;;
  1574. (defun dl_onl (sp ep pt / cpt sa ea ang)
  1575.   (if (inters sp ep pt
  1576.               (polar pt (+ (angle sp ep) (/ pi 2))
  1577.                      (/ (getvar "tracewid") 10)
  1578.               )
  1579.               T)
  1580.     T 
  1581.     nil
  1582.   )
  1583. )
  1584. ;;;
  1585. ;;; Test a point `pt' to see if it is on the arc `arc'.
  1586. ;;;
  1587. ;;; dl_ona == DLine_ON_Arc_segment
  1588. ;;;
  1589. (defun dl_ona (arc pt / cpt sa ea ang)
  1590.   (setq cpt (trans (dl_val 10 arc) (dl_val -1 arc) 1) 
  1591.         sa  (dl_val 50 arc)           ; angle of current ent start point
  1592.         ea  (dl_val 51 arc)           ; angle of current ent end point
  1593.         ang (angle cpt pt)            ; angle to pt.
  1594.   )
  1595.   (if (> sa ea)
  1596.     (if (or (and (> ang sa) (< ang (+ ea (* 2 pi))))
  1597.             (and (> ang (- ea (* 2 pi))) (< ang ea))
  1598.         ) 
  1599.       T 
  1600.       nil
  1601.     )
  1602.     (if (and (> ang sa) (< ang ea)) T nil)
  1603.   )
  1604. )
  1605. ;;;
  1606. ;;; Get the best intersection point of an arc and a line.  The criteria
  1607. ;;; are as follows:
  1608. ;;; 
  1609. ;;;   1) The best point will lie on both the arc and the line.
  1610. ;;;   2) It will be the point which causes the shortest arc to be created
  1611. ;;;      such that (1) is satisfied.
  1612. ;;;   3) If closing, then always use the point closest to nextpt.  Unless,
  1613. ;;;      the points are equidistant, then use 1 and 2 above to tiebreak.
  1614. ;;;   4) If breaking an arc with a line, always use the points nearest the
  1615. ;;;      break point.
  1616. ;;;
  1617. ;;; dl_bp == DLine_Best_Point_of_arc_and_line
  1618. ;;;
  1619. (defun dl_bp (en1 p1 p2 pp1 pp2 / temp temp1 temp2)
  1620.   (setq temp1 (dl_onl p1 p2 pp2)
  1621.         temp2 (dl_ona en1 pp2)
  1622.         temp  (if (or (= flg 1) (= flg 3)) T nil)
  1623.   )
  1624.   (if (and temp1 temp2)
  1625.     (if (and (< uctr 2) 
  1626.              (and brk_e1 brk_e2))
  1627.       pp1
  1628.       (if (and temp (not fang)) pp1 pp2)
  1629.     )
  1630.     pp1
  1631.   )
  1632. )
  1633. ;;; ----------------- End Line Drawing Functions --------------------
  1634. ;;; ---------------- Begin Arc  Drawing Functions -------------------
  1635. ;;;
  1636. ;;; Draw curved DLINE
  1637. ;;;
  1638. ;;; dl_das == DLine_Draw_Arc_Segment
  1639. ;;;
  1640. (defun dl_das (flgn orad nn / tmp1 ent1 pt ang )
  1641.   (cond
  1642.     ((= uctr 0)
  1643.       (setq sent1 tmp)
  1644.       (dl_a01 brk_e1 "1" strtpt nil)  ; DLine_draw_Arc_0_and_1
  1645.       (dl_a01 brk_e2 "3" nextpt T)    ; DLine_draw_Arc_0_and_1
  1646.     )
  1647.     ((= uctr 1)
  1648.       (setq sent1 tmp)
  1649.       (dl_a01 brk_e1 "2" strtpt nil)  ; DLine_draw_Arc_0_and_1
  1650.       (dl_a01 brk_e2 "4" nextpt T)    ; DLine_draw_Arc_0_and_1
  1651.       (dl_mae nil T)
  1652.       (dl_mae nil nil)
  1653.       ;; Now break the line or arc found at the start point
  1654.       ;; if there is one, and we are in a breaking mood.
  1655.       (if (and dl:brk brk_e1)
  1656.         (progn
  1657.           (dl_mae T T)
  1658.           (dl_mae T nil)
  1659.           (command "_.BREAK" brk_e1 savpt1 savpt2)
  1660.         )
  1661.       )
  1662.       ;; Do not set brk_e1 nil... it will be set later.
  1663.       ;; Now break the line or arc found at the end point 
  1664.       ;; if there is one, and we are in a breaking mood.
  1665.       (if (and dl:brk brk_e2)
  1666.         (progn
  1667.           (if (eq brk_e1 brk_e2)
  1668.             (progn
  1669.               ;; Delete both arcs so we can find the arc or line that
  1670.               ;; we found previously.
  1671.               (entdel (nth 0 wnames))  
  1672.               (entdel (nth 1 wnames))  
  1673.               (dl_ved "brk_e2" nextpt)
  1674.               ;; Restore first line
  1675.               (entdel (nth 0 wnames))
  1676.               (entdel (nth 1 wnames))
  1677.             )
  1678.           )
  1679.           (if (null brk_e1)
  1680.             (progn
  1681.               (dl_mae T T)
  1682.               (dl_mae T nil)
  1683.             )
  1684.           )
  1685.           (command "_.BREAK" brk_e2 savpt3 savpt4)
  1686.         )
  1687.       )
  1688.       ;; Do not set brk_e2 nil... it will be set later.
  1689.     )
  1690.     ((= (rem uctr 2.0) 0) 
  1691.       (setq fang nil)
  1692.       (dl_da2)                        ; Draw arc part 2
  1693.       (if fang 
  1694.         (setq ftmp fang
  1695.               fang nil
  1696.         )
  1697.       )
  1698.       (setq save_1 ent)
  1699.       (setq sent1 (cdr(assoc -1 ent)))
  1700.       (setq pt2 (dl_a01 brk_e2 "3" nextpt T)) ; DLine_draw_Arc_0_and_1
  1701.       (if ftmp 
  1702.         (setq fang ftmp
  1703.               ftmp nil
  1704.         )
  1705.       )
  1706.     )
  1707.     (T
  1708.       (dl_da2)                        ; Draw arc part 2
  1709.       (if fang 
  1710.         (setq ftmp fang
  1711.               fang nil
  1712.         )
  1713.       )
  1714.       (setq save_2 ent)
  1715.       (setq sent1 (cdr(assoc -1 ent)))
  1716.       (setq pt2 (dl_a01 brk_e2 "4" nextpt T)) ; DLine_draw_Arc_0_and_1
  1717.       (if ftmp 
  1718.         (setq fang fang
  1719.               ftmp nil
  1720.         )
  1721.       )
  1722.  
  1723.       ;; Now break the line or arc found at the end point 
  1724.       ;; if there is one, and we are in a breaking mood.
  1725.       (if (and dl:brk brk_e2)
  1726.         (progn
  1727.           (dl_mae T T)
  1728.           (dl_mae T nil)
  1729.           (command "_.BREAK" brk_e2 savpt3 savpt4)
  1730.         )
  1731.       )
  1732.       ;; Do not set brk_e2 nil... it will be set later.
  1733.     )
  1734.   )
  1735.   (setq uctr   (1+ uctr))
  1736. )
  1737. ;;;
  1738. ;;; Set pt1 or pt2 based on whether there is an arc or line to be broken.
  1739. ;;;
  1740. ;;; dl_a01 == DLine_draw_Arcs_0_and_1
  1741. ;;;
  1742. (defun dl_a01 (bent1 n pt flg / pt1 pt2 ang1 ang2 anga angb)
  1743.   ;; "n" is the point to save for end capping
  1744.   (setq n (strcat "savpt" n))
  1745.   ;; "tmp" is the arc just created.
  1746.   ;; "bent1" is the line or arc to be broken, if there is one...
  1747.   (if bent1
  1748.     (if (= (dl_val 0 bent1) "LINE")
  1749.       (progn
  1750.         (set (read n) (dl_ial tmp (trans (dl_val 10 bent1) 0 1)
  1751.                                   (trans (dl_val 11 bent1) 0 1) pt)) 
  1752.       )
  1753.       (progn
  1754.         (setq curcpt (trans (dl_val 10 sent1) (dl_val -1 sent1) 1) 
  1755.               prvcpt (trans (dl_val 10 bent1) (dl_val -1 bent1) 1)
  1756.               pt1    (polar prvcpt (dl_val 50 bent1) (dl_val 40 bent1))
  1757.               pt2    (polar curcpt (dl_val nn sent1) (dl_val 40 sent1))
  1758.               ang1   (angle prvcpt pt1)
  1759.         )
  1760.         (if (not (equal ang1 (angle prvcpt strtpt) 0.01))
  1761.           (setq pt1  (polar prvcpt (dl_val 51 bent1) (dl_val 40 bent1))
  1762.                 ang1 (angle prvcpt pt1)
  1763.                 ang2 (angle curcpt pt2)
  1764.                 anga (- ang1 ang2)
  1765.                 angb (- ang2 ang1)
  1766.           )
  1767.         )
  1768.         (if (or (and (< anga 0.0872665)
  1769.                      (> anga -0.0872665))
  1770.                 (and (< angb 0.0872665)
  1771.                      (> angb -0.0872665))
  1772.             )
  1773.           (progn
  1774.             (set (read n) pt)
  1775.             (if (= bent1 brk_e1) 
  1776.               (setq brk_e1 nil)
  1777.               (setq brk_e2 nil)
  1778.             )
  1779.           )
  1780.           (set (read n) (dl_iaa sent1 bent1 pt flg))
  1781.         )
  1782.       )
  1783.     )
  1784.     (progn
  1785.       (setq cpt (trans (dl_val 10 tmp) (dl_val -1 tmp) 1))
  1786.       (set (read n) (polar cpt (angle cpt pt) orad))
  1787.     )
  1788.   )
  1789.   (eval (read n))
  1790. )
  1791. ;;;
  1792. ;;; Do more of the arc drawing stuff.  This is where we call the modify 
  1793. ;;; functions for the previous arc or line segment.  The line end being
  1794. ;;; modified is always the group 11 end, but we have to test the start
  1795. ;;; and end angle of an arc to tell which end to modify.
  1796. ;;;
  1797. ;;; dl_da2 == DLine_Draw_Arc_segment_part_2
  1798. ;;;
  1799. (defun dl_da2 (/ pt)
  1800.   ;; get the corresponding previous entity
  1801.   (setq tmp1 (nth (- uctr 2) wnames) 
  1802.         ent1 (entget tmp1))
  1803.   (if (= (dl_val 0 tmp1) "LINE")     
  1804.     ;; if it's a line
  1805.     (setq pt (dl_mls T 11))             
  1806.     ;; if it's an arc
  1807.     (setq pt (dl_mas nil T nil nil strtpt)) 
  1808.   )
  1809.   ;; pt is a point in the current UCS, not ECS
  1810.   (if pt
  1811.     (progn
  1812.       (setq ang (- (angle cpt pt) ange))
  1813.       (entmod (setq ent (subst (cons nn ang) 
  1814.                        (assoc nn ent) 
  1815.                        ent)))         ; modify arc endpt
  1816.     )
  1817.   )
  1818.   (if flgn                            ; if closing 
  1819.     (progn
  1820.       (setq tmp1 (nth flgn wnames)     
  1821.             ent1  (entget tmp1))  ; get the flagged entity
  1822.       (if (= (dl_val 0 tmp1) "LINE")     
  1823.         ;; if it's a line
  1824.         (setq pt (dl_mls T 10))   
  1825.         ;; if it's an arc
  1826.         (setq pt (dl_mas T T nil nil nextpt)) 
  1827.       )
  1828.       (if pt
  1829.         (progn
  1830.           (setq ang (- (angle cpt pt) ange))
  1831.           (setq nn (if (= nn 50) 51 50))
  1832.           (entmod (setq ent (subst (cons nn ang) 
  1833.                          (assoc nn ent) 
  1834.                          ent)))       ; modify arc endpt
  1835.         )                             
  1836.       )
  1837.     )                             
  1838.   )
  1839. )
  1840. ;;;
  1841. ;;; Modify the endpoints of an arc by changing the start and end angles.
  1842. ;;;
  1843. ;;; dl_mae == DLine_Modify_Arc_Endpoints
  1844. ;;;
  1845. (defun dl_mae (eflg sflg / nn1 nn2)
  1846.   (if (= nn 50)
  1847.     (setq nn1 50 nn2 51)
  1848.     (setq nn1 51 nn2 50)
  1849.   )
  1850.   (if sflg
  1851.     (if eflg
  1852.       (setq save_1 (subst (cons nn2 
  1853.                                 (angle 
  1854.                                   (trans cpt    1 (cdr(assoc -1 save_1)))
  1855.                                   (trans savpt3 1 (cdr(assoc -1 save_1)))
  1856.                                 )
  1857.                           )
  1858.                           (assoc nn2 save_1) save_1)
  1859.       )
  1860.       (setq save_1 (subst (cons nn1 
  1861.                                 (angle 
  1862.                                   (trans cpt    1 (cdr(assoc -1 save_1)))
  1863.                                   (trans savpt1 1 (cdr(assoc -1 save_1)))
  1864.                                 )
  1865.                           )
  1866.                           (assoc nn1 save_1) save_1)
  1867.       )
  1868.     )
  1869.     (if eflg
  1870.       (setq save_2 (subst (cons nn2 
  1871.                                 (angle 
  1872.                                   (trans cpt    1 (cdr(assoc -1 save_1)))
  1873.                                   (trans savpt4 1 (cdr(assoc -1 save_2)))
  1874.                                 )
  1875.                           )
  1876.                           (assoc nn2 save_2) save_2)
  1877.       )
  1878.       (setq save_2 (subst (cons nn1 
  1879.                                 (angle 
  1880.                                   (trans cpt    1 (cdr(assoc -1 save_1)))
  1881.                                   (trans savpt2 1 (cdr(assoc -1 save_2)))
  1882.                                 )
  1883.                           )
  1884.                           (assoc nn1 save_2) save_2)
  1885.       )
  1886.     )
  1887.   )
  1888.   (if sflg
  1889.     (entmod save_1)
  1890.     (entmod save_2)
  1891.   )
  1892. )
  1893. ;;;
  1894. ;;; Modify arc                        ; flg2 = nil if arc to line
  1895. ;;;                                   ;      = T   if arc to arc
  1896. ;;;
  1897. ;;; dl_mas == DLine_Modify_Arc_Segment
  1898. ;;;
  1899. (defun dl_mas (flg3 flg2 spt ept pt / nnn pt1 pt2 rad1 ange)
  1900.   ;; get some stuff
  1901.   (setq cpt1   (trans (dl_val 10 tmp1) (dl_val -1 tmp1) 1)           
  1902.         rad1   (dl_val 40 tmp1)
  1903.         ang1   (dl_val 50 tmp1)
  1904.   )
  1905.   (if (null pt)                       ; if a point is not passed in:
  1906.     (setq pt (nth 0 spts))            ; set to initial saved start point.
  1907.   )               
  1908.   (setq ange (trans '(1 0 0) (dl_val -1 tmp1) 1)
  1909.         ange (angle '(0 0 0) ange)
  1910.         ang1 (+ ang1 ange)
  1911.   )
  1912.   (if (> ang1 (* 2 pi))
  1913.     (setq ang1 (- ang1 (* 2 pi)))
  1914.   )
  1915.   (if (equal (angle cpt1 pt) ang1 0.01) ; figure out if we're looking
  1916.     (setq nnn 50)                     ; for the start or end point of
  1917.     (setq nnn 51)                     ; the beginning arc, then
  1918.   )                                   ; get the intersection point
  1919.   ;; if arc to arc
  1920.   (if flg2
  1921.     ;; then
  1922.     (progn
  1923.       ;; find intersection with arc
  1924.       (setq pt1 (dl_iaa tmp tmp1 (if flg3 nextpt strtpt) flg2))   
  1925.       (if pt1 
  1926.         (progn
  1927.           (setq ang1 (- (angle cpt1 pt1) ange))
  1928.           (setq ent1 (subst (cons nnn ang1) 
  1929.                             (assoc nnn ent1) 
  1930.                             ent1))                 
  1931.           (entmod ent1)               ; modify arc endpt
  1932.         )
  1933.       )
  1934.     )
  1935.     ;; else
  1936.     (progn 
  1937.       ;; find arc intersection with line from spt to ept
  1938.       (setq pt1 (dl_ial tmp1 spt ept pt)) 
  1939.       (setq ang1 (- (angle cpt1 pt1) ange))
  1940.       (setq ent1 (subst (cons nnn ang1) 
  1941.                         (assoc nnn ent1) 
  1942.                         ent1))                 
  1943.       (entmod ent1)                   ; modify arc endpt
  1944.     )
  1945.   )
  1946.   pt1
  1947. )
  1948. ;;; ---------------- Begin Arc to Arc Functions ---------------------
  1949. ;;;
  1950. ;;; This routine does a variety of tasks: it calculate up to two 
  1951. ;;; intersection points of two arcs,
  1952. ;;; then it attempts to determine which of the points serves as a 
  1953. ;;; best-fit to the following criteria:
  1954. ;;; 
  1955. ;;;   1) One end of the arc must lie "on" the arc. 
  1956. ;;;   2) Given that the point given in 1 above is pt1,
  1957. ;;;      and that the other point is pt2, then if the arc crosses over
  1958. ;;;      the other arc then use pt2, otherwise the arc does not cross over
  1959. ;;;      the other arc so use pt1.
  1960. ;;;      
  1961. ;;; If the two arcs do not intersect, then a line will be drawn
  1962. ;;; from the point of intersection of the arc and the perpendicular from
  1963. ;;; the line of the two arc centerpoints;  The arcs will be 
  1964. ;;; trimmed or extended as needed to meet these points.
  1965. ;;; 
  1966. ;;; If the two arcs are tangent, then they are
  1967. ;;; trimmed/extended to this point. 
  1968. ;;;
  1969. ;;; Intersection point of two arcs or circles
  1970. ;;; a    = radius of ename 1
  1971. ;;; b    = distance from curcpt to prvcpt
  1972. ;;; c    = radius of ename 2
  1973. ;;; curcpt = center point of first circle or arc  -- bent1, bent2, tmp
  1974. ;;; prvcpt = center point of second circle or arc -- sent1, sent2, tmp1
  1975. ;;; npt  = near point for nearest test
  1976. ;;;
  1977. ;;; dl_iaa == DLine_Intersect_Arc_and_Arc
  1978. ;;;
  1979. (defun dl_iaa  (en1 en2 npt flga / a b c s ang alpha alph ipt 
  1980.                                    curcpt prvcpt temp temp1 temp2)
  1981.   (setq curcpt  (trans (dl_val 10 en1) (dl_val -1 en1) 1) ; the "last" entity
  1982.         prvcpt  (trans (dl_val 10 en2) (dl_val -1 en2) 1) ; the previous entity
  1983.         a       (dl_val 40 en2)
  1984.         b       (distance curcpt prvcpt)
  1985.         c       (dl_val 40 en1)
  1986.         s       (/ (+ a b c) 2.0)
  1987.         ang     (angle curcpt prvcpt)
  1988.   )
  1989.   (cond
  1990.     ;; circles are tangent
  1991.     ;; If (- s a) == 0, this would cause a divide by zero below...
  1992.     ((or (= (- s a) 0) (equal b (+ a c) 0.001) (equal b (abs (- a c)) 0.001))
  1993.       ;; Circles are tangent.
  1994.       (setq ipt nil)
  1995.     )
  1996.     ;; circles do not intersect
  1997.     ((and (or (> b (+ a c)) (if (> c a) (< (+ a b) c) (< (+ c b) a)))                 
  1998.           (not (equal (+ a b ) c (/ (+ a b c) 1000000))))
  1999.       ;; No intersection.
  2000.       (if (= flg 4) 
  2001.         (progn
  2002.           (setq ipt (polar curcpt (angle curcpt prvcpt) c))
  2003.           (command "_.LINE" (polar prvcpt (angle prvcpt ipt) a) ipt "")
  2004.         )
  2005.         (progn
  2006.           (setq ipt (polar curcpt (angle curcpt prvcpt) c))
  2007.           (command "_.LINE" (polar prvcpt (angle prvcpt ipt) a) ipt "")
  2008.         )
  2009.       )
  2010.     )
  2011.     (T
  2012.       ;; general law of cosines formula -- (- s a) != 0
  2013.       (setq alpha (* 2.0 (atan (sqrt (abs (/ (* (- s b) (- s c)) 
  2014.                                              (* s (- s a)))))))
  2015.       )
  2016.       
  2017.       (setq tpt1 (polar curcpt (+ ang alpha) c)
  2018.             tpt2 (polar curcpt (- ang alpha) c)
  2019.             anga  (angle curcpt npt)
  2020.             angb  (angle prvcpt npt)
  2021.       )
  2022.       ;; Two intersections. Now...
  2023.       ;; If drawing arcs, fang is set, we're past the first segment...
  2024.       ;; Reset the `near' point based on the previous ipt.  This can be
  2025.       ;; quite different and necessary from the `npt' passed in.
  2026.       (if (and dl_arc fang (> uctr 1)) 
  2027.         (setq npt (polar prvcpt fang c))
  2028.       )
  2029.       (if (< (distance tpt1 npt) (distance tpt2 npt))
  2030.         (setq temp tpt1
  2031.               tpt1 tpt2
  2032.               tpt2 temp
  2033.         )
  2034.       )
  2035.       (setq temp (angle prvcpt curcpt)) ; angle from prev ent to this ent
  2036.       (setq ipt (dl_bap en1 en2 tpt2 tpt1 nil))
  2037.       (if fang 
  2038.         (setq fang nil)
  2039.         (if dl_arc (setq fang (angle cpt ipt)))
  2040.       )
  2041.     )
  2042.   )
  2043.   (setq cpt curcpt)
  2044.   (setq cpt1 prvcpt)
  2045.   ipt                                 ; return point
  2046. )
  2047. ;;;
  2048. ;;; Get the best point for the arc/arc intersection.
  2049. ;;;
  2050. ;;; dl_bap == DLine_Best_Point_to_Arc
  2051. ;;;
  2052. (defun dl_bap (en1 en2 pp1 pp2 flg / temp1 temp2)
  2053.   (setq temp1 (dl_ona en1 pp2)
  2054.         temp2 (dl_ona en2 pp2)
  2055.   )
  2056.   (if temp2
  2057.     (if (and (< uctr 2) 
  2058.              (and brk_e1 brk_e2))
  2059.       pp1
  2060.       (if temp1 
  2061.         (if (< uctr 2) 
  2062.           pp2
  2063.           (if (not fang) pp2 pp1)
  2064.         )
  2065.         pp1
  2066.       )
  2067.     )
  2068.     pp1
  2069.   )        
  2070. )
  2071. ;;; ----------------- End Arc  Drawing Functions --------------------
  2072. ;;; -------------------- Begin Misc Functions -----------------------
  2073. ;;;
  2074. ;;; Add the entity name to the list in wnames.
  2075. ;;;
  2076. ;;; dl_atl == DLine_Add_To_List
  2077. ;;;
  2078. (defun dl_atl ()
  2079.   (setq wnames (if (null wnames) 
  2080.                  (list (entlast)) 
  2081.                  (append wnames (list tmp)))
  2082.   )
  2083.   wnames
  2084. )
  2085. ;;;
  2086. ;;; The value of the assoc number of <ename>
  2087. ;;;
  2088. (defun dl_val (v temp)
  2089.   (cdr(assoc v (entget temp)))
  2090. )
  2091. ;;;
  2092. ;;; List stripper : strips the last "v" members from the list
  2093. ;;;
  2094. (defun dl_lsu (lst v / m)
  2095.   (setq m 0 temp '())
  2096.   (repeat (- (length lst) v)
  2097.     (progn
  2098.       (setq temp (append temp (list (nth m lst))))
  2099.       (setq m (1+ m))
  2100.   ) )
  2101.   temp
  2102. )
  2103. ;;;
  2104. ;;; Bitwise DLINE endcap setting function.
  2105. ;;;
  2106. (defun endcap ()
  2107.   (initget "Auto Ambos Final Ninguno Inicial")
  2108.   (setq dl:ecp (getkword 
  2109.     "\n¿Que tipo de remates?  Ambos/Final/Ninguno/Inicial/<Auto>: "))
  2110.   (cond
  2111.     ((= dl:ecp "Ninguno")
  2112.       (setq dl:ecp 0)
  2113.     )
  2114.     ((= dl:ecp "Inicial")
  2115.       (setq dl:ecp 1)
  2116.     )
  2117.     ((= dl:ecp "Final")
  2118.       (setq dl:ecp 2)
  2119.     )
  2120.     ((= dl:ecp "Ambos")
  2121.       (setq dl:ecp 3)
  2122.     )
  2123.     (T  ; Auto
  2124.       (setq dl:ecp 4)
  2125.     )
  2126.   )
  2127. )
  2128. ;;;
  2129. ;;; Set these defaults when loading the routine.
  2130. ;;;
  2131. (if (null dl:ecp) (setq dl:ecp 4))    ; default to auto endcaps
  2132. (if (null dl:snp) (setq dl:snp T))    ; default to snapping ON
  2133. (if (null dl:brk) (setq dl:brk T))    ; default to breaking ON
  2134. (if (null dl:osd) (setq dl:osd 0))    ; default to center alignment
  2135. ;;;
  2136. ;;; These are the c: functions.
  2137. ;;;
  2138. (defun c:dl () (dline))
  2139. (defun c:dline () (dline))
  2140.  
  2141. (princ "  DLINE cargada. (Version corregida por J. Erce.) ")
  2142. (princ)
  2143.