Đến nội dung


Hình ảnh
- - - - -

[Yêu cầu] - Chọn nhanh các đối tượng dạng đường (line, curve..) nối tiếp nhau


  • Please log in to reply
36 replies to this topic

#1 ThuyLinh313

ThuyLinh313

    biết lệnh mtext

  • Members
  • PipPipPipPip
  • 288 Bài viết
Điểm đánh giá: 142 (tàm tạm)

Đã gửi 25 December 2012 - 07:38 AM

Mình tìm thấy 1 lisp của tác giả Lee Mac tại link này http://lee-mac.com/chainsel.html
Đây là 1 ý tưởng rất hay trong việc select nhanh các đối tượng dạng đường (*line, curve...) nối tiếp nhau của Lee Mac. Tuy nhiên thuật toán mà anh này sử dụng không được hay lắm: tốc độ xử lý của lisp quá chậm, không chọn được các đối tượng pline khác elevation (khác cao độ - Mình thường xuyên gặp trường hợp này) nên ứng dụng của nó không thực sự hiệu quả.

Vì những nhược điểm trên nên mình chỉ "chôm" ý tưởng của tác giả về đây để các bạn cùng thảo luận viết 1 lisp tốt hơn chứ không lấy lisp. Các cao thủ cadviet cùng ra tay nhé :)
  • 0

#2 ketxu

ketxu

    Copier - Paster - Editor

  • Moderator
  • PipPipPipPipPipPipPip
  • 5681 Bài viết
Điểm đánh giá: 2605 (tuyệt vời)

Đã gửi 25 December 2012 - 09:16 AM

Mình thấy duyệt như thế là giải pháp thông dụng nhất rồi ^^ Thay vì tìm trên toàn bản vẽ thì có thể duyệt ssget nhỏ xinh ở 2 đầu cũng được.
Với lại với lisp này bạn thêm tọa độ 3d vào cũng đâu có khó ^^ Chắc số lượng đối tượng trên bản vẽ của TL nhiều nên mới xảy ra tình trạng quá chậm ^^
  • 1

Thành viên nhóm CadMagic.
Mời bạn ghé thăm facebook nhóm - Page viết lisp theo yêu cầu  :
CAD MAGIC


#3 Doan Van Ha

Doan Van Ha

    biết lệnh adcenter

  • CADViet Team
  • PipPipPipPipPipPipPip
  • 5447 Bài viết
Điểm đánh giá: 2624 (tuyệt vời)

Đã gửi 25 December 2012 - 09:30 AM

Tôi nghĩ cách duyệt qua kiểu chọn "X" này sẽ làm chậm đáng kể nếu như gặp 1 bản vẽ lớn. Có thể tạo 1 hàm con để duyệt chỉ 2 tập ở 2 đầu mút của mỗi đối tượng chắc sẽ nhanh hơn.
  • 0

* Chỉ nên yêu cầu Lisp khi bạn làm việc đó mất cả ngày nhưng họ chỉ viết 1 giờ. Đừng nêu yêu cầu Lisp khi bạn chỉ làm 1 giờ nhưng bắt họ phải mất cả ngày.

* Nhờ viết lisp cũng như đi khám bệnh. Chỉ gởi căn cước và than sắp chết thì không bác sỹ nào cứu sống được.


#4 ThuyLinh313

ThuyLinh313

    biết lệnh mtext

  • Members
  • PipPipPipPip
  • 288 Bài viết
Điểm đánh giá: 142 (tàm tạm)

Đã gửi 25 December 2012 - 02:06 PM

Đúng vậy các bạn ạ. Chỉ những bản vẽ lớn, các đối tượng nằm trên nhiều layer không quản lý được thì mới cần dùng đến lisp này. Nhất là bản vẽ của mấy anh địa chính chạy Microstation khi xuất sang cad thì toàn Line với Arc, làm việc với những bản vẽ này cực lắm! còn với những bản vẽ có số đối tượng nhỏ thì có nhiều cách khác để select đối tượng.
Mình đang nghĩ đến phương án viết lại lisp này như sau:
- Chọn đối tượng gốc -> lấy ra tọa độ 2 đầu mút của nó.
- kiểm tra tại các đầu mút, nếu tìm thấy tại các điểm này các đối tượng *Line, Curve khác có tọa độ trùng hoặc gần trùng (theo 1 sai số người dùng nhập) thì đưa đầu mút còn lại của đối tượng tìm thấy vào danh sách cho các lần lặp tiếp theo.
- lặp đến khi danh sách các đầu mút kiểm tra hết thì thôi.
Bằng trực quan mình nghĩ là cách làm này nhanh hơn lisp của Leemac vì không cần kiểm tra toàn bộ đối tượng trên bản vẽ, nhưng chưa có thời gian thử.
  • 0

