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

[Yêu cầu] Lisp đo và điền giá trị diện tích

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

- Xin chào cả nhà hôm này mình lại có một việc rất cần đến sự giúp đỡ của các bạn. Mình cần đo diện tích và đánh số thứ tự cho từng lô đất, nội dung lisp mình xin trình bày cụ thể như sau:

- Mình đã làm sẵn một block thuộc tính có tên là KHLODAT, trong block có hai thuộc tính là DT(diện tích), LODAT(tên và số thứ tự lô đất).

- Ví dụ LK-09:01 được hiểu như sau:

+ LK-09: tên lô đất (cái này được khai báo ban đầu và được cố định trong suốt quá trình thực hiện lệnh)

+ 01: số thứ tự lô đất (được khai báo số bắt đầu khi thực hiện lệnh và sẽ tự cộng thêm 1 sau mỗi lần diện tích của một lô đất được đo)

- Cấu trúc lisp:

+Đánh lệnh
clo
:

+ Số thứ
T
ự <01>/Tên
L
ô đất<LK-09>/<Chỉ điểm>:

+ Sau khi khai báo ban đầu và chỉ điểm vào vùng cần đo diện tích, diện tích đã được nhớ và lisp sẽ hỏi hai lựa chọn như sau:
C
hỉ điểm/ Chọn đường Thẳng

- Nếu ta chọn C thì sẻ chỉ 2 điểm : block sẽ được điền ra nằm trên đường thẳng đi qua hai điểm vừa chỉ.

- Mặc định là chọn T: chọn đường thẳng và block sẽ được điền ra nằm trên đường thẳng vừa chọn.

- Tường tự như vậy mỗi lần đo thì số thứ tự của lô đất sẽ dc cộng thêm 1.

LK-09:01

LK-09:02

……..

- Mình có gửi kèm theo bản cad và file lisp có code tượng tự như ý lisp trên, lệnh là
tdo
lisp sẽ hỏi tên mốc ban đầu và sẽ tự cộng thêm một vào tên mốc sau mỗi lần cắm mốc

- Mong cả nhà giúp đỡ, chân thành cám ơn!!!!!

Link tải file:

Ảnh Minh Họa

cadviet_2.jpg

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 thử xem nhá!

Tuy nhiên mình làm hơi khác yêu cầu của bạn một tý. Nguyên lý hoạt động là:

1.Chọn Block mẫu, vì block bạn có thể thay đổi khi thì LK-09: khi thì LK-10: .... vì vậy phải chọn.

2.pick diểm trong vùng tính dt, cái này ko phải nói

3.chọn điểm gốc đặt block, và chọn thêm một điểm để xác định góc quay. Nếu làm như bạn yêu cầu thì phải thêm tùy chọn C hoặ T thì cũng mất thời gian hơn là mặc định chọn 2 điểm.

(defun c:clo(/ bm bn tenlo tengoc stt st p1 p2 pt ang area po)
 (setq bm (entsel "\nchon Block mau:")
bn (cdr (assoc 2 (entget(car bm))))
Tenlo (cdr (assoc 1 (entget(entnext(entnext(car bm))))))
po (vl-string-position (ascii ":") tenlo)
tengoc (substr tenlo 1 (+ po 1))
stt (getint "\nso lo dat bat dau:")
)
  ;;;;;;;;;;;
 (while (setq pt (getpoint "\npick diem:"))
(setq p1 (getpoint "\nChon diem dat Block:")
  p2 (getpoint p1 "\nChon diem 2:")
  ang (/(*(angle p1 p2)180)pi)
  )
(command "-BOUNDARY" pt "")
(setq area (vlax-curve-getArea (entlast)))
(setq st (if (< stt 10) (strcat "0" (rtos stt)) (rtos stt)))
(entdel(entlast))
(command "insert" bn p1 "1" "" (+ ang 90) (rtos area 2 1) (strcat tengoc st))  
(setq	stt (+ stt 1))
)
 (princ)
 )

  • 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

Bạn thử xem nhá!

Tuy nhiên mình làm hơi khác yêu cầu của bạn một tý. Nguyên lý hoạt động là:

1.Chọn Block mẫu, vì block bạn có thể thay đổi khi thì LK-09: khi thì LK-10: .... vì vậy phải chọn.

2.pick diểm trong vùng tính dt, cái này ko phải nói

3.chọn điểm gốc đặt block, và chọn thêm một điểm để xác định góc quay. Nếu làm như bạn yêu cầu thì phải thêm tùy chọn C hoặ T thì cũng mất thời gian hơn là mặc định chọn 2 điểm.

