Chuyển đến nội dung
Diễn đàn CADViet
Đăng nhập để thực hiện theo  
LoveLisp

[Hỏi] Làm thế nào để truy xuất thông tin bên trong Block?

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

Trên layer 0 có chứa nhiều đối tượng, các đối tượng này nằm trong Block

nhưng tất cả block đó không nằm trên layer 0.

Dùng câu lệnh (ssget "X" (8 . "0")) thì không chọn nó được.

Bạn có cách gì để chọn layer nằm bên trong Block không?

Mình đã thử qua các lệnh qselect, FILTER của CAD cũng không ăn thua.

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 npham không đọc kỹ câu hỏi rồi :) Ý OP là chọn các đối tượng nested ^^.

Hãy tìm trên mạng vài ví dụ về duyệt qua các đối tượng trong Block, thấy cái nào khớp layer 0 thì bạn cho vào 1 list Ename, rồi sau đó xử lý chúng :) Còn chọn gripset thì chắc là không được đâu 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

nếu muốn chọn block sao bạn không dùng '((0 . "INSERT")(2 . "NAME")) ?

Thực tình là thế này: Mình có layerA, nó không chứa đối tượng nào hết. Tuy nhiên khi mình dùng lệnh LayDel để xóa lớp đó thì nó báo rằng có nhiều Block chứa đối tượng nằm trên lớp đó (nhưng nó không nói có bao nhiêu và những Block tên gì mới mệt chớ).

Mình nghĩ rằng trong lệnh LayDel đã có cách gì đó để chọn mà không cần duyệt qua từng Block (vì bản vẽ của mình rất nhiều Block mà mình thấy nó hầu như chẳng tốn chút thời gian nào để đưa ra thông báo).

Có ai biết mã nguồn của lệnh LayDel không?

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

...Hãy tìm trên mạng vài ví dụ về duyệt qua các đối tượng trong Block...

hic, hic... thì mình đang tìm trên mạng đây, và tìm trên chính diễn đàn của người Việt!

Bạn biết cách duyệt qua từng Block thì xin chỉ giáo!! Hoặc bạn biết thì xin gửi link hữu ích nào đó cũng đượ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

À, mình đưa 1 ví dụ để bạn xử lý nhé.

(defun c:test(/ nla lstBlk lstBl)
(vl-load-com)
(setq nla "0") 														;Layer chi dinh
(setq adoc (vla-get-activedocument (vlax-get-acad-object))) 			;Active Document
 (vlax-for block (vla-get-blocks adoc) 								;Duyet qua tung Block Definition trong collection Block
   (if   (not (wcmatch (strcase (vla-get-name block) t) "*_space*")) 	;Bo qua Anonymous
     (vlax-for   ent block 											;Duyet qua tung doi tuong Ent trong Block
       (progn
		(if (and (wcmatch nla (vla-get-layer ent))(not (vl-position (vla-get-name block) lstBlk)))
			(setq lstBlk (cons (vla-get-name block) lstBlk))
		)
	)  
      )
    )  																;=> Sau buoc nay la lay duoc cac block chua layer nla
  )


(mapcar '(lambda(x) (if (setq ss (ssget "x" (list (cons 0 "INSERT")(cons 2 x))))
								(setq lstBl (cons (cons x (sslength ss)) lstBl))
								(setq lstBl (cons (cons x 0) lstBl))
				)
		)
			lstBlk
) 
;=> Sau doan nay lay duoc list loai bloc + so luong cua moi Block da chen tren ban ve
(princ (strcat "\nCac Block sau co chua doi tuong thuoc layer " nla ": \n"))
(mapcar '(lambda(x)(princ (strcat "\nBlock " (car x) " - So luong : " (vl-princ-to-string (cdr x))))) lstBl) ;In ra man hinh
(princ)
)

  • 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

À, mình đưa 1 ví dụ để bạn xử lý nhé.

