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

Hỏi về Lisp (thuật toán, ý tưởng, coding,...)

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

Đoạn code trên không ổn ketxu ạ. nó chỉ có tác dụng với các lệnh của cad. có 2 vấn đề sảy ra nó không giải quyết được:

- Các lệnh lisp (defun c:lenh....) nó hoàn toàn không nhận biết.

- Các lệnh lisp có sử dụng hàm command bên trong, nó sẽ lấy luôn command cuối cùng sử dụng trong lệnh lisp đó. mà thường thì đó là các lệnh UCS hoặc Undo.

Lệnh mà mình muốn lấy là lệnh cuối cùng giống như khi ta vừa sử dụng 1 lệnh, space hay enter tiếp thì cad gọi lại lệnh vừa sử dụng í.

vlr-command-reactor dùng cho các lệnh của CAD.

 

Muốn theo dõi các lệnh-hàm Lisp thì dùng : vlr-lisp-reactor : ( vlr-lispWillStart, vlr-lispEnded, vlr-lispCancelled)

  • 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

Lệnh là Lệnh Command, nó khác với user define command chứ ^^. Yêu cầu ban đầu ra răng thì nó như vậy Thuylinh ơi :) Chứ ngoài lisp ra còn VBA, NET, ARX ... thì mấy dòng kia làm sao giải quyết vấ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

Thế có nghĩa là với đoạn code trên, kể cả khi sửa lại với các hàm bạn gia_bach nêu bên trên thì cũng chỉ giải quyết được với lệnh cad và lệnh lisp. Các lệnh viết bằng VBA, NET, ARX ... như bạn nêu sẽ không lấy được phải không?