Bước 3 chèn Block lp_hai có thể sử dụng cách này :

Sử dụng hàm (setq curve (nentselp (setq pt (getpoint "\nDiem / Duong thang Insert Block :"))))

- Nếu curve trả về Nil, tức là điểm user chọn không có đối tượng nào -> Yêu cầu chọn thêm 1 điểm nữa giống lp_hai đã làm

- Nếu curve trả về khác Nil, tức là có ename và điểm chọn

Lúc này ta có góc của vertex curve chọn + điểm chèn => làm tiếp như trường hợp 1

Lấy góc của vertex curve (*Line) tại điểm chọn, lp_hai tham khảo ở 1 lisp gần đây nhất :

http://www.cadviet.com/forum/index.php?showtopic=54656&view=findpost&p=169583

Như vậy thao tác của user vừa nhanh, lại vừa bao gồm cả 2 trường hợp :)

  • 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ước 3 chèn Block lp_hai có thể sử dụng cách này :

Sử dụng hàm (setq curve (nentselp (setq pt (getpoint "\nDiem / Duong thang Insert Block :"))))

- Nếu curve trả về Nil, tức là điểm user chọn không có đối tượng nào -> Yêu cầu chọn thêm 1 điểm nữa giống lp_hai đã làm

- Nếu curve trả về khác Nil, tức là có ename và điểm chọn

Lúc này ta có góc của vertex curve chọn + điểm chèn => làm tiếp như trường hợp 1

Lấy góc của vertex curve (*Line) tại điểm chọn, lp_hai tham khảo ở 1 lisp gần đây nhất :

Đầu tiên em xin cảm ơn bác!

Nói chung em chỉ biết những code đơn giản thôi. hhehhe, hơi gà! Vì thế em cũng rất mong dc học hỏi nhiều ở các bác.

Theo hướng dẫn của bác thì em sửa lại là thêm cái hàm con : curve-no-nil vì mổi lần xài đoạn code:

(setq p1 (vlax-safearray->list p1)

p2 (vlax-safearray->list p2))

đòi hỏi p1 và p2 phải được giải phóng, có đúng vậy ko bác?

và thấy lisp chạy như sau:

1)Lisp áp dụng tốt khi chọn 2 điểm(tức là curve = nil)

2)Lisp áp dụng tốt khi Curve là line (vì chỉ có 2 đầu nên xác định góc theo phương của đường thẳng)

3)Nếu chọn điểm thứ nhất nằm trên một curve nào đó thì mặc định góc quay theo trường hợp 2(cái này hơi ép User!!?)

4)khi curve là PL có nhiều đỉnh thì nó lại xác định góc theo 2 điểm đầu và cuối nên đôi khi không đúng góc yêu cầu

Rất mong bác chỉ giáo để em tiến bộ :)