(defun c:test(/ nla lstBlk lstBl)
(vl-load-com)
(setq nla "0") 														;Layer chi dinh
(setq adoc (vla-get-activedocument (vlax-get-acad-object))) 			;Active Document
 (vlax-for block (vla-get-blocks adoc) 								;Duyet qua tung Block Definition trong collection Block
   (if   (not (wcmatch (strcase (vla-get-name block) t) "*_space*")) 	;Bo qua Anonymous
     (vlax-for   ent block 											;Duyet qua tung doi tuong Ent trong Block
       (progn
		(if (and (wcmatch nla (vla-get-layer ent))(not (vl-position (vla-get-name block) lstBlk)))
			(setq lstBlk (cons (vla-get-name block) lstBlk))
		)
	)  
  	)
	)  																;=> Sau buoc nay la lay duoc cac block chua layer nla
  )


(mapcar '(lambda(x) (if (setq ss (ssget "x" (list (cons 0 "INSERT")(cons 2 x))))
								(setq lstBl (cons (cons x (sslength ss)) lstBl))
								(setq lstBl (cons (cons x 0) lstBl))
				)
		)
			lstBlk
)
;=> Sau doan nay lay duoc list loai bloc + so luong cua moi Block da chen tren ban ve
(princ (strcat "\nCac Block sau co chua doi tuong thuoc layer " nla ": \n"))
(mapcar '(lambda(x)(princ (strcat "\nBlock " (car x) " - So luong : " (vl-princ-to-string (cdr x))))) lstBl) ;In ra man hinh
(princ)
)

Tuyệt quá!! Đúng là siêu đại cao thủ! Bái phục, bái phục! Cám ơn, cám ơn!

Các câu lệnh được viết rất gọn gàng, trong sáng và mạnh mẽ, không thừa chữ nào, thật là đáng để học hỏi!

  • 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

Tuyệt quá!! Đúng là siêu đại cao thủ! Bái phục, bái phục! Cám ơn, cám ơn!

Các câu lệnh được viết rất gọn gàng, trong sáng và mạnh mẽ, không thừa chữ nào, thật là đáng để học hỏi!

Bạn làm mình sốc quá ^^

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

Sao mình dùng lisp này thì trên màn hình cad2007 chỉ xuất hiện mủi tên con trỏ rồi 5s sau chuyển thành sợi tóc.

Tốt nhất là bạn nên đọc nội dung mọi người nói từ đầu đến cuối, xem mục đích của lisp là 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

Thêm một cách nữa để chọn các block có chứa layer nào đó (có thể mở rộng để chọn theo color,linetype...).

(defun C:HA( / lay dsent)	;Doan Van Ha CADViet.com
(setq lay (getstring "\nNhap ten lop nam trong block: ") ss (ssadd))
(foreach ent (acet-ss-to-list (ssget '((0 . "INSERT"))))
 (foreach ent1 (acet-ss-to-list (acet-explode ent))
  (if (equal lay (cdr (assoc 8 (entget ent1))))
(setq dsent (if (not (member ent dsent)) (cons ent dsent) dsent))))
 (command "u"))
(setq ss (if dsent (acet-list-to-ss dsent) nil))		; ss la tap hop chon cua cac block co chua layer lay (2 dong duoi chi de test).
(princ (strcat "\nSo block co chua doi tuong thuoc layer " lay " la: " (if ss (itoa (sslength ss)) "0")))
(princ))

  • 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

Cách dùng mẹo này cũng hay, tuy nhiên, nếu để dùng trong 1 lisp thì e nghĩ là không nên, vì nó có vài nhược điểm sau :

- Số lượng của loại block . Cái này k chi tiết cũng k sao, tùy thuộc mục đích sử dụng. Nhưng mấy điểm sau thì nguy hiểm hơn :

- Command "U"

- Duyệt qua toàn bộ block đã được chèn trên bản vẽ (chứ k phải các định nghĩa block). Nếu bản vẽ có nhiều block cùng 1 loại đã được chèn, công việc Explode, duyệt qua từng đối tượng, Undo sẽ lặp đi lặp lại, tất nhiên tốc độ của nó sẽ bị giảm đi theo số lần tương ứng.

- Bỏ qua các block chưa được chè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

Cách dùng mẹo này cũng hay, tuy nhiên, nếu để dùng trong 1 lisp thì e nghĩ là không nên, vì nó có vài nhược điểm sau :

- Số lượng của loại block . Cái này k chi tiết cũng k sao, tùy thuộc mục đích sử dụng. Nhưng mấy điểm sau thì nguy hiểm hơn :

- Command "U"

- Duyệt qua toàn bộ block đã được chèn trên bản vẽ (chứ k phải các định nghĩa block). Nếu bản vẽ có nhiều block cùng 1 loại đã được chèn, công việc Explode, duyệt qua từng đối tượng, Undo sẽ lặp đi lặp lại, tất nhiên tốc độ của nó sẽ bị giảm đi theo số lần tương ứng.

- Bỏ qua các block chưa được chèn

1). "- Duyệt qua..." : cần thiết thì sort theo tên block để giảm số lượng.

2). "- Bỏ qua các block chưa được chèn": block chưa được chèn vào bản vẽ thì làm sao chọn đượ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

1). "- Duyệt qua..." : cần thiết thì sort theo tên block để giảm số lượng.

2). "- Bỏ qua các block chưa được chèn": block chưa được chèn vào bản vẽ thì làm sao chọn được???