Mình nghĩ chủ quan rằng Cad lấy được như vậy thì chắn hẳn họ (lập trình viên autodesk) phải lưu nó vào đâu đó chứ nhỉ. Kiếm hoài không ra :(

 

PS: Ketxu hay gia_bach có thể giúp mình sửa lại đoạn code trên không? Mấy hàm trên hơi trừu tượng, mình đã cố thử sửa nhưng kết quả lung tung hết cả. Mình không sử dụng các ứng dụng VBA, NET, Arx nên chỉ cần chạy với lệnh cad và lệnh lisp là tốt rồi. Nếu có thể thì các bạn viết thành 1 hàm con với kết quả cuối cùng trả về là string để mình sử dụng nó như thế này :

(defun c:xxx

... do something...

(command (get-last-cmd) ... )

... keep doing something...

(princ)); end program.

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

Các bác cho hỏi các hàm reactor chỉ có tác dụng trên bản vẽ hiện hành phải không, khi đóng bản vẽ và mở lại thì không còn tác dụng? Ví dụ lisp vẽ đường tâm của Leemac. Bác nào biết trả lời giúp. Thanks.

;;--------------=={ Associative Centerlines }==---------------;;
;;                                                        	;;
;;  Uses reactors to update centerlines following     		;;
;;  modification of associated circles. Stores entity handles ;;
;;  in entity xData to enable reactor rebuild upon loading,   ;;
;;  allowing retention of associativity between sessions. 	;;
;;------------------------------------------------------------;;
;;  Author: Lee Mac, Copyright ? 2011 - www.lee-mac.com   	;;
;;------------------------------------------------------------;;
;;  Version 1.0	-	12-05-2011                        	;;
;;------------------------------------------------------------;;
(setq cl:ratio 1.25 cl:app "LMAC_CL")
;;------------------------------------------------------------;;
(defun c:cl ( / _line ss e c r l1 l2 )
 (if
(and
 	(setq ss
   	(ssget
     	(list '(0 . "CIRCLE") '(-4 . "<NOT") (list -3 (list cl:app)) '(-4 . "NOT>"))
   	)
 	)
 	(or (tblsearch "APPID" cl:app) (regapp cl:app))
)
(progn
 	(defun _line ( p1 p2 h )
   	(entmakex
     	(list (cons 0 "LINE") (cons 10 p1) (cons 11 p2)
       	(list -3
         	(list cl:app
           	(cons 1002 "{") (cons 1005 h) (cons 1002 "}")
         	)
       	)
     	)
   	)
 	)
 	(repeat (setq i (sslength ss))
   	(setq e  (entget (ssname ss (setq i (1- i))))
         	h  (cdr (assoc  5 e))
         	c  (cdr (assoc 10 e))
         	r  (* cl:ratio (cdr (assoc 40 e)))
         	l1 (_line (polar c 0. r) (polar c pi r) h)
         	l2 (_line (polar c (/ pi 2.) r) (polar c (/ (* 3. pi) 2.) r) h)
   	)
   	(entmod
     	(list (assoc -1 e)
       	(list -3
         	(list cl:app
           	(cons 1002 "{")
           	(cons 1005 (cdr (assoc 5 (entget l1))))
           	(cons 1005 (cdr (assoc 5 (entget l2))))
           	(cons 1002 "}")
         	)
       	)
     	)
   	)
   	(vlr-object-reactor (list (vlax-ename->vla-object (cdr (assoc -1 e)))) (list cl:app h)
     	(list
       	(cons :vlr-modified 'cl:circle:callback)
     	)
   	)
   	(vlr-object-reactor (mapcar 'vlax-ename->vla-object (list l1 l2)) (list cl:app h)
     	(list
       	(cons :vlr-modified 'cl:line:callback)
     	)
   	)
 	)
)
 )
 (princ)
)
;;------------------------------------------------------------;;
(defun c:clremove ( / _massoc ss fl i e r d h x )
 (defun _massoc ( x l )
(if (setq a (assoc x l))
 	(cons (cdr a) (_massoc x (cdr (member a l))))
)
 )

 (princ "\nSelect Circles to Remove Associativity <All>: ")
 (setq fl (list '(0 . "CIRCLE") (list -3 (list cl:app))) i -1)

 (if
(setq ss
 	(cond
   	( (ssget fl) )
   	( (ssget "_X" fl) )
 	)
)
(while (setq e (ssname ss (setq i (1+ i)))) (setq e (entget e (list cl:app)))
 	(foreach r (cdar (vlr-reactors :vlr-object-reactor))
   	(if
     	(and
       	(setq d (vlr-data r))
       	(listp d)
       	(eq cl:app (car d))
       	(or (not (cadr d)) (eq (cdr (assoc 5 e)) (cadr d)))
     	)
     	(vlr-remove r)
   	)
 	)
 	(foreach h (_massoc 1005 (cdadr (assoc -3 e)))
   	(if (setq x (entget (handent h)))
     	(entmod (list (assoc -1 x) (list -3 (list cl:app))))
   	)
 	)
 	(entmod (list (assoc -1 e) (list -3 (list cl:app))))
)
 )
 (princ)
)    
;;------------------------------------------------------------;;
(defun cl:circle:callback ( owner reactor params / xtyp xval c r )
 (if
(and
 	(vlax-read-enabled-p owner)
 	(progn (vla-getxdata owner cl:app 'xtyp 'xval) xval)
 	(setq
   	c (vlax-get owner 'center)
   	r (* cl:ratio (vlax-get owner 'radius))
 	)
)
(mapcar
 	(function
   	(lambda ( h a )
     	(if (or (entget (setq h (handent h))) (entdel h))
       	(entmod
         	(list (cons -1 h) (cons 10 (polar c a r)) (cons 11 (polar c (+ a pi) r)))
       	)
     	)
   	)
 	)
 	(cddr (mapcar 'vlax-variant-value (vlax-safearray->list xval))) (list 0. (/ pi 2.))
)
 )
 (princ)
)
;;------------------------------------------------------------;;
(defun cl:line:callback ( owner reactor params )
 (setq *data (list owner reactor))
 (vlr-command-reactor (list cl:app)
(list
 	(cons :vlr-commandended 	'cl:line:modify)
 	(cons :vlr-commandcancelled 'cl:line:cancelled)
 	(cons :vlr-commandfailed	'cl:line:cancelled)
)
 )
 (vlr-remove reactor)
 (princ)
)
;;------------------------------------------------------------;;
(defun cl:line:modify ( reactor params / xtyp xval h ) (vlr-remove reactor)
 (if
(and *data (not (vlax-erased-p (car *data))) (progn (vla-getxdata (car *data) cl:app 'xtyp 'xval) xval)  
 	(or
   	(entget
     	(setq h
       	(handent
         	(caddr
           	(mapcar 'vlax-variant-value (vlax-safearray->list xval))
         	)
       	)
     	)
   	)
   	(entdel h)
 	)
)
(progn
 	(cl:circle:callback (vlax-ename->vla-object h) nil nil)
 	(vlr-add (cadr *data))
 	(setq *data nil)
)
 )  
 (princ)
)
;;------------------------------------------------------------;;
(defun cl:line:cancelled ( reactor params ) (vlr-remove reactor)
 (if *data
(progn
 	(vlr-add (cadr *data))
 	(setq *data nil)
)
 )
 (princ)
)
;;------------------------------------------------------------;;
(
 (lambda ( / r d s i e o xtyp xval )
(foreach r (cdar (vlr-reactors :vlr-object-reactor))
 	(if (and (setq d (vlr-data r)) (listp d) (eq cl:app (car d)))
   	(vlr-remove r)
 	)
)
(if (setq s (ssget "_X" (list '(0 . "CIRCLE") (list -3 (list cl:app)))))
 	(repeat (setq i (sslength s))
   	(setq e (ssname s (setq i (1- i))))
   	(vlr-object-reactor (list (setq o (vlax-ename->vla-object e))) (list cl:app (cdr (assoc 5 (entget e))))
     	(list
       	(cons :vlr-modified 'cl:circle:callback)
     	)
   	)
   	(vla-getxdata o cl:app 'xtyp 'xval) (setq xval (mapcar 'vlax-variant-value (vlax-safearray->list xval)))
   	(vlr-object-reactor
     	(mapcar
       	(function
         	(lambda ( h )
           	(or (entget (setq h (handent h))) (entdel h)) (vlax-ename->vla-object h)
         	)
       	)
       	(list (caddr xval) (cadddr xval))
     	)
     	(list cl:app (cdr (assoc 5 (entget e)))) (list (cons :vlr-modified 'cl:line:callback))
   	)
 	)
)
 )
)
(vl-load-com) (princ)
;;------------------------------------------------------------;;
;;                 		End of File                    	;;
;;------------------------------------------------------------;;

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

(defun c:xxx

... do something...

(command (get-last-cmd) ... )

... keep doing something...

(princ)); end program.

Cảm ơn các bạn!

(defun ST-Get-List-Command(objReactor lstOfCommand)
(setq #lstCmds (reverse (cons (car lstOfCommand) (reverse #lstCmds)))))
(or #CmdList1
(setq #CmdList1 (vlr-editor-reactor nil '(
(:vlr-lispWillStart . ST-Get-List-Command)
(:vlr-unknownCommand . ST-Get-List-Command)
(:vlr-commandWillStart . ST-Get-List-Command)
)))
)
(defun lastCmd()(last #lstCmds))

Bạn cẩn thận chỗ hàm Lisp k sử dụng trong hàm chuẩn Command nhé. Nếu có sử dụng thì hãy dùng phương thức sendkey

  • 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

Cho mình hỏi 1 vấn đề về sử lý đối tượng khung viewport bằng lisp.

1. Làm thế nào đề xác định tỉ lệ của khung view và mã DXF của nó là bao nhiêu.

2. Từ 1 viewport hình chữ nhật có sẵn trong nền Layout làm thế nào để xác định được 4 điểm của khung view tương ứng với các vị trí trong nền Model.

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ảm ơn bạn Ketxu nhé. Mình tiếp tục ngâm cứu hàm trên của bạn xem có vỡ ra được tẹo nào không. mấy hàm reactor này khó hiểu thật!

@Avi612:

1. Hình như là trong đoạn code này. cái này mình viết lâu rồi nên cũng không nhớ rõ có phải nó không (nó nằm trong ứng dụng tự động điền tỷ lệ bản vẽ vào khung tên block - lấy thông tin tỷ lệ từ zoom scale xp của viewport).

(defun dxf (nmb e) (cdr (assoc nmb (entget e))))
(foreach ssn  (convert-ss-to-list (ssget "C" (car pt) (cadr pt) '((0 . "VIEWPORT,LWPOLYLINE"))))
(if (= (dxf 0 (dxf 330 ssn)) "VIEWPORT")
(setq ssn (dxf 330 ssn)))
(setq lst (cons (/ 1 (vla-get-customscale (vlax-ename->vla-object ssn))) lst)))

2. Mình nhớ không nhầm thì trong code của lệnh Align space của express tool có đoạn code giúp giải quyết vấn đề này. bạn nghiên cứu thử xem

  • 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

Hình như đoạn hàm trên sai rồi bạn biến "pt" chưa khai báo thì sao hàm này chạy được, bạn xem lại dòng lệnh foreach dùm mì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

Code để bạn tham khảo, chứ có phải chép lại đâu Avi612

Phần lấy tỉ lệ chính là chỗ CustomScale đó

 

(vla-get-customscale (vlax-ename->vla-object(ssname (ssget ":S" (list (cons 0 "VIEWPORT"))) 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

 

Bạn có thể giải thích rõ hơn không. Thanks.

Ý là khi đóng và mở bản vẽ thì phải load, remove cái reactor cũ rồi tạo lại cái reactor mới có tác dụng

Đồng nghĩa với reactor sẽ mất cũng giống như 1 hàm, khi đóng và mở bản vẽ thì phải làm động tác Load lại vậ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

Qua mấy ngày nghiên cứu về chủ đề reactor thì mình có kết luận thế này:

- Reactor: là 1 đối tượng dữ liệu bản vẽ, nó kết nối các sự kiện autocad (event-name) với các hàm lisp (callback_function) ngay khi sự kiện sảy ra. Vì là đối tượng dữ liệu bản vẽ nên giống như mọi đối tượng khác, nó sẽ tồn tại cùng bản vẽ cho đến khi bị remove đi.

- Sự kết nối mà 1 reactor tạo ra giữa event-namecallback-function theo mặc định là không bền vững. sự kết nối này bị mất đi khi đóng bản vẽ dù đối tượng reactor vẫn tồn tại trong cơ sở dữ liệu của bản vẽ đó. Có thể thiết lập tính bền vững cho kết nối bằng các hàm (vlr-pers reactor) và (vlr-pers-release reactor)

- Hàm callback-function là 1 hàm lisp nên nó cần phải được load khi mở bản vẽ thì kết nối của reactor mới có tác dụng. Trong trường hợp kết nối của reactor được thiết lập bền vững, khi sự kiện sảy ra mà hàm callback-function chưa được load thì chương trình báo lỗi.

 

Như vậy là kết luận trên của bạn Tue_NV chưa hoàn toàn chính xác.

- reactor không tự động bị mất đi, nó chỉ bị mất khi ta chủ động xóa nó.

- vì thế ta chỉ cần load lại hàm callback-function chứ không cần phải tái tạo lại reactor.

 

Mình mới nghiên cứu nên những ý kiến trên có thể đúng, có thể sai, mong các bạn góp ý và hi vọng các bạn tiếp tục thảo luận về chủ đề này, hơi khó 1 chút nhưng khá hay. Mình tìm thấy mấy topic trong 4r bàn về reactor nhưng hơi ít thông tin để tham khả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

Code để bạn tham khảo, chứ có phải chép lại đâu Avi612

Phần lấy tỉ lệ chính là chỗ CustomScale đó

 

(vla-get-customscale (vlax-ename->vla-object(ssname (ssget ":S" (list (cons 0 "VIEWPORT"))) 0 )))

 

@Ketxu: Thanks cái đã.

 

Mình đã áp dụng được cú pháp trên và tìm được 1 cách khác nữa là dùng giá trị của mã DXF 41 chia cho giá trị của mã DXF 45 nó vẫn trả về đúng tỉ lệ customscale.

 

Và cho mình hỏi thêm:

-- Nếu như đã lấy được giá trị customscale của khung viewport bằng 2 cách trên rồi thì làm cách nào để có thể áp ngược lại cho nó 1 giá trị mới (do ta nhập vào).

Ví dụ:

Khung viewport có tỉ lệ customscale hiện tại là 2. --->mình muốn chuyển nó thành 5 (giá trị 5 do ta nhập vào).

Nếu được xin mọi người hướng dẫn mình xử lý nó theo 2 cách luôn.

1. Là dùng các hàm vla, vl....

2. Là dùng các viết với các hàm thông thường khác.

Mục đích để so sánh sự khác biệt và với những giá trị nhập vào là số thực thì sai số giữa 2 cách có nhiều ko.

Thanks mọi người trướ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): Visual: Có vla-get-customscale thì cũng có vla-put-customscale

2). Lisp: dùng subst

Tôi hiện không có cad nên chưa test, bạn test thử xem.

  • 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

@avi626 & DVH: Bạn không thể entmake hoặc entmod với đối tượng Viewport.

@Ketxu: Đoạn code trên (lấy lệnh cuối cùng bạn viết lại cho mình í) vẫn chưa sử dụng được Ketxu ạ. Với lệnh thuần cad hoặc thuần lisp thì chạy rất tốt, nhưng với lệnh lisp chứa command thì nó vẫn lấy command bên trong chứ không lấy lệnh lisp. Sau mấy ngày đánh vật với nó thì mình cũng chịu thua rùi. Có lẽ là không thể thực hiện được với phương pháp 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

Các bạn cho mình hỏi: Có cách nào để xác định 1 textstyle đang sử dụng 1 font shx dùng loại bảng mã gì không? (TCVN, Unicode, VNi)?

Mình dùng nó cho ứng dụng tự động thay đổi bảng mã cho bộ gõ Unikey khi chỉnh sửa hay viết 1 text trong cad.

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: Đoạn code trên (lấy lệnh cuối cùng bạn viết lại cho mình í) vẫn chưa sử dụng được Ketxu ạ. Với lệnh thuần cad hoặc thuần lisp thì chạy rất tốt, nhưng với lệnh lisp chứa command thì nó vẫn lấy command bên trong chứ không lấy lệnh lisp. Sau mấy ngày đánh vật với nó thì mình cũng chịu thua rùi. Có lẽ là không thể thực hiện được với phương pháp này.

Cần viết thêm hàm callback cho sự kiện :vlr-lispEnded

Sự kiện :vlr-lispWillStart : lấy lệnh Lisp + stop hàm callback thu thập lệnh CAD .

Sự kiện :vlr-lispEnded : khởi động lại hàm callback thu thập lệnh CAD.

 

Tham khảo :

(setq ThuyLinh313 t)
(defun Stop_ST-Get-Cad-Command(objReactor lstOfCommand)
 (setq ThuyLinh313 nil)
 (setq #lstCmds (reverse (cons (car lstOfCommand) (reverse #lstCmds)))))
(defun Start_ST-Get-Cad-Command(objReactor lstOfCommand)
 (setq ThuyLinh313 t)  )
(defun ST-Get-Cad-Command(objReactor lstOfCommand)
 (if ThuyLinh313
(setq #lstCmds (reverse (cons (car lstOfCommand) (reverse #lstCmds))))))
(or #CmdList1
(setq #CmdList1 (vlr-editor-reactor nil '(
(:vlr-lispWillStart . Stop_ST-Get-Cad-Command)
(:vlr-lispEnded . Start_ST-Get-Cad-Command)          
;(:vlr-unknownCommand . ST-Get-List-Command)
(:vlr-commandWillStart . ST-Get-Cad-Command) ))))
(defun lastCmd()(last #lstCmds))

  • 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

@avi626 & DVH: Bạn không thể entmake hoặc entmod với đối tượng Viewport.

@Ketxu: Đoạn code trên (lấy lệnh cuối cùng bạn viết lại cho mình í) vẫn chưa sử dụng được Ketxu ạ. Với lệnh thuần cad hoặc thuần lisp thì chạy rất tốt, nhưng với lệnh lisp chứa command thì nó vẫn lấy command bên trong chứ không lấy lệnh lisp. Sau mấy ngày đánh vật với nó thì mình cũng chịu thua rùi. Có lẽ là không thể thực hiện được với phương pháp này.

Xin lỗi TL, lúc code mình mới chỉ gộp lại thôi, quên béng là có mấy cái phản hồi.

Khi lisp start thì nhận được ngay tên lisp, nhưng lúc này cái reactor lệnh CAD nó vẫn còn, nên nó bắt luôn cả hàng bên trong. Vậy tốt nhất TL dừng reactor lệnh CAD khi lisp willstart, lisp end thì trả lại

 

P/s : ẩu quá, bác Gia_bach đã thịt nó 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

Cần viết thêm hàm callback cho sự kiện :vlr-lispEnded

Sự kiện :vlr-lispWillStart : lấy lệnh Lisp + stop hàm callback thu thập lệnh CAD .

Sự kiện :vlr-lispEnded : khởi động lại hàm callback thu thập lệnh CAD.

Nghĩ mãi mới hiểu phương pháp của bạn Gia_Bach. Quá hay luôn!! Mình triển khai thử xem đến đâu. Cảm ơn Gia_Bach và Ketxu nhiều 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

Cho mình hỏi chút về vấn đề Shell trong lập trình lisp:

 

Giả sử mình có đoạn code này:

 

(defun c:test ()

 

(command "shell" "D:/run.exe")

 

)

 

Nhiệm vụ của file run.exe là tạo 1 file mới A.txt chẳng hạn (hoặc đơn giản hơn chỉ là chờ gõ enter rồi thoát) . Nhưng trên thực tế chạy lisp có lúc chạy file run.exe kia được có lúc lại không được giống như bị cancel (ví dụ khi tạo file cad mới rồi load lisp trên chạy thì bị lỗi), mình không hiểu lý do là tại sao cả ? Bạn nào có kinh nghiệm chỉ mình với.

 

Xin hỏi thêm nữa là có cách nào chạy file .exe khác cách trên 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

...............

 

Xin hỏi thêm nữa là có cách nào chạy file .exe khác cách trên không ?

(command "ai_editcustfile" "D:/run.exe")

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

×