Chuyển đến nội dung
Diễn đàn CADViet
ssg

Hướng dẫn lập trình Lisp

Các bài được khuyến nghị

Trong bản vẽ có nhiều UCS. làm thế nào ta có thể thay đổi hệ tọa độ qua lại giữa các UCS này?

Cụ thể: bản vẽ có 2 UCS người dùng tự định nghĩa là A và B. khi A đang hiện hành mình muốn chuyển sang B thì làm như thế nào?

Chia sẻ bài đăng này


Liên kết tới bài đăng
Chia sẻ trên các trang web khác

Cho mình hỏi về hàm lọc, ban đầu chọn 1 tập hợp đối tượng => đặt biến là ss

 

(setq ss (ssget))

 

Mình muốn tách ss thành thành phần ss1 (chứ text) và ss2 (chứa line, polyline) ss3 (chứa dim) thì phải dùng lệnh như thế nào ?

Chia sẻ bài đăng này


Liên kết tới bài đăng
Chia sẻ trên các trang web khác
Cho mình hỏi về hàm lọc, ban đầu chọn 1 tập hợp đối tượng => đặt biến là ss

 

(setq ss (ssget))

 

Mình muốn tách ss thành thành phần ss1 (chứ text) và ss2 (chứa line, polyline) ss3 (chứa dim) thì phải dùng lệnh như thế nào ?

Có nhiều cách. Tue_NV xin trình bày 1 cách :

Đầu tiên, chọn 1 tập hợp đối tượng => đặt biến là ss

(setq ss (ssget))

-> Lập tức, lấy ss1 (chứa text)