1. No comment ^^ Vì đã đi theo cách của bác thì nó nên là 1 bước Bắt buộc, chứ k phải là "nếu cần" nữa ạ ^^. bác cứ tưởng tượng 1 bản vẽ có 1000 block như nhau, mà bác cứ cho chạy hoài, chạy hoài... thì há chẳng vô nghĩa sao ^^

2. Không có yêu cầu Chọn gripset

Thực tình là thế này: Mình có layerA, nó không chứa đối tượng nào hết. Tuy nhiên khi mình dùng lệnh LayDel để xóa lớp đó thì nó báo rằng có nhiều Block chứa đối tượng nằm trên lớp đó (nhưng nó không nói có bao nhiêu và những Block tên gì mới mệt 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

1). "- Duyệt qua..." : cần thiết thì sort theo tên block để giảm số lượng.

2). "- Bỏ qua các block chưa được chèn": block chưa được chèn vào bản vẽ thì làm sao chọn được???

Mình cũng nghĩ như bạn "ketxu". Mình thấy có thể dễ dàng lấy tên của tất cả các block trên bản vẽ (kể cả các block chưa được chèn) bằng lệnh (tblnext "block" T) và (tblnext "block").

Lisp của bạn "Doan Van Ha" có nhược điểm là khi Block chèn theo 2 phương có tỉ lệ khác nhau thì sẽ không thể Explode đượ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

Mọi Block đều nằm trong collection Blocks mà. Chỉ có điều lúc đó bảo chọn để ra số lượng thì hơi vất ^^

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êm một cách nữa để chọn các block có chứa layer nào đó (có thể mở rộng để chọn theo color,linetype...).

