Đến nội dung


Hình ảnh
- - - - -

Dùng mảng (array) trong lisp


  • Please log in to reply
5 replies to this topic

#1 ndtnv

ndtnv

    biết lệnh minsert

  • Members
  • PipPipPipPipPipPip
  • 437 Bài viết
Điểm đánh giá: 384 (khá)

Đã gửi 24 September 2008 - 04:44 PM

Dùng safearray trong LISP tiện lợi hơn nhiều so với dùng list
VD khi viết bảng TKCT, nếu dùng biến thường thì mỗi loại thép phải đặt cho 1 tên.
Như vậy, ta khó dùng các vòng lặp để gán và lấy biến. Nếu dùng list thì việc gán trị rất phức tạp.
Giải pháp là dùng safearray .
Sau đây là hướng dẫn dùng safearray dịch từ help của acad
Creates a safearray
(vlax-make-safearray type '(l-bound . u-bound) ['(lbound . u-bound)...)]
1 array có thể có tối đa 16 chiều. Các biến trong array được khởi tạo như sau :
Numbers
0
Strings
Zero-length string.
Booleans
:vlax-false
Object
nil
Variant
Uninitialized (vlax-vbEmpty)
Arguments
type
Kiểu của safearray được định theo các hằng số sau:
vlax-vbInteger (2) Integer
vlax-vbLong (3) Long integer
vlax-vbSingle (4) Single-precision floating-point number
vlax-vbDouble (5) Double-precision floating-point number
vlax-vbString (8) String
vlax-vbObject (9) Object
vlax-vbBoolean (11) Boolean
vlax-vbVariant (12) Variant
Số nguyên trong ngoặc là giá trị các hằng số. Bạn nên dùng các hằng số thay cho các số nguyên vì có thể thay đổi trong các phiên bản khác của AutoCAD.
'(l-bound . ubound)
Chỉ số dưới và trên của 1 chiều.
Return Values
The safearray created.
Examples
Tạo safearray 1 chiều l oại double bắt đầu từ chỉ số 0:
_$ (setq point (vlax-make-safearray vlax-vbDouble '(0 . 3)))
#<safearray...>
Dùng hàm vlax-safearray->list để thể hiện nội dung của safearray như 1 list:
_$ (vlax-safearray->list point)
(0.0 0.0 0.0 0.0)
Kết quả cho thấy mỗi phần tử trong array được khởi tạo là zero.
Tạo safearray 2 chiều l oại string bắt đầu từ chỉ số 1:
_$ (setq matrix (vlax-make-safearray vlax-vbString '(1 . 2) '(1 . 2) ))
#<safearray...>
  • 2

#2 ndtnv

ndtnv

    biết lệnh minsert

  • Members
  • PipPipPipPipPipPip
  • 437 Bài viết
Điểm đánh giá: 384 (khá)

Đã gửi 24 September 2008 - 04:50 PM

Để gán trị dùng các hàm
vlax-safearray-fill
vlax-safearray-put-element
Để lấy trị dùng
vlax-safearray-get-element
1 số hàm khác
vlax-safearray-get-dim
vlax-safearray-get-l-bound
vlax-safearray-get-ul-bound
Cách dùng xem help
  • 0

#3 thiep

thiep

    biết dimbaseline

  • Members
  • PipPipPipPipPip
  • 369 Bài viết
Điểm đánh giá: 260 (khá)

Đã gửi 05 June 2009 - 12:39 PM

Để gán trị dùng các hàm
vlax-safearray-fill
vlax-safearray-put-element ...
Cách dùng xem help

Chào bạn ndtnv, bài viết của bạn đã lâu, nhưng đề tài về safearray không cũ chút nào. Tôi đang học cách tạo 1 safearray từ 1 bảng List, nhưng tôi không hiểu gì về cách khai báo kiểu biến. Tôi đã đọc Help nhưng không rõ, Help viết quá ngắn gọn, và không ví dụ nhiều NDTNV có thể giải thích cho tôi cách khai báo từng kiểu cho từng trường hợp nhé:
0 Uninitialized (vlax-vbEmpty)
1 Contains no valid data (vlax-vbNull)
3 Long integer (vlax-vbLong)
4 Single-precision floating-point number (vlax-vbSingle)
5 Double-precision floating-point number (vlax-vbDouble)
9 Object (vlax-vbObject)
11 Boolean (vlax-vbBoolean)
Tôi có sưu tầm 1 Lisp do NguyenHoanh sưu tầm, gồm các hàm làm việc với Block, trong Lisp đó có Hàm
(defun list->variantArray (ptsList / arraySpace sArray)
(setq arraySpace
(vlax-make-safearray
vlax-vbdouble
(cons 0 (- (length ptsList) 1))
)
)
(setq sArray (vlax-safearray-fill arraySpace ptsList))
(vlax-make-variant sArray)
)
ptsList tôi nghĩ là 1 list của các tọa độ POINT (điểm chèn Block), nhưng khi tôi khai báo 1 list giống như thế thì máy cứ báo lỗi:
error: vlax-safearray-fill failed. Invalid initialization list. # ((390718.0 1.53408e+006 0.0) (390706.0 1.53409e+006 0.0) ....)
Nhờ bạn hướng dẫn giùm nhé. Trân trọng.
  • 0

#4 ndtnv

ndtnv

    biết lệnh minsert

  • Members
  • PipPipPipPipPipPip
  • 437 Bài viết
Điểm đánh giá: 384 (khá)

Đã gửi 08 June 2009 - 04:34 PM

Chào bạn ndtnv, bài viết của bạn đã lâu, nhưng đề tài về safearray không cũ chút nào. Tôi đang học cách tạo 1 safearray từ 1 bảng List, nhưng tôi không hiểu gì về cách khai báo kiểu biến. Tôi đã đọc Help nhưng không rõ, Help viết quá ngắn gọn, và không ví dụ nhiều NDTNV có thể giải thích cho tôi cách khai báo từng kiểu cho từng trường hợp nhé:
0 Uninitialized (vlax-vbEmpty)
1 Contains no valid data (vlax-vbNull)
3 Long integer (vlax-vbLong)
4 Single-precision floating-point number (vlax-vbSingle)
5 Double-precision floating-point number (vlax-vbDouble)
9 Object (vlax-vbObject)
11 Boolean (vlax-vbBoolean)
Tôi có sưu tầm 1 Lisp do NguyenHoanh sưu tầm, gồm các hàm làm việc với Block, trong Lisp đó có Hàm
(defun list->variantArray (ptsList / arraySpace sArray)
(setq arraySpace
(vlax-make-safearray
vlax-vbdouble
(cons 0 (- (length ptsList) 1))
)
)
(setq sArray (vlax-safearray-fill arraySpace ptsList))
(vlax-make-variant sArray)
)
ptsList tôi nghĩ là 1 list của các tọa độ POINT (điểm chèn Block), nhưng khi tôi khai báo 1 list giống như thế thì máy cứ báo lỗi:
error: vlax-safearray-fill failed. Invalid initialization list. # ((390718.0 1.53408e+006 0.0) (390706.0 1.53409e+006 0.0) ....)
Nhờ bạn hướng dẫn giùm nhé. Trân trọng.

Lisp của bạn dùng chưa đúng cách nên có lỗi. Bạn phải post lên toàn bộ thì mới kiểm được.

Các kiểu biến:
vlax-vbInteger (2) Integer , trị khởi tạo = 0
- Số nguyên có độ dài 2 bytes, có giá trị –32,768 to +32,767
vlax-vbLong (3) Long integer , trị khởi tạo = 0
- Số nguyên có độ dài 4 bytes, có giá trị –2147483648 to +2147483647
vlax-vbSingle (4) Single-precision floating-point number , trị khởi tạo = 0.0
- Số thực chính xác đơn có độ dài 4 bytes
vlax-vbDouble (5) Double-precision floating-point number , trị khởi tạo = 0.0
- Số thực chính xác kép có độ dài 8 bytes
lax-vbString (8) String , trị khởi tạo = ""
- Kiểu chuỗi
9 Object (vlax-vbObject)
- Kiểu đối tượng
11 Boolean (vlax-vbBoolean)
- Kiểu Boolean gồm 2 giá trị là: nil và T
vlax-vbVariant (12) Variant , trị khởi tạo =
- Kiểu Variant
Vậy tùy theo mảng của bạn chứa kiểu nào, bạn khai báo kiểu tương ứng là số hay hằng.
VD (trong help) tạo 1 mảng double 3 phần tử ta có 2 cách khai báo:
(setq sa (vlax-make-safearray 5 '(0 . 2)))
hoặc là
(setq sa(vlax-make-safearray vlax-vbDouble '(0 . 2)))
Nếu bạn quen dùng chỉ số từ 1 thì có thể khai báo
(setq sa (vlax-make-safearray vlax-vbDouble '(1 . 3)))

Bạn nên dùng các VD trong help, đổi khai báo kiểu rồi chạy thử thì sẽ nắm vững hơn

Trong lisp trên, câu lệnh:
(setq arraySpace (vlax-make-safearray vlax-vbdouble (cons 0 (- (length ptsList) 1)) ) )
sẽ tạo 1 safearray có tên là arraySpace, kiểu double, số phần tử = số phần tử của ptsList
ptsList là 1 list có các phần tử kiểu double
Câu lệnh:
(setq sArray (vlax-safearray-fill arraySpace ptsList))
sẽ fill các phần tử của ptsList vào mảng arraySpace , sau đó gán cho sArray
  • 2

#5 thiep

thiep

    biết dimbaseline

  • Members
  • PipPipPipPipPip
  • 369 Bài viết
Điểm đánh giá: 260 (khá)

Đã gửi 08 June 2009 - 05:17 PM

Lisp của bạn dùng chưa đúng cách nên có lỗi. Bạn phải post lên toàn bộ thì mới kiểm được.

...
ptsList là 1 list có các phần tử kiểu double
Câu lệnh:
(setq sArray (vlax-safearray-fill arraySpace ptsList))
sẽ fill các phần tử của ptsList vào mảng arraySpace , sau đó gán cho sArray

Ndtnv thân,
Đọc xong, tôi đã hiểu được 1 phần nào cái sArray này. Xin hỏi thêm:
Giả sử ptsList của tôi là 1 list 6 phần tử chứa tọa độ và tên của các text, đơn giản như sau:
(((1.0 1.0 0.0) "A") ((1.0 2.0 0.0) "B") ((1.0 3.0 0.0) "C")) ((2.0 1.0 0.0) "D") ((2.0 2.0 0.0) "E") ((2.0 3.0 0.0) "F")))
trong trường hợp này thì phải khai báo như thế nào?
  • 0

#6 ndtnv

ndtnv

    biết lệnh minsert

  • Members
  • PipPipPipPipPipPip
  • 437 Bài viết
Điểm đánh giá: 384 (khá)

Đã gửi 09 June 2009 - 04:34 PM

Ndtnv thân,
Đọc xong, tôi đã hiểu được 1 phần nào cái sArray này. Xin hỏi thêm:
Giả sử ptsList của tôi là 1 list 6 phần tử chứa tọa độ và tên của các text, đơn giản như sau:
(((1.0 1.0 0.0) "A") ((1.0 2.0 0.0) "B") ((1.0 3.0 0.0) "C")) ((2.0 1.0 0.0) "D") ((2.0 2.0 0.0) "E") ((2.0 3.0 0.0) "F")))
trong trường hợp này thì phải khai báo như thế nào?

Bạn nên dùng 2 safearray riêng để chứa tọa độ và tên point
(setq point (vlax-make-safearray vlax-vbdouble  '(0 . 5) '(0 . 2)))
(setq name (vlax-make-safearray vlax-vbString '(0 . 5) ))
(vlax-safearray-fill point (list '(1.0 1.0 0.0) '(1.0 2.0 0.0) '(1.0 3.0 0.0) '(2.0 1.0 0.0) '(2.0 2.0 0.0) '(2.0 3.0 0.0) ))
(vlax-safearray-fill name '("A" "B" "C" "D" "E" "F"))
Nếu dùng kiểu vlax-vbVariant thì phức tạp hơn nhiều
- Khai báo ptsList là 1 safearray
- Tạo safearray chứa tọa độ điểm, đổi thành kiểu variant
như trong hàm (defun list->variantArray () ...)
- Các tên điểm cũng đổi thành kiểu variant
- Đưa safearray của point vào ptsList
Nếu có thời gian, bạn hãy xem cách dùng safearray để lưu tọa độ trong AutoLISP Tutorial
  • 3