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ị

Em đang gặp một vấn đề sau.Em đã có 1 đưòng cong bây giờ muốn duỗi nó ra thành đường thẳng nhưng ko đo đưọc chiều dài.Các bác có cái lisp nào đo chiều dài đường cong không giúp em với.Cảm ơn nhiều :bigsmile:

Không cần lisp bạn ạ, lệnh Dim là đủ rồi, cần gõ DAR là đo được chiều dài cung thôi.

Không thì dung lisp tính tổng chiều dài các đối tượng này:

;;;--- ADDLEN.lsp - Total lengths of objects. 
;;;    Polylines, LWPolylines, Splines, Arcs, Circles, Lines, and Ellipse
;;;
;;;
;;;
;;;--- Copyright 2005 by JefferyPSanders.com
;;;    All rights reserved.
;;;
;;;
;;;
;;;--- Created on 11/25/05
;;;


(defun C:ADDLEN()

 (setvar "cmdecho" 0)

 ;;;--- Function to get the length of an ARC entity
 (defun getArc(en)
   (command "lengthen" en "")
   (getvar "perimeter")
 )

 ;;;--- Function to get the length of a LINE entity
 (defun getLine(en)
   (setq enlist(entget en))
   (distance (cdr(assoc 10 enlist)) (cdr(assoc 11 enlist)))
 )

 ;;;--- Function to get the length of a POLY, CIRCLE, SPLINE, OR ELLIPSE
 (defun getPoly(en)
   (command "area" "Object" en)
   (getvar "perimeter")
 )  

 ;;;--- Main application

 ;;;--- Let the user select objects
 (if(setq eset(ssget))
   (progn

     ;;;--- Set up a variable to hold the length
     (setq totalLen 0)

     ;;;--- Set up a counter
     (setq cntr 0)

     ;;;--- Cycle through each entity in the selection set
     (while(< cntr (sslength eset))

       ;;;--- Get the first entity's name
       (setq en(ssname eset cntr))

       ;;;--- Get the DXF group codes
       (setq enlist(entget en))

       ;;;--- Get the type of entity
       (setq enType(cdr(assoc 0 enlist)))

       ;;;--- Get the length based on entity type
       (cond
         ((= enType "ARC"       )(setq len(getArc en)))
         ((= enType "CIRCLE"    )(setq len(getPoly en)))
         ((= enType "ELLIPSE"   )(setq len(getPoly en)))
         ((= enType "LINE"      )(setq len(getLine en)))
         ((= enType "LWPOLYLINE")(setq len(getPoly en)))
         ((= enType "POLYLINE"  )(setq len(getPoly en)))
         ((= enType "SPLINE"    )(setq len(getPoly en)))
         (T (setq len 0.0))
       )

       ;;;--- Format the entity type to be 12 characters long
       (while(< (strlen enType) 12)(setq enType(strcat enType " ")))

       ;;;--- Inform the user of progress
       (princ "\n Found ")
       (princ enType)
       (princ " with a length of: ")
       (princ (rtos len))

       ;;;--- Total the length
       (setq totalLen(+ totalLen len))


       ;;;--- Increment the counter to get the next entity
       (setq cntr (+ cntr 1))
     )
   )
 )

 (setvar "cmdecho" 1)

 ;;;--- Inform the user of the results
 (alert (strcat "\n Found " (itoa cntr) " entitie(s) with a Total Length of " (rtos totalLen)))

 ;;;--- Suppress the last echo for a clean exit
 (princ)
)

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,mình có sử dụng 1 vài lisp nhưng đôi khi lúc đầu sử dụng lisp bình thường nhưng sau 1 hồi thì không sử dụng được nữa.Mình phải tắt cad đi rồi mở lại mới sử dụng được.Mong các bạn chỉ cho mình cách khắc phục.Thanks

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ó rất nhiều trường hợp, thường là các lisp sẽ có các biến trùng tên nhau (các ý tưởng nhớn thường gặp nhau mà :cheers: ) ví dụ ta thấy các biến như a1, t1, k1 thường đươc dùng để đặt tên biến rất nhiều... các biến này trong mỗi lisp sẽ được gán các kiểu dữ liệu khác nhau (string, byte...) và có các giá trị khác nhau, nếu trong quá trình lập trình người viết Lisp không chú ý đến điều này để đưa các biến về giá trị nil thì khi bạn sử dụng nhiều lisp trong 1 bản vẽ, các biến này vẫn giữ giá trị, khi chạy các lisp khác nó lại được gán giá trị khác và khi bạn chạy lại lisp của nó nó sẽ đơ luôn vì nó đã mang một kiểu dữ liệu khác, bạn phải tắt bản vẽ để laoij bỏ giá trị của các biến này.

