Bài toán đặt ra: Trong autocad chúng ta có 1 block tên “1”. Bài viết này sẽ cung cấp cách để tạo lisp copy block trên theo phương ngang với các khoảng cách nhập vào lần lượt là 150,150,160,170,150.
Dưới đây là mã LISP để thực hiện công việc này:
(defun c:copyblocks ()
(setq blkname “1”) ; Tên của block cần copy
(setq distances ‘(150 150 160 170 150)) ; Danh sách các khoảng cách để sao chép block
(setq pt (getpoint “\nChọn điểm bắt đầu: “)) ; Lấy điểm bắt đầu từ người dùng
(foreach dist distances
(command “insert” blkname pt “” “” “”) ; Chèn block tại vị trí hiện tại
(setq pt (list (+ (car pt) dist) (cadr pt))) ; Cập nhật vị trí x của điểm bằng cách thêm khoảng cách
)
(princ)
)
Chúng ta sẽ tối ưu lisp thêm một chút để cho phép người dùng nhập vào tên của block và danh sách các khoảng cách khi sử dụng lệnh trong AutoCAD:
(defun c:copyblocks ()
(setq blkname (getstring “\nNhập tên block cần copy: “)) ; Lấy tên block từ người dùng
(setq distancestr (getstring “\nNhập danh sách các khoảng cách (cách nhau bởi dấu phẩy): “)) ; Lấy chuỗi khoảng cách từ người dùng
(setq distances (read (strcat “(” (vl-string-translate “,” ” ” distancestr) “)”))) ; Chuyển đổi chuỗi thành danh sách khoảng cách
(if (not (tblsearch “BLOCK” blkname)) ; Kiểm tra xem block có tồn tại không
(progn
(princ (strcat “\nBlock \”” blkname “\” không tồn tại.”))
(exit)
)
)
(setq pt (getpoint “\nChọn điểm bắt đầu: “)) ; Lấy điểm bắt đầu từ người dùng
(foreach dist distances
(command “_.insert” blkname pt “” “” “”) ; Chèn block tại vị trí hiện tại
(setq pt (list (+ (car pt) dist) (cadr pt))) ; Cập nhật vị trí x của điểm bằng cách thêm khoảng cách
)
(princ) ; Kết thúc lệnh mà không trả lại kết quả gì
)
Bây giờ chúng ta sẽ sửa lisp sao cho block được chọn trực tiếp từ bản vẽ và điểm bắt đầu là điểm gốc của block đó:
(defun c:copyblocks ()
(setq ss (ssget “_+.:E:S” ‘((0 . “INSERT”))))
(if (null ss)
(progn
(princ “\nKhông có block nào được chọn.”)
(exit)
)
)
(setq blkent (ssname ss 0)) ; Lấy entity name của block đầu tiên trong selection set
(setq blkname (cdr (assoc 2 (entget blkent)))) ; Lấy tên block từ entity data
(setq pt (cdr (assoc 10 (entget blkent)))) ; Lấy điểm gốc của block được chọn
(setq distancestr (getstring “\nNhập danh sách các khoảng cách (cách nhau bởi dấu phẩy): “)) ; Lấy chuỗi khoảng cách từ người dùng
(setq distances (read (strcat “(” (vl-string-translate “,” ” ” distancestr) “)”))) ; Chuyển đổi chuỗi thành danh sách khoảng cách
(foreach dist distances
(setq pt (list (+ (car pt) dist) (cadr pt))) ; Cập nhật vị trí x của điểm cho block tiếp theo
(command “_.insert” blkname pt “” “” “”) ; Chèn block tại vị trí mới
)
(princ) ; Kết thúc lệnh mà không trả lại kết quả gì
)
Bây giờ chúng ta sẽ sửa lisp sao cho các đối tượng được chọn không giới hạn chỉ là block, mà có thể là đường line, polyline…
(defun c:cpb ()
(setq oldosmode (getvar “OSMODE”)) ; Lưu cài đặt OSMODE hiện tại
(setq ent (entsel “\nChọn đối tượng để sao chép: “)) ; Người dùng chọn đối tượng
(if (null ent)
(progn
(setvar “OSMODE” oldosmode) ; Khôi phục cài đặt OSMODE
(princ “\nKhông có đối tượng nào được chọn.”)
(exit)
)
)
(setq basept (getpoint “\nChọn điểm bắt đầu: “)) ; Người dùng chọn điểm bắt đầu
(setq pt basept) ; Đặt điểm hiện tại là điểm bắt đầu
(setvar “OSMODE” 0) ; Tắt bắt điểm
(setq distancestr (getstring “\nNhập danh sách các khoảng cách (cách nhau bởi dấu phẩy): “)) ; Lấy chuỗi khoảng cách từ người dùng
(setq distances (read (strcat “(” (vl-string-translate “,” ” ” distancestr) “)”))) ; Chuyển đổi chuỗi thành danh sách khoảng cách
(foreach dist distances
(command “_.copy” (car ent) “” basept pt “”) ; Sao chép đối tượng từ basept đến pt
(setq pt (list (+ (car pt) dist) (cadr pt))) ; Cập nhật điểm để đặt đối tượng tiếp theo
)
(setvar “OSMODE” oldosmode) ; Khôi phục cài đặt OSMODE
(princ) ; Kết thúc lệnh mà không trả lại kết quả gì
)
Cuối cùng là lisp hoàn chỉnh với việc copy nhiều đối tượng được chọn đồng thời theo dãy khoảng cách được nhập từ bàn phím
(defun c:cvv ()
(setq oldosmode (getvar "OSMODE")) ; Lưu cài đặt OSMODE hiện tại
(setq ents (ssget '((0 . "*")))) ; Người dùng chọn đối tượng
(if (null ents)
(progn
(setvar "OSMODE" oldosmode) ; Khôi phục cài đặt OSMODE
(princ "\nKhông có đối tượng nào được chọn.")
(exit)
)
)
(setq basept (getpoint "\nChọn điểm bắt đầu: ")) ; Người dùng chọn điểm bắt đầu
(setq pt basept) ; Đặt điểm hiện tại là điểm bắt đầu
(setvar "OSMODE" 0) ; Tắt bắt điểm
(setq distancestr (getstring "\nNhập danh sách các khoảng cách (cách nhau bởi dấu phẩy): ")) ; Lấy chuỗi khoảng cách từ người dùng
(setq distances (read (strcat "(" (vl-string-translate "," " " distancestr) ")"))) ; Chuyển đổi chuỗi thành danh sách khoảng cách
(setq cnt 0) ; Đếm số đối tượng được chọn
(repeat (sslength ents)
(setq ent (ssname ents cnt))
(setq cnt (1+ cnt))
(setq pt basept) ; Đặt lại điểm bắt đầu cho mỗi đối tượng
(foreach dist distances
(command "_.copy" ent "" basept pt "") ; Sao chép đối tượng từ basept đến pt
(setq pt (list (+ (car pt) dist) (cadr pt))) ; Cập nhật điểm để đặt đối tượng tiếp theo
)
)
(setvar "OSMODE" oldosmode) ; Khôi phục cài đặt OSMODE
(princ) ; Kết thúc lệnh mà không trả lại kết quả gì
)
Cách sử dụng lisp:
- Lưu mã LISP vào một tệp với phần mở rộng
.lsp
. - Trong AutoCAD, load tệp LISP vào bằng cách gõ lệnh
(load "đường_dẫn_đến_file_lisp")
. - Gọi lệnh
copyblocks
để bắt đầu quá trình. - Chọn block mà bạn muốn sao chép trên bản vẽ.
- Nhập chuỗi các khoảng cách khi được yêu cầu, các khoảng cách phân cách nhau bởi dấu phẩy. Ví dụ 150,230,160,352
Facebook Comments