CADLISPMASTER
Stop wasting time on repetitive AutoCAD tasks. CAD LISP Master provides free, efficient AutoLISP codes and clear tutorials designed to automate your workflow and speed up your drafting.

Draw Curved Arrows in AutoCAD: Dynamic Polyline Arrowhead Generator

Create dynamic curved arrows with auto-scaling arrowheads in AutoCAD using ARW.lsp. Free AutoLISP script for fast drawing callouts and direction indic

Create Dynamic Curved Arrows Instantly

Indicating circulation paths, structural movement, or detail callouts in AutoCAD often requires drawing curved arrows. The standard native process—drawing an arc, creating a separate solid hatch or arrowhead block, and rotating it to align perfectly with the arc's endpoint—takes far too many steps for a basic annotation. Standard leaders often lack the smooth curvature control needed for tight drawing spaces.

The ARW.lsp (Curved Arrow Generator) utility converts arrow creation into a fast 3-click process. It builds a single, unified polyline featuring a curved tail and a proportional arrowhead. You can dynamically adjust the arc's curvature on screen in real time before placing the mark.


Key Workflow Highlights

  • Real-Time Visual Preview: Drag your crosshairs on screen to adjust the arc bulge dynamically before confirming arrow placement.

  • Smart Auto-Scaling: Uses an Auto mode to size the arrowhead proportionally based on total arc distance, or allows you to enter a fixed length for strict drawing standards.

  • Unified Polyline Output: Generates both the arc stem and filled arrowhead as a single connected polyline object, making it easy to move, stretch, or erase as a single unit.


How to Use ARW.lsp

  1. Load ARW.lsp in AutoCAD using the APPLOAD command.

  2. Type ARW in the command prompt and hit Enter.

  3. Specify your arrow length (press Enter to accept Auto mode, or type a custom numerical length).

  4. Click your start point (tail) and your end point (arrowhead direction).

  5. Move your crosshairs to visually stretch the arc curvature preview.

  6. Left-click once you are satisfied with the arc shape to finalize the curved arrow.


AutoLISP Code (ARW.lsp)

Copy the code below and save it as ARW.lsp inside your AutoCAD support folder:

(defun c:ARW ( / *error* doc old_osmode old_cmdecho pt1 pt2 pt_mid chord_dist ang_chord ang_perp loop gr code data vec d_mouse h b temp_ent temp_obj final_arc_ent arcObj total_len arrow_len arrow_width pt_base_wcs pt_mid_arc_wcs pt_base_ucs pt_mid_arc_ucs user_input )
  (vl-load-com)
  (setq doc (vla-get-ActiveDocument (vlax-get-acad-object)))
  (defun *error* (msg)
    (if (and temp_ent (entget temp_ent)) (entdel temp_ent))
    (if (and final_arc_ent (entget final_arc_ent)) (entdel final_arc_ent))
    (if old_osmode (setvar "OSMODE" old_osmode))
    (if old_cmdecho (setvar "CMDECHO" old_cmdecho))
    (vla-EndUndoMark doc)
    (princ "\nCAD Lisp [www.daolpro.com]")
    (princ)
  )
  (setq old_osmode (getvar "OSMODE"))
  (setq old_cmdecho (getvar "CMDECHO"))
  (setvar "CMDECHO" 0)
  (vla-StartUndoMark doc)
  (if (not *ARW_GLOBAL_LEN*) (setq *ARW_GLOBAL_LEN* "Auto"))
  (initget 6 "Auto")
  (setq user_input (getreal (strcat "\nSpecify arrow length or [Auto] <" (if (numberp *ARW_GLOBAL_LEN*) (rtos *ARW_GLOBAL_LEN*) *ARW_GLOBAL_LEN*) ">: ")))
  (cond
    ((= user_input "Auto") (setq *ARW_GLOBAL_LEN* "Auto"))
    ((numberp user_input) (setq *ARW_GLOBAL_LEN* user_input))
  )
  (if (setq pt1 (getpoint "\nSpecify start point: "))
    (if (setq pt2 (getpoint pt1 "\nSpecify end point: "))
      (progn
        (setq pt_mid (list (/ (+ (car pt1) (car pt2)) 2.0) (/ (+ (cadr pt1) (cadr pt2)) 2.0) 0.0)
              chord_dist (distance pt1 pt2)
              ang_chord (angle pt1 pt2)
              ang_perp (+ ang_chord (/ pi 2.0))
        )
        (entmake (list '(0 . "LWPOLYLINE") '(100 . "AcDbEntity") '(100 . "AcDbPolyline") '(90 . 2) '(70 . 0) (cons 10 (trans pt1 1 0)) (cons 10 (trans pt2 1 0))))
        (setq temp_ent (entlast)
              temp_obj (vlax-ename->vla-object temp_ent)
              loop T
        )
        (princ "\nSpecify arc curvature (dynamic preview): ")
        (while loop
          (setq gr (grread T 15 0)
                code (car gr)
                data (cadr gr)
          )
          (cond
            ((= code 5)
             (setq vec (angle pt_mid data)
                   d_mouse (distance pt_mid data)
                   h (* d_mouse (cos (- vec ang_perp)))
             )
             (if (< (abs h) 0.001) (setq h 0.001))
             (setq b (- (/ (* 2.0 h) chord_dist)))
             (vla-SetBulge temp_obj 0 b)
            )
            ((= code 3) (setq loop nil))
            ((or (= code 25) (and (= code 2) (= data 27))) (setq loop nil pt2 nil))
          )
        )
        (if (and temp_ent (entget temp_ent)) (entdel temp_ent))
        (if (and pt2 b)
          (progn
            (entmake (list '(0 . "LWPOLYLINE") '(100 . "AcDbEntity") '(100 . "AcDbPolyline") '(90 . 2) '(70 . 0) (cons 10 (trans pt1 1 0)) (cons 10 (trans pt2 1 0))))
            (setq final_arc_ent (entlast)
                  arcObj (vlax-ename->vla-object final_arc_ent)
            )
            (vla-SetBulge arcObj 0 b)
            (setq total_len (vlax-curve-getDistAtParam arcObj (vlax-curve-getEndParam arcObj)))
            (if (numberp *ARW_GLOBAL_LEN*)
              (setq arrow_len *ARW_GLOBAL_LEN*)
              (setq arrow_len (* chord_dist 0.08))
            )
            (setq arrow_width (* arrow_len 0.4))
            (if (>= arrow_len total_len) (setq arrow_len (* total_len 0.5)))
            (setq pt_base_wcs (vlax-curve-getPointAtDist arcObj (- total_len arrow_len))
                  pt_mid_arc_wcs (vlax-curve-getPointAtDist arcObj (* (- total_len arrow_len) 0.5))
                  pt_base_ucs (trans pt_base_wcs 0 1)
                  pt_mid_arc_ucs (trans pt_mid_arc_wcs 0 1)
                )
            (if (and final_arc_ent (entget final_arc_ent)) (entdel final_arc_ent))
            (setvar "OSMODE" 0)
            (command "_.pline" pt1 "_a" "_s" pt_mid_arc_ucs pt_base_ucs "_l" "_w" arrow_width 0.0 pt2 "")
            (setvar "OSMODE" old_osmode)
          )
        )
      )
    )
  )
  (vla-EndUndoMark doc)
  (setvar "CMDECHO" old_cmdecho)
  (princ "\nCAD Lisp [www.daolpro.com]")
  (princ)
)

Annotation Tip

Because ARW.lsp outputs a single 2D polyline, you can quickly adjust line weights or assign specific callout layers directly via the Properties palette (CHPROP) without affecting the arrowhead geometry.

Post a Comment