(setq ss1 (ssget "P" '((0 . "TEXT"))))

 

-> Tập ss2

(setq ss2 (ssget "P" '((0 . "*LINE"))))

 

-> Tập ss3

(setq ss3 (ssget "P" '((0 . "DIMENSION"))))

 

 

Trong bản vẽ có nhiều UCS. làm thế nào ta có thể thay đổi hệ tọa độ qua lại giữa các UCS này?

Cụ thể: bản vẽ có 2 UCS người dùng tự định nghĩa là A và B. khi A đang hiện hành mình muốn chuyển sang B thì làm như thế nào?

Ý của bạn như thế này phải không?

 

(setq name (getstring t "\nnhap ten UCS"))

(vl-cmdf "UCS" "NA" "R" name)

  • Vote tăng 3

Chia sẻ bài đăng này


Liên kết tới bài đăng
Chia sẻ trên các trang web khác
@Tue_VN: thanks bạn rất nhiều, xin hỏi còn cách lọc khác nữa không (dùng hàm lọc lấy thông số từ biến ss)

Bạn dùng thử cái ni xem có được không nhé.

(defun c:ldt (/ ss i n e le)
(setq ss (ssget)
       i 0
       n (sslength ss)
       ss1 (ssadd)
       ss2 (ssadd)
       ss3 (ssadd)
)
(while ((setq e (ename ss i)
       le (cdr (assoc 0 (entget e)))
)
(if (= le "TEXT")
   (setq ss1 (ssadd e ss1))
)
(if ( or (= le "LINE") (= le "LWPOLYLINE") (= le "POLYLINE") )
   (setq ss2 (ssadd e ss2))
)
(if (= le "DIMENSION")
   (setq ss3 (ssadd e ss3))
)
(setq i (1+ i))
)
)

Chúc bạn vui.

  • Vote tăng 1

Chia sẻ bài đăng này


Liên kết tới bài đăng
Chia sẻ trên các trang web khác
@Tue_VN: thanks bạn rất nhiều, xin hỏi còn cách lọc khác nữa không (dùng hàm lọc lấy thông số từ biến ss)

Bạn thử cái này

(defun laydt(ss kieu)
 (acet-list-to-ss
  (vl-remove-if '(lambda(x)
		   (null (wcmatch (acet-dxf 0 (entget x)) kieu)))
	   	 (acet-ss-to-list ss)
  )
 )
)

1. Tạo hàm con như trên

2.Tậo tập chọn ss

(setq ss (ssget))

Lấy tập ss1

(setq ss1 (Laydt ss "TEXT"))

Lấy tập ss2

(setq ss2 (Laydt ss "*LINE"))

Lấy tập ss3

(setq ss3 (Laydt ss "DIMENSION"))

  • Vote tăng 2

Chia sẻ bài đăng này


Liên kết tới bài đăng
Chia sẻ trên các trang web khác

Vẫn theo cách thức như các bài trước, mời bạn chạy thử chương trình rồi ta bàn bạc tiếp. Lần này nhiều thứ lôi thôi hơn, ssg đã chuẩn bị sẵn, bạn chỉ việc copy toàn bộ thư mục Relax vào thư mục gốc của AutoCAD, sau đó appload file relax.lsp là xong. Nếu appload thành công sẽ xuất hiện menu có tên Relax ở vị trí thứ 10 (tính từ trái qua) giống như hình trên.

bác Hoành cho em hỏi cụ thể thư mục gốc nói ở trên là chỗ nào ko ạ, thanksss ( bài viết của Bác rất bổ ích ) ^^

Chia sẻ bài đăng này


Liên kết tới bài đăng
Chia sẻ trên các trang web khác
Vẫn theo cách thức như các bài trước, mời bạn chạy thử chương trình rồi ta bàn bạc tiếp. Lần này nhiều thứ lôi thôi hơn, ssg đã chuẩn bị sẵn, bạn chỉ việc copy toàn bộ thư mục Relax vào thư mục gốc của AutoCAD, sau đó appload file relax.lsp là xong. Nếu appload thành công sẽ xuất hiện menu có tên Relax ở vị trí thứ 10 (tính từ trái qua) giống như hình trên.

bác Hoành cho em hỏi cụ thể thư mục gốc nói ở trên là chỗ nào ko ạ, thanksss ( bài viết của Bác rất bổ ích ) ^^

Bác SSg chuyển sang dùng nick này à....

Chia sẻ bài đăng này


Liên kết tới bài đăng
Chia sẻ trên các trang web khác
Bác SSg chuyển sang dùng nick này à....

Đâu, bạn ấy copy nguyên lời anh ssg đó mà bác ^^

Chia sẻ bài đăng này


Liên kết tới bài đăng
Chia sẻ trên các trang web khác

Có cách nào để entmod 1 đối tuợng con của đối tuợng xref không nhỉ. chỉnh sửa nội dung 1 đối tuợng text chẳng hạn. đôi khi mình luời không muốn mở Xref editor :)

Chia sẻ bài đăng này


Liên kết tới bài đăng
Chia sẻ trên các trang web khác

Thật mệt mỏi với hàm Command quá!

Các chương trình sử lý 1 khối luợng lớn các công việc bằng hàm Command không những gây chậm mà còn có nhuợc điểm rất khó chịu là khi chuơng trình chạy xong, muốn undo lại rất cực khổ, chờ dài cổ mới xong, ngoài ra còn kèm theo 1 loạt thông báo (Lisp Expression) ngứa mắt, đôi khi làm treo máy luôn. Biết vậy nhưng thỉnh thoảng vẫn fải dùng đến Command.

Các bác có cách nào khắc phục được vấn đề này không? hoặc chí ít là tắt cái dòng thông báo kia đi khi undo, chắc sẽ nhanh hơn chút xíu.

Chia sẻ bài đăng này


Liên kết tới bài đăng
Chia sẻ trên các trang web khác

Thật mệt mỏi với hàm Command quá!

Các chương trình sử lý 1 khối luợng lớn các công việc bằng hàm Command không những gây chậm mà còn có nhuợc điểm rất khó chịu là khi chuơng trình chạy xong, muốn undo lại rất cực khổ, chờ dài cổ mới xong, ngoài ra còn kèm theo 1 loạt thông báo (Lisp Expression) ngứa mắt, đôi khi làm treo máy luôn. Biết vậy nhưng thỉnh thoảng vẫn fải dùng đến Command.

Các bác có cách nào khắc phục được vấn đề này không? hoặc chí ít là tắt cái dòng thông báo kia đi khi undo, chắc sẽ nhanh hơn chút xíu.

Ơ sao bác không dùng hàm bẫy lỗi và set undo điểm đầu -> cuối cho nó đỡ khổ.

Chia sẻ bài đăng này


Liên kết tới bài đăng
Chia sẻ trên các trang web khác

có lẽ phamngoctukts chưa hiểu điều mình nói.

bạn viết code như thế này.

(defun C:test nil

(command "undo" "begin")

.... làm 1 việc gì đó khoảng 5000 lần bằng hàm command. (viết 1 nội dung text ra màn hình chẳng hạn)

(command "undo" "end") (princ))

rồi sau khi chạy lệnh test bạn thử undo lại xem. mời bạn ngồi chờ <_<

Chia sẻ bài đăng này


Liên kết tới bài đăng
Chia sẻ trên các trang web khác

Mình muốn làm tròn tọa độ đỉnh của một polyline có sẵn trên bản vẽ về 2 số lẽ nhưng chưa biết cách nào. Bạn nào biết hướng dẫn cho mình hoặc chỉ mình trang nào đề cập vđ này. Mình tìm kg thấy. Cám ơn các bạn

Chia sẻ bài đăng này


Liên kết tới bài đăng
Chia sẻ trên các trang web khác

1 cách đơn giản là bác chuyển các giá trị đó thành chuỗi bằng hàm rtos rồi lại chuyển nguợc lại thành số thực.

(atof (rtos x 2 2))

Chia sẻ bài đăng này


Liên kết tới bài đăng
Chia sẻ trên các trang web khác

1 cách đơn giản là bác chuyển các giá trị đó thành chuỗi bằng hàm rtos rồi lại chuyển nguợc lại thành số thực.

(atof (rtos x 2 2))

Cách làm tròn số thực thì mình biết rồi, nhưng cách truy xuất đỉnh của polyline line, lưu vào biến, làm tròn rồi cập nhật lại vào polyline thì mình chưa rõ.

Mình tìm được hàm lấy tọa độ đỉnh trên cadviet

(setq en (ssname (ssget '((0 . "LWPOLYLINE"))) 0) lstp (ACET-GEOM-VERTEX-LIST en))

nhưng hàm này chỉ chạy trên cad đời cao, mình vẫn sd cad2002 thì nó kg chạy, bạn nào biết hàm khác thấp hơn thì chỉ cho mình với. Mình vẫn chưa tìm đc hàm cập nhật lại vào polyline.

Chia sẻ bài đăng này


Liên kết tới bài đăng
Chia sẻ trên các trang web khác

Không biết cad2002 có Visual Lisp chưa nhỉ.

bác thử cái này để lấy list toạ độ LWpolyline xem

(defun get-vertex-lwpline (e/ iv L) 
(setq iv -1 L '())
(repeat (fix (1+ (vlax-curve-getEndParam e)))
(setq  iv (1+ iv) L (append L (list (vlax-curve-getPointAtParam e iv))))))

nếu vẫn không đuợc thì đành chơi cái này vậy - autolisp nên chạy dc với mọi bản cad

(defun get-vertex-lwpline (e / lstpt)
(setq lstpt '())
(foreach x (entget e)
(if (= (car x) 10) (setq lstpt (append (list (cdr x)) lstpt)))) lstpt)

Làm tròn tọa độ về 2 chữ số

(mapcar '(lambda (x1) (mapcar '(lambda (x2) (atof(rtos x2 2 2))) x1)) (get-vertex-lwpline (car(entsel))))

Còn việc cập nhật list point đã được làm tròn cho đường pline mình nghĩ là đơn giản thôi mà.

từ record của pline, bác loại bỏ mọi fần tử có mã DXF 10, 40, 41, 42, 91 rồi chèn các điểm point mới vào vị trí sau mã 39. entmod với record mới này là ok

Chia sẻ bài đăng này


Liên kết tới bài đăng
Chia sẻ trên các trang web khác

Không biết cad2002 có Visual Lisp chưa nhỉ.

bác thử cái này để lấy list toạ độ LWpolyline xem

(defun get-vertex-lwpline (e/ iv L) 
(setq iv -1 L '())
(repeat (fix (1+ (vlax-curve-getEndParam e)))
(setq  iv (1+ iv) L (append L (list (vlax-curve-getPointAtParam e iv))))))

nếu vẫn không đuợc thì đành chơi cái này vậy - autolisp nên chạy dc với mọi bản cad

(defun get-vertex-lwpline (e / lstpt)
(setq lstpt '())
(foreach x (entget e)
(if (= (car x) 10) (setq lstpt (append (list (cdr x)) lstpt)))) lstpt)

Làm tròn tọa độ về 2 chữ số

(mapcar '(lambda (x1) (mapcar '(lambda (x2) (atof(rtos x2 2 2))) x1)) (get-vertex-lwpline (car(entsel))))

Còn việc cập nhật list point đã được làm tròn cho đường pline mình nghĩ là đơn giản thôi mà.

từ record của pline, bác loại bỏ mọi fần tử có mã DXF 10, 40, 41, 42, 91 rồi chèn các điểm point mới vào vị trí sau mã 39. entmod với record mới này là ok

Bạn coi lại nhé :

(rtos -618.003 2 2) -> "-618.00" -> ok. Nhưng (atof "-618.00") -> -618.0 (Không đúng)

Ngoài ra, cần phải thiết lập biến Dimzin=0 :rolleyes:

Chia sẻ bài đăng này


Liên kết tới bài đăng
Chia sẻ trên các trang web khác

Bạn coi lại nhé :

(rtos -618.003 2 2) -> "-618.00" -> ok. Nhưng (atof "-618.00") -> -618.0 (Không đúng)

Ngoài ra, cần phải thiết lập biến Dimzin=0 :rolleyes:

Chúng ta đang bàn đến việc làm tròn số, không fải về việc thể hiện 1 số duới dạng chuỗi như thế nào bạn ạ.

[round 618.003 ; 2] = 618.00 = 618.0 = 618.000000000000000000000000000000000000000 = 618

vì thế chả cần biến Dimzin làm gì.

Chia sẻ bài đăng này


Liên kết tới bài đăng
Chia sẻ trên các trang web khác

Không biết cad2002 có Visual Lisp chưa nhỉ.

bác thử cái này để lấy list toạ độ LWpolyline xem

(defun get-vertex-lwpline (e/ iv L) 
(setq iv -1 L '())
(repeat (fix (1+ (vlax-curve-getEndParam e)))
(setq  iv (1+ iv) L (append L (list (vlax-curve-getPointAtParam e iv))))))

nếu vẫn không đuợc thì đành chơi cái này vậy - autolisp nên chạy dc với mọi bản cad

(defun get-vertex-lwpline (e / lstpt)
(setq lstpt '())
(foreach x (entget e)
(if (= (car x) 10) (setq lstpt (append (list (cdr x)) lstpt)))) lstpt)

Làm tròn tọa độ về 2 chữ số

(mapcar '(lambda (x1) (mapcar '(lambda (x2) (atof(rtos x2 2 2))) x1)) (get-vertex-lwpline (car(entsel))))

Còn việc cập nhật list point đã được làm tròn cho đường pline mình nghĩ là đơn giản thôi mà.

từ record của pline, bác loại bỏ mọi fần tử có mã DXF 10, 40, 41, 42, 91 rồi chèn các điểm point mới vào vị trí sau mã 39. entmod với record mới này là ok

cad2002 có vl rồi nhưng chắc nó chưa có hàm ACET-GEOM-VERTEX-LIS

Việc sd hàm entmod với cod 10 trong trường hợp polyline mình nghỉ kg đc vì hàm assoc chỉ trả về cặp dữ liệu có cod 10 đầu tiên thôi trong khi đó dữ liệu của polyline có nhiều cặp có cod 10. Kg biết mình có nhầm lẫn gì kg

Chia sẻ bài đăng này


Liên kết tới bài đăng
Chia sẻ trên các trang web khác

cad2002 có vl rồi nhưng chắc nó chưa có hàm ACET-GEOM-VERTEX-LIS

Việc sd hàm entmod với cod 10 trong trường hợp polyline mình nghỉ kg đc vì hàm assoc chỉ trả về cặp dữ liệu có cod 10 đầu tiên thôi trong khi đó dữ liệu của polyline có nhiều cặp có cod 10. Kg biết mình có nhầm lẫn gì kg

Theo thiển ý của mình, bạn có thể làm như thế này xem sao:

- Duyệt từng phần tử trong danh sách record đối tượng (hàm foreach).

- Nếu phần tử nào có (= 10 (car pt)) thì thay X,Y,Z của nó bằng x,y,z [trong đó x=(atof (rtos X 2 2))]

Chia sẻ bài đăng này


Liên kết tới bài đăng
Chia sẻ trên các trang web khác

Chắc cũng k cần list point ra đâu bạn TRUNGNGAMY ạ.

Với LWPlolyline thì :

(defun c:test()
(defun round(x)(atof (rtos x 2 2)))
(foreach x (setq ent (entget (car(entsel))))
(if (= (car x) 10)
	(entmod (setq ent(subst (list 10 (round (cadr x))(round (caddr x))) x ent)))
)
)
)

P/S : nick bạn làm mình nhớ VLTK quá ^^

  • Vote tăng 2

Chia sẻ bài đăng này


Liên kết tới bài đăng
Chia sẻ trên các trang web khác

Chắc cũng k cần list point ra đâu bạn TRUNGNGAMY ạ.

Với LWPlolyline thì :

(defun c:test()
(defun round(x)(atof (rtos x 2 2)))
(foreach x (setq ent (entget (car(entsel))))
(if (= (car x) 10)
	(entmod (setq ent(subst (list 10 (round (cadr x))(round (caddr x))) x ent)))
)
)
)

P/S : nick bạn làm mình nhớ VLTK quá ^^

Cám ơn bạn. Mình lập trình autolíp đã lâu nhưng kg nghĩ ra cú pháp lạ và hay như vậy. Có lẽ cái kiến thức cũ kỹ của mình đã lỗi thời rồi.

(Nick của mình của mình kg liên quan gì đến VLTK đâu ạ)

Chia sẻ bài đăng này


Liên kết tới bài đăng
Chia sẻ trên các trang web khác

Mình muốn làm tròn tọa độ đỉnh của một polyline có sẵn trên bản vẽ về 2 số lẽ nhưng chưa biết cách nào. Bạn nào biết hướng dẫn cho mình hoặc chỉ mình trang nào đề cập vđ này. Mình tìm kg thấy. Cám ơn các bạn

Một yêu cầu khá là "ngộ" !

 

 

Chắc cũng k cần list point ra đâu bạn TRUNGNGAMY ạ.

Với LWPlolyline thì :

(defun c:test()
(defun round(x)(atof (rtos x 2 2)))
(foreach x (setq ent (entget (car(entsel))))
(if (= (car x) 10)
	(entmod (setq ent(subst (list 10 (round (cadr x))(round (caddr x))) x ent)))
)
)
)

P/S : nick bạn làm mình nhớ VLTK quá ^^

Đại cao thủ xuất hiện.

Bái phục ! Bái phục !

Chia sẻ bài đăng này


Liên kết tới bài đăng
Chia sẻ trên các trang web khác

Tạo một tài khoản hoặc đăng nhập để nhận xét

Bạn cần phải là một thành viên để lại một bình luận

Tạo tài khoản

Đăng ký một tài khoản mới trong cộng đồng của chúng tôi. Điều đó dễ mà.

Đăng ký tài khoản mới

Đăng nhập

Bạn có sẵn sàng để tạo một tài khoản ? Đăng nhập tại đây.

Đăng nhập ngay

×