[CAD LISP] Create Dynamic Curved Arrows Instantly (ARW.lsp)
When drafting in AutoCAD, you frequently need to draw curved arrows to
indicate directions, annotations, or fluid flows in your drawings. Doing
this manually—either by drawing an arc and then manually attaching a
separate arrowhead, or messing around with complex leader settings—is
incredibly tedious and a massive waste of time. It is especially frustrating
when you need to match the curvature perfectly, only to find the arrowhead
looks disproportionate or detached.
If you have dozens of details to annotate, this repetitive task slows down
your workflow and opens the door to human error. That is why automating this
process with a dedicated routine is essential for any professional drafter
looking to maintain speed and accuracy.
Why You Should Use the 'ARW' LISP
- Effortless Arrow Creation: Combines an arc and a perfectly scaled arrowhead into a single, fluid polyline command.
- Dynamic Real-Time Preview: Allows you to visually adjust the arc's curvature on your screen before finalizing it.
- Smart Size Adjustments: Features an 'Auto' scaling option that automatically sets the arrowhead size based on the distance, while also letting you input a custom fixed value.
- Clean and Professional Output: Keeps your drawing neat by generating a single lightweight polyline instead of messy, fragmented objects.
How It Works (Step-by-Step Guide)
- Load the LISP File: Load the ARW.lsp file into AutoCAD using the APPLOAD command.
- Run the Command: Type ARW in the command line and press Enter.
- Set the Arrowhead Length: The prompt will ask you to specify the arrow length. You can press Enter to accept the default Auto mode, or enter a specific numeric value.
- Pick the Start and End Points: Click the starting point of the arrow, and then click the endpoint where the arrowhead will face.
- Adjust Curvature and Finish: Move your mouse to dynamically adjust the arc's curvature. Once you like how it looks, click to instantly generate the perfect curved arrow.
Wrapping Up
The ARW LISP is a straightforward yet powerful utility designed to
remove one of the most annoying micro-tasks in AutoCAD drafting. By
reducing a multi-step design process into a seamless point-and-click
routine, you can keep your momentum and focus on what truly matters in
your design.
Here's a LISP you can add to your startup suite. It'll save you a ton
of time today. Let me know if you run into any bugs.
The LISP Code
(defun c:ARW ( / *error* old_osmode 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)
(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))
(setvar "CMDECHO" 1)
(princ)
)
(setq old_osmode (getvar "OSMODE"))
(setvar "CMDECHO" 0)
(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)
(princ "\nCurved arrow polyline created successfully.")
)
(princ "\nCancelled.")
)
)
)
)
(setvar "CMDECHO" 1)
(princ)
)

Post a Comment