(defun C:HA( / lay dsent)	;Doan Van Ha CADViet.com
(setq lay (getstring "\nNhap ten lop nam trong block: ") ss (ssadd))
(foreach ent (acet-ss-to-list (ssget '((0 . "INSERT"))))
 (foreach ent1 (acet-ss-to-list (acet-explode ent))
  (if (equal lay (cdr (assoc 8 (entget ent1))))
(setq dsent (if (not (member ent dsent)) (cons ent dsent) dsent))))
 (command "u"))
(setq ss (if dsent (acet-list-to-ss dsent) nil))		; ss la tap hop chon cua cac block co chua layer lay (2 dong duoi chi de test).
(princ (strcat "\nSo block co chua doi tuong thuoc layer " lay " la: " (if ss (itoa (sslength ss)) "0")))
(princ))

 

Bác cho em hỏi một câu nhé, đừng cười đấy

theo cách của bác thì em có một layer có tên VD: Tuong bao, như vậy giữa 2 chữ có một dấu cách, làm thế nào đánh được tên lớp nằm trong block

Cảm ơn 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
Tuyệt quá!! Đúng là siêu đại cao thủ! Bái phục, bái phục! Cám ơn, cám ơn! Các câu lệnh được viết rất gọn gàng, trong sáng và mạnh mẽ, không thừa chữ nào, thật là đáng để học hỏi!
À, mình đưa 1 ví dụ để bạn xử lý nhé.
 (defun c:test(/ nla lstBlk lstBl) (vl-load-com) (setq nla "0") ;Layer chi dinh (setq adoc (vla-get-activedocument (vlax-get-acad-object))) ;Active Document (vlax-for block (vla-get-blocks adoc) ;Duyet qua tung Block Definition trong collection Block (if (not (wcmatch (strcase (vla-get-name block) t) "*_space*")) ;Bo qua Anonymous (vlax-for ent block ;Duyet qua tung doi tuong Ent trong Block (progn (if (and (wcmatch nla (vla-get-layer ent))(not (vl-position (vla-get-name block) lstBlk))) (setq lstBlk (cons (vla-get-name block) lstBlk)) ) ) ) ) ;=> Sau buoc nay la lay duoc cac block chua layer nla ) (mapcar '(lambda(x) (if (setq ss (ssget "x" (list (cons 0 "INSERT")(cons 2 x)))) (setq lstBl (cons (cons x (sslength ss)) lstBl)) (setq lstBl (cons (cons x 0) lstBl)) ) ) lstBlk ) ;=> Sau doan nay lay duoc list loai bloc + so luong cua moi Block da chen tren ban ve (princ (strcat "\nCac Block sau co chua doi tuong thuoc layer " nla ": \n")) (mapcar '(lambda(x)(princ (strcat "\nBlock " (car x) " - So luong : " (vl-princ-to-string (cdr x))))) lstBl) ;In ra man hinh (princ) ) 

 

Thank bác phát

bác có thể giải thích rõ cái lisp này được không em chưa hiểu nhiều về lisp nhưng cũng muốn học đòi thay đổi cái lisp này, hj hj lại không được

 

(setq adoc (vla-get-activedocument (vlax-get-acad-object)))

 

Dòng trên có nghĩa là j bác

 

Cảm ơn bác rất nhiề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

 

Bác cho em hỏi một câu nhé, đừng cười đấy

theo cách của bác thì em có một layer có tên VD: Tuong bao, như vậy giữa 2 chữ có một dấu cách, làm thế nào đánh được tên lớp nằm trong block

Cảm ơn bác

Với lisp của bác ĐVH, bạn thay

(getstring "\nNhap ten lop nam trong block: ")

bằng

(getstring T "\nNhap ten lop nam trong block: ")

Option T (not nil) cho phép nhập String có dấu " "

 

 

 

(setq adoc (vla-get-activedocument (vlax-get-acad-object)))

Dòng đấy lấy đối tượng VLA Activedocument (bản vẽ đang thao tác). Nếu bạn bắt đầu chơi với lisp thì những khái niệm này sẽ khó xơi đấy ^^

  • 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

 

Bác cho em hỏi một câu nhé, đừng cười đấy

theo cách của bác thì em có một layer có tên VD: Tuong bao, như vậy giữa 2 chữ có một dấu cách, làm thế nào đánh được tên lớp nằm trong block

Cảm ơn bác

Nhập: "Tuong bao", chứ đừng nhập: Tuong bao!

  • 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

Mình cũng nghĩ như bạn "ketxu". Mình thấy có thể dễ dàng lấy tên của tất cả các block trên bản vẽ (kể cả các block chưa được chèn) bằng lệnh (tblnext "block" T) và (tblnext "block").

Lisp của bạn "Doan Van Ha" có nhược điểm là khi Block chèn theo 2 phương có tỉ lệ khác nhau thì sẽ không thể Explode được.

Ủa, chèn theo các tỉ lệ X, Y, Z khác nhau vẫn explode được mà. Hiện đang không thích (command "U") nên chắc sẽ chuyển qua kiểu khá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

Với lisp của bác ĐVH, bạn thay

 

bằng

 

Option T (not nil) cho phép nhập String có dấu " "

 

 

 

 

Dòng đấy lấy đối tượng VLA Activedocument (bản vẽ đang thao tác). Nếu bạn bắt đầu chơi với lisp thì những khái niệm này sẽ khó xơi đấy ^^

 

Em cũng đọc nhiều tài liệu trên diễn đàn rồi nhưng vẫn lơ mơ, tạm thời em đang học cách chỉnh sửa lisp đơn giản để phù hợp với mình hơn

Chưa cái nào thành công cả.

Hu hu

Thank bác nhé

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 bạn cho mình hỏi thêm vấn đề này: Nếu trong Block đó có ... nhiều Block con nữa thì sao nhỉ???

Mọi Block đều nằm trong collection Blocks mà. Chỉ có điều lúc đó bảo chọn để ra số lượng thì hơi vất ^^

Cái này có thể chọn Blocks có chứa Layer nào đó, mà Layer này có thể nằm trong Block nhiều tầng

;Doan Van Ha CADViet.com
(defun C:HA ( / lay ename chon dsent dschon)
(setq ss nil lay (getstring T "\nNhap ten Layer nam trong Block: "))
(setq dsent (acet-ss-to-list (ssget '((0 . "INSERT")))))
(HA dsent)
(setq ss (acet-list-to-ss dschon)))		;Ten cua tap hop chon la ss [co the dung (command "erase" ss "") de test].
(defun HA(dsent)
(foreach ent dsent
 (setq ename (cdr (assoc -2 (tblsearch "BLOCK" (cdr (assoc 2 (entget ent)))))))
 (while ename
  (cond ((and (= lay (cdr (assoc 8 (entget ename)))) (/= "INSERT" (cdr (assoc 0 (entget ename))))) (setq chon ent))
         	((and (= lay (cdr (assoc 8 (entget ename)))) (= "INSERT" (cdr (assoc 0 (entget ename))))) (HA (list ent))))
  (setq ename (entnext ename)))
 (if chon (setq dschon (cons ent dschon)))))

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

Dùng đệ quy bác HA chú ý khử đệ quy ^^

Test với 2 block, trong mỗi block chứa 1 block khác :

Select objects: Hard error occurred ***

internal stack limit reached (simulated)"\n*** INTERNAL ERROR: VL namespace

mismatch\n"" type Y to reset: "

Hard error occurred ***

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
Đăng nhập để thực hiện theo  

×