#5 Doan Van Ha

Doan Van Ha

    biết lệnh adcenter

  • CADViet Team
  • PipPipPipPipPipPipPip
  • 5447 Bài viết
Điểm đánh giá: 2624 (tuyệt vời)

Đã gửi 25 December 2012 - 02:08 PM

Quả thật là lisp của LM, test với bản vẽ cỡ 80.000 objects thì nó đứng khựng luôn!
Lisp hiệu chỉnh này giải quyết được vấn đề tốc độ khi bản vẽ quá lớn.
P/S (27/12/2012): xin xem lisp hoàn tất ở bài #25. Tác giả xóa code ở đây để khỏi chật topic và thuận tiện cho người down load.
  • 3

* Chỉ nên yêu cầu Lisp khi bạn làm việc đó mất cả ngày nhưng họ chỉ viết 1 giờ. Đừng nêu yêu cầu Lisp khi bạn chỉ làm 1 giờ nhưng bắt họ phải mất cả ngày.

* Nhờ viết lisp cũng như đi khám bệnh. Chỉ gởi căn cước và than sắp chết thì không bác sỹ nào cứu sống được.


#6 LoveLisp

LoveLisp

    biết lệnh extend

  • Members
  • PipPipPip
  • 195 Bài viết
Điểm đánh giá: 20 (tàm tạm)

Đã gửi 25 December 2012 - 04:44 PM

Cám ơn bác HẠ! Từ trước đến nay khi mình theo dõi trên diễn đàn, tất cả các hàm của bác viết đều có tên là HA. Đó là dấu ấn cá nhân của bác, em không có ý kiến gì. Tuy nhiên, mình hay lưu lại các lisp của bác, mà lệnh nào cũng HA, hàm con nào cũng HA, điều này tạo ra một chút khó khăn! :)
Vậy, liệu bác có thể đặt tên lệnh, tên hàm con khác đi được không (tùy do bác quyết định dựa vào tính năng của hàm)?
Xin lỗi bác vì góp ý này, mình các lisp mình down được của bác lên đến vài chục rồi! :)
  • 0

#7 LoveLisp

LoveLisp

    biết lệnh extend

  • Members
  • PipPipPip
  • 195 Bài viết
Điểm đánh giá: 20 (tàm tạm)

Đã gửi 25 December 2012 - 05:11 PM

Oh, sao mình thấy hàm con có biến cục bộ và biến toàn cục trùng tên nhỉ? (biến ent)
  • 0

#8 LoveLisp

LoveLisp

    biết lệnh extend

  • Members
  • PipPipPip
  • 195 Bài viết
Điểm đánh giá: 20 (tàm tạm)

Đã gửi 25 December 2012 - 05:16 PM

Lisp cho phép dùng kỹ thuật đệ quy hả các bác? Thế mà bây giờ mình mới biết.
  • 0

#9 Doan Van Ha

Doan Van Ha

    biết lệnh adcenter

  • CADViet Team
  • PipPipPipPipPipPipPip
  • 5447 Bài viết
Điểm đánh giá: 2624 (tuyệt vời)

Đã gửi 25 December 2012 - 06:52 PM

@LoveLisp:
1). Bạn cứ vô tư đổi "HA" thành "LL", không ai kiện tác quyền đâu.
2). Hai biến trùng tên thì hơi ngộ tí xíu.
3). Nếu không có đệ quy thì e sẽ có nhiều bài toán không giải được.
:lol:
  • 0

* Chỉ nên yêu cầu Lisp khi bạn làm việc đó mất cả ngày nhưng họ chỉ viết 1 giờ. Đừng nêu yêu cầu Lisp khi bạn chỉ làm 1 giờ nhưng bắt họ phải mất cả ngày.

* Nhờ viết lisp cũng như đi khám bệnh. Chỉ gởi căn cước và than sắp chết thì không bác sỹ nào cứu sống được.


