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

[Yêu cầu] viết Lisp dời text về vị trí điểm point gần nhất

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

Thể theo y/c của bác PhamThanhBinh và bạn Hochoaihetdot cùng chủ topic, tôi viết lại Lisp này để sử dụng thuận tiện hơn.

Tốc độ tương đương Lisp bác Bình nhưng sẽ không để "lọt lưới".

Đã test trên bản vẽ (đính kèm) gồm 5000 Texts và 5000 Points thì Lisp của tôi và của bác Bình đều mất tầm 15".

Có thể phân mảnh nhỏ dần để tăng tốc độ, nhưng khá rắc rối nên làm biếng lắm.

Các bạn test cho vui nhé!

File Cad::

http://www.cadviet.com/upfiles/3/67029_tim_diem_gan_text.dwg

File Lisp (gồm 3 LisP của KET, PTB, DVH):

 

;;; this lisp was downloaded from http://www.cadviet.com/forum/topic/90291-yeu-cau-viet-lisp-doi-text-ve-vi-tri-diem-point-gan-nhat/
;by Ketxu, khoang 4'15" cho 5000 Texts + 5000 Points.
(defun C:KET(/ lst lstData lstT lstP p)
 (and
  (setq ss (ssget (list (cons 0 "TEXT,POINT"))))
  (setq time (getvar "millisecs"))
  (not (command "undo" "be"))
  (setq lstData (mapcar 'entget (acet-ss-to-list ss)))
  (foreach e lstData
   (if (= (cdadr e) "TEXT")
    (setq lstT (cons e lstT)) (setq lstP (cons e lstP)))))
 (foreach oT lstT
  (setq p (acet-dxf 11 oT))
  (setq lstP (vl-sort lstP '(lambda(x y)(< (distance (acet-dxf 10 x) p)(distance (acet-dxf 10 y) p)))))
  (entmod (append oT (list (cons 11 (acet-dxf 10 (car lstP))))))
  (setq lstP (cdr lstP)))
 (command "undo" "e")
 (setq phut (/ (- (getvar "millisecs") time) 60000.0))
 (princ (strcat "\nThoi gian chay chuong trinh: " (itoa (fix phut)) "'" (itoa (fix (* 60 (- phut (fix phut))))) "\"."))
 (princ))
;by PhamThanhBinh, khoang 15" cho 5000 Texts + 5000 Points.
(defun C:PTB (/ oldos sslst box polst p)
 (setq sslst (mapcar 'entget (acet-ss-to-list (ssget (list (cons 0 "text"))))))
 (setq time (getvar "millisecs"))
 (command "undo" "be")
 (foreach e sslst
  (setq box (acet-ent-geomextents (cdr (assoc -1 e)))
        polst (mapcar 'entget (acet-ss-to-list (ssget "c" (car box) (cadr box) (list (cons 0 "point")))))
        p (cdr (assoc 11 e)))
  (if polst
   (progn
    (setq polst (vl-sort polst '(lambda (x y) (< (distance (cdr (assoc 10 x)) p) (distance (cdr (assoc 10 y)) p)))))
    (entmod (subst (cons 11 (cdr (assoc 10 (car polst)))) (assoc 11 e) e)))))
 (command "undo" "e")
 (setq phut (/ (- (getvar "millisecs") time) 60000.0))
 (princ (strcat "\nThoi gian chay chuong trinh: " (itoa (fix phut)) "'" (itoa (fix (* 60 (- phut (fix phut))))) "\"."))
 (princ))
;by DoanVanHa, khoang 15" cho 5000 Texts + 5000 Points.
(defun C:DVH(/ ss time lst1 lst2 p1 p2 dis lst3 phut)
 (and
  (setq ss (ssget (list (cons 0 "TEXT,POINT"))))
  (setq time (getvar "millisecs"))
  (not (command "undo" "be"))
  (foreach e (mapcar 'entget (acet-ss-to-list ss))
   (if (= (cdadr e) "TEXT")
    (setq lst1 (cons (list (cdr (assoc -1 e)) (cdr (assoc 11 e))) lst1)) (setq lst2 (cons (cdr (assoc 10 e)) lst2))))
  (= (length lst1) (length lst2))
  (foreach n lst1
   (setq ent1 (car n)
         p1 (cadr n)
p2 (car lst2)
lst3 (list ent1 p1 p2 (distance p1 p2)))
   (foreach p2 lst2
    (if (< (setq dis (distance p1 p2)) (cadddr lst3))
     (setq lst3 (list ent1 p1 p2 dis))))
   (entmod (subst (cons 11 (setq p2 (caddr lst3))) (cons 11 (cadr lst3)) (entget (car lst3))))
   (setq lst2 (vl-remove p2 lst2)))
   (not (command "undo" "e")))
 (setq phut (/ (- (getvar "millisecs") time) 60000.0))
 (princ (strcat "\nThoi gian chay chuong trinh: " (itoa (fix phut)) "'" (itoa (fix (* 60 (- phut (fix phut))))) "\"."))
 (princ))
 
  • 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

gửi Gia_Bach file minh họa lỗi của lisphttp://www.cadviet.com/upfiles/3/126823_yc_viet_lisp.dwg

Hề hề hề,

Thank bác DoanVanHa về thuật toán mới.

@ANHSURVEY: Bạn nên hiểu chút chut về lisp để biết rằng lisp không thể là công cụ vạn năng cho mọi trường hợp của người sử dụng. Nó chỉ có thể giúp người sử dụng giải quyết vấn đề nhanh hơn khi người sử dụng quản lý bản vẽ của mình một cách thống nhất và có kiểm soát ở mức độ tối thiểu để đảm bảo điều kiện làm việc của lisp.

Thông thường người viết lisp sẽ phải căn cứ vào các bản cẽ cụ thể do người yêu cầu đưa ra để xác định các tham số điều kiện làm việc của lisp. Từ đó viết ra một đoạn code để lisp làm việc với các điều kiện đó và cho ra kết quả mong muốn của người sử dụng. Do người viết lisp thường không có cùng hcuye6n môn cũng như môi trường làm việc với người yêu cầu nên khó có thể xác định được chính xác những gì cần phải xác lập khi định ra các điều kiện làm việc này của lisp. và đó là lý do mà lisp có thể chạy tốt với bản vẽ mẫu mà người yêu cầu đã gửi, nhưng lại có trục trặc khi người yêu cầu sử dụng với các bản vẽ khác.

Do vậy người yêu cầu viết lisp cần phải có kiến thức nhất định về lisp để có thể căn cứ vào lisp đã được viết, hiệu chỉnh lại các điều kiện làm việc của nó cho phù hợp với bản vẽ mà mình sử dụng mới có thể cho kết quả như ý muốn. Còn việc cứ áp dụng bừa các lisp được viết ra mà không hiểu gì về nó sẽ là một điều nguy hiểm bởi nó có thể phá nát công sức của bạn mà bạn không thể khắc phục được.

Cụ thể với các trường hợp lỗi mà bạn đã post lên cho thấy các đối tượng text của bạn được quản lý không thống nhất, lúc thì căn phải, lúc thì căn giữa.... Vi trí tương đối của chúng so với point cần chuyển về cũng không thực sự là "gần nhất" (trường hợp hai text A2-041 và A2-0450 trong ví dụ thứ ba bạn đưa ra).

Và đó cũng chính là lý do mà lisp không cho ra kết quả như ý muốn được. Không chỉ lisp do mình viết mà với tất cả các lisp khác của bác ketxu hay bác DoanvanHa cũng có thể sẽ gặp lỗi ở trường hợp này.

Hy vọng bạn hiểu và sẽ tự hoàn thiện khả năng của mình để có thể đáp ứng yêu cầu của công việc. 

  • 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ụ thể với các trường hợp lỗi mà bạn đã post lên cho thấy các đối tượng text của bạn được quản lý không thống nhất, lúc thì căn phải, lúc thì căn giữa.... Vi trí tương đối của chúng so với point cần chuyển về cũng không thực sự là "gần nhất" (trường hợp hai text A2-041 và A2-0450 trong ví dụ thứ ba bạn đưa ra).

Và đó cũng chính là lý do mà lisp không cho ra kết quả như ý muốn được. Không chỉ lisp do mình viết mà với tất cả các lisp khác của bác ketxu hay bác DoanvanHa cũng có thể sẽ gặp lỗi ở trường hợp này.

Hy vọng bạn hiểu và sẽ tự hoàn thiện khả năng của mình để có thể đáp ứng yêu cầu của công việc. 

Bác Bình: cái đám texts và points này không tương thích, nghĩa là số texts không bằng số points nên lisp nghỉ chơi, chứ không lỗi.

Thực ra, ai cũng có thể đưa ra 1 cảnh báo nhưng tôi muốn chủ topic phải có trách nhiệm với chính mình thôi, bởi câu hỏi rất hời hợt.

Dùng AND là vì lí do đó, còn dùng IF thì khác ngay thô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

 

Thể theo y/c của bác PhamThanhBinh và bạn Hochoaihetdot cùng chủ topic, tôi viết lại Lisp này để sử dụng thuận tiện hơn.

Tốc độ tương đương Lisp bác Bình nhưng sẽ không để "lọt lưới".

Đã test trên bản vẽ (đính kèm) gồm 5000 Texts và 5000 Points thì Lisp của tôi và của bác Bình đều mất tầm 15".

Có thể phân mảnh nhỏ dần để tăng tốc độ, nhưng khá rắc rối nên làm biếng lắm.

Các bạn test cho vui nhé!

File Cad::

http://www.cadviet.com/upfiles/3/67029_tim_diem_gan_text.dwg

File Lisp (gồm 3 LisP của KET, PTB, DVH):

 

;;; this lisp was downloaded from http://www.cadviet.com/forum/topic/90291-yeu-cau-viet-lisp-doi-text-ve-vi-tri-diem-point-gan-nhat/
;by Ketxu, khoang 4'15" cho 5000 Texts + 5000 Points.
(defun C:KET(/ lst lstData lstT lstP p)
 (and
  (setq ss (ssget (list (cons 0 "TEXT,POINT"))))
  (setq time (getvar "millisecs"))
  (not (command "undo" "be"))
  (setq lstData (mapcar 'entget (acet-ss-to-list ss)))
  (foreach e lstData
   (if (= (cdadr e) "TEXT")
    (setq lstT (cons e lstT)) (setq lstP (cons e lstP)))))
 (foreach oT lstT
  (setq p (acet-dxf 11 oT))
  (setq lstP (vl-sort lstP '(lambda(x y)(< (distance (acet-dxf 10 x) p)(distance (acet-dxf 10 y) p)))))
  (entmod (append oT (list (cons 11 (acet-dxf 10 (car lstP))))))
  (setq lstP (cdr lstP)))
 (command "undo" "e")
 (setq phut (/ (- (getvar "millisecs") time) 60000.0))
 (princ (strcat "\nThoi gian chay chuong trinh: " (itoa (fix phut)) "'" (itoa (fix (* 60 (- phut (fix phut))))) "\"."))
 (princ))
;by PhamThanhBinh, khoang 15" cho 5000 Texts + 5000 Points.
(defun C:PTB (/ oldos sslst box polst p)
 (setq sslst (mapcar 'entget (acet-ss-to-list (ssget (list (cons 0 "text"))))))
 (setq time (getvar "millisecs"))
 (command "undo" "be")
 (foreach e sslst
  (setq box (acet-ent-geomextents (cdr (assoc -1 e)))
        polst (mapcar 'entget (acet-ss-to-list (ssget "c" (car box) (cadr box) (list (cons 0 "point")))))
        p (cdr (assoc 11 e)))
  (if polst
   (progn
    (setq polst (vl-sort polst '(lambda (x y) (< (distance (cdr (assoc 10 x)) p) (distance (cdr (assoc 10 y)) p)))))
    (entmod (subst (cons 11 (cdr (assoc 10 (car polst)))) (assoc 11 e) e)))))
 (command "undo" "e")
 (setq phut (/ (- (getvar "millisecs") time) 60000.0))
 (princ (strcat "\nThoi gian chay chuong trinh: " (itoa (fix phut)) "'" (itoa (fix (* 60 (- phut (fix phut))))) "\"."))
 (princ))
;by DoanVanHa, khoang 15" cho 5000 Texts + 5000 Points.
(defun C:DVH(/ ss time lst1 lst2 p1 p2 dis lst3 phut)
 (and
  (setq ss (ssget (list (cons 0 "TEXT,POINT"))))
  (setq time (getvar "millisecs"))
  (not (command "undo" "be"))
  (foreach e (mapcar 'entget (acet-ss-to-list ss))
   (if (= (cdadr e) "TEXT")
    (setq lst1 (cons (list (cdr (assoc -1 e)) (cdr (assoc 11 e))) lst1)) (setq lst2 (cons (cdr (assoc 10 e)) lst2))))
  (= (length lst1) (length lst2))
  (foreach n lst1
   (setq ent1 (car n)
         p1 (cadr n)
p2 (car lst2)
lst3 (list ent1 p1 p2 (distance p1 p2)))
   (foreach p2 lst2
    (if (< (setq dis (distance p1 p2)) (cadddr lst3))
     (setq lst3 (list ent1 p1 p2 dis))))
   (entmod (subst (cons 11 (setq p2 (caddr lst3))) (cons 11 (cadr lst3)) (entget (car lst3))))
   (setq lst2 (vl-remove p2 lst2)))
   (not (command "undo" "e")))
 (setq phut (/ (- (getvar "millisecs") time) 60000.0))
 (princ (strcat "\nThoi gian chay chuong trinh: " (itoa (fix phut)) "'" (itoa (fix (* 60 (- phut (fix phut))))) "\"."))
 (princ))
 

 

Mình đã đọc code của DoanVanHa.

Về cơ bản, lisp DVH gần như giống lisp ketxu. Nhưng có 1 cải thiện rất hay là (setq lst2 (vl-remove p2 lst2)).

Tức là sau mỗi vòng lặp, đã tìm được điểm point nào gần nhất rồi thì loại ra khỏi list để vòng lặp sau giảm bớt 1 vòng lặp.

Cảm ơn bác Hạ!

  • 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 đã đọc code của DoanVanHa.

Về cơ bản, lisp DVH gần như giống lisp ketxu. Nhưng có 1 cải thiện rất hay là (setq lst2 (vl-remove p2 lst2)).

Tức là sau mỗi vòng lặp, đã tìm được điểm point nào gần nhất rồi thì loại ra khỏi list để vòng lặp sau giảm bớt 1 vòng lặp.

Cảm ơn bác Hạ!

Có 1 điều rất cơ bản nữa mà HHVD chưa nhận ra: đó là cách tạo lst1 và lst2. Nếu lst1 và lst2 lấy toàn bộ dữ liệu của đối tượng thì khi xử lý chúng trong vòng lặp sẽ rất chậm >> tôi chỉ lấy lst1 gồm 2 dữ liệu là ename và point, lst2 chỉ 1 dữ liệu là point.

2 cách lấy dữ liệu khác nhau này nó làm giảm thời gian chạy chương trình từ 3 đến 4 lần lận!

  • 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

Mình đã đọc code của DoanVanHa.

Về cơ bản, lisp DVH gần như giống lisp ketxu. Nhưng có 1 cải thiện rất hay là (setq lst2 (vl-remove p2 lst2)).

Tức là sau mỗi vòng lặp, đã tìm được điểm point nào gần nhất rồi thì loại ra khỏi list để vòng lặp sau giảm bớt 1 vòng lặp.

Cảm ơn bác Hạ!

Hề hề hề,

Thực ra thì lisp của Ketxu cũng đã loại bỏ các điểm đã được chọn xong ra khỏi list point như của bác DoanvanHa, tuy nhiên cái list của bác Ha đúng là có ít dữ liệu hơn.

Vấn đề ờ đây còn phụ thuộc vào cả cái trật tự nhập text của chủ thớt nữa. Nếu các text không nhập đúng với trật tự point thì sẽ có trường hợp tréo ngoe Chẳng hạn như hai điểm A2-041 và A2-045 của bản vẽ chủ thớt gửi lên. Với cách này nếu text nào nhập trước thì nó sẽ xơi cái điểm gần nhất chứ chưa hẳn là đúng trật tự mong muốn.

Vì vậy mình mới có lời nhắc chủ thớt nên quản lý bản vẽ theo một quy định nhất định sẽ thuận lợi hơn cho việc xử lý bằng lisp về sau này.

  • 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ó 1 điều rất cơ bản nữa mà HHVD chưa nhận ra: đó là cách tạo lst1 và lst2. Nếu lst1 và lst2 lấy toàn bộ dữ liệu của đối tượng thì khi xử lý chúng trong vòng lặp sẽ rất chậm >> tôi chỉ lấy lst1 gồm 2 dữ liệu là ename và point, lst2 chỉ 1 dữ liệu là point.

2 cách lấy dữ liệu khác nhau này nó làm giảm thời gian chạy chương trình từ 3 đến 4 lần lận!

Code của KET chậm hơn là do SORT danh sách chứ không phải do lấy toàn bộ dữ liệu. KET cũng có dòng remove p/tử đã dùng.

Sort chỉ có ý nghĩa khi cần lấy nhiều hơn 1 phần tử (phần tử thứ 2, thứ ba ...).

 

Lisp DVH vs PTB

- code DVH : do duyệt qua toàn bộ danh sách nên thích hợp với t/hợp danh sách data vừa và nhỏ, nếu ch/dài d/sách là đủ lớn (vd: gấp 10 lần file mẫu) thì th/gian chưa phải tối ưu.

- code DVH kô để lọt lưới nhưng khả năng xảy ra t/hợp "râu ông này cắm cằm bà kia" là có.  (và còn có đoạn "mặc áo vào rồi cởi áo ra")

- code PTB : do Select theo đường bao của Text nên k/quả đôi khi kô đạt 100% (bác Bình cũng đã có cách khắc phục). Cá nhân tôi thích p/pháp này hơn.

- cả hai : việc để "lọt lưới" hay "bắt cặp sai" phụ thuộc nhiều vào cách chủ thớt quản lý file, không có Lisp nào "chắc chắn 100%". 

  • 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

Hề hề hề,

Thực ra thì lisp của Ketxu cũng đã loại bỏ các điểm đã được chọn xong ra khỏi list point như của bác DoanvanHa, tuy nhiên cái list của bác Ha đúng là có ít dữ liệu hơn.

Vấn đề ờ đây còn phụ thuộc vào cả cái trật tự nhập text của chủ thớt nữa. Nếu các text không nhập đúng với trật tự point thì sẽ có trường hợp tréo ngoe Chẳng hạn như hai điểm A2-041 và A2-045 của bản vẽ chủ thớt gửi lên. Với cách này nếu text nào nhập trước thì nó sẽ xơi cái điểm gần nhất chứ chưa hẳn là đúng trật tự mong muốn.

Vì vậy mình mới có lời nhắc chủ thớt nên quản lý bản vẽ theo một quy định nhất định sẽ thuận lợi hơn cho việc xử lý bằng lisp về sau này.

Code hiện tại của bạn các bạn chỉ chạy tốt trên bản vẽ chuẩn,

Code hiện tại của bạn DVH có thể gây sai dây chuyền trên toàn bộ bản vẽ.

Code hiện tại của bạn PTB có thể gây sai cục bộ nhiều nơi trên bản vẽ.

Nếu không chuẩn như bản vẽ đưa lên thì khó có thể tìm được chỗ sai để xử lý.

Thực ra thì khó có bản vẽ nào là không có lỗi, nhất là khi bản vẽ đó lại do người khác cung cấp. Vì vậy tôi nghĩ là gặp trường hợp chọn được số điểm khác 1 thì không xử lý mà sẽ đánh dấu VD đổi màu text (tương tự như lisp chọn bộ 5 text mà tôi và bạn đã tham gia).

Các trường hợp đúng sẽ xử lý. Sau khi chạy xong, viết tiếp 1 đoạn để kiểm tra đánh dấu point nào không có text(VD ở vị trí A2-201).

Phần xử lý còn lại là dành cho chủ thớt, như vậy tuy sẽ mất thời gian hơn 1 ít nhưng bảo đảm điều quan trọng nhất là tìm được chỗ sai để xử lý.

  • 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

Code của KET chậm hơn là do SORT danh sách chứ không phải do lấy toàn bộ dữ liệu. KET cũng có dòng remove p/tử đã dùng.

Sort chỉ có ý nghĩa khi cần lấy nhiều hơn 1 phần tử (phần tử thứ 2, thứ ba ...).

 

Lisp DVH vs PTB

- code DVH : do duyệt qua toàn bộ danh sách nên thích hợp với t/hợp danh sách data vừa và nhỏ, nếu ch/dài d/sách là đủ lớn (vd: gấp 10 lần file mẫu) thì th/gian chưa phải tối ưu.

- code DVH kô để lọt lưới nhưng khả năng xảy ra t/hợp "râu ông này cắm cằm bà kia" là có.  (và còn có đoạn "mặc áo vào rồi cởi áo ra")

- code PTB : do Select theo đường bao của Text nên k/quả đôi khi kô đạt 100% (bác Bình cũng đã có cách khắc phục). Cá nhân tôi thích p/pháp này hơn.

- cả hai : việc để "lọt lưới" hay "bắt cặp sai" phụ thuộc nhiều vào cách chủ thớt quản lý file, không có Lisp nào "chắc chắn 100%". 

Bản chất y/c của chủ topic là bắt từng cặp đôi một gần nhau, sau đó move text đến point. Do đó, nếu cơ sở dữ liệu sắp xếp không đúng thì kết quả sai là đành chịu thôi. Cái này chắc không có ai hoặc không có phương pháp nào có thể khắc phục được (?)

Màu xanh: 10000 (5000+5000) thì đã test, nhiều hơn sợ treo máy nên chưa test. Có thể PTB nhanh hơn DVH.

Màu đỏ: không có chuyện râu ông nọ cắm cằm bà kia và cũng không có chuyện nhảy cà tưng, vì:

- Mỗi text chỉ xét 1 lần. Nó chọn point gần nhất để ôm hôn, sau đó biến mất, không còn dịp để ôm hôn con khác nữa.

- Point nào đã kéo text về thì point đó sẽ bị loại ra khỏi vòng chiến đấu rồi.

Màu tím: nếu khoảng cách giữa text và point là cố định thì cái của bác PTB gọn gàng. Còn như khoảng cách giữa text và point không cố định (nhưng vẫn đi liền từng cặp - gần nhau) thì trở thành phiêu lưu. Biến PDMODE hoặc tăng khoảng cách Window thì biết mấy cho vừa?

@ndtnv: bạn có thể nói rõ sự sai dây chuyền được khô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

Một ví dụ sai dây chuyền : giả sử Text A2--227 xét trước nó sẽ bắt cặp với point màu tím, sau đó Text A2-232 chỉ còn chọn lựa duy nhất là bắt cặp với point màu xanh

Và điều uan trọng là sau khi chạy Lisp, không có khả năng k/tra k/quả đúng hay sai.

Với t/hợp lọt lưới thì dễ dàng k/tra xem có thằng nào "cô đơn" không?15454_error11.jpg

......

Màu đỏ: không có chuyện râu ông nọ cắm cằm bà kia và cũng không có chuyện nhảy cà tưng, vì:

- Mỗi text chỉ xét 1 lần. Nó chọn point gần nhất để ôm hôn, sau đó biến mất, không còn dịp để ôm hôn con khác nữa.

- Point nào đã kéo text về thì point đó sẽ bị loại ra khỏi vòng chiến đấu rồi.

@ndtnv: bạn có thể nói rõ sự sai dây chuyền được khô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

Bản chất y/c của chủ topic là bắt từng cặp đôi một gần nhau, sau đó move text đến point. Do đó, nếu cơ sở dữ liệu sắp xếp không đúng thì kết quả sai là đành chịu thôi. Cái này chắc không có ai hoặc không có phương pháp nào có thể khắc phục được (?)

Màu xanh: 10000 (5000+5000) thì đã test, nhiều hơn sợ treo máy nên chưa test. Có thể PTB nhanh hơn DVH.

Màu đỏ: không có chuyện râu ông nọ cắm cằm bà kia và cũng không có chuyện nhảy cà tưng, vì:

- Mỗi text chỉ xét 1 lần. Nó chọn point gần nhất để ôm hôn, sau đó biến mất, không còn dịp để ôm hôn con khác nữa.

- Point nào đã kéo text về thì point đó sẽ bị loại ra khỏi vòng chiến đấu rồi.

Màu tím: nếu khoảng cách giữa text và point là cố định thì cái của bác PTB gọn gàng. Còn như khoảng cách giữa text và point không cố định (nhưng vẫn đi liền từng cặp - gần nhau) thì trở thành phiêu lưu. Biến PDMODE hoặc tăng khoảng cách Window thì biết mấy cho vừa?

@ndtnv: bạn có thể nói rõ sự sai dây chuyền được không?

Giả sử có 1 cặp text và point sai ở vị trí A2-012 như trong hình, Text A2-012 là phần tử đầu tiê19626_dc.jpgn,

  

Giả sử có 1 cặp text và point sai ở vị trí A2-012 như trong hình, Text A2-012 là phần tử đầu tiên,

nó sẽ bắt cặp với point ở A2-013. Nếu Text A2-013 là phần tử tiếp theo thì đến lượt nó sẽ chọn point ở A2-001. Nếu theo đề xuất của tôi thì sẽ xử lý ở A2-001 và A2-013. Còn Text A2-012 và point còn lại sẽ đánh dấu là lỗ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

@Gia_Bach + ndtnv:

Chúng ta đang bàn về một bài toán thực tế, vì vậy đôi lúc cũng phải chấp nhận xây dựng thuật toán trên những cơ sở thực tế. Thực tế đó là các text và point phải nhóm thành từng cặp với nhau.

Lisp của bác PTB chạy tốt nếu vị trí tương đối của từng cặp text-point gần như nhau và giá trị này là cố định.

Lisp của tôi cho phép vị trí tương đối của từng cặp có thể thay đổi.

Nếu 1 bản vẽ có số lượng text và point khác nhau, hoặc bằng nhau nhưng sắp xếp không theo quy luật gì cả thì có Ông Trời cũng bó tay thôi.

Hình đính kèm minh họa 1 trường hợp đơn giản nhất nhưng có 2 đáp án. Chả biết cách nào là đúng cả!

67029_ghep_text.png

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ài toán của bác Anhsurvey đưa ra là trường hợp đơn giản thôi các bác ạ. Không phức tạp như các bác nêu. Thường thì bài toán đạt yêu cầu chủ thớt là ok, còn biến tấu sáng tạo thế nào lại là chuyện khác.

Không biết chủ thớt có đúng ý như này không? Đó là việc nổ bung số liệu dạng điểm chạy trên TOPO (HS, Nova...). (Đối tượng này có thể gồm STT, Cao độ, Mô tả....) Nó thuộc dạng Proxy, nên khi nổ bung thì Text nó rời rạc. Chủ thớt muốn đưa về cùng 1 vị trí đó mà. ^^

P/s: Dạo này em bận quá nên không vào Cadviet được mấ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

 

Hình ðính kèm minh họa 1 trýờng hợp ðõn giản nhất nhýng có 2 ðáp án. Chả biết cách nào là ðúng cả!

67029_ghep_text.png

Nhý vậy thì bài toán này vẫn giải ðýợc. Nhýng vòng lặp nhiều.

Xét point1. 

Khoảng cách point 1 ðến tẽxt A = dis1A

Khoảng cách point 1 ðến tẽxt B = dis1B

 

Ðế ðây, chýa so sánh dis1A với dis1B ðể kết luận cho point1 hôn A hay B.

Mà tiếp tục Xét point2 

Khoảng cách point 2 ðến tẽxt A = dis2A

Khoảng cách point 2 ðến tẽxt B = dis2B

 

Ðến ðây ta so sánh tìm ra dis nhỏ nhất giữa  dis1A,  dis1B,  dis2A,  dis2B

Ví dụ dis2A nhỏ nhất thì cho point2 hôn text A. Và loại hẳn những dis liên quan ðến cặp ðiểm này ðể xét tiếp.

 

Tổng quát hõn tí có 3 point P1, P2, P3 và 3 text T1, T2, T3

Týõng ứng có tập hợp khảng cách (P1T1, P1T2, P1T3, P2T1, P2T2, P2T3, P3T1, P3T2, P3T3)

Tìm khoảng cách nhỏ nhất: Ví dụ: P2T3. Ta làm 2 ðộng tác:

 (1) Nhóm P2 và T3 thành cặp ðôi hoàn hảo

 (2) Loại tấc cả khoảng cách nào có sự tham gia của P2 và T3 khỏi list khoảng cách

list khoảng cách bây giờ (P1T1, P1T2, P3T1, P3T2).

Tiếp tục ðến khi nào list khoảng cách bị loại hết...

 

 

Chýõng trình chạy sẽ lâu lắc nhýng mà ðúng yêu cầu khoảng cách nào gần nhất thì thành cặ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

Hoan nghênh!

Thử cái này xem sao.

http://www.cadviet.com/upfiles/3/127168_tmp.lsp

Nhanh hơn cả 2 lisp của DVH và PTB.

Học được 2 điều:

1). Lấy list point chỉ gồm x và y chứ không có z như của tôi. Cái này tăng tốc không nhiều.

2). Dùng vl-sort nhanh hơn foreach. Cái này không ngờ lại tăng tốc đáng kể (srr, tác giả chỉ sort 10 đối tượng).

P/S: Tuy nhiên, 2 hàm sort ss1 và ss2 thì hình như thừa (?)

  • 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

1. Chỉ lấy x y mà không lấy z là vì trong file dwg đầu tiên tri so z của các point khác nhau, neu lay luon z thì hàm distance se cho ket qua sai, chứ viec này không nhằm tăng tốc chuong trình.

2. Phải sort cả Point va Text từ x nhỏ y nhỏ đến x lớn y lớn, sau đó so sánh 1 Text với 10 Point gần nó nhất.

  • 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

1. Chỉ lấy x y mà không lấy z là vì trong file dwg đầu tiên tri so z của các point khác nhau, neu lay luon z thì hàm distance se cho ket qua sai, chứ viec này không nhằm tăng tốc chuong trình.

2. Phải sort cả Point va Text từ x nhỏ y nhỏ đến x lớn y lớn, sau đó so sánh 1 Text với 10 Point gần nó nhất.

Đỏ: tôi không hiểu quy tắc làm việc của hàm sort như thế nào, nhưng hình như nó phải so sánh tất cả các phần tử của list sau đó mới sắp xếp theo thứ tự. Nếu đúng như vậy thì việc sort trước không có ý nghĩa.

Bạn thử delete 2 hàm sort đó đi thì tốc độ không giảm (thậm chí tăng).

  • 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

Tôi khọng biết nội bộ hàm vl-sort thực hiện như thế nào, chỉ biết kết quả nó trả về là 2 dãy text va point sắp theo thứ tự từ nhỏ đến lớn.

 

Khi mình quơ cả đám text+point với hàm ssget thì cả 10000 cái text và point đó nó nằm lộn xộn trong hai dãy ss1 và ss2.

 

Dĩ nhiên mình phải sort 2 cai dãy đó truoc thi khi so sánh mình chỉ cần so sanh1 text với 10 point thôi (tôi lấy 10 là cũng hơi nhiều) , chứ nếu không thì với 1 text bạn phải so sánh vị trí của nó với vị trí của 5000 point, đó là lý do tại sao nếu bỏ 2 hàm sort đó thì chuong trình sẽ chậm đi nhiều.

  • 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ôi khọng biết nội bộ hàm vl-sort thực hiện như thế nào, chỉ biết kết quả nó trả về là 2 dãy text va point sắp theo thứ tự từ nhỏ đến lớn.

 

Khi mình quơ cả đám text+point với hàm ssget thì cả 10000 cái text và point đó nó nằm lộn xộn trong hai dãy ss1 và ss2.

 

Dĩ nhiên mình phải sort 2 cai dãy đó truoc thi khi so sánh mình chỉ cần so sanh1 text với 10 point thôi (tôi lấy 10 là cũng hơi nhiều) , chứ nếu không thì với 1 text bạn phải so sánh vị trí của nó với vị trí của 5000 point, đó là lý do tại sao nếu bỏ 2 hàm sort đó thì chuong trình sẽ chậm đi nhiều.

Hôm qua tôi đọc nhanh quá nên cứ tưởng con số 10 là dxf của point, ai ngờ nó là số lượng point để xét trong 1 lần.

Nói chung, giải pháp này nhanh và phù hợp khi các cặp text-point có vị trí tương đối giữa 2 đối tượng là cố định (cũng như giải pháp của bác Bình).

Khi text và point vẫn đi từng cặp với nhau, nhưng vị trí tương đối giữa 2 đối tượng có thể thay đổi thì cũng tiềm ẩn sự nhảy nhầm.

Mà, nếu vị trí tương đối của tất cả cặp text-point là constant thì đâu cần phải sort tới 10, chỉ cần lấy thằng đầu tiên là chính 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

Tôi khọng biết nội bộ hàm vl-sort thực hiện như thế nào, chỉ biết kết quả nó trả về là 2 dãy text va point sắp theo thứ tự từ nhỏ đến lớn.

 

Khi mình quơ cả đám text+point với hàm ssget thì cả 10000 cái text và point đó nó nằm lộn xộn trong hai dãy ss1 và ss2.

 

Dĩ nhiên mình phải sort 2 cai dãy đó truoc thi khi so sánh mình chỉ cần so sanh1 text với 10 point thôi (tôi lấy 10 là cũng hơi nhiều) , chứ nếu không thì với 1 text bạn phải so sánh vị trí của nó với vị trí của 5000 point, đó là lý do tại sao nếu bỏ 2 hàm sort đó thì chuong trình sẽ chậm đi nhiều.

Hề hề hề,

Thank bác tot77 về thuật toán mới.Việc Sort thành hai list texts và points với trật tự vị trí của chúng nếu trật tự của các cặp point +text là tương ứng sẽ giúp lisp chạy nhanh hơn.

Việc bác bỏ qua tọa độ Z cũng là một điều hợp lý nếu như chủ thớt chỉ yêu cầu xét khoảng cách theo mặt phẳng chiếu ..... nằm. Còn trường hợp mà chủ thớt lại yêu cầu xét theo khoảng cách không gian thực thì ..... chủ thớt phải sửa lại lisp vậy.

Tuy nhiên có một vấn đề là nếu việc quản lý bản vẽ này không thống nhất thì cũng sẽ khá oái oăm. Tỷ như text thứ n lại gần điểm thứ n+1 hơn là điểm thứ n, hoặc text thứ n gần với các điểm thứ n+1 và n+3 ... n+9  nhất và bằng nhau thì cũng gay.

Vấn đề này hoàn toàn phụ thuộc vào chủ thớt, và nếu chủ thớt hiểu được cấu trúc của lisp để tự hiệu chỉnh là tốt nhất. Còn việc bắt bệnh thì quả thật không dễ có thể biết hết các bệnh do việc quản lý bản vẽ này là của chủ thớt.

Theo quan điểm của mình thì ý kiến bác ndtnv là khá hợp lý trong trường hợp chủ thớt không thể tự mình xác định cái quy luật để quản lý bản vẽ hiệu quả.

  • 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ũng không cần phức tạp như các bác đã nêu. vì bài toán của mình là có các text của các cọc ép dự ứng lực đã được phun lên cad. và có tọa độ hoàn công các cọc thì bị lệch khỏi vị trí thiết kế, cái này không theo trật tự nào cả. khi đo bằng máy toàn đạc điện tử thì không thể gán tên cọc cùng lúc mà chỉ lấy tọa độ của nó rồi phun lên cad, cuối cùng dùng lisp dời text về point hoàn công rồi xuất ra. vậy 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

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


×