Chuyển đến nội dung
Diễn đàn CADViet
  • Thông báo

    • Nguyen Hoanh

      CADViet đã hoàn tất nâng cấp   14/09/2017

      Chào các bạn, CADViet đã hoàn tất việc nâng cấp lên phiên bản mới. Tất cả các chức năng đã hoạt động theo kỳ vọng của ban quản trị. Nếu có vấn đề gì cần phản hồi, các bản post ở đây nhé: Trân trọng, Nguyễn Hoành.
ketxu

Insert Attribute Block function

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

ketxu    2.653

Bạn victor nhờ viết cái Insert Block vào mid point của các đối tượng, e đã làm đại loại như thế này :

BB

Lệnh bb ạ.Code chỉ có đoạn tạo hộp thoại của bác gi_bach, đoạn midpoint của bác Hoành, phần e viết mỗi cái insert vào mà chưa xong vì trong lúc làm thì em gặp vấn đề về insert ATT block :

Nếu dùng command (như e đang tạm để), thì các bác biết là nó ..lâu thôi rồi :( tầm một nghìn đối tượng thì cứ gọi là... :wacko:

=> Nên e cần 1 func entmake cho nhanh. Do hiểu biết về ATT quá kém, nên e k làm cho mình cái nào ưng ý được :( Cái e đang dùng thử thì tọa độ của att không được như ý, toàn túm tụm lại

 

(defun AttInsert (BlockName Pnt / Ename NextEnt Data Attdefs)
(cond
;; get Parent entity name
((setq Ename (tblobjname "block" BlockName))

;; first sub entity
(setq NextEnt (entnext Ename))

;; get ATTDEF subentities
(while NextEnt
(setq Data (entget NextEnt))
(if (= "ATTDEF" (cdr (assoc 0 Data)))
(setq Attdefs (cons Data Attdefs))
)
(setq NextEnt (entnext NextEnt))
)

(and
;; entmake insert
(entmake
(list
'(0 . "INSERT")
(cons 8 (getvar "clayer"))
'(66 . 1)
(cons 2 BlockName)
(cons 10 pnt)
(cons 41 1.0)
(cons 42 1.0)
(cons 43 1.0)
'(50 . 0.0)
)
)

;; entmake ATTRIBs based on ATTDEFS
(foreach x (reverse Attdefs)
(entmake
(list
'(0 . "ATTRIB")
(assoc 8 x)
(assoc 10 x)
(assoc 40 x)
(assoc 1 x)
(assoc 50 x)
(assoc 41 x)
(assoc 51 x)
(assoc 7 x)
(assoc 71 x)
(assoc 72 x)
(assoc 11 x)
(assoc 2 x)
(assoc 70 x)
(assoc 73 x)
(assoc 74 x)
)
)
)
;; entmake SEQEND
(entmake '((0 . "SEQEND")(8 . "0")))
)
)
(T nil)
)
)

Các bác đỡ hộ em chỗ bí này với. Hic

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
Thaistreetz    515

Ketxu dùng cái này thay cho lệnh insert block thử xem

Mình viết tổng quát, bạn có thể rút gọn nó cho fù hợp với nhu cầu

trong code này thì tham số:

list_att là list giá trị của các att (định dạng là string) muốn đưa vào block cần insert, Nếu block thường thì để tham số này là nil.

ang là và góc xoay của block tính bằng radial.

scale là tỷ lệ insert của block

xdata là dữ liệu mở rộng, nhu cầu thông thường thì không cần cái này, bạn nên bỏ nó đi

;;;=============== Make insert block
(defun DXF (code en)(cdr (assoc code (entget en))))
(defun MakeInsert (Blkname inspoint scale ang list_att layer color xdata / lst obj i)
(setq lst '() i -1 en (cdr (last (tblsearch "block" Blkname))) obj (entget en))
(if (= (cdr(assoc 0 obj)) "ATTDEF")
(setq lst (list (list
	(cdr(assoc 10 obj))(cdr(assoc 11 obj))(cdr(assoc 50 obj))(cdr(assoc 8 obj))(cdr(assoc 62 obj))
	(cdr(assoc 40 obj))(assoc 7 obj)(assoc 71 obj)(assoc 72 obj)(assoc 2 obj)))))
(while (setq en (entnext en))
(if (= (cdr(assoc 0 (setq obj(entget en)))) "ATTDEF")
	(setq lst (cons (list
	(cdr(assoc 10 obj))(cdr(assoc 11 obj))(cdr(assoc 50 obj))(cdr(assoc 8 obj))(cdr(assoc 62 obj))
	(cdr(assoc 40 obj))(assoc 7 obj)(assoc 71 obj)(assoc 72 obj)(assoc 2 obj))lst))))
(entmakex(list
	'(0 . "INSERT")'(100 . "AcDbEntity")
	(cons 8 (if Layer Layer (getvar "Clayer")))
	(cons 62 (if Color Color 256))
	'(100 . "AcDbBlockReference")
	(if list_att '(66 . 1) '(66 . 0))
	(cons 2 Blkname)
	(cons 10 (trans inspoint 1 0))
	(cons 41 scale)(cons 42 scale)(cons 43 scale)
	(cons 50 Ang)
	(cons -3 (if xdata (list xdata) nil))))
(if lst
(foreach LL (reverse lst)	(entmake(list
	'(0 . "ATTRIB")'(100 . "AcDbEntity")(cons 8 (cadddr LL))
	(if (nth 4 LL) (cons 62 (nth 4 LL))(cons 62 256))'(100 . "AcDbText")
	(cons 10(mapcar'+(trans inspoint 1 0)(mapcar'(lambda(x)(* scale x))(polar'(0 0 0)(+(angle'(0 0 0)(car LL))ang)(distance'(0 0 0)(car LL))))))
	(cons 40 (* scale (nth 5 LL)))
	(cons 1 (nth (setq i (1+ i))list_att))
	(cons 50 (+ ang (caddr LL)))
	'(41 . 1.0)(nth 6 LL)(nth 7 LL)(nth 8 LL)
	(if (= 0(cdr (nth 7 LL))(cdr(nth 8 LL)))(cons 11(list 0 0 0))
	(cons 11(mapcar'+(trans inspoint 1 0)(mapcar'(lambda(x)(* scale x))(polar'(0 0 0)(+(angle'(0 0 0)(cadr LL))ang)(distance'(0 0 0)(cadr LL)))))))
	'(100 . "AcDbAttribute")'(280 . 0)(last LL)'(70 . 0)'(280 . 1)))))
(dxf 330 (entmakex (list '(0 . "SEQEND") (cons 8 (if Layer Layer (getvar "Clayer")))))))

  • 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
ketxu    2.653

Cám ơn bác, hàm khá tổng quát rồi. Nhưng vấn đề của em là khi để người dùng dùng, làm sao em biết người ta chọn 1 block att có những thuộc tính, giá trị nào để list ? Hay là lại làm 1 vòng lặp getAtt theo blockName nữa bác nhỉ :) Nếu chỉ có cách đó thì e sẽ áp dụng xem sao.

P/S : thực chất cái hàm đầu tiên e post lên cũng làm công việc duyệt qua các att r lại tạo lại, nhưng e vẫn chưa tìm đc chỗ lỗi làm cho các att text dính vào nhau tại tọa độ 0 . E thì nghi dòng (assoc 10 x), hoặc do cách tạo att để cố định base point là 0,0,0

  • 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
Thaistreetz    515

Đúng là lỗi tại (assoc 10 x). Trong đối tượng BLOCK thì các mã 10 và 11 là tọa độ OCS của ATTDEF. còn trong đối tượng INSERT thì nó là tọa độ WCS (hoặc UCS) của ATTRIB.

Bạn chú ý là toạ độ của ATTRIB trong đối tượng INSERT không bị phụ thuộc vào toạ độ của ATTDEF trong BLOCK nhé. chính vì thế việc khai báo tọa độ không chuẩn có thể dẫn đến hình dạng đối tượng Insert không giống hình dạng đối tượng block gốc. lần đầu tiên tạo hàm con trên mình cũng gặp fải vấn đề này.

Vậy nên khi entmake đối tượng Insert bằng 1 block có chứa ATTDEF thì ta fải khai báo tọa độ của ATTRIB được tạo ra trong WCS hoặc UCS. Còn khi dùng hàm command để chèn block att thì nó đã tính toán hộ ta tọa độ của ATTRIB rồ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
victor85    10

Cảm ơn bác ketxu nhé. lisp chạy rất ổn và nhanh rùi, giao diên cũng thân thiện và ok lắm. thanks bác mấy cái nào.

Mình up nó lên các bạn dùng thử nhé: http://www.mediafire.com/file/eay59vj1aa63f6i/bb.VLX

Tác dụng chính của lisp là thay thế mọi đối tượng 2D bằng 1 block bất kỳ vào tâm hình học của đối tượng. Kết hợp với sở thích dùng block mình nghĩ sẽ có nhiều trường hợp cần đến 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
ketxu    2.653

E đã sửa lại insert point của ATT nhưng vẫn bị miss vị trí 1 số ATT. Các bác test lại hộ e với :(

(defun AttInsert (BlockName Pnt / Ename NextEnt Data Attdefs)
(cond
;; get Parent entity name
((setq Ename (tblobjname "block" BlockName))

;; first sub entity
(setq NextEnt (entnext Ename))

;; get ATTDEF subentities
(while NextEnt
(setq Data (entget NextEnt))
(if (= "ATTDEF" (cdr (assoc 0 Data)))
(setq Attdefs (cons Data Attdefs))
)
(setq NextEnt (entnext NextEnt))
)

(and
;; entmake insert
(entmake
(list
'(0 . "INSERT")
(cons 8 (getvar "clayer"))
'(66 . 1)
(cons 2 BlockName)
(cons 10 pnt)
(cons 41 1.0)
(cons 42 1.0)
(cons 43 1.0)
'(50 . 0.0)
)
)

;; entmake ATTRIBs based on ATTDEFS
(foreach x (reverse Attdefs)
(entmake
(list
'(0 . "ATTRIB")
(assoc 8 x)
(cons 10 (mapcar '+ (trans Pnt 1 0)(polar '(0 0 0)(angle'(0 0 0)(cdr (assoc 10 x)))(distance '(0 0 0)(cdr (assoc 10 x)))))) 
(assoc 40 x)
(assoc 1 x)
(assoc 50 x)
(assoc 41 x)
(assoc 51 x)
(assoc 7 x)
(assoc 71 x)
(assoc 72 x)
(assoc 11 x)
(assoc 2 x)
(assoc 70 x)
(assoc 73 x)
(assoc 74 x)
)
)
)
;; entmake SEQEND
(entmake '((0 . "SEQEND")(8 . "0")))
)
)
(T nil)
)
)

File test

  • 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
victor85    10

Bác ketxu ơi, thế cái lisp hôm trước bác sent mình đã ổn chưa vậy hay là vẫn còn bị văng ATT? dùng thử thấy cũng chưa gặp phải lỗi j? Hì tiện thể bác xem thử có phát triển lên thành insert vào các grip point của đối tượng luôn ko nhé?? Xong tui thanks tiếp bác nhiêu nhiều luôn :) =d>

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
phamngoctukts    708

Bác ketxu ơi, thế cái lisp hôm trước bác sent mình đã ổn chưa vậy hay là vẫn còn bị văng ATT? dùng thử thấy cũng chưa gặp phải lỗi j? Hì tiện thể bác xem thử có phát triển lên thành insert vào các grip point của đối tượng luôn ko nhé?? Xong tui thanks tiếp bác nhiêu nhiều luôn :) =d>

Lisp đó của bạn ổn rồi (vì dùng command) nhưng mà tốc độ bị chậm. Ở đây ketxu đang tìm cách tối ưu thôi bạn không cần qua tâm. Lúc nào xong chắc ketxu sẽ reply cho ban.

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
Thaistreetz    515

@ketxu: code của bạn sẽ không "miss" bất kỳ ATTRIB nao nếu các đối tuợng gốc ATTDEF có điểm canh lề là left. nguợc lại nó sẽ "miss" tất cả ATTRIB nếu đối tuợng gốc ATTDEF có điểm canh lề khác left. mà sự khác nhau giữa canh lề kiểu left và những kiểu còn lại chắc bạn biết rồi.

PS: "Miss" mình để trong dấu nháy kép vì thực ra nó không hề miss. zoom extents sẽ thấy liền. bạn chưa giải quyết đuợc vấn đề là do chưa chịu đọc kỹ code của mình.

  • 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
ketxu    2.653

Hehe.Tất nhiên là e zoom thấy nó chạy tít mù khơi nên mới quy nó vào dạng mis ^^.Đúng là e chưa rào hàng nên nó lung tung ^^ Tks bác đã nhắc nhở, khi nào rảnh e sẽ sửa lạ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
Skywings    46

@Thaistreetz: mình dùng lisp của bác thì gặp 2 vấn đề:

- đối tượng của mình để màu BY LAYER thì giá trị hàm (if (nth 4 LL) (cons 62 (nth 4 LL))) là nil dẫn đến lỗi "error: bad DXF group: nil", mình chỉ định mã màu luôn thì qua được bước này.

- (dxf 330 (entmakex (list '(0 . "SEQEND") (cons 8 (if Layer Layer (getvar "Clayer"))))))) dòng này bị báo lỗi "error: no function definition: DXF", mong bác bổ sung hàm DXF nà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
Thaistreetz    515

@Thaistreetz: mình dùng lisp của bác thì gặp 2 vấn đề:

- đối tượng của mình để màu BY LAYER thì giá trị hàm (if (nth 4 LL) (cons 62 (nth 4 LL))) là nil dẫn đến lỗi "error: bad DXF group: nil", mình chỉ định mã màu luôn thì qua được bước này.

- (dxf 330 (entmakex (list '(0 . "SEQEND") (cons 8 (if Layer Layer (getvar "Clayer"))))))) dòng này bị báo lỗi "error: no function definition: DXF", mong bác bổ sung hàm DXF này :) !

Oh, tại mình không để ý cái hàm con.

(defun DXF (code en)(cdr (assoc code (entget en))))

Về vấn đề màu Bylayer, bạn có thể up bản vẽ lên để mình test lại không? code mình viết thế kia là đã loại bỏ trường hợp màu là bylayer rồ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
Skywings    46

Oh, tại mình không để ý cái hàm con.

(defun DXF (code en)(cdr (assoc code (entget en))))

Về vấn đề màu Bylayer, bạn có thể up bản vẽ lên để mình test lại không? code mình viết thế kia là đã loại bỏ trường hợp màu là bylayer rồi.

Thk bác đã bổ sung hàm DXF, chạy ok ^^!

Bác tải file này kiểm tra thử nhé http://www.mediafire.com/?1sunvxizv81ix01!

Còn một vấn đề mình muốn hỏi là khi tạo Block Att, các Att mình chọn tùy chọn invisible, lisp của bác nó hiện ra hết, có cách nào cho nó ẩn lun hô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
Thaistreetz    515

Ah, bạn makeblock bằng các đối tuợng có màu bylayer. Mình chưa sử dụng vào truờng hợp này nên chưa fát hiện lỗi.

Bạn sửa dòng này

(if (nth 4 LL) (cons 62 (nth 4 LL)))'(100 . "AcDbText")

bằng dòng này

(if (nth 4 LL) (cons 62 (nth 4 LL))(cons 62 256))'(100 . "AcDbText")

hoặc có thể copy lại code mình đã edit ở trên.

về vấn đề invisible mình chưa làm được.

  • 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
phamngoctukts    708

E đã sửa lại insert point của ATT nhưng vẫn bị miss vị trí 1 số ATT. Các bác test lại hộ e với :(

(defun AttInsert (BlockName Pnt / Ename NextEnt Data Attdefs)
(cond
;; get Parent entity name
((setq Ename (tblobjname "block" BlockName))

;; first sub entity
(setq NextEnt (entnext Ename))

;; get ATTDEF subentities
(while NextEnt
(setq Data (entget NextEnt))
(if (= "ATTDEF" (cdr (assoc 0 Data)))
(setq Attdefs (cons Data Attdefs))
)
(setq NextEnt (entnext NextEnt))
)

(and
;; entmake insert
(entmake
(list
'(0 . "INSERT")
(cons 8 (getvar "clayer"))
'(66 . 1)
(cons 2 BlockName)
(cons 10 pnt)
(cons 41 1.0)
(cons 42 1.0)
(cons 43 1.0)
'(50 . 0.0)
)
)

;; entmake ATTRIBs based on ATTDEFS
(foreach x (reverse Attdefs)
(entmake
(list
'(0 . "ATTRIB")
(assoc 8 x)
(cons 10 (mapcar '+ (trans Pnt 1 0)(polar '(0 0 0)(angle'(0 0 0)(cdr (assoc 10 x)))(distance '(0 0 0)(cdr (assoc 10 x)))))) 
(assoc 40 x)
(assoc 1 x)
(assoc 50 x)
(assoc 41 x)
(assoc 51 x)
(assoc 7 x)
(assoc 71 x)
(assoc 72 x)
(assoc 11 x)
(assoc 2 x)
(assoc 70 x)
(assoc 73 x)
(assoc 74 x)
)
)
)
;; entmake SEQEND
(entmake '((0 . "SEQEND")(8 . "0")))
)
)
(T nil)
)
)

File test

Vì em chỉ xử lý cái DXF 10 mà không xử lý thằng DXF 11 nên nó mới bị thế.

Em thử lại cái này

(defun AttInsert (BlockName Pnt / Ename NextEnt Data Attdefs)
(cond
;; get Parent entity name
((setq Ename (tblobjname "block" BlockName))

;; first sub entity
(setq NextEnt (entnext Ename))

;; get ATTDEF subentities
(while NextEnt
(setq Data (entget NextEnt))
(if (= "ATTDEF" (cdr (assoc 0 Data)))
(setq Attdefs (cons Data Attdefs))
)
(setq NextEnt (entnext NextEnt))
)

(and
;; entmake insert
(entmake
(list
'(0 . "INSERT")
(cons 8 (getvar "clayer"))
'(66 . 1)
(cons 2 BlockName)
(cons 10 pnt)
(cons 41 1.0)
(cons 42 1.0)
(cons 43 1.0)
'(50 . 0.0)
)
)

;; entmake ATTRIBs based on ATTDEFS
(foreach x (reverse Attdefs)
 (setq px10 (+ (car(cdr(assoc 10 x))) (car pnt))
py10 (+ (cadr(cdr(assoc 10 x))) (cadr pnt))
pz10 (+ (caddr(cdr(assoc 10 x))) (caddr pnt))
px11 (+ (car(cdr(assoc 11 x))) (car pnt))
py11 (+ (cadr(cdr(assoc 11 x))) (cadr pnt))
pz11 (+ (caddr(cdr(assoc 11 x))) (caddr pnt))
pt10 (list px10 py10 pz10)
pt11 (list px11 py11 pz11)
)
(entmake
(list
'(0 . "ATTRIB")
(assoc 8 x)
 (cons 10 pt10)
(cons 11 pt11)
(assoc 40 x)
(assoc 1 x)
(assoc 50 x)
(assoc 41 x)
(assoc 51 x)
(assoc 7 x)
(assoc 71 x)
(assoc 72 x)
(assoc 2 x)
(assoc 70 x)
(assoc 73 x)
(assoc 74 x)
)
)
)
;; entmake SEQEND
(entmake '((0 . "SEQEND")(8 . "0")))
)
)
(T nil)
)
)

  • 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
ketxu    2.653

Em đang phân vân rẽ nhánh điều kiện của dxf 72 cơ. Nhưng có lẽ không cần, tối về e test thử. Tks bác 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
phamngoctukts    708

Em đang phân vân rẽ nhánh điều kiện của dxf 72 cơ. Nhưng có lẽ không cần, tối về e test thử. Tks bác nhiều ^^

nếu rẽ nhánh thì không đơn giản đâu vì nó còn 73 74 nữa

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
ketxu    2.653

Cám ơn các bác đã trợ giúp, phần thay thế đã nhanh hơn quá nhiều, thay thế 1500 block (trong block có 5 att) cũng chỉ mất tầm 5,6s ^^ Up lại bản fix cho bạn victor

 

BB

  • 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

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


×