Ứng dụng REACTOR trong quản lý bản vẽ theo layer.
Trong truờng hợp quản lý bản vẽ theo layer, thông thuờng các đối tuợng khác nhau sẽ thuộc các layer khác nhau (có ngoại lệ).
VD : đối tuợng LINE thuộc layer “LINE”, đối tuợng Text thuộc layer “TEXT”, đối tuợng Dimension (kích thuớc) thuộc layer “DIMENSION”, ...
Cách vẽ thông thuờng là :
1. vẽ đối tuợng truớc, sau đó mới tạo layer rồi chuyển đối tuợng qua layer đó.
2. cách thứ 2 là tạo hàng loạt layer theo qui định, sau đó truớc khi vẽ đối tuợng sẽ set layer tuơng ứng về hiện hành. Vd : vẽ đối tuợng LINE thì set layer “LINE” về hiện hành.
Cách vẽ thứ 1 có lợi điểm là không cần quan tâm đến layer hiện hành, sau khi hoàn thành có thể sử dụng lệnh FILTER hay LISP để lọc các kiểu đối tuợng rồi chuyển qua layer tuơng ứng.
Cách vẽ thứ 2 có vẻ rắc rối hơn vì mỗi lần vào lệnh CAD lại phải thay đổi layer tuơng ứng về hiện hành.
Do đó phát sinh nhu cầu : làm thế nào để mỗi khi tạo đối tuợng mới, CAD “hiểu đuợc” chúng ta muốn đặt đối tuợng đó vào Layer tuơng ứng? (không cần thiết phải qua buớc set layer)
Truớc đây tôi có viết 1 lisp sử dụng biến hệ thống "CMDACTIVE", nhưng quả thật trong các t/hợp các lệnh có liên quan đến hộp thoại “vấn đề chưa đuợc giải quyết rốt ráo”.
Link tham khảo
Rất may là các lệnh REACTOR (hàm VLR-***) có cung cấp cho chúng ta cách giải quyết vấn đề.
Các bạn có thể tham khảo thêm trong “tàng kinh” của VisualLisp.
Cụ thể là : (vlr-command-reactor data callbacks) cho phép xây dựng các hành động tuơng ứng với các khả năng có thể xảy ra (tạm gọi là sự kiện) khi gọi 1 lệnh CAD.
Một vài sự kiện khi gọi 1 lệnh CAD :
- sự kiện bắt đầu gọi lệnh : :vlr-commandWillStart
- sự kiện khi lệnh kết thúc: :vlr-commandEnded
- sự kiện hủy bỏ lệnh : :vlr-commandCancelled
Như vậy đối với truờng hợp muốn Cad “hiểu đuợc” Layer tuơng ứng với mỗi lệnh, chúng ta phải xây dựng các hàm :
- đáp ứng sự kiện bắt đầu gọi lệnh ":vlr-commandWillStart”
- đáp ứng sự kiện khi lệnh kết thúc “:vlr-commandEnded”
- đáp ứng sự kiện khi hủy bỏ lệnh “:vlr-commandEnded”
- tạo 1 danh sách các lệnh và layer tưong úng .
VD: khi gọi lệnh LINE, CAD sẽ kiểm tra xem layer hiện hành có phải là “LINE” không ?
- Nếu đúng → kết thúc
- Nếu sai → chuyển layer “LINE” về hiện hành (nếu chưa có : tao mới layer)
Tuơng tự cho các sự kiện khi kết thúc lệnh LINE hay sự kiện khi hủy bỏ lệnh (nguời dùng nhấn phím Cancel)
Chú ý :
- vì mỗi nguời (cty) có qui định về Layer khác nhau nên cần phải có 1 buớc hiệu chỉnh cho phù hợp.
Cụ thể là tìm dòng (setq COMLAYLST (list
(list "DIMANGULAR" "KT-DIM" )
(list "DTEXT" "TEXT" )
….....................
; Add your own command layer lists here....
))
và thay thế hay bổ sung-xóa các cặp danh sách tuơng ứng theo định dạng (list "tênLệnhCadViếtHoa" "tênLayer" ).
VD : thay dòng (list "DTEXT" "TEXT" ) bằng (list "DTEXT" "ChuSo" )
hay thêm (list "LINE" "DuongThang" )
→ (setq COMLAYLST (list
(list "DIMANGULAR" "KT-DIM" )
(list "DTEXT" "ChuSo" ) (list "LINE" "DuongThang" )
))
- để tắt Reactor gọi lệnh Layer_Off, bật Reactor lại gọi lệnh Layer_On
- trong t/hợp Layer tuơng ứng ở tình trạng : Lock, Freeze, Thaw kết quả còn bị lỗi. <_<
Duới đây là toàn bộ code của Ứng dụng REACTOR trong quản lý bản vẽ theo layer.
(vl-load-com)
(defun StartCommand (CALL CALLBACK / COMLAYLST)
(setq COMLAYLST (list
(list "DIMANGULAR" "KT-DIM" )
(list "DIMALIGNED" "KT-DIM" )
(list "DIMBASELINE" "KT-DIM" )
(list "DIMCENTER" "KT-DIM" )
(list "DIMCONTINUE" "KT-DIM" )
(list "DIMDIAMETER" "KT-DIM")
(list "DIMLINEAR" "KT-DIM")
(list "DIMRADIUS" "KT-DIM" )
(list "QDIM" "KT-DIM" )
(list "LEADER" "KT-DIM" )
(list "TEXT" "TEXT" )
(list "MTEXT" "TEXT" )
(list "DTEXT" "TEXT" )
; Add your own command layer lists here....
))
(if (setq N (assoc (strcase (car CALLBACK)) COMLAYLST))
(progn
(setq *Currentlayers* (cons (getvar "CLAYER") *Currentlayers*))
(if (setq objLay(make_layers (cadr N) ))
(vla-put-activelayer *DOC* objLay ) ) )
(setq *Currentlayers* (cons nil *Currentlayers*)) )
(princ) )
(defun MAKE_LAYERS (LAY_NAM / LAYOBJ LAYSOBJ )
(or *DOC* (setq *DOC* (vla-get-activedocument (vlax-get-acad-object))))
(setq LAYSOBJ (vla-get-layers *DOC*))
(if (tblobjname "layer" LAY_NAM)
(setq LAYOBJ (vla-item LAYSOBJ LAY_NAM))
(setq LAYOBJ (vl-catch-all-apply 'vla-add (list LAYSOBJ LAY_NAM))) )
(if (vl-catch-all-error-p LAYOBJ)
(not (print (vl-catch-all-error-message LAYOBJ)))
(progn
(if (= (strcase (vla-get-name LAYOBJ)) (strcase (getvar "clayer")))
(setvar "clayer" "0") )
(vla-put-lock LAYOBJ :vlax-false)
(vla-put-layeron LAYOBJ :vlax-true)
(vla-put-freeze LAYOBJ :vlax-false)
LAYOBJ ) ))
(defun endCommand (CALL CALLBACK)
(if *Currentlayers*
(if (car *Currentlayers*)
(progn
(vla-put-lock
(vla-item
(vla-get-layers *DOC*)
(car *Currentlayers*) )
:vlax-false )
(setvar "CLAYER" (car *Currentlayers*)) ) ) )
(setq *Currentlayers* (cdr *Currentlayers*)))
(defun cancelCommand (CALL CALLBACK)
(if *Currentlayers*
(if (car *Currentlayers*)
(progn
(vla-put-lock
(vla-item
(vla-get-layers *DOC*)
(car *Currentlayers*) )
:vlax-false )
(setvar "CLAYER" (car *Currentlayers*)) ) ) )
(setq *Currentlayers* (cdr *Currentlayers*)))
(defun C:Layer_On ()
(and *vlr-CWS (not (vlr-added-p *vlr-CWS)) (vlr-add *vlr-CWS))
(and *vlr-CE (not (vlr-added-p *vlr-CE)) (vlr-add *vlr-CE))
(and *vlr-CC (not (vlr-added-p *vlr-CC)) (vlr-add *vlr-CC))
(or *vlr-CWS
(setq *vlr-CWS (vlr-command-reactor nil '((:vlr-commandwillstart . StartCommand)))))
(or *vlr-CE
(setq *vlr-CE (vlr-command-reactor nil '((:vlr-commandEnded . endCommand)))))
(or *vlr-CC
(setq *vlr-CC (vlr-command-reactor nil '((:vlr-commandCancelled . cancelCommand)))))
(princ "\nLayer Reactor ON")
(princ))
(c:Layer_On)
(defun C:Layer_Off ()
(and *vlr-CWS (vlr-added-p *vlr-CWS) (vlr-remove *vlr-CWS))
(and *vlr-CE (vlr-added-p *vlr-CE) (vlr-remove *vlr-CE))
(and *vlr-CC (vlr-added-p *vlr-CC) (vlr-remove *vlr-CC))
(princ "\nLayer Reactor OFF")
(princ))