Hiển thị các bài đăng có nhãn Hướng dẩn viết lisp. Hiển thị tất cả bài đăng
Hiển thị các bài đăng có nhãn Hướng dẩn viết lisp. Hiển thị tất cả bài đăng

Thứ Sáu, 27 tháng 8, 2010

Tạo PLINE trong lisp:

Vấn đề vướng khó chịu nhất của bà con (kể cả mình) khi viết lisp là làm việc với pline:
-Trường hợp đơn giản nhất là vẽ 1 pline với số đỉnh bất kỳ sau đó lấy giá trị diện tích của nó miễn cưỡng lắm thì viết như sau:
(DEFUN c:dtpl ( )
(setq a (getpoint "\nChon diem dau tien: "))
(setq b (getpoint a"\nChon diem tiep theo: "))
(command "pline" a b "")
(setq plhoinay (entlast))
(setq a b)
(while (setq b (getpoint a"\nChon diem tiep theo : "))
(command "pline" a b "")
(command "pedit" "m" "L" plhoinay "" "j" "0" "")
(setq plhoinay (entlast))
(setq a b)
)
(command "pedit" plhoinay "c" "")
(command "area" "object" "last")
(setq dientich (getvar "area"))
(alert (rtos dientich 2 2))
(princ)
)

Giải thích lisp trên như sau:

(setq a (getpoint "\nChon diem dau tien: "))
Hỏi chọn 1 điểm trên màn hình và gán cho biến a
(setq b (getpoint a"\nChon diem tiep theo: "))
Hỏi chọn 1 điểm trên màn hình và gán cho biến b
(command "pline" a b "")
Thực hiện lệnh pline vẽ từ a đến b, kết thúc lệnh pline
(setq plhoinay (entlast))
Gán pl vừa tạo cho biến hoinay
(setq a b)
Gán điểm b hiện tại thành điểm a
(while (setq b (getpoint a"\nChon diem tiep theo : "))
Khởi động vòng lặp tồn tại khi điều kiện biến điểm b được gán bằng pick điểm, nếu enter thì kết thúc vòng lặp
(command "pline" a b "")
Thực hiện lệnh pline vẽ từ a đến b, kết thúc lệnh pline.......lưu ý lúc này điểm a chính là điểm b của đoạn trên đã được gán qua nhé
(command "pedit" "m" "L" plhoinay "" "j" "0" "")
Thực hiện lệnh pedit lựa chọn m, chọn pline vừa tạo, chọn pline tạo trong đoạn trước đã gán cho biến plhoinay, chọn J để nối thành 1 pline liên tục
(setq plhoinay (entlast))
Gán pl vừa tạo cho biến hoinay
(setq a b)
Gán điểm b hiện tại thành điểm a
)
kết thúc vòng lặp nếu nhấn enter, lúc này sản phẩm là 1 đường pline hở
Đoạn bên dưới là thủ tục đóng kín pline và lấy giá trị diện tích và báo ra kết quả. Nhưng nếu vùng muốn tính diện tích chứa cả cung tròn thì việt viết nhại theo lệnh pline là rất khó khăn và cuối cùng mình cũng tìm ra giải pháp bắng cách lisp trả hẳn về cad thực hiện xong lệnh pline xong thì lisp tiếp tục chạy.



Bài này Duy đang viết dở nha bạn ........

Thứ Tư, 21 tháng 7, 2010

Hướng dẩn viết DCL bài mở đầu:

Bạn nên theo dỏi theo tên bài viết tăng từ nhỏ tới lớn thì mới đúng trình tự!


Đến đây phần lisp coi như tạm đủ dùng, về cơ bản thì bây nhiêu đó nắm vững và ứng dụng linh hoạt thì làm được ối chuyện. Phần hổ trợ thêm cho lisp mà gần gủi nhất là hộp thoại: Cái này chủ yếu giải quyết khâu oai và màu mè. Kiến thức này của mình cũng ít nhưng cũng mạnh dạn làm vài bài giúp các bạn có khái niệm cơ bản để có thể tự nghiên cứu chuyên thêm tuỳ vào khả năng của mỗi người.

**Chương trình dùng viết hộp thoại: Tất cả các chương trình soạn thảo văn bản. Mình vẫn dùng notepad. Lưu nó ra định dạng *.DCL là được.
**Trong 1 file *.DCL có thể chứa nhiều hộp thoại trong đó:
-Mở đầu bằng
tenhopthoai : dialog {
label = "noidungtieude";

-Kết thúc bằng
}

