Đến nội dung


Hình ảnh
- - - - -

[Thảo luận] - Tạo Dynamic block (Block động) bằng Lisp


  • Please log in to reply
23 replies to this topic

#1 Thaistreetz

Thaistreetz

    biết lệnh adcenter

  • Advance Member
  • PipPipPipPipPipPipPip
  • 903 Bài viết
Điểm đánh giá: 505 (tốt)

Đã gửi 09 May 2012 - 06:02 PM

Topic này được lập theo nhu cầu của bạn Skywings - cần tạo code để tích hợp luôn các block cần dùng vào trong code của chương trình của bạn ấy, trong đó có cả dynamic block hay còn gọi là block động. Mình lập topic trả lời cho skywings cũng đồng thời để chia sẻ phương pháp cho bác nào có nhu cầu và để chúng ta thảo luận,
Bác nào có phương pháp hay hơn muốn chia sẻ thì thảo luận tại đây tránh làm loãng topic giới thiệu chương trình của Skywings.


Cho đến thời điểm này có thể nói 1 chắc chắn rằng chúng ta không có phương pháp để tạo block động bằng lisp, hay kể cả là vba. Các diễn đàn nước ngoài thấy tụi nó kêu bó tay, trong help developer cũng nói rõ điều này, các ngôn ngữ khác thì mình không rõ. Vậy mình tạo nó bằng cách nào? thực tế nó rất đơn giản nếu chúng ta nghĩ khác cách làm thông thường 1 chút.

Ở đây mình lợi dụng khả năng đọc, ghi và lưu 1 tập tin bất kì ở định dạng không mã hóa của lisp. Và may mắn là Autocad cung cấp cho chúng ta khả năng đọc và ghi 1 file bản vẽ ra 2 loại định dạng:
- DWG: Định dạng mã hóa mà mặc định chúng ta hay dùng.
- DXF: Định dạng mở, không mã hóa, có thể đọc được cấu trúc của nó bằng bất kỳ công cụ đọc văn bản nào. Định dạng này do chưa được biên dịch nên tải vào cad chậm hơn dwg, đồng thời dung lượng file thường cao hơn.
Thay vì cố gắng tìm cách make 1 dynamic block ngay trong bản vẽ thì mình sẽ make 1 file dxf chứa dynamic block đó rồi sau đó tải nó vào bản vẽ.

Ý tưởng là vậy. mình cụ thể hóa nó bằng các bước như sau:
- Tạo 1 dynamic block bằng cad theo ý muốn cho chương trình của bạn và lưu nó lại với định dạng dxf. Vì cad có khả năng tương thích ngược với các bản cad đời trước khá tốt nên lời khuyên là chọn định dạng dxf của phiên bản 2007 để lưu. Nó nhẹ hơn mấy thằng ku em nó sau này. dxf của cad2007 được chọn cũng là vì đây là bản cad đầu tiên hỗ trợ dynamic block.
- Dùng lisp mình viết dưới đây để đọc nội dung file dxf trên và tạo ra code để make.
- kết quả thu được là 1 file lisp, nội dung của nó là 1 hàm con có thể make được block của bạn.

