Người làm hồ sơ đất đai và hạ tầng đi tìm lisp xuất tọa độ trong CAD vì cùng một việc: ghi toạ độ từng góc thửa lên bản vẽ rồi lập bảng thống kê, thay vì gõ tay từng con số.
Viện tải bản đang lưu hành về đọc từng dòng, tìm ra ba chỗ hỏng, rồi viết lại một bản của mình. Bài này có cả mã nguồn lẫn tệp để tải. Muốn học trọn khâu dựng hình và trình bày hồ sơ thì xem khóa AutoCAD Xây Dựng.
Xuất tọa độ trong CAD: việc cần làm gồm những gì
Một nhãn toạ độ đúng quy cách gồm bốn phần: đường dẫn từ điểm ra chỗ trống, hai dòng số xếp chồng, một vòng tròn mang số hiệu điểm, và cuối cùng là bảng thống kê gom hết lại.
Chỗ quyết định nằm ở thứ tự hai con số. Trắc địa Việt Nam quy ước X là trục bắc, Y là trục đông, trong khi AutoCAD thì X là ngang và Y là dọc. Nói cách khác, X trong bảng toạ độ phải lấy từ Y của AutoCAD.
Mọi bản lisp lưu hành đều đổi trục sẵn, và không hỏi bạn một câu nào. Dùng cho bản đồ địa chính thì đúng, nhưng dùng cho mặt bằng kiến trúc thì con số ra ngược mà không có dấu hiệu gì báo.
Một cách gọi khác hay gặp là lisp pick tọa độ trong cad, và nó chỉ ý định hẹp hơn: bấm một điểm rồi lấy ra cặp số, không cần nhãn cũng không cần bảng. Việc ấy AutoCAD làm sẵn bằng lệnh ID, và cách nhập toạ độ bằng bàn phím nằm ở bài nhập tọa độ trong CAD. Tệp lisp chỉ đáng dùng khi bạn cần nhãn và bảng, tức là khi làm hồ sơ chứ không phải khi tra một con số.
Tải lisp xuất tọa độ trong CAD của Viện
Tải tệp XTD-IIC.lsp — 7 KB, hai lệnh. Mã để nguyên trong bài, vì chạy mã lạ trên máy mình là việc đáng cẩn thận.
| Lệnh | Việc nó làm |
|---|---|
XTD | chọn các điểm, ghi nhãn toạ độ lên bản vẽ và lập bảng thống kê |
XTDCSV | chọn các điểm rồi ghi thẳng ra tệp .csv, mở bằng Excel |
Cả hai đều hỏi quy ước trục trước khi làm, mặc định là trắc địa. Ai vẽ kiến trúc thì gõ C để giữ nguyên trục của AutoCAD.
(vl-load-com)
(defun IIC-GIOI-THIEU ()
(princ "\nLisp được lập trình bởi RDSIC - Viện Tin học Xây dựng")
(princ "\nwebsite: https://iic.huce.edu.vn - Tel: 0989 427 809")
)
;; Tao chu bang entmake, KHONG dung (command "text" ...): kieu chu co chieu cao
;; co dinh thi dong hoi chieu cao bien mat va moi doi so sau do lech mot nhip.
;; can: 0 trai, 1 giua
(defun IIC:CHU (p cao noi can)
(entmake (list (cons 0 "TEXT") (cons 10 p) (cons 11 p) (cons 40 cao)
(cons 1 noi) (cons 72 can) (cons 73 0)))
)
(defun IIC:NET (a b)
(entmake (list (cons 0 "LINE") (cons 10 a) (cons 11 b)))
)
(defun IIC:TRON (p r)
(entmake (list (cons 0 "CIRCLE") (cons 10 p) (cons 40 r)))
)
;; Tra ve (chuoi-X chuoi-Y) theo quy uoc dang chon.
(defun IIC:CAP (p td)
(if td
(list (rtos (cadr p) 2 2) (rtos (car p) 2 2))
(list (rtos (car p) 2 2) (rtos (cadr p) 2 2))
)
)
(defun IIC:HOI-TRUC ( / k )
(initget "TracDia Cad")
(setq k (getkword "\nQuy uoc truc [TracDia/Cad] <TracDia>: "))
(/= k "Cad")
)
(defun IIC:CHON-DIEM ( / p ds )
(setq ds nil)
(while (setq p (getpoint "\nChon diem (Enter de dung): "))
(setq ds (cons p ds))
)
(reverse ds)
)
(defun c:XTD ( / e-cu os-cu ce-cu h td ds n i p cap sx sy
p1 p2 p3 rong r pb hang cot1 cot2 cot3 y0 td1 td2 dz-cu )
(IIC-GIOI-THIEU)
(setq e-cu *error*
os-cu (getvar "osmode")
ce-cu (getvar "cmdecho"))
;; Khoi phuc du nguoi dung bam ESC giua chung. Thieu doan nay thi bat diem bi
;; tat am tham va nhom hoan tac bi bo ngo - dung loi cua cac ban dang luu hanh.
(defun *error* (m)
(setvar "osmode" os-cu) (setvar "cmdecho" ce-cu)
(if dz-cu (setvar "dimzin" dz-cu))
(command "_.UNDO" "_End")
(setq *error* e-cu)
(if (and m (not (wcmatch (strcase m) "*CANCEL*,*QUIT*")))
(princ (strcat "\nIIC loi: " m)))
(princ)
)
(command "_.UNDO" "_Begin")
(setvar "cmdecho" 0)
;; DIMZIN = 8 lam rtos cat het so 0 thua, toa do 3200.00 ra thanh 3200.
;; Tat trong luc chay roi tra lai, ke ca khi bam ESC.
(setq dz-cu (getvar "dimzin"))
(setvar "dimzin" 0)
(setq h (getvar "TEXTSIZE"))
(if (<= h 0) (setq h 2.5))
(setq h (cond ((getreal (strcat "\nChieu cao chu <" (rtos h 2 2) ">: "))) (h)))
(setq td (IIC:HOI-TRUC))
(setq ds (IIC:CHON-DIEM))
(if (null ds)
(princ "\nKhong chon diem nao.")
(progn
(setvar "osmode" 0)
(setq n (length ds) i 0 rong 0.0 r (* 1.5 h))
(while (< i n)
(setq p (nth i ds)
cap (IIC:CAP p td)
sx (car cap)
sy (cadr cap)
p1 (list (+ (car p) (* 3 h)) (+ (cadr p) (* 3 h)))
rong (max rong (* (max (strlen sx) (strlen sy)) h 0.72))
)
;; Khe ho chu - net: 0.55 lan chieu cao chu o tren, va o duoi cung vay.
;; De 0.35 thi chu dinh sat net, nhin roi (anh Binh bat 20/09/2026).
(setq p2 (list (+ (car p1) rong (* 0.6 h)) (cadr p1))
p3 (list (+ (car p2) r (* 0.3 h)) (cadr p1)))
(IIC:NET p p1)
(IIC:NET p1 p2)
(IIC:CHU (list (+ (car p1) (* 0.3 h)) (+ (cadr p1) (* 0.55 h))) h sx 0)
(IIC:CHU (list (+ (car p1) (* 0.3 h)) (- (cadr p1) (* 1.55 h))) h sy 0)
(IIC:TRON p3 r)
(IIC:CHU (list (car p3) (- (cadr p3) (* 0.5 h))) h (strcat "N" (itoa (1+ i))) 1)
(setq i (1+ i))
)
(setq pb (getpoint "\nVi tri dat bang (goc tren ben trai): "))
(if pb
(progn
(setq td1 (if td "Toa do X (bac)" "Toa do X")
td2 (if td "Toa do Y (dong)" "Toa do Y")
cot1 (* 5 h)
cot2 (max (+ rong (* 2 h)) (* (strlen td1) h 0.78))
cot3 (max (+ rong (* 2 h)) (* (strlen td2) h 0.78))
hang (* 2.2 h) y0 (cadr pb) i 0)
(IIC:NET pb (list (+ (car pb) cot1 cot2 cot3) y0))
(setq y0 (- y0 hang))
(IIC:CHU (list (+ (car pb) (* 0.5 cot1)) (+ y0 (* 0.6 h))) h "STT" 1)
(IIC:CHU (list (+ (car pb) cot1 (* 0.5 cot2)) (+ y0 (* 0.7 h))) h td1 1)
(IIC:CHU (list (+ (car pb) cot1 cot2 (* 0.5 cot3)) (+ y0 (* 0.7 h))) h td2 1)
(IIC:NET (list (car pb) y0) (list (+ (car pb) cot1 cot2 cot3) y0))
(while (< i n)
(setq cap (IIC:CAP (nth i ds) td))
(IIC:CHU (list (+ (car pb) (* 0.5 cot1)) (- y0 (* 1.4 h))) h
(strcat "N" (itoa (1+ i))) 1)
(IIC:CHU (list (+ (car pb) cot1 (* 0.5 cot2)) (- y0 (* 1.5 h))) h (car cap) 1)
(IIC:CHU (list (+ (car pb) cot1 cot2 (* 0.5 cot3)) (- y0 (* 1.5 h))) h (cadr cap) 1)
(setq y0 (- y0 hang) i (1+ i))
(IIC:NET (list (car pb) y0) (list (+ (car pb) cot1 cot2 cot3) y0))
)
(IIC:NET pb (list (car pb) y0))
(IIC:NET (list (+ (car pb) cot1) (cadr pb)) (list (+ (car pb) cot1) y0))
(IIC:NET (list (+ (car pb) cot1 cot2) (cadr pb)) (list (+ (car pb) cot1 cot2) y0))
(IIC:NET (list (+ (car pb) cot1 cot2 cot3) (cadr pb))
(list (+ (car pb) cot1 cot2 cot3) y0))
)
)
(princ (strcat "\nDa ghi " (itoa n) " diem."))
)
)
(setvar "osmode" os-cu) (setvar "cmdecho" ce-cu)
(setvar "dimzin" dz-cu)
(command "_.UNDO" "_End")
(setq *error* e-cu)
(princ)
)
;; XTDCSV - ghi thang ra tep .csv, mo bang Excel duoc ngay.
(defun c:XTDCSV ( / e-cu td ds n i cap f duong dz-cu )
(IIC-GIOI-THIEU)
(setq e-cu *error* f nil)
(setq dz-cu (getvar "dimzin"))
(setvar "dimzin" 0)
(defun *error* (m)
(if f (close f))
(if dz-cu (setvar "dimzin" dz-cu))
(setq *error* e-cu)
(if (and m (not (wcmatch (strcase m) "*CANCEL*,*QUIT*")))
(princ (strcat "\nIIC loi: " m)))
(princ)
)
(setq td (IIC:HOI-TRUC))
(setq ds (IIC:CHON-DIEM))
(if (null ds)
(princ "\nKhong chon diem nao.")
(progn
(setq duong (getfiled "Ghi toa do ra tep" "toado" "csv" 1))
(if duong
(progn
(setq f (open duong "w") n (length ds) i 0)
(write-line (if td "STT,X (bac),Y (dong)" "STT,X,Y") f)
(while (< i n)
(setq cap (IIC:CAP (nth i ds) td))
(write-line (strcat "N" (itoa (1+ i)) "," (car cap) "," (cadr cap)) f)
(setq i (1+ i))
)
(close f)
(setq f nil)
(princ (strcat "\nDa ghi " (itoa n) " diem ra " duong))
)
)
)
)
(setvar "dimzin" dz-cu)
(setq *error* e-cu)
(princ)
)
Hướng dẫn dùng, từng bước một
Bước 1 — Nạp tệp
Gõ APPLOAD, trỏ tới tệp, bấm Load, rồi bấm Close. Muốn khỏi nạp lại mỗi lần mở máy thì thêm tệp vào ô Startup Suite ngay trong hộp ấy. Cách nạp chi tiết nằm ở bài lisp cắt dim.
Bước 2 — Chạy lệnh XTD
Gõ XTD rồi Enter. Ba câu hỏi lần lượt hiện ra:
Chieu cao chu <2.50>:
Quy uoc truc [TracDia/Cad] <TracDia>:
Chon diem (Enter de dung):
Chiều cao chữ để mặc định là lấy theo biến TEXTSIZE của bản vẽ. Quy ước trục cứ Enter nếu làm hồ sơ đất đai. Rồi bấm lần lượt các góc thửa, xong thì Enter.
Bước 3 — Đặt bảng thống kê
Vi tri dat bang (goc tren ben trai):
Bấm một điểm ở chỗ trống. Bảng tự dựng với ba cột, bề rộng cột lấy theo con số dài nhất, và tiêu đề ghi rõ cột nào là bắc, cột nào là đông. Máy báo:
Da ghi 5 diem.
Bước 4 — Hoặc xuất thẳng ra Excel
Gõ XTDCSV, chọn điểm như trên, rồi chọn chỗ lưu. Tệp .csv mở bằng Excel ra đúng ba cột, khỏi phải chép tay từ bảng trên bản vẽ sang bảng tính.
Ba chỗ bản lisp đang lưu hành làm hỏng
Chúng tôi tải bản phổ biến nhất về, giải nén, và đọc hết 104 dòng mã. Nó chạy được, và ý tưởng thì đúng. Nhưng có ba chỗ hỏng, cả ba đều kiểm được trên máy.
Thứ nhất là bảng mã. Trong mã nguồn, tiêu đề cột viết là Täa ®é Y. Đó là chữ Tọa độ Y gõ bằng bảng mã TCVN3 của những năm 2000, chỉ hiện đúng khi bản vẽ dùng đúng phông ấy. Trên máy dùng phông Unicode thông thường, nó ra đúng như ảnh trên.
Thứ hai là phần thập phân. Trang rtos của Autodesk ghi rõ hàm này chịu ảnh hưởng của nhiều biến: "according to the settings of mode, precision, and the AutoCAD UNITMODE, DIMZIN, LUNITS, and LUPREC system variables". Hàm rtos cắt sạch số 0 thừa khi biến DIMZIN bằng 8, mà 8 là giá trị của phần lớn bản vẽ theo hệ mét. Toạ độ 584320.00 in ra thành 584320. Hồ sơ trắc địa mất hai chữ số thập phân là hỏng. Bản của Viện tắt DIMZIN trong lúc chạy rồi trả lại nguyên giá trị cũ, kể cả khi bạn bấm ESC.
Thứ ba là không có bẫy lỗi. Bản cũ mở một nhóm hoàn tác bằng Undo Begin nhưng không có hàm *error*. Bấm ESC giữa chừng là nhóm ấy bỏ ngỏ, và biến CMDECHO nằm lại ở 0 — chúng tôi đo được đúng con số ấy sau khi bấm ESC. Dòng lệnh từ đó thôi hiện lệnh đang chạy, và người dùng không hiểu vì sao.
Nói cho công bằng: có một điều chúng tôi đoán sai. Chúng tôi tưởng bản cũ cũng bỏ quên chế độ bắt điểm, nhưng đo thì OSMODE vẫn về đúng giá trị cũ. Chỗ ấy họ làm đúng.
Mã của Viện khác ở đâu
| Chỗ | Bản lưu hành | Bản của Viện |
|---|---|---|
| Quy ước trục | đổi sẵn, không hỏi | hỏi một câu, mặc định trắc địa |
| Phần thập phân | phụ thuộc DIMZIN, hay mất | ép đúng hai chữ số rồi trả biến về |
| Bấm ESC giữa chừng | nhóm hoàn tác bỏ ngỏ, CMDECHO kẹt ở 0 | có hàm *error*, trả lại hết |
| Tiêu đề bảng | bảng mã TCVN3, ra chữ lạ | chữ thường, không dấu, chạy ở mọi phông |
| Bề rộng cột | tính theo số, tiêu đề tràn sang cột bên | lấy số lớn hơn giữa bề rộng số và bề rộng tiêu đề |
| Xuất ra Excel | không có | lệnh XTDCSV |
Một khác biệt nữa nằm ở chỗ ít ai để ý: biến cục bộ. Bản cũ để bảy biến chạy ra ngoài phạm vi hàm, gồm cả những tên rất dễ trùng như k và n. Tệp lisp khác đang nạp cùng phiên mà dùng chung tên ấy thì hai bên ghi đè lẫn nhau, và lỗi hiện ra ở chỗ chẳng liên quan gì. Bản của Viện khai hết biến trong danh sách cục bộ.
Còn một chi tiết kỹ thuật đáng nói. Bản cũ tạo chữ bằng (command "text" ...). Cách ấy hỏng khi kiểu chữ hiện hành đặt chiều cao cố định, vì lúc đó dòng hỏi chiều cao biến mất và mọi đối số sau đó lệch đi một nhịp. Bản của Viện dựng chữ bằng entmake, không phụ thuộc kiểu chữ.
Ba điều hay nghe nhưng không đúng
| Điều hay nghe | Thực tế |
|---|---|
| Lisp xuất toạ độ nào cũng như nhau | Khác ở chỗ đổi trục, số lẻ và bẫy lỗi — ba chỗ quyết định hồ sơ đúng hay sai |
| Bảng ra chữ lạ là do máy thiếu phông | Là do mã nguồn viết bằng bảng mã đời cũ, đổi phông không chữa được |
| Muốn có tệp Excel thì phải chép tay | Ghi thẳng ra .csv từ lisp, mở bằng Excel là xong |
Câu hỏi thường gặp
Lisp lấy tọa độ chạy xong mà số không có phần thập phân?
Đó là biến DIMZIN. Đặt nó về 0 trước khi chạy, hoặc dùng tệp ở bài này vì nó tự xử lý rồi trả biến về.
Vì sao cột X trong bảng lại là số của trục đứng?
Vì quy ước trắc địa Việt Nam lấy X là trục bắc. AutoCAD gọi trục đứng là Y, nên bảng phải đổi. Làm mặt bằng kiến trúc thì chọn Cad để giữ nguyên.
Ghi tọa độ trong CAD cho hàng trăm điểm có chậm không?
Không. Lệnh chỉ vẽ nét và chữ, không gọi lệnh nặng nào. Chỗ mất thời gian là bấm chuột chọn điểm.
Bấm nhầm rồi thì sao?
Gõ U một lần. Cả lượt được gộp thành một bước hoàn tác, nên không phải bấm nhiều lần.
Tệp .csv mở bằng Excel bị dồn hết vào một cột?
Đó là do Excel đang đặt dấu phân cách là chấm phẩy. Mở bằng chức năng nhập dữ liệu rồi chọn dấu phẩy, hoặc đổi trong tuỳ chọn vùng của Windows.