#10 ThuyLinh313

ThuyLinh313

    biết lệnh mtext

  • Members
  • PipPipPipPip
  • 288 Bài viết
Điểm đánh giá: 142 (tàm tạm)

Đã gửi 26 December 2012 - 07:30 AM

Bạn DVH xem lại. mình test thấy lỗi thế này

Command: HA
Select objects:
; error: exceeded maximum number of selection sets

Lỗi này bị khi mình zoom để màn hình có thể hiện toàn bộ phạm vi đối tượng được chọn.
nếu 1 phần các đối tượng chọn không nằm trong phạm vi hiển thị của màn hình thì mới không lỗi.
Danh sách các đối tượng được chọn khép kín.

Mình đoán lỗi này nằm trong cách lặp đệ quy của bạn, không thoát được vòng lặp dẫn đến việc chương trình select mãi vượt quá số selection sets cho phép.

Ngoài ra việc bạn chỉ cho cho chọn các đối tượng hiển thị trong phạm vi nhìn thấy của màn hình mình nghĩ là không ổn. bởi trước khi chọn ta có biết các đối tượng được nối tiếp với nhau chạy đến đâu thì hết đâu.
  • 0

#11 gia_bach

gia_bach

    biết lệnh adcenter

  • CADViet Team
  • PipPipPipPipPipPipPip
  • 1435 Bài viết
Điểm đánh giá: 1426 (rất tốt)

Đã gửi 26 December 2012 - 08:56 AM

Mình tìm thấy 1 lisp của tác giả Lee Mac tại link này http://lee-mac.com/chainsel.html
Đây là 1 ý tưởng rất hay trong việc select nhanh các đối tượng dạng đường (*line, curve...) nối tiếp nhau của Lee Mac. Tuy nhiên thuật toán mà anh này sử dụng không được hay lắm: tốc độ xử lý của lisp quá chậm, không chọn được các đối tượng pline khác elevation (khác cao độ - Mình thường xuyên gặp trường hợp này) nên ứng dụng của nó không thực sự hiệu quả.

Vì những nhược điểm trên nên mình chỉ "chôm" ý tưởng của tác giả về đây để các bạn cùng thảo luận viết 1 lisp tốt hơn chứ không lấy lisp. Các cao thủ cadviet cùng ra tay nhé :)

ThuyLinh313 hơi vội vã khi kết luận về hàm "Chain Selection" của "chú" Lee!
Tính tổng quát của 1 vấn đề là rất quan trọng.
"Chain Selection" là thuật toán tổng quát của Lee giải bài toán "chọn các Curve nối tiếp nhau". Nhưng bạn lại dựa trên bài toán cụ thể của mình (pline khác cao độ - bản vẽ của mấy anh địa chính ...) để minh họa kết luận của mình.

Sorry, nó giống như công bố của 1 tổ chức gì đó - đại loại là : "Người Việt Nam hạnh phúc nhất nhì thế giới ?!"

Với từng bài toán cụ thể sẽ có cách giải quyết khác nhau (VD : "phương pháp chia ô" mà TrungNgaMy có giới thiệu trên CadViet)
Như vậy, bài toán của "mấy anh địa chính" sẽ có cách tiếp cận khác.
Hy vọng là mọi người sẽ tìm ra cách tốt nhất.


Quả thật là lisp của LM, test với bản vẽ cỡ 80.000 objects thì nó đứng khựng luôn!
Lisp hiệu chỉnh này giải quyết được vấn đề tốc độ khi bản vẽ quá lớn.