-Trong đó:
+ tenhopthoai là tên lisp dùng để gọi hộp thoại này (lưu ý đặt tên khác nhau cho các hộp thoại và viết liên tục không khoảng cách)
+ Noidungtieude là nội dung hiển thị phía trên của hộp thoại (Cái này ưng viết sao cũng được có thể có khoảng cách chủ yếu dùng báo tên hoặc chức năng hộp thoại này. Muốn bỏ trống thì label = " ";

**Số dấu {} trong 1 định nghĩa hộp thoại là bằng nhau.
**Hộp thoại chỉ là cái vỏ còn nội dung bên trong, hoạt động thế nào là do lisp quyết định. Trước tiên cứ thiết kế hộp thoại cho ưng ý cái đã, từ từ tính tới nội dung.
*Mẹo: khi viết xong hộp thoại muốn nghía xem nó như nào mà chưa cần viết lisp để gọi hắn lên thì bạn làm như sau:

-Khởi động cad.
-Vào Tools => Autolisp => Visual lisp editor. Nó khở động lên chương trình.
-Bạn vào File => Open và open cái file *.DCL muốn nghía lên.
-Vào Tools => Inter face tools => Preview DCL Editor. Nó sẽ hiện cái hộp thoại lên cho bạn xem trước.

**Mọi hộp thoại ít nhất phải có 1 nút dùng thoát khỏi hộp thoại mà ko thực hiện chức năng nào như sau.
:button {
label = "Cancel";
key = "Cancel";
is_cancel = true;
}


**Bắt đầu là thủ tục để có 1 nút nhấn cho hộp thoại.

:button {
label = "Ten nut 1";
width = 0;
key = "btn_bieuthuc1";
}


Vậy hộp thoại đơn giản như sau:



tenhopthoai : dialog {
label = "noidungtieude";


:button {
label = "Cancel";
key = "Cancel";
is_cancel = true;
}


}




Hình dáng như sau:

Hộp thoại này chỉ có duy nhất nút thoát khỏi hộp thoại. Kết hợp thêm 1 nút nửa để làm việc khác như sau:




tenhopthoai : dialog {
label = "noidungtieude";


:button {
label = "Ten nut 1";
width = 0;
key = "btn_bieuthuc1";
}

:button {
label = "Cancel";
key = "Cancel";
is_cancel = true;
}


}

Hình dáng như sau:

Khi không nói gì thì các nội dung trong hộp thoại sẽ xếp từ trên xuống dưới. Muốn sắp xếp lại thì dùng 2 cú pháp sắp sếp ( xem bài sau).

Chủ Nhật, 4 tháng 7, 2010

Hướng dẩn viết lisp bài 30:

Bạn nên theo dỏi theo tên bài viết tăng từ nhỏ tới lớn thì mới đúng trình tự!


Đáp án đây. Hy vọng bạn đã hoàn thành giống như sau:

(defun c:vht ()
(command "undo" "be")
(setq luubatdiem (getvar "osmode"))
(setvar "osmode" 0)

(Princ "\nChon cac text :")
(setq tapdoituong (ssget '((0 . "text"))))
(setq diemchuan (getpoint "\nChon diem canh le: "))
(setq thutu 0)
(setq sodoituong (sslength tapdoituong))

(while (< thutu sodoituong)
(setq doituong (ssname tapdoituong thutu))
(setq laynoidung (entget doituong))
(setq diemve (cdr (assoc 10 laynoidung)))

(setq xmoi (car diemchuan))
(setq ymoi (cadr diemve))
(setq diemmoi (list xmoi ymoi))

(command "move" doituong "" diemve diemmoi)
(setq thutu (+ thutu 1))
)
(command "undo" "end")
(setvar "osmode" luubatdiem)
(Princ)
)

**Sau đây mình nói về cách lấy thông tin của đối tượng bằng lisp:
Giả sử rằng bạn có đối tượng (doituong) bạn có được bằng cách nào thì tùy. Muốn lấy thông tin từ nó bạn phải làm việc giống như là mở cửa bước vào trong phòng. Dùng hàm enteget:
(setq laynoidung (entget doituong))
Khi đã vào phòng thì có nhiều thứ để lấy. Mổi thông tin của đối tượng có 1 con số đại diện ví dụ điểm canh lề thứ nhất của text là số 10. Dùng hàm cdr và assoc sẽ lấy được thông tin tương ứng với con số đó.
(setq diemve (cdr (assoc 10 laynoidung)))
Mình sẽ gỏ lại bảng các số đại diện như từ điển bạn cần thông số gì thì vào tra nhé. (Một vài cái hay dùng thôi chứ nhiều lắm mình gỏ không nổi, bạn mua sách về lisp sẽ có bảng này).

CHUNG:
Layer của đối tượng: 8
Kiểu của đối tượng: 0
Màu của đối tượng: 62
Tên dạng đường: 6

TEXT:
Nội dung text: 1
Độ lớn text: 40
Style: 7
Điểm canh lề thứ nhất: 10

BLOCK: (INSERT) Lưu ý block thì trong từ điển của cad là đối tượng INSERT
Tên BLOCK: 2
Điểm chèn: 10
Góc quay: 50
Tỉ lệ theo trục X: 41
Tỉ lệ theo trục Y: 42
Tỉ lệ theo trục Z: 43

LINE:
Điểm đầu: 10
Điểm cuối: 11

CIRCLE:
Tọa độ tâm: 10
Bán kính: 40

PLINE: (LWPOLYLINE)
Độ rộng: 43
Số lượng đỉnh: 90

DIMENSION:
Style: 3

Vậy cách lấy thông tin text như sau:
Nội dung text: (setq noidung (cdr (assoc 1 laynoidung)))
Độ lớn text: (setq dolon (cdr (assoc 40 laynoidung)))
Style: (setq style (cdr (assoc 7 laynoidung)))
Điểm canh lề thứ nhất: (setq diemve (cdr (assoc 10 laynoidung)))

Thứ Hai, 7 tháng 6, 2010

Cách làm 1 bộ lisp di động.

*Bạn có trong tay một bộ lisp ưng ý và dùng đã quen. Đôi lúc bạn ngồi 1 máy khác cảm thấy rất bất tiện, cài lisp của mình vào thì sợ ảnh hưởng đến người khác.
*Mình cũng bị tình trạng này và đến nay đã tìm ra cách giải quyết nên khoe với mọi người. Cách này mình gọi là lisp di động.
-Nhiều bạn sẽ nghỉ lisp thì để đâu cũng không quan trọng chỉ cần load lên thôi có gì phải tinh vi,,,,,,,,,,, Vấn đề là lisp nhiều khi không đơn thuần chỉ là các file lisp mà còn rất nhiều thứ kèm theo ví dụ:
+File dwg dùng chèn vào phục vụ nhu cầu nào đó của lisp.
+File dcl dùng hiển thị hộp thoại.
+Các file sld dùng cho hộp thoại và các mục đích trang trí, minh họa khác.
Nói chung là có rất nhiều loại file kèm theo cần phải dùng trong ứng dụng lisp.

-Thông thường người viết lisp có hai cách ứng xử với các file này:
+Chỉ đích danh file với đầy đủ đường dẩn ví dụ:
(command ".INSERT" "C:\\tienich\\dwg\\cott.dwg" (list (car a)(cadr a)) 1 1 0)
+Chỉ tên file không có đường dẩn và tạo Support File Search Path đến thư mục chứa file ví dụ:
(command ".INSERT" "cott.dwg" (list (car a)(cadr a)) 1 1 0)
Và Add thư mục C:\\tienich\\dwg\\ vào Support File Search Path.
-Cả hai trường hợp trên phù hợp khi lisp nằm cố định trên máy. Bây giờ bạn chép tất cả vào CD hoặc USB để đem nó đi máy khác thì đường dẩn sẽ không còn ổn định (mổi máy mổi khác) Tôi xin trình bày cách mà tôi áp dụng cho ứng dụng lisp của mình như sau:

-Tổ chức một thư mục tổng (tôi đặt tên tienich).Bên trong là các thư mục con theo từng loại file (để dể kiểm soát) ví dụ tôi đặt như sau:
+DWG
+DCL
+LENH
+FLIEHETHONG

-Tạo 1 file bất kỳ tốt nhất nên là file có định dạng đặt biệt chút cho đở nhầm lẩn (trường hợp của tôi là file DUY.ICO). Đặt file này trong thư mục tổng ví dụ: tienich\\duy.ico. Tác dụng của file này tôi sẽ trình bày phía dưới.
-Cải tạo tất cả các dòng trong lisp có liên quan đến file bên ngoài như sau:

(start_image "img_1")
(slide_image 0 0 (dimx_tile "img_1")(dimy_tile "img_1") (strcat odiachay "\\tienich\\dcl\\lgoduy.sld"))
(end_image)

(setq DCL_ID (load_dialog (strcat odiachay "\\tienich\\dcl\\VEKHOIDAC.DCL")))

(command "INSERT" (strcat odiachay "\\tienich\\dwg\\cos") (list (car p0cos)(cadr p0cos)) 1 1 0)

Nghĩa là cần phải xác định biến odiachay thì các dường dẩn đến file mới hoàn thiện.
-Tạo file lisp để khi load lên sẽ làm tất cả các bước sau:
+Xác định biến odiachay.
+Load tất cả các file lsp cần load.
Nội dung như sau:

(setq vitrifilekiemtraduongdan (getfiled "DE XAC DINH DUONG DAN BAN HAY CHON FILE DUY.ICON " "" "ico" 0))
(setq dodaiduongdantienichdocduoc (strlen vitrifilekiemtraduongdan))
(setq dodaiduongdantienichdocduoctru (- dodaiduongdantienichdocduoc 16))
(setq tenodiachay (substr vitrifilekiemtraduongdan 1 dodaiduongdantienichdocduoctru))
(setq odiachay tenodiachay)

(load(strcat odiachay "/tienich/lenh/thuvienndung"))
(load(strcat odiachay "/tienich/lenh/thuvienchitiet"))
(load(strcat odiachay "/tienich/lenh/tienichchonht"))
(load(strcat odiachay "/tienich/lenh/thongke"))


Phần màu xanh dùng để load các file lisp.
Phần màu cam dùng xác định biến odiachay cách làm việc như sau:
+Hiển thị hộp thoại open file với tiêu đề DE XAC DINH DUONG DAN BAN HAY CHON FILE DUY.ICON, định dạng file mặc định là file *.ico.
+Đọc ra đường dẩn đầy đủ của file DUY.ICO.
+Đếm số ký tự trong chuổi vừa thu được.
+Trừ số ký tự đi 16 (là số ký tự của chuỗi tienich\\duy.ico).
+Lấy giá ra chuỗi con của chuổi tên file đầy đủ từ vị trí đầu tiên đến vị trí thứ đã trừ đi 16.
Giá trị này chính là biến odiachay.

*Tất nhiên có nhiều cách hay hơn để làm việc lisp di động này nhưng mình làm được như vậy và dùng thấy rất ổn nên giới thiệu lên đây mong giúp được cho nhửng bạn đang bị vướng vấn đề như mình.
*Tham khảo sản phẩm ở Đây!

Thứ Ba, 18 tháng 5, 2010

Hướng dẩn viết lisp bài 29:

Bạn nên theo dỏi theo tên bài viết tăng từ nhỏ tới lớn thì mới đúng trình tự!

Một chức năng hay của lisp là có thể thao tác lặp lại một vài thao tác trên từng đối tượng của tập hợp chọn.
Ứng dụng vòng lặp While.
Ví dụ bạn có tập hợp tapdoituong gồm các text hình thành từ
(setq tapdoituong (ssget '((0 . "text"))))
Bây giờ bạn muốn vẽ 1 hình tròn tâm tại điểm chèn text bán kính 100.
Việc vẽ 1 hình tròn bằng lisp khi biết tâm và bán kính bằng lisp thì đơn giản rồi.
(command "circle" diemve 100)
Vấn đề là làm lần lượt cho từng text trong cả tập hợp chọn.
Dùng hàm sslength để lấy ra số lượng đối tượng trong tập hợp chọn
(setq sodoituong (sslength tapdoituong))
Hàm ssname lấy ra đối tượng thứ thutu trong tập hợp tapdoituong
(setq doituong (ssname tapdoituong thutu))
Đầu tiên cho thutu = 0 sau đó áp dụng vòng lặp While với điều kiện thutu< sodoituong, cuối vòng lặp cho thutu = thutu+1 đến khi thutu= sodoituong thì vòng lặp sẽ dừng lại.

Đoạn lisp như sau:
(defun c:vht ()
(command "undo" "be")
(setq luubatdiem (getvar "osmode"))
(setvar "osmode" 0)

(Princ "\nChon cac text :")
(setq tapdoituong (ssget '((0 . "text"))))
(setq thutu 0)
(setq sodoituong (sslength tapdoituong))

(while (< thutu sodoituong)
(setq doituong (ssname tapdoituong thutu))
(setq laynoidung (entget doituong))
(setq diemve (cdr (assoc 10 laynoidung)))
(command "circle" diemve 100)
(setq thutu (+ thutu 1))
)
(command "undo" "end")
(setvar "osmode" luubatdiem)
(Princ)
)

Bạn chạy thử lisp này chọn các text nó sẽ vẽ các hình tròn vào điểm chèn của từng text.
Đoạn sau giúp lấy ra điểm chèn của text:
(setq laynoidung (entget doituong))
(setq diemve (cdr (assoc 10 laynoidung)))
Bài sau mình sẽ nói về cách lấy các thông tin về đối tượng cad bằng lisp, có bao hàm cả hai dòng trên. Bài này bạn chấp nhận nó đã nhé.
*Để thực hành mình ra 1 đề bài bạn viết thử nhé.
Viết lisp hỏi chọn các text, hỏi chọn điểm canh lề, move các text được chọn sao cho điểm canh lề của text thẳng hàng theo phương thẳng đứng.
*Gợi ý:
-Cơ bản đoạn lisp như trên.
-Sau khi chọn đối tượng thêm phần hỏi chọn điểm canh lề. (diemchuan)
-Sau khi lấy được điểm canh lề text (trường hợp này là diemve). Bỏ dòng vẽ hình tròn mà thay bằng dòng move.
-Move từng text từ điểm canh lề (diemve) đến điểm mới. Điểm mới xác định bằng cách lấy giá trị x của diemchuan và y của diemve.
*Sẽ có đáp án trong bài tới.

Hướng dẩn viết lisp bài 28:

Bạn nên theo dỏi theo tên bài viết tăng từ nhỏ tới lớn thì mới đúng trình tự!

*Trong khi viết lisp đôi khi có các dữ liệu nhập vào lặp lại cứ mỗi lần lisp hỏi lại phải nhập vào. Cách hay hơn là dữ liệu nào nhập vào rồi thì ghi nhớ lại cho lần sau nếu cần giá trị khác thì nhập vào còn nếu vẫn dùng giá trị cũ thì chỉ cần enter là có giá trị cũ để dùng.
-Sau đây là đoạn lisp giúp cho bạn có thêm 2 hàm có tác dụng lưu giữ giá trị nhập vào. Mình tìm thấy nó trong 1 đĩa cd ko biết rỏ tác giả và cũng không tìm hiểu cách làm việc của nó cứ biết tác dụng và ứng dụng vào công việc thôi. Bạn cũng vậy nhé cứ lưu đoạn này lại sau đó dùng theo cách mình hướng dẩn.

;---------------------------------------
(defun nstr (stri def)
(princ stri)
(princ "<")
(princ " ")
(princ def)
(princ ">")
(princ ":")
(princ " ")
);defun nstr
;--------------------
(defun nstr1 (stri)
(princ stri)
(princ "<")
(princ "Nhap vao")
(princ ">")
(princ ":")
(princ " ")
);defun nstr1
;---------------------
(defun nint (prompt def / temp)
(if def
(setq temp (getint (nstr prompt def)))
(setq def (getint (nstr1 prompt)))
);if def
(if temp
(setq def temp)
def
);if temp
);defun nint
;---------------------
(defun dnint (prompt def / temp)
(if def
(setq temp (getreal (nstr prompt def)))
(setq def (getreal (nstr1 prompt)))
);if def
(if temp
(setq def temp)
def
);if temp
);defun nint
;--------------------
(defun ndist (po prompt def / temp) ;nhan kh/cach va luu gia tri mac dinh
(if def
(setq temp (getdist po (nstr prompt def)))
(setq def (getdist po (nstr1 prompt)))
)if def
(if temp
(setq def temp)
def
);if temp
);defun ndist
;-----------------------------------


Cách dùng:
-Hàm ndint: lưu giữ giá trị số. Giá trị số này được nhập từ bàn phím.


(setq giatri (dnint "\nTi le chinh "giatri1))
(setq giatri1 giatri)

Ví dụ đoạn lisp scale với tỉ lệ scale được lưu lại.

(Defun c:sclt (a)
(command "undo" "be")
(Prompt "\nChon doi tuong muon chinh ti le")
(setq dtthu (ssget))
(setq a (getpoint "\nChon tam phong: "))
(setq tilechinh (dnint "\nTi le chinh "tiledchinh1))
(setq tiledchinh1 tilechinh)
(command "scale" dtthu "" (list (car a)(cadr a)) tilechinh)
(command "undo" "end")
(Prin I)
)

*Cách dùng:
-Hàm ndist: lưu giữ giá trị khoảng cách. Giá trị này được chuyễn thành số, giá trị này có thể được nhập từ bàn phím.

(setq giatri (ndist a "\nDo cao khoi muon ve "giatri1))
(setq giatri1 giatri)
Trong đó a là điểm đã được xác định.
Ví dụ đoạn lisp vẽ box với cao độ khối được lưu lại.

(Defun c:khoi (a)
(command "undo" "be")
(setq a (getpoint "\nDiem thu nhat:"))
(setq b (getcorner a"\nDiem thu hai: "))
(setq dckhoive (ndist a "\nDo cao khoi muon ve "cckhoive1))
(setq cckhoive1 dckhoive)
(command "box" (list (car a) (cadr a) (caddr a)) (list (car b) (cadr b) (caddr b)) dckhoive)
(command "undo" "end")
(Prin I)
)


Bạn lưu ý đoạn định nghĩa hai hàm này chỉ cần load lên 1 lần trong 1 phiên làm việc thì các lisp có dùng 2 hàm này điều chạy được cả nhé.

Thứ Hai, 12 tháng 4, 2010

Trò chơi xếp lisp:


Để viết lisp mình dùng phương pháp giống như chơi trò xếp gạch, nghĩa là các đoạn đã viết thành công mình sẽ lưu lại thành kiểu từ điển sau đó thì xếp nó lại với nhau theo nhu cầu của mình. Xin chia sẽ với các bạn bộ từ điển viết lisp của mình.

Đoạn mở đầu cho tất cả các lisp:
(defun c:tenlenh ()
(command "undo" "be")

Trong đó tenlenh là cái mà bạn gỏ vào thanh command để thực thi lệnh lisp.


Đoạn kết thúc cho tất cả các lisp:
(command "undo" "end")
(princ)
)


Còn tất cả các đoạn bên dưới thì ghép vào giữa hai đoạn trên thì coi như bạn viết được lisp rồi đó.


Lưu bắt điểm tự động :
(setq luubatdiem (getvar "osmode"))

Trả lại bắt điểm tự động:
(setvar "osmode" luubatdiem)

Lưu tên layer hiện hành :
(setq luulayer (getvar "clayer"))

Trả lại layer hiện hành :
(setvar "clayer" luulayer)

Lưu bán kính lệnh fillet hiện hành :
(setq luubankinh (getvar "filletrad"))

Trả lại bán kính lệnh fillet hiện hành :
(setvar "filletrad" luubankinh)

Lưu kiểu chử hiện hành :
(setq luukieuchu (getvar "TEXTSTYLE"))

Trả lại kiểu chử hiện hành :
(setvar "TEXTSTYLE" luukieuchu)

Đoạn chọn điểm a bằng clik chuột trái:
(setq a (getpoint "\nChon diem: "))

Đoạn chọn điểm b bằng clik chuột trái có đường dẩn hướng nối với điểm a:
(setq b (getpoint a"\nChon diem: "))

Đoạn lấy khoảng cách từ a đến b:
(setq daiab (distance a b))
Đoạn lấy góc mà đoạn ab tạo với trục x: (giá trị thu được là radian)
(setq gocab (angle a b))

Đoạn đổi giá trị góc từ radian sang độ:
(setq gocdo (* 180 (/ gocradian pi)))

Đoạn vẽ line từ a tới b:
(command ".line" a b "")

Đoạn vẽ circle tâm a bán kính a b:
(command ".circle" a b)

Đoạn chọn 1 nhóm đối tượng lưu thành biến doituong:
(setq doituong (ssget))

Đoạn chọn 1 nhóm đối tượng bằng cách chọn pline bao quanh lưu thành biến doituong:
(setq plst (acet-geom-vertex-list (car (entsel "\n Chon pline gioi han"))))
(setq doituong (ssget "wp" plst))

Đoạn move nhóm đối tượng doituong từ a tới b:
(command ".move" doituong "" a b)

Đoạn move nhóm đối tượng vừa chọn trước đó từ a tới b:
(command ".move" "previous" "" a b)

Đoạn move đối tượng vừa được tạo mới nhất từ a tới b:
(command ".move" "last" "" a b)

Đoạn làm xuất hiện bảng chọn color của cad và trả về giá trị mau là số từ 1 đến 225.
(princ "\nChon mau lop :")(setq mau (acad_colordlg 7))

Đoạn lưu giá trị là số: Biến kết quả để dùng là biến giatri
(if (= giatri nil)
(setq giatri1 5.0)
(setq giatri1 giatri)
)
(setq giatri (GETREAL (strcat "\nNhap so can luu: <" (rtos giatri1 2 2) ">")))
(if (= giatri nil)
(setq giatri giatri1)
)

Đoạn lưu kết quả là chử: Biến kết quả để dùng là giatric
(if (= giatric nil)
(setq giatric1 "mau")
(setq giatric1 giatric)
)
(setq giatric (GETSTRING (strcat "\nNhap chu can luu: <" giatric1 ">")))
(if (= giatric "")
(setq giatric giatric1)
)

Thứ Tư, 7 tháng 4, 2010

Hướng dẩn viết lisp bài 27:

Bạn nên theo dỏi theo tên bài viết tăng từ nhỏ tới lớn thì mới đúng trình tự!

*Đọc dữ liệu từ file txt. Gồm 3 bước:
-Mở file (hàm open).
-Đọc dữ liệu từ file (hàm read-line).
-Đóng file (hàm close)

*Viết dữ liệu vào file txt. Gồm 3 bước:
-Mở file (hàm open).
-Viết dữ liệu vào file (hàm write-line).
-Đóng file (hàm close)

*Hàm Open dùng mở 1 file để đọc hoặc viết dữ liệu vào file. Cú pháp:
(open tenfile kieumo) trong đó:
-tenfile: là đường dẩn đầy đủ của file. Ví dụ “D:\\tailieukythuat\\duy.txt”
-kieumo: là ký tự viết thường “a” “r” “w” dùng xác định kiểu mở file:
+”a” mở file tenfile để chép dữ liệu nối tiếp vào cuối file. Nếu tìm thấy file con trỏ nằm cuối file, dữ liệu chép vào sẽ nối vào cuối file. Nếu không tìm thấy file tenfile sẽ được tạo mới, con trỏ nằm đầu file.
+”r” mở file tenfile để đọc dữ liệu. Con trỏ nằm tại vị trí dòng đầu tiên của file. Nếu không tìm thấy file này hàm trả về nil.
+”w” mở file tenfile để chép dữ liệu vào file này. Nếu tìm thấy dữ liệu trong file sẽ bị chép đè lên. Nếu không tìm thấy file tenfile sẽ được tạo mới, con trỏ nằm đầu file.

*Khi open 1 file bạn cấp cho nó 1 tên đại diện. Nhớ rằng file phải được đóng bằng hàm close trước khi thoát khỏi acad nếu không file có nguy cơ bị văng đi đâu đó không tìm ra.

-Ví dụ mở file C:\\tailieukythuat\\duy.txt viết dòng tailieukythuat.com và đóng file lại như sau:

(setq tenfile (open “C:\\tailieukythuat\\duy.txt” “a”))
(setq noidungviet “tailieukythuat.com”)
(write-line noidungviet tenfile)
(close tenfile)

-Ví dụ mở file C:\\tailieukythuat\\duy.txt đọc dòng dầu tiên và đóng file lại như sau:

(setq tenfile (open “C:\\tailieukythuat\\duy.txt” “r”))
(setq noidungdoc (read-line tenfile))
(close tenfile)

-Lưu ý khi thực hiện xong hàm read-line thì con trỏ sẽ nhảy xuống dòng kế tiếp nên muốn đọc nội dung dòng thứ n của file C:\\tailieukythuat\\duy.txt thì mình dùng hàm repeat n lần với dòng (setq noidungdoc (read-line tenfile)). Ví dụ đọc dòng thứ 3 và gán cho biến noidungdoc:

(setq tenfile (open “C:\\tailieukythuat\\duy.txt” “r”))
(repeat 3
(setq noidungdoc (read-line tenfile))
)
(close tenfile)

Hướng dẩn viết lisp bài 26:

Bạn nên theo dỏi theo tên bài viết tăng từ nhỏ tới lớn thì mới đúng trình tự!

Sau khi có đường dẩn 1 file thì có thể làm rất nhiều việc với nó: Ví dụ copy, delete .v.v. Mình có thể thực hiện các lệnh dos từ dòng lệnh lisp bằng cách gọi lệnh shell trước khi gọi lệnh dos.
Để chắc ăn có 1 số bạn trẻ bây giờ không học dos như lớp già tụi mình hồi xưa mình đưa ra 1 số ví dụ dùng lệnh dos để các bạn tham khảo:
1/Tạo thư mục tailieukythuat trong ổ đĩa c
(command "SHELL" "MD C:\\tailieukythuat" )
2/Copy file duy.txt trong thư mục D:\\tailieukythuat vào thư mục C:\\tailieukythuat
(command "SHELL" "copy D:\\tailieukythuat\\duy.txt C:\\tailieukythuat" )
3/Copy tất cả các file trong thư mục D:\\tailieukythuat vào thư mục C:\\tailieukythuat
(command "SHELL" "copy D:\\tailieukythuat\\*.* C:\\tailieukythuat" )
4/Copy file duy.txt trong thư mục D:\\tailieukythuat vào thư mục hiện hành của cad
(command "SHELL" "copy D:\\tailieukythuat\\duy.txt " )
5/Copy tất cả các file trong thư mục D:\\tailieukythuat vào thư mục hiện hành của cad
(command "SHELL" "copy D:\\tailieukythuat\\*.* " )
6/Xóa file duy.txt trong thư mục D:\\tailieukythuat
(command "SHELL" "del D:\\tailieukythuat\\duy.txt" )
7/Xóa tất cả các file trong thư mục D:\\tailieukythuat
(command "SHELL" "del D:\\tailieukythuat\\*.*" )

Đấy ứng dụng lệnh dos vào lisp chủ yếu để tạo thư mục, copy file, xóa file. Có 1 cái hạn chế là không xóa thư mục được nhưng bây nhiêu là đủ dùng rồi.

Hướng dẩn viết lisp bài 25:

Bạn nên theo dỏi theo tên bài viết tăng từ nhỏ tới lớn thì mới đúng trình tự!

Có nhiều trường hợp bạn cần làm việc với một vài file để phục vụ 1 nhu cầu nào đó của lisp. Giới thiệu các hàm liên quan:
*Hàm getfiled làm xuất hiện hộp thoại chọn file Cú pháp:
(getfiled tieude tenfile duoi kieu) trong đó:
-tieude: là nội dung dòng chử xuất hiện trên tiêu đề hộp thoại.
-tenfile: là tên file hoặc đường dẩn mặc định xuất hiện sẵn trong hộp thoại.
-duoi: là phẩn mở rộng của file.
-kieu: là kiểu hộp thoại open hay save:
+1: Hộp thoại save.
+8: Hộp thoại open.
-Lưu ý các thông số trên điều phải được xác định, tham số nào không sử dụng phải gán cho nó giá trị rổng "".
-Dù hộp thoại là save hay open thì kết quả của hàm getfiled là một chuổi dạng đường dẩn, làm gì với nó do mình quyết định.
-Ví dụ: Lisp chọn 1 file để insert vào bản vẽ:

(defun c:chen ()
(command "undo" "be")
(setq filechen (getfiled "Chon flie de chen" "" "dwg" 8))
(setq a (getpoint "\nChon diem chen: "))
(command "INSERT" filechen a 1 1 0)
(command "undo" "end")
(princ)
)

Hướng dẩn viết lisp bài 24:

Bạn nên theo dỏi theo tên bài viết tăng từ nhỏ tới lớn thì mới đúng trình tự!

Nhìn cái lisp trên bạn sẽ thấy có hai đoạn nội dung giống y hệt nhau dẫn đến lisp quá dài. Cách giải quyết: Cứ cái đoạn nào có nội dung giống nhau mà lại xuất hiện nhiều lần thì làm như sau:
(defun doanlap ()
Nội dung đoạn
)
Lưu ý sau defun không có c:
Sau đó cứ chổ nào cần nguyên cái đoạn đó chỉ cần thay bằng dòng
(doanlap) là được. Ví dụ lisp đánh cos sửa lại như sau:


(defun vonglapcos ()
(setvar "osmode" 0)
(setq daiab (distance a b))
(setq giatri (/ daiab motmet))
(setq c (list (- (car a) 250) (+ (cadr a) 410)))
(setq trenduoi (- (cadr a) (cadr b)))
(if (= trenduoi 0) (PROGN
(setq dau "%%p ")
)
)
(if (> trenduoi 0) (PROGN
(setq dau "+ ")
)
)
(if (< trenduoi 0) (PROGN
(setq dau "- ")
)
)
(setq noidung (strcat dau (rtos giatri 2 3)))
(command "-style" "tlkt" "VNI-HELVE" "0" "1" "0" "n" "n")
(command ".TEXT" c 250 0 noidung)
(setq timfile (findfile "c:\\tailieukythuat\\dwg\\caodo.dwg"))
(if (= timfile nil) (PROGN
(princ "\nKhong tim thay file caodo.dwg")
)
)
(if (/= timfile nil) (PROGN
(command "INSERT" "c:\\tailieukythuat\\dwg\\caodo.dwg" a 1 1 0)
)
)
(setvar "osmode" luubatdiem)
)
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
(defun c:cos ()
(command "undo" "be")
(setq motmet (getreal "\nMot met ban ve bang bao nhieu: "))
(setq luubatdiem (getvar "osmode"))
(setq a (getpoint "\nChon diem muon danh cos: "))
(setvar "osmode" 128)
(setq b (getpoint a"\nChon cao do 0.000: "))
(Vonglapcos)
(while
(setq a (getpoint b"\nChon diem muon danh cos : "))
(setq luubatdiem (getvar "osmode"))
(Vonglapcos)
)
(command "undo" "end")
(princ)
)

Hướng dẩn viết lisp bài 23:

Bạn nên theo dỏi theo tên bài viết tăng từ nhỏ tới lớn thì mới đúng trình tự!

Bài trước mình đã giới thiệu vòng lặp repeat là vòng lặp đơn giản nhất. Hôm nay mình giới thiệu tiếp vòng lặp có điều kiện. Hàm WHILE.
-Cú pháp như sau:
(while (điều kiện)
(các thao tác lặp lại)
)
-Cách dùng đơn giản nhất như sau:
(while
(các thao tác lặp lại)
)
Đoạn trên có tác dụng nếu nhấn enter thì vòng lặp sẽ dừng lại nếu không các thao tác sẽ được lặp lại. Ví dụ với lisp sau:
-Đây là lisp nguyên mẫu:
(defun c:doanthang ()
(setq a (getpoint "\nChon diem: "))
(setq b (getpoint a"\nChon diem: "))
(command ".line" a b "")
(princ)
)
-Tác dụng hỏi chọn 2 điểm và vẽ đoạn thẳng qua 2 điểm, kết thúc lệnh. Bây giờ bạn muốn lisp tiếp tục hỏi chọn điểm và tiếp tục vẽ đoạn thẳng khi nào nhấn enter thì kết thúc lệnh (giống lệnh line của cad)

(defun c:doanthang ()
(setq a (getpoint "\nChon diem: "))
(setq b (getpoint a"\nChon diem: "))
(command ".line" a b "")
(setq a b)
(while
(setq b (getpoint a"\nChon diem tiep theo : "))
(command ".line" a b "")
(setq a b)
)
(princ)
)
-Hai đoạn lisp trên mình tạm thời bỏ qua phần lưu bắt điểm và undo để bạn dể nhận ra sự thay đổi.
-Bạn lưu ý dòng (setq a b) có tác dụng sau khi vẽ đoạn thẳng từ a tới b thì gán điểm b cho biến a lúc này điểm b trở thành điểm a sau đó chọn tiếp điểm b lại vẽ từ a tới b, lại gán b cho a cứ như vậy. Khi bạn enter thì vòng lặp kết thúc, kết thúc lệnh.
-Tương tự bạn có thể sửa lại lisp đánh cos làm cho chọn được nhiều điểm đánh cao độ trong 1 lần gọi lệnh như sau:





(defun c:cos ()
(command "undo" "be")
(setq motmet (getreal "\nMot met ban ve bang bao nhieu: "))
(setq luubatdiem (getvar "osmode"))
(setq a (getpoint "\nChon diem muon danh cos: "))
(setvar "osmode" 128)
(setq b (getpoint a"\nChon cao do 0.000: "))
(setvar "osmode" 0)
(setq daiab (distance a b))
(setq giatri (/ daiab motmet))
(setq c (list (- (car a) 250) (+ (cadr a) 410)))
(setq trenduoi (- (cadr a) (cadr b)))
(if (= trenduoi 0) (PROGN
(setq dau "%%p ")
)
)
(if (> trenduoi 0) (PROGN
(setq dau "+ ")
)
)
(if (< trenduoi 0) (PROGN
(setq dau "- ")
)
)
(setq noidung (strcat dau (rtos giatri 2 3)))
(command "-style" "tlkt" "VNI-HELVE" "0" "1" "0" "n" "n")
(command ".TEXT" c 250 0 noidung)
(setq timfile (findfile "c:\\tailieukythuat\\dwg\\caodo.dwg"))
(if (= timfile nil) (PROGN
(princ "\nKhong tim thay file caodo.dwg")
)
)
(if (/= timfile nil) (PROGN
(command "INSERT" "c:\\tailieukythuat\\dwg\\caodo.dwg" a 1 1 0)
)
)
(setvar "osmode" luubatdiem)
(while
(setq a (getpoint b"\nChon diem muon danh cos : "))
(setq luubatdiem (getvar "osmode"))
(setvar "osmode" 0)
(setq daiab (distance a b))
(setq giatri (/ daiab motmet))
(setq c (list (- (car a) 250) (+ (cadr a) 410)))
(setq trenduoi (- (cadr a) (cadr b)))
(if (= trenduoi 0) (PROGN
(setq dau "%%p ")
)
)
(if (> trenduoi 0) (PROGN
(setq dau "+ ")
)
)
(if (< trenduoi 0) (PROGN
(setq dau "- ")
)
)
(setq noidung (strcat dau (rtos giatri 2 3)))
(command "-style" "tlkt" "VNI-HELVE" "0" "1" "0" "n" "n")
(command ".TEXT" c 250 0 noidung)
(setq timfile (findfile "c:\\tailieukythuat\\dwg\\caodo.dwg"))
(if (= timfile nil) (PROGN
(princ "\nKhong tim thay file caodo.dwg")
)
)
(if (/= timfile nil) (PROGN
(command "INSERT" "c:\\tailieukythuat\\dwg\\caodo.dwg" a 1 1 0)
)
)
(setvar "osmode" luubatdiem)
)
(command "undo" "end")
(princ)
)

Hướng dẩn viết lisp bài 22:

Bạn nên theo dỏi theo tên bài viết tăng từ nhỏ tới lớn thì mới đúng trình tự!

Khi bạn thực hiện lisp trên nếu tại thư mục C:\tailieukythuat\dwg\ lại không tồn tại file caodo.dwg thì sẽ xuất hiện lổi tại dòng insert, lisp báo ra 1 mớ lổi dòm không ưng xíu nào. Mình nên kiểm tra file C:\tailieukythuat\dwg\caodo.dwg có tồn tại hay không. Nếu có thì thực hiện lệnh nếu không thì thông báo không tìm thấy và bỏ qua câu lệnh insert.
-Hàm findfile sẽ giúp bạn kiểm tra file có tồn tại hay không, nếu không hàm trả về giá trị nil, Kết hợp hàm if để đưa ra quyết định trong 2 trường hợp: tìm thấy và không tìm thấy

(defun c:cos ()
(command "undo" "be")
(setq motmet (getreal "\nMot met ban ve bang bao nhieu: "))
(setq luubatdiem (getvar "osmode"))
(setq a (getpoint "\nChon diem muon danh cos: "))
(setvar "osmode" 128)
(setq b (getpoint a"\nChon cao do 0.000: "))
(setvar "osmode" 0)
(setq daiab (distance a b))
(setq giatri (/ daiab motmet))
(setq c (list (- (car a) 250) (+ (cadr a) 410)))
(setq trenduoi (- (cadr a) (cadr b)))
(if (= trenduoi 0) (PROGN
(setq dau "%%p ")
)
)
(if (> trenduoi 0) (PROGN
(setq dau "+ ")
)
)
(if (< trenduoi 0) (PROGN
(setq dau "- ")
)
)
(setq noidung (strcat dau (rtos giatri 2 3)))
(command "-style" "tlkt" "VNI-HELVE" "0" "1" "0" "n" "n")
(command ".TEXT" c 250 0 noidung)
(setq timfile (findfile "c:\\tailieukythuat\\dwg\\caodo.dwg"))
(if (= timfile nil) (PROGN
(princ "\nKhong tim thay file caodo.dwg")
)
)
(if (/= timfile nil) (PROGN
(command "INSERT" "c:\\tailieukythuat\\dwg\\caodo.dwg" a 1 1 0)
)
)
(setvar "osmode" luubatdiem)
(command "undo" "end")
(princ)
)

Hướng dẩn viết lisp bài 21:

Bạn nên theo dỏi theo tên bài viết tăng từ nhỏ tới lớn thì mới đúng trình tự!

*Đến lúc này kiến thức về lisp của bạn đã đủ để viết lisp đánh cos cao độ rồi. Mình làm mẫu để bạn có thể quen dần với cách đặt và giải quyết vần đề bằng lisp nhé.
*Đặt vấn đề:
-Khi vẽ bạn có nhu cầu đánh cao độ cho các mặt đứng, mặt cắt. Cách thông thường là bạn có sẳn cái BLOCK rồi chèn vào COPY để tại các vị trí cần thiết xong đo và sửa các gía trị của text cho phù hợp. Cái phiền là bạn phải đo, tính theo tỉ lệ vẽ từ đó mới có giá trị điền vào các text, còn phải thêm dấu phía trước giá trị text nửa. Ví dụ +3.600.
-Giải quyết vấn đề bằng cách làm các công việc sau:
a/Tạo 1 BLOCK có tên caodo.dwg lưu vào thư mục nào đó (ở đây mình dùng C:\tailieukythuat\dwg\caodo.dwg). Khi tạo Block này bạn nên tạo ở Layer 0 có màu là bylayer, để khi chèn vào nó đi theo các thông số của layer hiện hành. Điểm chèn BLOCK nằm đúng mũi tên của BLOCK.
b/Viết lisp với các chức năng sau:
+Hỏi 1 mét vẽ bằng bao nhiêu: (dùng getreal)
+Hỏi chọn điểm đánh cao độ: (dùng getpoint)
+Hỏi chọn cao độ 0.000: (dùng getpoint) lúc này lưu chế độ bắt điểm lại và gán chế độ bắt điểm bằng 128 (bắt vuông góc).
+Chèn BLOCK caodo.dwg vào điểm đánh cao độ vừa chọn. Lúc này gán chế độ bắt điểm bằng 0.
+Tính toán tọa độ để viết text căn cứ vào tọa độ điểm vừa chèn.
+Đo khoảng cách từ điểm đánh cao độ đến điểm có cao độ 0.000.
+Chia khoảng cách đo được cho giá trị vẽ 1 mét.
+Làm tròn sau dấu phẩy là 3 chử số: (dùng rtos)
+Lấy giá trị y của điểm đánh cos trừ cho giá trị y của điểm cao độ 0.000
+Nếu giá trị này >0 thì gán dấu phía trước của text là dấu +.
+Nếu giá trị này <0 thì gán dấu phía trước của text là dấu -.
+Nếu giá trị này =0 thì gán dấu phía trước của text là dấu .
+Viết text gồm dấu phía trước và giá trị cao độ tại điểm vừa tính được.
-Dưới đây là hình minh họa về hình dáng BLOCK cao độ, các thông số về tọa độ viết text so với điểm chèn, độ lớn text mình sử dụng trong đoạn lisp mẫu.


(defun c:cos ()
(command "undo" "be")
(setq motmet (getreal "\nMot met ban ve bang bao nhieu: "))
(setq luubatdiem (getvar "osmode"))
(setq a (getpoint "\nChon diem muon danh cos: "))
(setvar "osmode" 128)
(setq b (getpoint a"\nChon cao do 0.000: "))
(setvar "osmode" 0)
(setq daiab (distance a b))
(setq giatri (/ daiab motmet))
(setq c (list (- (car a) 250) (+ (cadr a) 410)))
(setq trenduoi (- (cadr a) (cadr b)))
(if (= trenduoi 0) (PROGN
(setq dau "%%p ")
)
)
(if (> trenduoi 0) (PROGN
(setq dau "+ ")
)
)
(if (< trenduoi 0) (PROGN
(setq dau "- ")
)
)
(setq noidung (strcat dau (rtos giatri 2 3)))
(command "-style" "tlkt" "VNI-HELVE" "0" "1" "0" "n" "n")
(command ".TEXT" c 250 0 noidung)
(command "INSERT" "c:\\tailieukythuat\\dwg\\caodo.dwg" a 1 1 0)
(setvar "osmode" luubatdiem)
(command "undo" "end")
(princ)
)

Bạn để ý dòng dùng INSERT block caodo.dwg nhé phần đường dẩn đến file phải dùng \\ để thể hiện thư mục vì khi đọc lisp sẽ bỏ bớt một dấu \. Hoặc bạn thể hiện bằng dấu xẹt ngược cũng được:
(command "INSERT" "c:\\tailieukythuat\\dwg\\caodo.dwg" a 1 1 0)
(command "INSERT" "c:/tailieukythuat/dwg/caodo.dwg" a 1 1 0)

Hướng dẩn viết lisp bài 20:

Bạn nên theo dỏi theo tên bài viết tăng từ nhỏ tới lớn thì mới đúng trình tự!

*Các lisp từ trước tới giờ nếu bạn chạy thử trên bản vẽ trống trơn thì chạy ngon nhưng bạn thử chạy trên bản vẽ có nhiều đối tượng rồi thì sẽ có khi chạy không đúng vì khi thực hiện các lệnh vẽ có chọn các điểm sẽ bị ảnh hưởng bởi chế độ bắt điểm tự động nên bắt sang các điểm không đúng với tính toán dẩn đến các hình vẽ sẽ không đúng ý.
-Cách giải quyết là tắt chế độ bắt điểm tự động đi. Cú pháp như sau:
(setvar "osmode" 0)
-Nhưng người dùng lisp của mình sẽ bực mình vì khi dùng lisp của mình thì mình tắt mất bắt điểm tự động của họ. Trong viết lisp việc thay đổi các thiết lập mặc định của người ta là không nên. Giải pháp là lưu thiết lập của họ lại bằng 1 biến tạm sau đó trả lại họ. Cách làm như sau:
+Lưu bắt điểm tự động (setq luubatdiem (getvar "osmode"))
+Trả lại bắt điểm tự động (setvar "osmode" luubatdiem)
-Như vậy trong lisp sau khi đã cung cấp dử liệu đầu vào như bắt điểm mình tiến hành lưu bắt điểm lại, tắt bắt điểm đi, thực hiện các thao tác vẽ, tính toán, trả lại bắt điểm trước khi kết thúc lệnh.
Ví dụ lisp sau khi thêm phần undo và bắt điểm:

(defun c:doanthang ()
(command "undo" "be")
(setq a (getpoint "\nChon diem: "))
(setq b (getpoint a"\nChon diem: "))
(setq luubatdiem (getvar "osmode"))
(setvar "osmode" 0)
(command ".line" a b "")
(setq c (list (/ (+ (car a) (car b)) 2) (/ (+ (cadr a) (cadr b)) 2)))
(command ".circle" c a)
(command ".circle" a b)
(setq traloi (strcase (getstring "\nBan co nuon array hay không? Y/:")))
(if (= traloi "N") (PROGN
)
)
(IF (= traloi "Y") (PROGN
(setq sl (getstring "\nSo luong:"))
(command ".array" "last" "" "p" c sl "" "")
)
)
(setvar "osmode" luubatdiem)
(command "undo" "end")
(princ)
)

Hướng dẩn viết lisp bài 19:

Bạn nên theo dỏi theo tên bài viết tăng từ nhỏ tới lớn thì mới đúng trình tự!

Bây giờ sau khi thực hiện lisp bạn dùng lệnh undo sẽ thấy nó undo từng chút từng chút chứ không giống lệnh của cad xíu nào vì trong lisp mình thực hiện một mớ lệnh nó sẽ từ từ undo từng lệnh một. Việc này gây phiền phức nếu trong lisp mình dùng rất nhiều lệnh bạn muốn lisp undo cũng giống như lệnh cad kìa. Cách làm như sau: Thêm hai dòng sau vào lisp.
+Thêm dòng sau vào sau dòng mở đầu:
(defund c:lenh ()
(command "undo" "be")
+Thêm dòng sau trước dòng kết thúc:
(command "undo" "end")
(Princ)
)

-Lúc này sau khi thực lisp bạn thực hiện lệnh undo nó sẽ undo nguyên tiến trình lisp thực hiện.
-Từ đây trở đi sẽ kết nạp thêm hai dòng này vào phần mở đầu và kết thúc lisp nhé.

Hướng dẩn viết lisp bài 18:

Bạn nên theo dỏi theo tên bài viết tăng từ nhỏ tới lớn thì mới đúng trình tự!

*Hàm If ứng dụng rất nhiều nhé bạn cần hết sức linh hoạt trong việc dùng nó để tạo tương tác giữa người dùng với lisp.
-Quay tuốt lại cái lisp array cái vòng tròn nhé: Bây giờ sau khi chọn điểm a và b, vẽ đường thẳng ab, vẽ đường tròn tâm c đường kính ab, vẽ đường tròn tâm a bán kính ab, thêm chức năng hỏi có muốn array cái đường tròn này ra không nếu nói có thì array còn nói không thì kết thúc lệnh.

(defun c:doanthang ()
(setq a (getpoint "\nChon diem: "))
(setq b (getpoint a"\nChon diem: "))
(command ".line" a b "")
(setq c (list (/ (+ (car a) (car b)) 2) (/ (+ (cadr a) (cadr b)) 2)))
(command ".circle" c a)
(command ".circle" a b)
(setq traloi (strcase (getstring "\nBan co nuon array hay không? Y/N:")))
(if (= traloi "N") (PROGN
)
)
(IF (= traloi "Y") (PROGN
(setq sl (getstring "\nSo luong:"))
(command ".array" "last" "" "p" c sl "" "")
)
)

(princ)
)

Bạn để ý dòng (setq traloi (strcase (getstring "\nBan co nuon array hay không? Y/N:"))) dùng hàm strcase trước hàm getstring để đảm bảo chuổi nhận được khi nhập vào luôn luôn là viết hoa vì hàm if kiểm tra mình để kiểm tra giá trị traloi là viết hoa như vậy thì khi bạn nhập chử Y là thường hay là hoa thì kết quả hàm if mới thực hiện việc array cái vòng tròn được.

*Đấy bây giờ bạn thấy mấy cái lisp giống lisp rồi đó nghen làm việc có trình tự lớp lang có hỏi có trả lời đây là giao tiếp với lisp đó. Ngon hen!

Hướng dẩn viết lisp bài 17:

Bạn nên theo dỏi theo tên bài viết tăng từ nhỏ tới lớn thì mới đúng trình tự!

*Khi chọn đối tượng lại nảy sinh vấn đề nếu lisp hỏi chọn đối tượng mà không có đối tượng nào được chọn hết lúc này doituong có giá trị là nil mà lisp vẩn tiếp tục chạy thì sẽ phát sinh lổi. Nên cần có hàm điều kiện kiểm tra nếu doituong khác nil thì tiếp tục chạy nếu doituong là nil thì báo là không có đối tượng nào và kết thúc lệnh:
-Hàm If là hàm điều kiện nếu như mà là thì. Cú pháp như sau:

(if (điều kiện 1) (PROGN

thì làm công tác 1
)
)
(IF (điều kiện 2) (PROGN
Thì làm công tác 2
)
)

*Các hàm so sánh:
< nhỏ hơn.
> lớn hơn.
<= nhỏ hơn hoặc bằng.
>= lớn hơn hoặc bằng.
= bằng.
/= không bằng.

Bây giờ áp dụng vào lisp trên để kiểm tra đối tượng chọn có giá trị hay không để đưa ra quyết định kết thúc lệnh hay thực hiện lệnh.

(defun c:tlkt ()
(princ "\nChon doi tuong")
(Setq doituong (Ssget))
(if (= doituong nil) (PROGN
(princ "\nKhong tim thay doi tuong nao!")
)
)
(IF (/= doituong nil) (PROGN
(setq a (getpoint "\nChon diem goc: "))
(setq b (getpoint a"\nChon diem den: "))
(setq so (getreal "\nSo lan di chuyen: "))
(setq daiab (distance a b))
(setq dodai (/ daiab so))
(setq gocab (angle a b))
(setq c (polar a gocab dodai))
(setq sol (fix so))
(repeat sol
(command "DELAY" "5000" "")
(command ".MOVE" doituong "" a c)
)
)
)
(princ)
)

-Chạy lệnh:
+Chọn 1 vùng trống nào đó lisp sẽ kết thúc và báo: Khong tim thay doi tuong nao!.
+Chọn có đối tượng lisp sẽ thực hiện như lisp lúc nảy.

Hướng dẩn viết lisp bài 16:

Bạn nên theo dỏi theo tên bài viết tăng từ nhỏ tới lớn thì mới đúng trình tự!

*Bây giờ dùng cái lisp trên sửa lại như sau:
Chọn 1 hoặc nhiều đối tượng có sẳn trên màn hình. Chọn điểm gốc a, chọn điểm đến b, hỏi số lần di chuyển. Move cái đối tượng vừa chọn từ a đến b từ từ với số đoạn di chuyển là số lần vừa nhập.
-Cần biết cú pháp để chọn đối tượng bằng lisp:
(Setq doituong (Ssget))
-Khi dùng dòng trên các đối tượng được chọn sẽ gán cho biến doituong. Để cho đẹp thêm dòng (princ "\nChon doi tuong") trước dòng chọn đối tượng để ghi dòng Chon doi tuong ra dòng lệnh trước khi chọn đối tượng.

(defun c:tlkt ()
(princ "\nChon doi tuong")
(Setq doituong (Ssget))
(setq a (getpoint "\nChon diem goc: "))
(setq b (getpoint a"\nChon diem den: "))
(setq so (getreal "\nSo lan di chuyen: "))
(setq daiab (distance a b))
(setq dodai (/ daiab so))
(setq gocab (angle a b))
(setq c (polar a gocab dodai))
(setq sol (fix so))
(repeat sol
(command "DELAY" "5000" "")
(command ".MOVE" doituong "" a c)
)
(princ)
)

Khi dùng dòng (Setq doituong (Ssget)) để chọn đối tượng thì tất cả các kiểu đối tượng được quét qua sẽ chọn hết nhưng có đôi lúc bạn có nhu cầu chỉ chọn 1 kiểu đối tượng nào đó thôi ví dụ: line, dimension, hatch, insert. . . thì dùng dòng sau:
(setq doituong (ssget '((0 . "text"))))
-Lúc này trong vùng quét của bạn chỉ nhận các đối tượng có kiểu nằm trong ngoặc kép (dòng trên cụ thể là đối tượng kiểu text) là được chọn thôi .

Hướng dẩn viết lisp bài 15:

Bạn nên theo dỏi theo tên bài viết tăng từ nhỏ tới lớn thì mới đúng trình tự!

Bây giờ bạn lại muốn số lần move text là do bạn nhập vào kia. Áp dụng hàm getreal xem nào:

(defun c:tlkt ()
(setq a (getpoint "\nChon diem viet: "))
(setq b (getpoint a"\nChon diem den: "))
(setq so (getreal "\nSo lan di chuyen: "))
(setq dolon (getvar "viewsize"))
(setq dolonchu (/ dolon 30))
(setq daiab (distance a b))
(setq dodai (/ daiab so))
(setq gocab (angle a b))
(setq c (polar a gocab dodai))
(command "-style" "tlkt" "VNI-HELVE" "0" "1" "0" "n" "n")
(command ".TEXT" "m" a dolonchu 0 "tailieukythuat.com")
(setq sol (fix so))
(repeat sol
(command "DELAY" "5000" "")
(command ".MOVE" "last" "" a c)
)
(command "DELAY" "5000" "")
(command ".ERASE" "last" "")
(princ)
)

Nếu bạn thay dòng:
(setq so (getreal "\nSo lan di chuyen: "))
Bằng dòng:
(setq so (getstring "\nSo lan di chuyen: "))
Thì lisp sẽ lổi ngay mặc dù bạn vẩn nhập vào là số nhưng chuổi thu được bằng hàm getstring không dùng để tính toán với các hàm + - * / được nên dòng
(setq dodai (/ daiab so))
Sẽ không lượng giá được, xuất hiện lổi và xẹtttttttttttttt lisp hỏng. Đây là điểm rất cần lưu ý trong viết lisp.
-Bạn thấy có 1 dòng lạ nửa:
(setq sol (fix so))
Vì vòng lặp repeat đòi hỏi đối số là số nguyên nghĩa là không có phẩy phiếc gì hết. Trong khi bạn nhập số lần di chuyển bằng hàm getreal kết quả lại là số thực ví dụ nhập 10 thì thực chất nó biểu diển trong lisp là dạng 10,000000000000000000000000000000... Bạn dùng hàm fix sẽ làm mất toàn bộ các ký tự sau dấu phẩy lúc này mới dùng kết quả thu được này cung cấp cho vòng lặp repeat được.