vd trong lisp 1, k1 được gán là kiểu byte nhưng ở lisp 2 nó lại là kiểu string, vậy đó.

Để khắc phục lỗi này bạn phải vô lisp đó xem thôi.

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,mình có sử dụng 1 vài lisp nhưng đôi khi lúc đầu sử dụng lisp bình thường nhưng sau 1 hồi thì không sử dụng được nữa.Mình phải tắt cad đi rồi mở lại mới sử dụng được.Mong các bạn chỉ cho mình cách khắc phục.Thanks

Có thể trường hợp của bạn như ý kiến của bạn kienxdhp trình bày.

Bạn hãy giải phóng các biến trong các Lisp đó sau khi chạy Lisp xong

Ví dụ :

(Defun c:ab(/ a b c)

.....

thì a b c là các biến sẽ được giải phóng, sau khi chạy Lisp nó không còn nhận giá trị 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

Em biết lệnh (entlast) trả về ename của đổi tượng được tạo ra cuối cùng trong 1 bản vẽ, Vậy đối tượng đầu tiên được tạo ra trong bản vẽ mình làm thế nào để có ename của nó ?

Em nghĩ nếu ta (command "erase" (entlast) "") cho đến khi còn 1 đối tượng thì có thể biết kết quả, nhưng mà như vậy thì bản vẽ bị xóa mất hết rồi.

Hi vọng các anh không thấy em dở hơi khi hỏi vấn đề 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
Em biết lệnh (entlast) trả về ename của đổi tượng được tạo ra cuối cùng trong 1 bản vẽ, Vậy đối tượng đầu tiên được tạo ra trong bản vẽ mình làm thế nào để có ename của nó ?

Em nghĩ nếu ta (command "erase" (entlast) "") cho đến khi còn 1 đối tượng thì có thể biết kết quả, nhưng mà như vậy thì bản vẽ bị xóa mất hết rồi.

Hi vọng các anh không thấy em dở hơi khi hỏi vấn đề này!

Hàm Entnext bạn ạ. Nó trả về ename của đối tượng đầu tiên.

  • 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ác bác cho Tue_NV hỏi 1 câu ạ :

Tue_NV tìm đọc trong Help thấy không có mã DXF quy định Block "động" (Block Authoring)

Mình chỉ thấy Block thuộc tính được quy định bằng mã Dxf=66 mà thôi,

Các bác cho Tue_NV hỏi có mã DXF quy định Block "động" (Block Authoring) này không ạ?

Mình tìm đọc trong Help hoài mà không thấy nó ở đâu??

Cảm ơn các 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
Em biết lệnh (entlast) trả về ename của đổi tượng được tạo ra cuối cùng trong 1 bản vẽ, Vậy đối tượng đầu tiên được tạo ra trong bản vẽ mình làm thế nào để có ename của nó ?

Em nghĩ nếu ta (command "erase" (entlast) "") cho đến khi còn 1 đối tượng thì có thể biết kết quả, nhưng mà như vậy thì bản vẽ bị xóa mất hết rồi.

Hi vọng các anh không thấy em dở hơi khi hỏi vấn đề này!

Cháu thử xem:

(defun c:Ent_Dau()

(setq i 0 ss (ssget "X") dsten '() ecuoi (entlast)

ntt (sslength ss) dskq (list ecuoi) lan 0

)

(repeat (sslength ss)

(setq ent (ssname ss i)

dsloai (entget ent)

ten (cdr (assoc -1 dsloai))

dsten (append dsten (list ten))

i (+ i 1)

)

(If (equal ent ecuoi)(setq dsvt (list i)))

(print (list ten (cdr (assoc 0 dsloai))))

)

(While (< (length dskq) ntt)

(Progn

(setq i 0 lan (1+ lan))

(repeat ntt

(setq ent1 (nth i dsten)

ent2 (entnext ent1)

i (1+ i)

)

(If (equal ent2 ecuoi)(setq ecuoi ent1 dskq (append dskq (list ecuoi)) dsvt (append dsvt (list i))))

)

)

)

(print dsten) ;la danh sach ten chua sap xep

(print dsvt) ;la danh sach vi tri da xep tuong ung trong dsten

(print dskq);la danh sach ten da sap xep

)

 

;Lệnh là ent_dau

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àm Entnext bạn ạ. Nó trả về ename của đối tượng đầu tiên.

- Đơn giản vậy mà em không biết. Chỉ quen dùng entnext có đối số mà không biết. Cảm ơn anh nhiều.

- Cho em hỏi thêm vấn đề nữa em có ename 2 đối tượng, làm sao biết đối tượng nào được tạo ra 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
- Đơn giản vậy mà em không biết. Chỉ quen dùng entnext có đối số mà không biết. Cảm ơn anh nhiều.

- Cho em hỏi thêm vấn đề nữa em có ename 2 đối tượng, làm sao biết đối tượng nào được tạo ra trước?

Dựa vào mã DXF=5

Thứ tự ABC trong mã. Anh nào xếp trước thì được tạo ra trước

  • Vote tăng 3

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 Tue_NV hỏi 1 câu ạ :

Tue_NV tìm đọc trong Help thấy không có mã DXF quy định Block "động" (Block Authoring)

Mình chỉ thấy Block thuộc tính được quy định bằng mã Dxf=66 mà thôi,

Các bác cho Tue_NV hỏi có mã DXF quy định Block "động" (Block Authoring) này không ạ?

Mình tìm đọc trong Help hoài mà không thấy nó ở đâu??

Cảm ơn các bác nhiều.

hì hì hỏi bác câu hơi ngốc chút mình mới biết block thuộc tính chưa biết block động. Bạn có thể upload một block động cho mình tham khảo được không? Cảm ơn bạn 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
hì hì hỏi bác câu hơi ngốc chút mình mới biết block thuộc tính chưa biết block động. Bạn có thể upload một block động cho mình tham khảo được không? Cảm ơn bạn nhiều.

Bác thử cái này: block author

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 Tue_NV hỏi 1 câu ạ :

Tue_NV tìm đọc trong Help thấy không có mã DXF quy định Block "động" (Block Authoring)

Mình chỉ thấy Block thuộc tính được quy định bằng mã Dxf=66 mà thôi,

Các bác cho Tue_NV hỏi có mã DXF quy định Block "động" (Block Authoring) này không ạ?

Mình tìm đọc trong Help hoài mà không thấy nó ở đâu??

Cảm ơn các bác nhiều.

Anh cũng chưa biết có mã DXF nào quy định Block "động" hay không ?

Tue_NV có thể dùng VLisp để tìm tên của Block "động" :

(defun DinamicBlkName (ent / obj)
 (setq obj (vlax-ename->vla-object ent) )
 (if (and
(= (vla-get-ObjectName Obj) "AcDbBlockReference")
(vlax-property-available-p obj 'EffectiveName) )
   (vlax-get-property obj 'EffectiveName)))

vd :

(defun c:Test (/ Sel ten)
 (if
   (and
     (setq Sel (entsel "\n Select block : "))
     (setq ten (DinamicBlkName (car Sel))) )
    (princ (strcat "\nBlk name : " ten))
   (princ "\nKhong phai Dinamic block.")  )
 (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
Anh cũng chưa biết có mã DXF nào quy định Block "động" hay không ?

Tue_NV có thể dùng VLisp để tìm tên của Block "động" :

(defun DinamicBlkName (ent / obj)
 (setq obj (vlax-ename->vla-object ent) )
 (if (and
(= (vla-get-ObjectName Obj) "AcDbBlockReference")
(vlax-property-available-p obj 'EffectiveName) )
   (vlax-get-property obj 'EffectiveName)))

Cảm ơn anh giabach đã hồi âm.

Chắc anh đã nhầm rồi. Bất kì Block nào cũng có EffectiveName của nó

Về Block động này thì em cũng đã biết cách kiểm tra => dựa vào Prop (IsDynamicBlock) của Block đó

Em chỉ muốn tìm mã DXF của Block động này để xử lý với tập chọn (ssget) được nhanh hơn, khỏi phải kiểm tra

Em cảm ơn anh

  • 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
Cảm ơn anh giabach đã hồi âm.

Chắc anh đã nhầm rồi. Bất kì Block nào cũng có EffectiveName của nó

Về Block động này thì em cũng đã biết cách kiểm tra => dựa vào Prop (IsDynamicBlock) của Block đó

Em chỉ muốn tìm mã DXF của Block động này để xử lý với tập chọn (ssget) được nhanh hơn, khỏi phải kiểm tra

Em cảm ơn anh

Ừ nhỉ, anh nhầm sang vấn đề khác (block anonymous).

Hình như Cad không cung cấp mã DXF cho DynamicBlock ?

(chỉ còn cách dựa vào Prop (IsDynamicBlock) như Tue_NV đã biết)

  • 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
Dựa vào mã DXF=5

Thứ tự ABC trong mã. Anh nào xếp trước thì được tạo ra trước

 

- Cảm ơn anh đã trả lời.

Em lại hỏi 1 câu nữa. Hàm (entnext [ename]) lấy đối tượng tạo ra kề sau đối tượng ename, vậy muốn tìm đối tượng kề trước thì lấy như thế nào.

Em cảm ơ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
Ừ nhỉ, anh nhầm sang vấn đề khác (block anonymous).

Hình như Cad không cung cấp mã DXF cho DynamicBlock ?

(chỉ còn cách dựa vào Prop (IsDynamicBlock) như Tue_NV đã biết)

Không có gì anh ạ, chỉ sợ nhất là đi nhầm... ngõ ...thôi

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 anh đã trả lời.

Em lại hỏi 1 câu nữa. Hàm (entnext [ename]) lấy đối tượng tạo ra kề sau đối tượng ename, vậy muốn tìm đối tượng kề trước thì lấy như thế nào.

Em cảm ơn.

Không có sẵn, bạn phải tự làm. Trước hết, cần hiểu về DXF 5 và hàm handent:

 

1- DXF 5 như Tue_NV đề cập gọi là handle của entity. Nó là một string biểu diễn số hexadecimal (hệ đếm 16). Entity tạo ra sau luôn luôn có handle lớn hơn handle của entity kề trước nó đúng bằng 1 đơn vị.

2- Hàm (handent [handle]) return entity có DXF 5 là "handle" (lưu ý nó là 1 string)

 

Xem ví dụ sau:

Command: (setq e (car (entsel)))
Select object: 

Command: (setq d (entget e))
((-1 . ) (0 . "LINE") (330 . ) (5 
. "C2") (100 . "AcDbEntity") (67 . 0) (410 . "Model") (8 . "0") (100 . 
"AcDbLine") (10 31.5048 15.8687 0.0) (11 18.92 22.1138 0.0) (210 0.0 0.0 1.0))

Command: (handent "c2")

Kết quả trả về đúng là e ở trên (có số "CMND" là 7ef91090)

 

Gợi ý cách làm:

1- Lấy handle của entity e đang xét. Ví dụ là "C2"

2- Tự xây dựng hàm số học để cộng trừ số hexadecimal. Dùng nó để trừ handle nhận được ở trên 1 đơn vị, kết quả bạn nhận được là "C1".

3- (handent "C1") là entity cần tìm

  • Vote tăng 5

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 anh đã trả lời.

Em lại hỏi 1 câu nữa. Hàm (entnext [ename]) lấy đối tượng tạo ra kề sau đối tượng ename, vậy muốn tìm đối tượng kề trước thì lấy như thế nào.

Em cảm ơn.

Cách làm thì bác ssg đã gợi ý. Và bạn có thể tìm đọc hệ thập lục phân (hexadecimal) ở trang wikipedia :

http://vi.wikipedia.org/wiki/H%E1%BB%87_th...B%A5c_ph%C3%A2n

Tue_NV mới viết xong Lisp đổi hệ thập lục phân sang hệ thập phân.

Các bạn test thử

(defun c:hex->dec(/ lis_hex lis_dec hex L kt S i j)
 (setq lis_hex '("0" "1" "2" "3" "4" "5" "6" "7" "8" "9" "A" "B" "C" "D" "E" "F"))
 (setq lis_dec '("0" "1" "2" "3" "4" "5" "6" "7" "8" "9" "10" "11" "12" "13" "14" "15"))
 (setq hex (strcase (getstring "\n Cho chuoi hexadecimal : ")))
 (setq L (strlen hex) i L j 0 S 0)
 (Repeat L
(setq kt (atoi (nth (vl-position (substr hex i 1) lis_hex) lis_dec)))
(setq S (+ S (* (expt 16 j ) kt)))
(setq i (1- i))
(setq j (1+ j))
)
 (alert (strcat "Chuoi hexadecimal : " hex " doi sang decimal : " (itoa S)))
)

Chỉnh sửa theo Tue_NV
  • Vote tăng 5

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 làm thì bác ssg đã gợi ý. Và bạn có thể tìm đọc hệ thập lục phân (hexadecimal) ở trang wikipedia :

http://vi.wikipedia.org/wiki/H%E1%BB%87_th...B%A5c_ph%C3%A2n

Tue_NV mới viết xong Lisp đổi hệ thập lục phân sang hệ thập phân.

Các bạn test thử

 

Cảm ơn anh Tue_NV nhiều nhiều. Em đã đọc tài liệu bổ ích của anh Và cũng tập tò sửa cái lisp của anh thành cái chuyễn decimal sang hexadecimal. Không biết có lượm thượm quá không?

(defun c:10t16( / lis_hex lis_dec dec hex L dec1 i kt)
 (setq lis_hex '("0" "1" "2" "3" "4" "5" "6" "7" "8" "9" "A" "B" "C" "D" "E" "F"))
 (setq lis_dec '("0" "1" "2" "3" "4" "5" "6" "7" "8" "9" "10" "11" "12" "13" "14" "15"))
 (setq dec (fix (getreal "\n Cho so decimal : ")))
 (setq hex (strcat)) 
 (setq L (1+ (fix (/ (log dec) (log 16))))  i (1- L) dec1 dec)
 (Repeat L
        (setq kt (nth (vl-position (itoa (fix (/ dec1 (expt 16 i)))) lis_dec) lis_hex))
        (setq hex (strcat hex kt))
        (setq dec1 (- dec1 (* (expt 16 i ) (fix (/ dec1 (expt 16 i))))))
        (setq i (1- i))
)
 (alert (strcat "Chuoi decimal " (itoa dec) " doi sang  hexadecimal : " hex))
)

 

Nếu được anh góp ý chỉ các chổ không cần thiết thì tốt quá. 1 lần nữa cảm ơn anh 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
Không có sẵn, bạn phải tự làm. Trước hết, cần hiểu về DXF 5 và hàm handent:

 

1- DXF 5 như Tue_NV đề cập gọi là handle của entity. Nó là một string biểu diễn số hexadecimal (hệ đếm 16). Entity tạo ra sau luôn luôn có handle lớn hơn handle của entity kề trước nó đúng bằng 1 đơn vị.

2- Hàm (handent [handle]) return entity có DXF 5 là "handle" (lưu ý nó là 1 string)

 

Gợi ý cách làm:

1- Lấy handle của entity e đang xét. Ví dụ là "C2"

2- Tự xây dựng hàm số học để cộng trừ số hexadecimal. Dùng nó để trừ handle nhận được ở trên 1 đơn vị, kết quả bạn nhận được là "C1".

3- (handent "C1") là entity cần tìm

 

Theo hướng dẫn của anh ssg cộng với ý tưởng trong lisp anh Tue_NV, em tự trả lời câu hỏi của mình với lisp sau.

(defun maklis ()
  (setq lis_hex '("0" "1" "2" "3" "4" "5" "6" "7" "8" "9" "A" "B" "C" "D" "E" "F"))
  (setq lis_dec '("0" "1" "2" "3" "4" "5" "6" "7" "8" "9" "10" "11" "12" "13" "14" "15"))
)
(defun DXF (code e) (cdr (assoc code (entget e))))
(defun 16t10 (hex / lis_hex lis_dec L kt S i j)
 (maklis)
  (setq L (strlen hex) i L j 0 S 0)
  (Repeat L
    (setq kt (atoi (nth (vl-position (substr hex i 1) lis_hex) lis_dec)))
    (setq S (+ S (* (expt 16 j ) kt)))
    (setq i (1- i))
    (setq j (1+ j))
)
  (itoa S)
)
(defun 10t16 (dec / lis_hex lis_dec hex L dec1 i kt)
 (maklis)
  (setq dec (fix dec))
  (setq hex (strcat)) 
  (setq L (1+ (fix (/ (log dec) (log 16))))  i (1- L) dec1 dec)
  (Repeat L
    (setq kt (nth (vl-position (itoa (fix (/ dec1 (expt 16 i)))) lis_dec) lis_hex))
(setq hex (strcat hex kt))
    (setq dec1 (- dec1 (* (expt 16 i ) (fix (/ dec1 (expt 16 i))))))
    (setq i (1- i))
)
  hex
)
(defun entbef (ena / ena2 han1)
 (setq han1 (dxf 5 ena))
 (setq ena2 (handent (10t16 (- (atof (16t10 han1)) 1))))
)
(defun C:test ()
 (setq ena1 (car (entsel "\nChon doi tuong ban muon lay ename cua doi tuong ke truoc")))
 (setq ena_bef (entbef ena1))
 (command "erase" ena_bef "")
)

Bước 2- "Tự xây dựng hàm số học để cộng trừ số hexadecimal. Dùng nó để trừ handle nhận được ở trên 1 đơn vị, kết quả bạn nhận được là "C1"." của anh em không làm trực tiếp bên hexadecimal được. Anh có thể viết hàm cộng trừ trực tiếp trên hệ hexadecimal không? Em làm như vậy thì dài dòng và không đúng hướng dẫn của anh thi phải.

Cảm ơn sự nhiệt tình của các anh. Rất vui được 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
Theo hướng dẫn của anh ssg cộng với ý tưởng trong lisp anh Tue_NV, em tự trả lời câu hỏi của mình với lisp sau.

(defun maklis ()
  (setq lis_hex '("0" "1" "2" "3" "4" "5" "6" "7" "8" "9" "A" "B" "C" "D" "E" "F"))
  (setq lis_dec '("0" "1" "2" "3" "4" "5" "6" "7" "8" "9" "10" "11" "12" "13" "14" "15"))
)
(defun DXF (code e) (cdr (assoc code (entget e))))
(defun 16t10 (hex / lis_hex lis_dec L kt S i j)
 (maklis)
  (setq L (strlen hex) i L j 0 S 0)
  (Repeat L
    (setq kt (atoi (nth (vl-position (substr hex i 1) lis_hex) lis_dec)))
    (setq S (+ S (* (expt 16 j ) kt)))
    (setq i (1- i))
    (setq j (1+ j))
)
  (itoa S)
)
(defun 10t16 (dec / lis_hex lis_dec hex L dec1 i kt)
 (maklis)
  (setq dec (fix dec))
  (setq hex (strcat)) 
  (setq L (1+ (fix (/ (log dec) (log 16))))  i (1- L) dec1 dec)
  (Repeat L
    (setq kt (nth (vl-position (itoa (fix (/ dec1 (expt 16 i)))) lis_dec) lis_hex))
(setq hex (strcat hex kt))
    (setq dec1 (- dec1 (* (expt 16 i ) (fix (/ dec1 (expt 16 i))))))
    (setq i (1- i))
)
  hex
)
(defun entbef (ena / ena2 han1)
 (setq han1 (dxf 5 ena))
 (setq ena2 (handent (10t16 (- (atof (16t10 han1)) 1))))
)
(defun C:test ()
 (setq ena1 (car (entsel "\nChon doi tuong ban muon lay ename cua doi tuong ke truoc")))
 (setq ena_bef (entbef ena1))
 (command "erase" ena_bef "")
)

Bước 2- "Tự xây dựng hàm số học để cộng trừ số hexadecimal. Dùng nó để trừ handle nhận được ở trên 1 đơn vị, kết quả bạn nhận được là "C1"." của anh em không làm trực tiếp bên hexadecimal được. Anh có thể viết hàm cộng trừ trực tiếp trên hệ hexadecimal không? Em làm như vậy thì dài dòng và không đúng hướng dẫn của anh thi phải.

Cảm ơn sự nhiệt tình của các anh. Rất vui được học hỏi!

Bạn có thể làm như sau :

1. Chuyển số thập lục phân sang hệ thập phân decimal

2. Cộng trừ số trong hệ thập phân decimal

3. Kết quả thu đuợc là hệ decimal -> chuyển sang hệ hexa

Tue_NV đang bận công việc. Hẹn gặp bạn sau. Ý tưởng là như 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
Bạn có thể làm như sau :

1. Chuyển số thập lục phân sang hệ thập phân decimal

2. Cộng trừ số trong hệ thập phân decimal

3. Kết quả thu đuợc là hệ decimal -> chuyển sang hệ hexa

Tue_NV đang bận công việc. Hẹn gặp bạn sau. Ý tưởng là như vậy

 

Cảm ơn anh Tue_NV. Hình như anh chưa đọc nội dung lisp em post. Vì lisp em post hoàn toàn giống ý tưởng anh vừa nêu.

Lấy mã dxf 5 của ename bằng hàm con dxf, chuyển sang hệ thập phân bằng hàm con 16t10 (chính là hàm hex->dec của anh, em edit tên cho dễ dùng), cộng trừ bên hệ thập phân rồi lấy kết quả chuyển sang lại hệ thập lục bằng hàm con 10t16.

Lấy ename của đối handle mới bằng hàm handent

 

Em thấy anh ssg hướng dẫn là "Tự xây dựng hàm số học để cộng trừ số hexadecimal", em nghĩ có lẽ có cách cộng trừ trực tiếp bên hệ thập lục chứ không cần chuyển qua thập phân cộng trừ xong lại phải chuyển sang lại thập lục phâ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
Em thấy anh ssg hướng dẫn là "Tự xây dựng hàm số học để cộng trừ số hexadecimal", em nghĩ có lẽ có cách cộng trừ trực tiếp bên hệ thập lục chứ không cần chuyển qua thập phân cộng trừ xong lại phải chuyển sang lại thập lục phân.

1- Lisp không có sẵn các hàm thao tác với hệ hexadecimal, nếu có nhu cầu phải tự xây dựng lấy.

Nếu chỉ giới hạn ở việc chọn entbef (mình thích từ "entback" hơn vì nó opposite với "entnext" hơn) thì trình tự như bạn đã làm là OK rồi. Tuy nhiên, đã tốn công sức vào đó thì nên xây dựng luôn các hàm thao tác với hexadecimal để có cái mà dùng khi cần đến sau này nên mình mới gợi ý như vậy. Cách làm tuỳ mỗi người, thoả sức mà sáng tạo!

 

2- Góp ý: hàm 16t10 của bạn cho return dạng integer thì hợp lý hơn

 

3- Trong help có một đoạn code cực hay, convert số decimal sang cơ số khác bất kỳ: nhị, bát, thập lục (thậm chí tam, tứ, ngũ... phân gì đó cũng được tuốt!). Bạn thấy hứng thú thì ngâm cứu và phát triển tiếp theo chiều ngược lại:

; BASE converts from a decimal integer to a string in another base.
(defun BASE ( bas int / ret yyy zot )
 (defun zot ( i1 i2 / xxx )
   (if (> (setq xxx (rem i2 i1)) 9)
     (chr (+ 55 xxx))
     (itoa xxx)
   )      
 )
 (setq ret (zot bas int) yyy (/ int bas))
 (while (>= yyy bas)
   (setq ret (strcat (zot bas yyy) ret))
   (setq yyy (/ yyy bas))
 )
 (strcat (zot bas yyy) ret)
)

 

Vài ví dụ ssg đã chạy thử (thập lục, nhị và... tam phân!)

 

Command: (base 16 27)

"1B"

 

Command: (base 2 7)

"111"

 

Command: (base 3 7)

"21"

  • 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

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


×