(defun C:HA ( / sf ss0 ent0)
;Doan Van Ha - CADViet.com - Ngay 25/12/2012
;Chuc nang: Chon doi tuong noi tiep nhau (LINE,ARC,LWPOLYLINE,SPLINE,POLYLINE,ELLIPSE).
;Lisp nay viet lai lisp cua Lee Mac de chay nhanh hon.
...

@ HA :
Đệ quy là "con dao hai lưỡi".
Trong t/hợp này Ha thử vẽ 1 tam giác bất kỳ rồi chạy Lisp, sẽ thấy mặt trái của đệ quy.
-> khử đệ quy là vấn đề cần quan tâm.
  • 4

#12 ThuyLinh313

ThuyLinh313

    biết lệnh mtext

  • Members
  • PipPipPipPip
  • 288 Bài viết
Điểm đánh giá: 142 (tàm tạm)

Đã gửi 26 December 2012 - 10:33 AM

Hì hì, Có thể mình đưa ra minh họa chưa sát với tính tổng quát của bài toán. Nhưng ngoại trừ việc xét các curve khác cao độ, thì minh họa của mình cũng đã chỉ ra 1 cách rõ ràng rằng thuật toán của "chú" Lee chưa thực sự tối ưu và ko mang lại hiệu quả tốt khi sử dụng pkn?
Để chứng minh, mình sẽ viết lại lisp này, và mình cam đoan mình sẽ viết nó tốt hơn Lee Mac - ít nhất là về khoản tốc độ. ^^

PS: Mình tò mò 1 chút! sao lại là "chú Lee" nhỉ, phải chăng cũng là 1 thành viên cv?
  • 1

#13 LoveLisp

LoveLisp

    biết lệnh extend

  • Members
  • PipPipPip
  • 195 Bài viết
Điểm đánh giá: 20 (tàm tạm)

Đã gửi 26 December 2012 - 10:34 AM

Mình gặp lỗi này:
Command:
Command: ha
Select objects:
; error: bad argument type: lselsetp nil
Command:

Đây là bản vẽ gây lỗi:
http://www.cadviet.c...ctionendend.dwg
  • 0

#14 LoveLisp

LoveLisp

    biết lệnh extend

  • Members
  • PipPipPip
  • 195 Bài viết
Điểm đánh giá: 20 (tàm tạm)

Đã gửi 26 December 2012 - 10:36 AM

Hóng lisp cải tiến của bạn ThuyLinh, nhớ xem giúp mình lỗi ở trên luôn nhé! :)
  • 0

#15 Doan Van Ha

Doan Van Ha

    biết lệnh adcenter

  • CADViet Team
  • PipPipPipPipPipPipPip
  • 5447 Bài viết
Điểm đánh giá: 2624 (tuyệt vời)

Đã gửi 26 December 2012 - 11:35 AM

Chú Lee này ở Anh chứ không phải ở... Hàn. Dân CV hay sưu tầm và học hỏi lisp của chú ấy, chứ không phải chú ấy là dân CV.
Code sửa lại theo góp ý của ThuyLinh+GiaBach. Mọi người test xem ổn không nhé! Và góp ý để học hỏi, bởi tôi cũng đồng quan điểm với bạn ThuyLinh là Lee chọn và duyệt tất cả bản vẽ thì oải quá. Điều kiện lọc của Lee cũng rườm rà nữa (nhưng chưa sửa).
P/S (27/12/2012): xin xem lisp hoàn tất ở bài #25. Tác giả xóa code ở đây để khỏi chật topic và thuận tiện cho người down load.
  • 2

* Chỉ nên yêu cầu Lisp khi bạn làm việc đó mất cả ngày nhưng họ chỉ viết 1 giờ. Đừng nêu yêu cầu Lisp khi bạn chỉ làm 1 giờ nhưng bắt họ phải mất cả ngày.

* Nhờ viết lisp cũng như đi khám bệnh. Chỉ gởi căn cước và than sắp chết thì không bác sỹ nào cứu sống được.


#16 ketxu

ketxu

    Copier - Paster - Editor

  • Moderator
  • PipPipPipPipPipPipPip
  • 5681 Bài viết
Điểm đánh giá: 2605 (tuyệt vời)

Đã gửi 26 December 2012 - 12:49 PM

Bác H dạo này viết lisp hay quá ^^
Theo ketxu thấy thì SS nên là list trước để kiểm tra trùng khử đệ quy, sau đó hãy chuyển list về Selectiionset thì hay hơn bác ạ, mỗi lần một ssnamex thì sẽ bị cộng dồn độ ... lâu
Theo ketxu thấy thì bộ lọc của LM khá tốt, kiểm tra cả Arc Ellipse ^^
- Ngoài ra cách chọn ssget tại đúng 1 điểm p vô tình đã loại ngay yêu cầu của bài toán : fuzz nhập vào rồi ^^
  • 2

Thành viên nhóm CadMagic.
Mời bạn ghé thăm facebook nhóm - Page viết lisp theo yêu cầu  :
CAD MAGIC