;;; Make Dynamic block by Lisp
;;; Copyright 2012 Thaistreetz - Cadviet.com
(defun c:mkb (/ lst openfile path)
(setq path (getfiled "Chon File block" "" "dxf" 8))
(setq openfile (open path "r"))
(while (setq readline (read-line openfile)) (setq lst (cons (strcat "\"" (acet-str-replace "\"" "\\\"" readline )"\"") lst)))
(close openfile)
(setq path (getfiled "Nhap ten File lisp" "" "lsp" 1))
(setq openfile (open path "w"))
(write-line "(defun insert-block (point scale / temp file lst)" openfile)
(write-line "(setq lst (list" openfile)
(foreach ll (reverse lst) (write-line ll openfile))
(write-line "))" openfile)
(write-line "(setq temp (strcat (string-right-trim 8 (findfile \"acad.dcl\")) \"temp.dxf\")" openfile)
(write-line " file (open temp \"W\"))" openfile)
(write-line " (foreach ll lst (write-line ll file))" openfile)
(write-line " (close file)" openfile)
(write-line " (command \"-insert\" temp point scale 0)" openfile)
(write-line " (vl-file-delete temp))" openfile)
(close openfile))
(defun String-right-trim (trim string /)
(cond ((= (type trim) 'STR) (vl-string-right-trim trim string))
((= (type trim) 'INT) (substr string 1 (- (strlen string) trim)))
(t string)))
PS:
- Ngoài Dynamic block, bằng phương pháp này bạn có thể tạo được các đối tương khác của cad mà chúng ta chưa có phương pháp tạo theo cách thông thường. Ví dụ các linetype có chứa true type font, hay các bảng đối tượng...
- Có thể bạn sẽ hoảng nếu đọc cấu trúc của hàm con được tạo, vì nó...dài lê thêê...ê...ê. Kệ nó, cái này bạn có thể yên tâm vì lisp xử lý chuỗi (string) rất nhanh. Con máy cùi bắp của mình xử lý 1 file dưới 1Mb đủ nhanh để không cảm thấy khó chịu vì độ trễ trong khi file tạo ra chỉ khoảng vài chục Kb đến vài trăm Kb là cùng.
- Lisp trên mình sử dụng command để insert block, nếu có thể hãy thay thế bằng các hàm vla để tránh lỗi có thể sảy ra khi insert block
  • 10

Hình đã gửi
IN HIM, I TRUST. THE TRUST IN MY GOD


#2 minhtu2004

minhtu2004

    biết lệnh chamfer

  • Members
  • PipPipPipPip
  • 219 Bài viết
Điểm đánh giá: 34 (tàm tạm)

Đã gửi 09 May 2012 - 06:38 PM

-Sẵn đây cho mình hỏi khỏi phải tạo 1 chủ đề mới. Chi tiết 3D có thể tạo được Dynamic block giống 2D không vậy.
VD: strech dối tượng 3D theo X, Y,Z và 1 vài thứ khác như 2D.
-Nếu có thể làm được xin hướng dẫn cụ thể làm như thế nào. Mong mọi người giúp đỡ.
  • 0

-Nhận thực hiện bản vẽ 3D bằng revit.
-Liên hệ: 01664793290.


#3 Detailing

Detailing

    biết lệnh imageclip

  • Members
  • PipPipPipPipPipPipPip
  • 667 Bài viết
Điểm đánh giá: 278 (khá)

Đã gửi 09 May 2012 - 08:57 PM

cái function STRING-RIGHT-TRIM ở đâu mà sao máy mình báo ko có nhỉ?
  • 1

Ideas don't matter, execution does!

1908412_308002392716743_8165279281236341


#4 Thaistreetz

Thaistreetz

    biết lệnh adcenter

  • Advance Member
  • PipPipPipPipPipPipPip
  • 903 Bài viết
Điểm đánh giá: 505 (tốt)

Đã gửi 09 May 2012 - 09:05 PM

Chết thật. Mình chưa gỡ project khỏi cad khi test lisp. Nó là hàm con của mình. đã bổ sung rồi nhé :D
  • 1

Hình đã gửi
IN HIM, I TRUST. THE TRUST IN MY GOD


#5 Detailing

Detailing

    biết lệnh imageclip

  • Members
  • PipPipPipPipPipPipPip
  • 667 Bài viết
Điểm đánh giá: 278 (khá)

Đã gửi 09 May 2012 - 09:18 PM

Chết thật. Mình chưa gỡ project khỏi cad khi test lisp. Nó là hàm con của mình. đã bổ sung rồi nhé :D

Đã test nhưng nó lại hỏi scale Y ???
nhập scale Y và rotation xong thì nó input dc nhưng ko còn "động" nữa, đây là file dxf và file lisp
http://www.cadviet.c...3237_dynblk.dxf
http://www.cadviet.c...3237_dynblk.lsp
  • 0

Ideas don't matter, execution does!

1908412_308002392716743_8165279281236341


#6 Skywings

Skywings

    biết lệnh erase

  • Members
  • PipPipPip
  • 102 Bài viết
Điểm đánh giá: 46 (tàm tạm)

Đã gửi 09 May 2012 - 09:40 PM

@Thaistreetz: TUYỆT VỜI! Cách làm của bác có thể gói luôn cả file thư viện các block vô Code được :rolleyes: !!
Tuy nhiên có một số lỗi nhỏ ở hàm INSERT-BLOCK trong file lisp xuất ra:

(setq temp (strcat (string-right-trim 8 (findfile "acad.dcl"))
"temp.dxf"
)
file (open temp "W")
)
(foreach ll lst (write-line ll file))
(close file)
(command "-insert" temp point scale 0)
(vl-file-delete temp)
mạo muội sửa thế này cho nó chạy ^^:

(setq temp (strcat (vl-string-right-trim "acad.dcl" (findfile "acad.dcl"))
"temp.dxf"
)
file (open temp "W")
)
(foreach ll lst (write-line ll file))
(close file)
(command "-insert" temp point scale "" "")
(entdel (entlast))
(vl-file-delete temp)
Thk u so much ^_^!
  • 0

#7 ketxu

ketxu

    Copier - Paster - Editor

  • Moderator
  • PipPipPipPipPipPipPip
  • 5682 Bài viết
Điểm đánh giá: 2605 (tuyệt vời)

Đã gửi 09 May 2012 - 09:58 PM

Cách của bác Thái hợp với ý đồ của ket, n mà chưa có thực hiện. Cảm ơn bác ^^. Tuy nhiên nên chỉ là insert vào Blocktable bằng entmake thì hay hơn ^^ Ngoài ra có thể dùng hàm vl-get-resource để làm 1 cheat ^^
  • 1

Thành viên nhóm CadMagic.
Mời bạn ghé thăm facebook nhóm - Page viết lisp theo yêu cầu  :
CAD MAGIC


#8 Thaistreetz

Thaistreetz

    biết lệnh adcenter

  • Advance Member
  • PipPipPipPipPipPipPip
  • 903 Bài viết
Điểm đánh giá: 505 (tốt)

Đã gửi 09 May 2012 - 10:21 PM

- @Detailing xem lại file dxf nhé. nó là 1 block thường mất rồi. nguyên nhân là bạn đã block cái block động của bạn 1 lần nữa (block động trong block). khi tạo xong block động bạn đừng đóng block editor vội. hãy nhấn nút save block as để lưu nó ra file dxf sẽ được 1 file block. file này nhẹ hơn 1 file bản vẽ (nếu đóng block editor rồi mới lưu thì nó là 1 file bản vẽ thông thường) bởi nó tự động loại bỏ các thông tin khác của bản vẽ không liên quan đến dữ liệu cấu thành file block đó.

- @Skywings: đúng là hiện tại toàn bộ thư viện block, linestyle, textstyle, dimstyle của mình đều được gói gọn trong code. chỉ duy nhất 1 file fas nên thoải mái cơ động.

- @Ketxu giải thích về vl-get-resource luôn đi. mình chưa dùng hàm này bao giờ
  • 0

Hình đã gửi
IN HIM, I TRUST. THE TRUST IN MY GOD


#9 Detailing

Detailing

    biết lệnh imageclip

  • Members
  • PipPipPipPipPipPipPip
  • 667 Bài viết
Điểm đánh giá: 278 (khá)

Đã gửi 09 May 2012 - 10:27 PM

- @Detailing xem lại file dxf nhé. nó là 1 block thường mất rồi. nguyên nhân là bạn đã block cái block động của bạn 1 lần nữa (block động trong block)
- @Skywings: đúng là hiện tại toàn bộ thư viện block, linestyle, textstyle, dimstyle của mình đều được gói gọn trong code. chỉ duy nhất 1 file fas nên thoải mái cơ động.
- @Ketxu giải thích về vl-get-resource luôn đi. mình chưa dùng hàm này bao giờ

bạn double click vào file dxf thử xem sao, mình mở bằng CAD 2010 thì nó là dynamic block là 1 line gồm 2 action stretch ở 2 đầu.
dxf đã dc save xuống version 2007
Tuy nhiên hướng của bạn cũng rất hay, mình chỉ ko hiểu sao nó lại ko chạy thôi.
  • 0

Ideas don't matter, execution does!

1908412_308002392716743_8165279281236341


#10 ketxu

ketxu

    Copier - Paster - Editor

  • Moderator
  • PipPipPipPipPipPipPip
  • 5682 Bài viết
Điểm đánh giá: 2605 (tuyệt vời)

Đã gửi 09 May 2012 - 10:44 PM

@aTh : Đổi tên file dxf thành 1 file txt và cho nó vào lúc biên dịch vlx. Khi nào cần dùng thì lấy ra và làm các bước tương tự như bác đã làm ạ. Cái này nhiều người áp dụng để giữ code gốc trong 1 file txt mã hóa. E chưa biết trường hợp với dxf có trục trặc gì không, nhưng thông thường là được
  • 1

Thành viên nhóm CadMagic.
Mời bạn ghé thăm facebook nhóm - Page viết lisp theo yêu cầu  :
CAD MAGIC


#11 Detailing

Detailing

    biết lệnh imageclip

  • Members
  • PipPipPipPipPipPipPip
  • 667 Bài viết
Điểm đánh giá: 278 (khá)

Đã gửi 09 May 2012 - 11:00 PM

Thaistreetz có thể gửi cho mình 1 file dxf + 1 lsp để test thử ko? làm theo cách hướng dẫn như trên vẫn ko dc.

p/s: có ai giải thích hộ xem mục đích dùng cái này để làm gì? che dấu DynBlock? gom toan bộ Block (library) vào chung 1 file VLX tương tự như resources? hay ....
thanks!
  • 0

Ideas don't matter, execution does!

1908412_308002392716743_8165279281236341


#12 ketxu

ketxu

    Copier - Paster - Editor

  • Moderator
  • PipPipPipPipPipPipPip
  • 5682 Bài viết
Điểm đánh giá: 2605 (tuyệt vời)

Đã gửi 09 May 2012 - 11:33 PM

Mục đích chính vẫn là cho hết vào code để đỡ rườm rà các file thư viện đi kèm ý mà bác ^^
  • 0

Thành viên nhóm CadMagic.
Mời bạn ghé thăm facebook nhóm - Page viết lisp theo yêu cầu  :
CAD MAGIC


#13 Thaistreetz

Thaistreetz

    biết lệnh adcenter

  • Advance Member
  • PipPipPipPipPipPipPip
  • 903 Bài viết
Điểm đánh giá: 505 (tốt)

Đã gửi 10 May 2012 - 12:01 AM

@Detailing. đây là block mẫu và file lisp mình đã tạo được, chạy ngon lành. file này minh lưu ở định dạng dxf 2010. cad mình đang dùng là 2010.
Mục đích chính đúng như ketxu nói. nó tăng tính cơ động cho ứng dụng vì người dùng không fải lo thiết lập suport path hoặc bị bắt buộc fải cài đặt chương trình vào 1 thu mục cố định.
Hãy thử tưởng tượng, bạn chỉ cần copy 1 file ứng dụng duy nhất của mình vào USB và mang nó đi bất cứ máy nào, chỉ việc cắm, load và chạy là bạn có thể thiết lập được môi trường làm việc quen thuộc của mình. không fải lo việc fải thiết lập các điều kiện để ứng dụng của bạn có thể chạy được và cũng không gây ra bất cứ thay đổi nào đến thiết lập của máy người khác sau khi rút usb ra.
  • 1

Hình đã gửi
IN HIM, I TRUST. THE TRUST IN MY GOD


#14 Tue_NV

Tue_NV

    KS Võ Quang Tuệ

  • Moderator
  • PipPipPipPipPipPipPip
  • 4296 Bài viết
Điểm đánh giá: 3804 (đỉnh cao)

Đã gửi 10 May 2012 - 06:43 AM

.................
Cho đến thời điểm này có thể nói 1 chắc chắn rằng chúng ta không có phương pháp để tạo block động bằng lisp, hay kể cả là vba, trong help cũng nói rõ điều này. các ngôn ngữ khác thì mình không rõ. Vậy mình tạo nó bằng cách nào? thực tế nó rất đơn giản nếu chúng ta nghĩ khác cách làm thông thường 1 chút.

Ở đây mình tận dụng khả năng đọc, ghi và lưu 1 tập tin bất kì ở định dạng không mã hóa của lisp. Và may mắn là Autocad cung cấp cho chúng ta khả năng đọc và ghi 1 file bản vẽ ra 2 loại định dạng:
- DWG: Định dạng mã hóa mà mặc định chúng ta hay dùng.
- DXF: Định dạng mở, không mã hóa, có thể đọc được cấu trúc của nó bằng bất kỳ công cụ đọc văn bản nào. Định dạng này do chưa được biên dịch nên tải vào cad chậm hơn dwg, đồng thời dung lượng file thường cao hơn.
Thay vì cố gắng tìm cách make 1 dynamic block ngay trong bản vẽ thì mình sẽ make 1 file dxf chứa dynamic block đó rồi sau đó tải nó vào bản vẽ.

Ý tưởng là vậy. mình cụ thể hóa nó bằng các bước như sau:
- Tạo 1 dynamic block bằng cad theo ý muốn cho chương trình của bạn và lưu nó lại với định dạng dxf. Vì cad có khả năng tương thích ngược với các bản cad đời trước khá tốt nên lời khuyên là chọn định dạng dxf của phiên bản 2007 để lưu. Nó nhẹ hơn mấy thằng ku em nó sau này. dxf của cad2007 được chọn cũng là vì đây là bản cad đầu tiên hỗ trợ dynamic block.
- Dùng lisp mình viết dưới đây để đọc nội dung file dxf trên và tạo ra code để make.
- kết quả thu được là 1 file lisp, nội dung của nó là 1 hàm con có thể make được block của bạn.


;;; Make Dynamic block by Lisp
;;; Copyright 2012 Thaistreetz - Cadviet.com
(defun c:mkb (/ lst openfile path)
(setq path (getfiled "Chon File block" "" "dxf" 8))
(setq openfile (open path "r"))
(while (setq readline (read-line openfile)) (setq lst (cons (strcat "\"" (acet-str-replace "\"" "\\\"" readline )"\"") lst)))
(close openfile)
(setq path (getfiled "Nhap ten File lisp" "" "lsp" 1))
(setq openfile (open path "w"))
(write-line "(defun insert-block (point scale / temp file lst)" openfile)
(write-line "(setq lst (list" openfile)
(foreach ll (reverse lst) (write-line ll openfile))
(write-line "))" openfile)
(write-line "(setq temp (strcat (string-right-trim 8 (findfile \"acad.dcl\")) \"temp.dxf\")" openfile)
(write-line " file (open temp \"W\"))" openfile)
(write-line " (foreach ll lst (write-line ll file))" openfile)
(write-line " (close file)" openfile)
(write-line " (command \"-insert\" temp point scale 0)" openfile)
(write-line " (vl-file-delete temp))" openfile)
(close openfile))
(defun String-right-trim (trim string /)
(cond ((= (type trim) 'STR) (vl-string-right-trim trim string))
((= (type trim) 'INT) (substr string 1 (- (strlen string) trim)))
(t string)))
PS:
- Ngoài Dynamic block, bằng phương pháp này bạn có thể tạo được các đối tương khác của cad mà chúng ta chưa có phương pháp tạo theo cách thông thường. Ví dụ các linetype có chứa true type font, hay các bảng đối tượng...
- Có thể bạn sẽ hoảng nếu đọc cấu trúc của hàm con được tạo, vì nó...dài lê thêê...ê...ê. Kệ nó, cái này bạn có thể yên tâm vì lisp xử lý chuỗi (string) rất nhanh. Con máy cùi bắp của mình xử lý 1 file dưới 1Mb đủ nhanh để không cảm thấy khó chịu vì độ trễ trong khi file tạo ra chỉ khoảng vài chục Kb đến vài trăm Kb là cùng.
- Lisp trên mình sử dụng command để insert block, nếu có thể hãy thay thế bằng các hàm vla để tránh lỗi có thể sảy ra khi insert block

Code bạn không áp dụng với Block Dynamic có ATTributes
Cách làm của mình thường dùng Lisp hoặc CAD -> Insert Block Dynamic từ 1 file *.Dwg có chứa Block Dyn để xử lý
hoặc là tạo 1 Palette thư viện (Tool Palette) để sau này thích cái gì thì lấy cái đó và kéo rồi thả
  • 0

#15 Thaistreetz

Thaistreetz

    biết lệnh adcenter

  • Advance Member
  • PipPipPipPipPipPipPip
  • 903 Bài viết
Điểm đánh giá: 505 (tốt)

Đã gửi 10 May 2012 - 07:32 AM

Vì sao lại không thể áp dụng với Dynamic Block có ATTributes được ạ? phương pháp này rõ ràng không có bất kỳ nguyên nhân nào khiến ATTributes trở thành 1 đối tượng cá biệt.
Đây là 1 lisp em lấy từ thư viện của em ra. có ATT và Động, tạo bằng phương pháp trên. nếu test lisp này, bác dùng thêm hàm con string-right-trim em post bên trên

(ai trả lời cho tui biết cái nút upload của diễn đàn chạy đâu mất rồi :( )
  • 1

Hình đã gửi
IN HIM, I TRUST. THE TRUST IN MY GOD


#16 Tue_NV

Tue_NV

    KS Võ Quang Tuệ

  • Moderator
  • PipPipPipPipPipPipPip
  • 4296 Bài viết
Điểm đánh giá: 3804 (đỉnh cao)

Đã gửi 10 May 2012 - 07:42 AM

Vì sao lại không thể áp dụng với Dynamic Block có ATTributes được ạ? phương pháp này rõ ràng không có bất kỳ nguyên nhân nào khiến ATTributes trở thành 1 đối tượng cá biệt.
Đây là 1 lisp em lấy từ thư viện của em ra. có ATT và Động, tạo bằng phương pháp trên. nếu test lisp này, bác dùng thêm hàm con string-right-trim em post bên trên

(ai trả lời cho tui biết cái nút upload của diễn đàn chạy đâu mất rồi :( )

Ồ! được rồi! Thanks bạn nhiều lắm! Cơ mà có cái ATTributes có Field thì value của ATT biến thành ###
Thanks bạn lần nữa!
  • 0

#17 vananhxinh

vananhxinh

    Chưa sử dụng CAD

  • Members
  • Pip
  • 3 Bài viết
Điểm đánh giá: 0 (bình thường)

Đã gửi 09 June 2012 - 11:04 AM

Mình hơi gà mấy cái này. Các bác có thể HD cụ thể giúp mình được ko. Tạo ra file lisp rồi cách sử dụng file lisp đó ntn. thanks
  • 0

#18 Thaistreetz

Thaistreetz

    biết lệnh adcenter

  • Advance Member
  • PipPipPipPipPipPipPip
  • 903 Bài viết
Điểm đánh giá: 505 (tốt)

Đã gửi 09 June 2012 - 06:37 PM

Nếu bạn có thể lập trình lisp thì bạn mới cần cái này. Còn nếu bạn là người dùng thôi thì không cần quan tâm đến topic này đâu
  • 0

Hình đã gửi
IN HIM, I TRUST. THE TRUST IN MY GOD


#19 nataca

nataca

    biết lệnh adcenter

  • Members
  • PipPipPipPipPipPipPip
  • 712 Bài viết
Điểm đánh giá: 553 (tốt)

Đã gửi 12 June 2012 - 01:27 PM

Chà chà. Nghĩ ra món này hay phết nhỉ.
  • 0

#20 Thaistreetz

Thaistreetz

    biết lệnh adcenter

  • Advance Member
  • PipPipPipPipPipPipPip
  • 903 Bài viết
Điểm đánh giá: 505 (tốt)

Đã gửi 12 June 2012 - 06:04 PM

Chà chà. Nghĩ ra món này hay phết nhỉ.

Sang làm A rồi có fải vẽ nữa đâu mà còn mò mẫm vô đây chi vậy hử?
  • 0

Hình đã gửi
IN HIM, I TRUST. THE TRUST IN MY GOD