(defun c:clo (/ bm bn tenlo tengoc stt st p1 p2 pt ang area po os curve)
 (setq bm 	(entsel "\nchon Block mau:")
bn 	(cdr (assoc 2 (entget (car bm))))
Tenlo  (cdr (assoc 1 (entget (entnext (entnext (car bm))))))
po 	(vl-string-position (ascii ":") tenlo)
tengoc (substr tenlo 1 (+ po 1))
stt	(getint "\nso lo dat bat dau:")
OS (getvar "osmode")
)
;;;;;;;;;;;
 (while (setq pt (getpoint "\npick diem:"))
(setvar "osmode" 512)
(setq curve (nentselp (setq p1 (getpoint "\nChon diem dat Block /Duong thang Insert Block:"))))
(setvar "osmode" OS)
(if (= curve nil)
 	(setq p2 (getpoint p1 "\nChon diem 2:")
	ang (/ (* (angle p1 p2) 180) pi)
	);curve = nil
 	(setq ang (/ (* (angle '(0 0 0) (vlax-curve-getFirstDeriv (car curve) (vlax-curve-getParamAtPoint (car curve) (vlax-curve-getClosestPointto (car curve) p1))))180)pi))
 	);kt if   
;;;;;;;;;;;
(command "-BOUNDARY" pt "")
(setq area (vlax-curve-getArea (entlast))	)
(setq st (if (< stt 10)
   	(strcat "0" (rtos stt))
   	(rtos stt)
 	)
)
(entdel (entlast))
(setq ang (+ ang 90))
(if (> ang 180) (setq ang (- ang 180)))
(command "insert"  bn  p1 "1" "" ang (rtos area 2 1)(strcat tengoc st))
(setq stt  (+ stt 1))
)
 (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

Xin lỗi lp_hai vì mình không down được file để test nên mình nói bo thế này :

Hàm (curve-no-nil) của bạn trả về góc của 2 điểm (trái dưới) (phải trên) của Bounding Box đối tượng, chứ không phải góc tiếp tuyến của curve tại điểm chọn.

Trước tiên ta có : (setq curve (nentselp (setq pt1 (getpoint "\nDiem / Duong thang Insert Block :"))))

Trường hợp Nil thì xong rồi, giờ ta bàn tới trường hợp điểm pick có *Line :

Lúc đó curve sẽ trả về list dạng : (<Entity name: 7efcd448> (567833.0 2.35934e+006 0.0)), phần tử đầu là ename của curve, phần tử 2 là điểm ta pick

=> Lấy (setq curve (car curve))

Trong ví dụ ket đưa ra bạn chú ý dòng này :

(setq ang (angle '(0 0 0) (vlax-curve-getFirstDeriv curve (vlax-curve-getParamAtPoint curve pt1))))

 

- (vlax-curve-getParamAtPoint curve pt1) : Xác định 'Param của curve tại Point click, chính là pt1 (mình k biết dịch sát nghĩa từ Param ^^, nôm na như cách đặt tên thứ tự vậy)

- (vlax-curve-getFirstDeriv curve param) : xác định vectơ tiếp tuyến với curve tại cái param vừa xác định

- angle '(0 0 0) (vecto tiếp tuyến) : cái này để lấy góc từ vecto theo radian

=> Hàm của bạn sẽ tương tự như này :

(defun curve-no-nil (curve pt) (angle '(0 0 0) (vlax-curve-getFirstDeriv curve (vlax-curve-getParamAtPoint curve pt))))

Và sử dụng trong lisp thì (curve-no-nil (car curve) pt1)

Bạn thử áp xụng xem có được không ^^ Vì mình không dám chắc khi chưa test ^^

 

P/S : mình cũng gà vậy, càng ngày càng thấy còn quá non, nên cứ tà tà mà học thêm thôi ^^ Và mình thích những người nhận ra điều đó để lắng nghe mọi lời góp ý, hơn là những người giỏi/ chưa giỏi nhưng bảo thủ ta đâ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

hehhehe. đúng là mở mang kiến thức.

bác rãnh thì xem lại lisp giúp em cái, chạy thì cũng ok rồi nhưng mà vướng cái chổ nó xoay theo chiều của pl bác ah!

với cho em hỏi: lúc trước em có đọc một hàm mà lấy điểm ngay tại nơi mình chọn PL luôn ấy, giống như trong lệnh Break của cad, mặt định điểm đầu tiên là điểm mà mình chọn đối tượ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

Chính là điểm pt1 trong hàm nentselp mà bạn ? (cadr của list trả về)

Với entsel cũng thế. Nentsel cũng thế ^^ Kết quả bao giờ cũng là list (ename điểm_chọn). Với nentselp thì mình đã cung cấp trước điểm_chọn cho nó bằng hàm getpoint.

Với góc xoay chèn Blocks, có khả năng bạn gặp trường hợp block lộn lại ^^

=> Nghiên cứu hàm này

(defun LM:MakeReadable ( a )<pre> ;; © Lee Mac 2010 (cond ( (and (> a (/ pi 2)) (<= a pi)) (- a pi) ) ( (and (> a pi) (<= a (/ (* 3 pi) 2))) (+ a pi) ) ( a ) ) </pre>

)

  • 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

Mình muốn quy tắc làm tròn nó là làm tròn xuống hoặc đơn giản là cắt bỏ số thập phân thôi. Ví dụ 6.568= 6.5.

Bác nào giúp mình với. Thank

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àm tròn xuống với n số sau thập phân: ;(lamtron 5.6666 1) -> 5.6

(defun lamtron (a n)  (/ (fix (* a (expt 10 n))) (float (expt 10 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

làm tròn xuống với n số sau thập phân: ;(lamtron 5.6666 1) -> 5.6

(defun lamtron (a n)  (/ (fix (* a (expt 10 n))) (float (expt 10 n))))

Y mình là làm tròn trong lisp trên cơ bạn à

  • Vote giảm 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

Y mình là làm tròn trong lisp trên cơ bạn à

 

Mình muốn quy tắc làm tròn nó là làm tròn xuống hoặc đơn giản là cắt bỏ số thập phân thôi. Ví dụ 6.568= 6.5.

Bác nào giúp mình với. Thank

Lâu quá không ghé diễn đàn, không biết bạn còn cần không để mình sửa lại giúp. Vì theo mấy Cad đời sau này cách hoạt động của nó không giống đời cũ, nên nhiều đoạn code không còn phù hợp :)

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


×