#17 gia_bach

gia_bach

    biết lệnh adcenter

  • CADViet Team
  • PipPipPipPipPipPipPip
  • 1435 Bài viết
Điểm đánh giá: 1426 (rất tốt)

Đã gửi 26 December 2012 - 01:14 PM

Chú Lee này ở Anh chứ không phải ở... Hàn. Dân CV hay sưu tầm và học hỏi lisp của chú ấy, chứ không phải chú ấy là dân CV.
Code sửa lại theo góp ý của ThuyLinh+GiaBach. Mọi người test xem ổn không nhé! Và góp ý để học hỏi, bởi tôi cũng đồng quan điểm với bạn ThuyLinh là Lee chọn và duyệt tất cả bản vẽ thì oải quá. Điều kiện lọc của Lee cũng rườm rà nữa (nhưng chưa sửa).


(defun C:HA ( / sf ss0 ent0 lst)
;Doan Van Ha - CADViet.com - Ngay 25/12/2012. Modify 26/12/2012
;Chuc nang: Chon doi tuong noi tiep nhau (LINE,ARC,LWPOLYLINE,SPLINE,POLYLINE,ELLIPSE).
;Lisp nay viet lai lisp cua Lee Mac de chay nhanh hon.
(vl-load-com)
(setq sf
(list
'(-4 . "<OR")
'(0 . "LINE,ARC")
'(-4 . "<AND") '(0 . "LWPOLYLINE,SPLINE") '(-4 . "<NOT") '(-4 . "&=") '(70 . 1) '(-4 . "NOT>") '(-4 . "AND>")
'(-4 . "<AND") '(0 . "POLYLINE") '(-4 . "<NOT") '(-4 . "&") '(70 . 89) '(-4 . "NOT>") '(-4 . "AND>")
'(-4 . "<AND") '(0 . "ELLIPSE") '(-4 . "<OR") '(-4 . "<>") '(41 . 0.0) '(-4 . "<>") (cons 42 (+ pi pi)) '(-4 . "OR>") '(-4 . "AND>")
'(-4 . "OR>")
(if (= 1 (getvar 'cvport)) (cons 410 (getvar 'ctab)) '(410 . "Model"))))
(if (setq ss0 (ssget "_+.:E:S" sf))
(progn
(command "zoom" "e")
(setq ss (ssadd (setq ent0 (ssname ss0 0))))
(HA (vlax-curve-getstartpoint ent0) ent0)
(HA (vlax-curve-getendpoint ent0) ent0)))
(command "zoom" "p")
(sssetfirst nil ss)
(princ))
;-----
(defun HA(p ent / ss1 i ent1 q1 q2)
(setq ss1 (ssdel ent (ssget "c" p p sf)) i -1)
(repeat (sslength ss1)
(setq ent1 (ssname ss1 (setq i (1+ i))))
(if (not (member ent1 (vl-remove-if 'listp (mapcar 'cadr (ssnamex ss)))))
(progn
(setq q1 (vlax-curve-getstartpoint ent1))
(setq q2 (vlax-curve-getendpoint ent1))
(cond
((equal p q1 1e-8)
(setq ss (ssadd ent1 ss))
(HA q2 ent1))
((equal p q2 1e-8)
(setq ss (ssadd ent1 ss))
(HA q1 ent1)))))))

Có thể thay đoạn : (member ent1 (vl-remove-if 'listp (mapcar 'cadr (ssnamex ss))))
bằng : (ssmemb ent1 ss)

Do bài toán cụ thể của tôi hơi khác mọi người!
Nên khi dùng đệ quy, SSGET bị giới hạn trong khoảng 128 lần
- > ; error: exceeded maximum number of selection sets

Trong t/hợp tương tự bản vẽ này : http://www.cadviet.c..._connect_00.dwg thì cách (ssget all) là tốt nhất ?
  • 1

#18 LoveLisp

LoveLisp

    biết lệnh extend

  • Members
  • PipPipPip
  • 195 Bài viết
Điểm đánh giá: 20 (tàm tạm)

Đã gửi 26 December 2012 - 01:36 PM

Bài toán này giới hạn ở 126 đối tượng về mỗi hướng, nghĩa là nếu pick vào 1 line thì nó có thể dò tối đa được 126+126=242 đối tượng. Tổng cộng không quá 243 đối tượng.
Khi biết chính xác con số này, ta có thể khống chế số lần đệ quy để không bị lỗi như trên.
  • 0

#19 Doan Van Ha

Doan Van Ha

    biết lệnh adcenter

  • CADViet Team
  • PipPipPipPipPipPipPip
  • 5447 Bài viết
Điểm đánh giá: 2624 (tuyệt vời)

Đã gửi 26 December 2012 - 01:48 PM

1). Bác H dạo này viết lisp hay quá ^^
2). Theo ketxu thấy thì SS nên là list trước để kiểm tra trùng khử đệ quy, sau đó hãy chuyển list về Selectiionset thì hay hơn bác ạ, mỗi lần một ssnamex thì sẽ bị cộng dồn độ ... lâu
3). Theo ketxu thấy thì bộ lọc của LM khá tốt, kiểm tra cả Arc Ellipse ^^
4). - Ngoài ra cách chọn ssget tại đúng 1 điểm p vô tình đã loại ngay yêu cầu của bài toán : fuzz nhập vào rồi ^^

1). Thanks! Cứ đi bòn từng chút ở đâu đó thì dần cũng đỡ tệ hơn.
2). Chính xác.
3). Lọc đủ nhưng code hơi rườm.
4). Bài toán gốc không có fuzz, chứ nếu có thì sửa lại chút xíu à.

1). Có thể thay đoạn : (member ent1 (vl-remove-if 'listp (mapcar 'cadr (ssnamex ss)))) bằng : (ssmemb ent1 ss)
2). Do bài toán cụ thể của tôi hơi khác mọi người! Nên khi dùng đệ quy, SSGET bị giới hạn trong khoảng 128 lần - > ; error: exceeded maximum number of selection sets
Trong t/hợp tương tự bản vẽ này : http://www.cadviet.c..._connect_00.dwg thì cách (ssget all) là tốt nhất ?

1). Khi viết, cứ nhớ mang máng có hàm gì đó kiểm tra ename có thuộc ss không, tự dưng quên mất ssmemb.
2). Đúng là ss giới hạn <=128. Để suy nghĩ xem có biện pháp gì xử vụ này không. Nếu không xử được thì chấp nhận chú Lee thôi.

Bài toán này giới hạn ở 126 đối tượng về mỗi hướng, nghĩa là nếu pick vào 1 line thì nó có thể dò tối đa được 126+126=242 đối tượng. Tổng cộng không quá 243 đối tượng.
Khi biết chính xác con số này, ta có thể khống chế số lần đệ quy để không bị lỗi như trên.

Lý luận của bạn không chính xác, bởi bản vẽ của bác Gia_Bach gởi lên chỉ có 218 em nhưng vẫn vượt.
  • 0

* Chỉ nên yêu cầu Lisp khi bạn làm việc đó mất cả ngày nhưng họ chỉ viết 1 giờ. Đừng nêu yêu cầu Lisp khi bạn chỉ làm 1 giờ nhưng bắt họ phải mất cả ngày.

* Nhờ viết lisp cũng như đi khám bệnh. Chỉ gởi căn cước và than sắp chết thì không bác sỹ nào cứu sống được.


#20 LoveLisp

LoveLisp

    biết lệnh extend

  • Members
  • PipPipPip
  • 195 Bài viết
Điểm đánh giá: 20 (tàm tạm)

Đã gửi 26 December 2012 - 02:08 PM

Để đơn giản, mình chỉ kiểm tra theo 1 phương, nghĩa là tất cả các đối tượng nối tiếp nhau và tạo nên 1 đường thẳng.
1. Bạn vẽ line 1 đơn vị, array nó ra 1 hàng 126 cột, chạy lệnh và pick vào đối tượng đầu tiên, OK!
2. Bạn vẽ line 1 đơn vị, array nó ra 1 hàng 127 cột, chạy lệnh và pick vào đối tượng đầu tiên, báo lỗi.
3. Xong bước 1, bạn đối xứng 125 đối tượng bên phải để tạo thêm 125 đối tượng bên trái, chạy lệnh và pick vào đối tượng chính giữa, OK!
4. Sau bước 3, nếu bạn thêm bất kỳ đối tượng nào về hai hướng đều báo lỗi cả!!!
  • 0