Chuyển đến nội dung
Diễn đàn CADViet
Đăng nhập để thực hiện theo  
thanhlamct

[yêu cầu] Viết lisp Break Pline tại điểm chèn Block.

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

Xin chào cả nhà.

Mình muốn nhờ mọi người viết giùm lisp như sau:

 

Hiện tại mình có 1 tuyến vẽ bằng Pline (hoặc Line), trên đó đã chèn các Block. Mình muốn dùng lisp Break tuyến Pline (hoặc Line) này tại điểm chèn của Block, sau đó nối lại thành 1 Pline. Hày nói cách khác là làm cho các điểm chèn của Block trên tuyến thành các đỉnh của Pline.

 

Xin cảm ơn cả nhà.

 

Bản vẽ kèm theo:

http://www.cadviet.com/upfiles/3/break_tai_block.dwg

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 chào cả nhà.

Mình muốn nhờ mọi người viết giùm lisp như sau:

 

Hiện tại mình có 1 tuyến vẽ bằng Pline (hoặc Line), trên đó đã chèn các Block. Mình muốn dùng lisp Break tuyến Pline (hoặc Line) này tại điểm chèn của Block, sau đó nối lại thành 1 Pline. Hày nói cách khác là làm cho các điểm chèn của Block trên tuyến thành các đỉnh của Pline.

 

Xin cảm ơn cả nhà.

 

Bản vẽ kèm theo:

http://www.cadviet.c...k_tai_block.dwg

Đây bạn!

;Doan Van Ha CADViet.com
(defun C:INS(/ obj p0 blk)
(setq oldcm (getvar "cmdecho") oldos (getvar "osmode"))
(setvar "cmdecho" 0) (setvar "osmode" 0)
(command "undo" "begin")
(setq obj (car (entsel "\n Chon Lwpolyline hoac Line...")))
(princ "\n Chon cac Block da insert tren Lwpolyline/Line...")
(setq blk (acet-ss-to-list (ssget '((0 . "INSERT")))))
(if (= (cdr (assoc 0 (entget obj))) "LINE")
 (progn
  (command "pedit" obj "")
  (setq obj (entlast))))
(if (= (cdr (assoc 0 (entget obj))) "LWPOLYLINE")
 (foreach ent blk
  (setq p0 (cdr (assoc 10 (entget ent))))
  (command "break" obj p0 p0)
  (command "pedit" obj "j" (entlast) "" "")))
(setvar "cmdecho" oldcm) (setvar "osmode" oldos)
(command "undo" "end")
(princ))

  • 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

Đây bạn!

;Doan Van Ha CADViet.com
(defun C:INS(/ obj p0 blk)
(setq oldcm (getvar "cmdecho") oldos (getvar "osmode"))
(setvar "cmdecho" 0) (setvar "osmode" 0)
(command "undo" "begin")
(setq obj (car (entsel "\n Chon Lwpolyline hoac Line...")))
(princ "\n Chon cac Block da insert tren Lwpolyline/Line...")
(setq blk (acet-ss-to-list (ssget '((0 . "INSERT")))))
(if (= (cdr (assoc 0 (entget obj))) "LINE")
 (progn
  (command "pedit" obj "")
  (setq obj (entlast))))
(if (= (cdr (assoc 0 (entget obj))) "LWPOLYLINE")
 (foreach ent blk
  (setq p0 (cdr (assoc 10 (entget ent))))
  (command "break" obj p0 p0)
  (command "pedit" obj "j" (entlast) "" "")))
(setvar "cmdecho" oldcm) (setvar "osmode" oldos)
(command "undo" "end")
(princ))

1. Giả sử như chọn nhầm lẫn Block có điểm chèn không nằm trên LINE thì Lisp chạy không đúng nữa.

-> Nên giải quyết thêm trường hợp : chọn Block -> Xét thêm điểm chèn của Block đó có nằm trên LINE hay PLINE hay không cái đã rồi mới thực hiện công việc tiếp theo.

Hoặc có thể chọn Block nằm trên Pline -> Xét điểm chèn .... -> Thực hiện công việc....

2. Giải quyết thêm việc chọn nhiều LINE/PLINE nữa.

Lisp trên chỉ cho phép chọn 1 LINE/PLINE

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ám ơn bạn Ha, nhưng đúng như bác Tue nói ý thứ 2, mình có cả một mạng lưới các Pline, không phải chỉ có 1 Pline như file mình gửi kèm. Nếu có thể chỉnh như bác Tue thì tốt quá.

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 chào cả nhà.

Mình muốn nhờ mọi người viết giùm lisp như sau:

 

Hiện tại mình có 1 tuyến vẽ bằng Pline (hoặc Line), trên đó đã chèn các Block. Mình muốn dùng lisp Break tuyến Pline (hoặc Line) này tại điểm chèn của Block, sau đó nối lại thành 1 Pline. Hày nói cách khác là làm cho các điểm chèn của Block trên tuyến thành các đỉnh của Pline.

 

Xin cảm ơn cả nhà.

 

Bản vẽ kèm theo:

http://www.cadviet.c...k_tai_block.dwg

Của bạn đây. Bạn thử nhé :


(defun C:INn(/ SS ENT OBJ )
;;;copy right by Tue_NV
(command "undo" "begin")
(setq ss (ssget '((0 . "*POLYLINE,LINE"))) i -1)
(while (setq ent (ssname ss (setq i (1+ i))))
	(if (= (acet-dxf 0 (entget ent)) "LINE")
(progn (command "pedit" "m" ent "" "y" "") (setq ent (ENTLAST)))
	)

	(setq obj (vlax-ename->vla-object ent))
	(foreach y (mapcar
'(lambda(x)
(acet-dxf 10 (entget x))
 )
(acet-ss-to-list (ssget "f" (acet-geom-vertex-list ent) '((0 . "INSERT"))))
)
(if (equal (vlax-curve-getClosestPointTo ent y nil) y 0.01)
(vlax-invoke Obj 'AddVertex (1+ (fix (vlax-curve-getparamatpoint ent y)))
(list (car y) (cadr y)))
)
	)
 )
 (command "undo" "END")
)

  • 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ám ơn bạn Ha, nhưng đúng như bác Tue nói ý thứ 2, mình có cả một mạng lưới các Pline, không phải chỉ có 1 Pline như file mình gửi kèm. Nếu có thể chỉnh như bác Tue thì tốt quá.

Hề hề hề,

Thực ra vấn đề này trên diễn đàn đã có lisp addvertext cho polyine. Là thành viên có hạng, bạn hoàn toàn có thể sửa đổi một chút cái lisp này để sử dụng cho mục đích của mình. Cụ thể như sau:

1/- Chọn tập các line hay pline chứa các block.

2/- chọn tập các block cần quan tâm.

3/- lặp qua tất cả các block đã chọn để lấy list các điểm chèn.

4/- lặp qua list này và list các đối tượng line , pline ở trên để xét điều kiện các điểm chèn có mằm trên một trong các line đó không. nếu có thì addvertext tại điểm đó

Hy vọng bạn sẽ làm được mà khỏi cần nhờ vả chi

hề hề hề,

nếu có khó khăn hãy post lên nhé.

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 vấn đề này trên diễn đàn đã có lisp addvertext cho polyine. Là thành viên có hạng, bạn hoàn toàn có thể sửa đổi một chút cái lisp này để sử dụng cho mục đích của mình. Cụ thể như sau:

1/- Chọn tập các line hay pline chứa các block.

2/- chọn tập các block cần quan tâm.

3/- lặp qua tất cả các block đã chọn để lấy list các điểm chèn.

4/- lặp qua list này và list các đối tượng line , pline ở trên để xét điều kiện các điểm chèn có mằm trên một trong các line đó không. nếu có thì addvertext tại điểm đó

Hy vọng bạn sẽ làm được mà khỏi cần nhờ vả chi

hề hề hề,

nếu có khó khăn hãy post lên nhé.

Hề hề hề...

Cảm ơn bác Bình đã nhắc nhở, nhưng dạo này không hay dùng tới lisp nên quên hết trơn, cũng tại công việc yêu cầu gấp mà không có thời gian nghiên cứu, đành nhờ các cao thủ ra tay cho nhanh.

Chúc bác và gia đình mạnh khỏe!

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 vấn đề này trên diễn đàn đã có lisp addvertext cho polyine. Là thành viên có hạng, bạn hoàn toàn có thể sửa đổi một chút cái lisp này để sử dụng cho mục đích của mình. Cụ thể như sau:

1/- Chọn tập các line hay pline chứa các block.

2/- chọn tập các block cần quan tâm.

3/- lặp qua tất cả các block đã chọn để lấy list các điểm chèn.

4/- lặp qua list này và list các đối tượng line , pline ở trên để xét điều kiện các điểm chèn có mằm trên một trong các line đó không. nếu có thì addvertext tại điểm đó

Hy vọng bạn sẽ làm được mà khỏi cần nhờ vả chi

hề hề hề,

nếu có khó khăn hãy post lên nhé.

Chào bác Bình

Ở bước 4 sao bác không chọn giải pháp là chọn các Block trên LINE/PLINE hàm (ssget "f".....) rồi xét Block đó có nằm trong Block đã chọn ở bước 2 hay không và đồng thời xét điều kiện điểm chèn có mằm trên LINE/PLINE đó hay không?

Việc bác lặp qua tất cả các Block rồi xét điểm chèn của chúng trên LINE/PLINE thì nó sẽ ảnh hưởng đến tốc độ làm việc của Lisp nếu số lượng Block là lớn vì mỗi Pline có thể có 1 , 2 cái Block mà bác lặp qua tất cả các Block luôn -> Không cần thiết đâu, bác nhỉ?

Người lập trình Lisp ngoài việc quan tâm đến kết quả của Lisp còn phải quan tâm đến tốc độ làm việc của nó nữa

  • 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

Chọn *Line trước cũng hay, vì mình có đối tượng để addvertext luôn hén ^^

Nhưng như thế nếu mạng dài dài, nhiều *Line, người dùng phải ngó ngó xem cái Line này nó có đi qua những block mình cần xử lý không mà chọn, còn nếu quét bao Line thì sẽ có những thằng chẳng đi qua những block cần xử lý, như vậy sẽ lãng phí (acet-geom-vertex-list) đúng không ạ ^^

Hay là :

1 - Quét chọn Block (theo mẫu hoặc không)

2 - Duyệt qua từng Block => (ssget "C" (dxf 10 Block)(dxf 10 Block) (list (cons 0 "LINE,*POLYLINE"))) => AddVertext

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ọn *Line trước cũng hay, vì mình có đối tượng để addvertext luôn hén ^^

Nhưng như thế nếu mạng dài dài, nhiều *Line, người dùng phải ngó ngó xem cái Line này nó có đi qua những block mình cần xử lý không mà chọn, còn nếu quét bao Line thì sẽ có những thằng chẳng đi qua những block cần xử lý, như vậy sẽ lãng phí (acet-geom-vertex-list) đúng không ạ ^^

Hay là :

1 - Quét chọn Block (theo mẫu hoặc không)

2 - Duyệt qua từng Block => (ssget "C" (dxf 10 Block)(dxf 10 Block) (list (cons 0 "LINE,*POLYLINE"))) => AddVertext

Làm như 2 ý của Ketxu thì điểm (dxf 10 Block) phải tuyệt đối nằm trên LINE/PLINE. Nếu có 1 khoảng hở cho phép nào đó thì không ổn. Vì nếu với khoảng hở cho phép nào đó thì (ssget "C" (dxf 10 Block)(dxf 10 Block) (list (cons 0 "LINE,*POLYLINE"))) trả về NIL -> Không chọn được anh nào cả

Và đương nhiên, sẽ có những điều tương đối Ketxu à

 

Cách làm của mình có thể cho phép 1 sai số nào đó bằng hàm (equal..... còn của Ketxu thì không

Hàm (ssget "f" (acet-geom-vertex-list ent) '((0 . "INSERT"))) hạn chế bớt những Block chọn thôi.

Và xử lý Các Block đó có nằm trong Block chọn hay không và điểm chèn của nó có nằm trên PLINE một cách tương đối bằng hàm equal

Chúc Ketxu 1 ngày chủ nhật vui vẻ...

 

@thanhlamct : Trả lời bạn ở bài viết dưới cho đỡ tốn diện tích "đất" :

File CAD bạn gửi mình không mở được. Không biết lỗi gì. Bạn lưu CAD đời thấp thử. Mình sử dụng CAD2008

Phiền bạn gửi lại nhé

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 như 2 ý của Ketxu thì điểm (dxf 10 Block) phải tuyệt đối nằm trên LINE/PLINE. Nếu có 1 khoảng hở cho phép nào đó thì không ổn. Vì nếu với khoảng hở cho phép nào đó thì (ssget "C" (dxf 10 Block)(dxf 10 Block) (list (cons 0 "LINE,*POLYLINE"))) trả về NIL -> Không chọn được anh nào cả

Và đương nhiên, sẽ có những điều tương đối Ketxu à

 

Cách làm của mình có thể cho phép 1 sai số nào đó bằng hàm (equal..... còn của Ketxu thì không

Hàm (ssget "f" (acet-geom-vertex-list ent) '((0 . "INSERT"))) hạn chế bớt những Block chọn thôi.

Và xử lý Các Block đó có nằm trong Block chọn hay không và điểm chèn của nó có nằm trên PLINE một cách tương đối bằng hàm equal

Chúc Ketxu 1 ngày chủ nhật vui vẻ...

 

Ý, đoạn (ssget "f" (acet-geom-vertex-list ent) '((0 . "INSERT"))) , nhất là (acet-geom-vertex-list ent) trong code của bác là bắt buộc chứ có phải hạn chế đâu, là thao tác tự động ssget fence và không có sự can thiệp của user ^^

- Còn tọa độ điểm chèn Block nằm chuẩn trên mạng thì tùy thuộc vào yêu cầu của OP, e không thấy bạn ấy có yêu cầu fuzz ^^

Nhưng xét ra thì đó cũng là điều cần xem xét thật ^^ Nếu cần fuzz, ta hoàn toàn có thể thay 2 dxf 10 bằng 2 điểm chéo fuzz, hề hề

Code của bác e đã chép lại để mót rồi, nhưng vớ vào anh acet-geom-vertex-list thì e ghét lắm. Vì vốn dĩ thằng này nó thuộc Express, hơn nữa nó lại không chơi với Line, cũng có nghĩa là khi code bắt đầu làm việc, bác đã chuyển hết Line đã chọn sang Pline (đoạn command) để xài thằng này, cũng như phục vụ công cuộc addvertex ở sau, trong khi có khả năng trong đống mạng chọn ban đầu có những thằng Line chẳng đi qua tâm bác Block nào cũng bị chuyển giới tính oan uổ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ào bác Tue_NV:

Lisp của bác rất tuyệt vời nếu mạng ít, nếu mạng nhiều như file em gửi kèm thì có vấn đề rồi.

Bác test thử nhé.

http://www.cadviet.c.../mang_pline.dwg

@thanhlamct : khi gửi file CAD lên diễn đàn, bạn nên cố gắng giảm Version về thấp nhất có thể để mọi người đọc dễ dàng hơn (đã có trong quy định post bà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

(defun C:INn(/ SS ENT OBJ pt doc ac)
;;;copy right by Tue_NV
(vl-load-com)
(command "undo" "begin")
(acet-sysvar-set (list "cmdecho" 0))

(setq ss (ssget '((0 . "*POLYLINE,LINE"))) i -1)
(while (setq ent (ssname ss (setq i (1+ i))))
 (if (= (acet-dxf 0 (entget ent)) "LINE")
   (progn (command "pedit" "m" ent "" "y" "") (setq ent (ENTLAST)))
 )
   (setq obj (vlax-ename->vla-object ent))
   (if (setq ss1 (ssget "f" (acet-geom-vertex-list ent) '((0 . "INSERT"))))
   (foreach y (mapcar
  	 '(lambda(x)(acet-dxf 10 (entget x)))
  	 (acet-ss-to-list ss1)
  			 )
(if (equal (setq pt (vlax-curve-getClosestPointTo ent y nil)) y 0.01)
   (vlax-invoke Obj 'AddVertex (1+ (fix (vlax-curve-getparamatpoint ent pt)))
   (list (car pt) (cadr pt)))
)
 )
 )
)
(acet-sysvar-restore)
 (command "undo" "END")
)

 

(defun C:INn1(/ ac doc i ss_tmp pt eLine)
(vl-load-com)
(setq doc (vla-get-activedocument (setq ac (vlax-get-acad-object))))
(command "undo" "begin")
(setq ss (ssget '((0 . "INSERT"))) i -1 )
(while (setq ent (ssname ss (setq i (1+ i))))
(vla-getboundingbox (vlax-ename->vla-object ent) 'll 'ur)
(vla-ZoomWindow ac (vlax-3D-point (vlax-safearray->list ll))(vlax-3D-point (vlax-safearray->list ur)))
 (if (setq ss_tmp (ssget "C" (setq pt (acet-dxf 10 (entget ent))) pt (list (cons 0 "LINE,*POLYLINE"))))
 (progn
 (foreach eLine (acet-ss-to-list ss_tmp)
  (if (= (cdadr (entget eLine)) "LINE")(progn (command "pedit" "m" eLine "" "y" "") (setq eLine (ENTLAST))))
  (setq eLine (vlax-ename->vla-object eLine))
  (vlax-invoke eLine 'AddVertex (1+ (fix (vlax-curve-getparamatpoint eLine (setq pt (vlax-curve-getClosestPointto eLine pt)))))(list (car pt) (cadr pt)))
 )
 )
)
)
 (command "undo" "END")
)

 

Những dòng vla-zoom sẽ làm chậm chương trình, nhưng nó giúp hàm ssget tránh lỗi, bạn có thể tùy ý giữ - bỏ

  • 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ảm ơn Ketxu, cũng là một giải pháp hiệu quả.

Tuy nhiên khi chạy nó zoom hơn 3000 Block, nhìn cũng hơi chóng mặt. hì hì...

Có thể khắc phục đượ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

Cảm ơn Ketxu, cũng là một giải pháp hiệu quả.

Tuy nhiên khi chạy nó zoom hơn 3000 Block, nhìn cũng hơi chóng mặt. hì hì...

Có thể khắc phục được không?

À, vậy bạn dùng cái INN đầu của bác Tuệ mà ket vừa edit lại 1 tí ở bên trên ấy (Code bác Tuệ vội vàng ở chỗ lấy List Ename khi chưa chắc chắn có ss Fence hay chưa ) , zoom thằng đường dẫn chắc là ít hơn thằng Block :) Hoặc đơn giản là bỏ dòng zoom đi :D (nếu khung nhìn bao đủ toàn bộ đối tượng).

Mà Ketxu sửa theo suy đoán, chứ k dòm hết các chỗ trên file vẽ xem chỗ nào đc, chỗ nào chưa được, bạn tự check nhé

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 đã Test cái Code ở trên rồi, chỗ được chỗ không.

Cũng như code đầu của bác Tuệ, khi selection chỉ ra có hơn 500 đối tượng

Còn code dưới thì ra ngay hơn 3000 đối tượng (chính là các Block).

Vì thế mà được chă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

Xong cho bạn rồi đây. Bạn chạy thử xem nhé :

(defun C:INn(/ OBJ ss ent i GetVert gv ssf )
;;;copy right by Tue_NV
 (defun GetVert (cur / i L LE) ;;;Vertexs of pline, or end points of line, arc
(setq i 0)
(vl-load-com)
(repeat (fix (+ (vlax-curve-getEndParam cur) 1))
 (if (not (member (setq pt (vlax-curve-getPointAtParam cur i)) L))
(setq L (append L (list pt)))
     )
   (setq i (1+ i))
)
   L
)

(command "undo" "begin")
(setq ss (ssget '((0 . "*POLYLINE,LINE"))) )
   (setq mm (ACET-GEOM-SS-EXTENTS-FAST ss))
 (vla-ZoomWindow (vlax-get-acad-object) (vlax-3D-point (car mm)) (vlax-3D-point (cadr mm)))
(setq i -1)
(if ss
(Progn

(while (setq ent (ssname ss (setq i (1+ i))))
 (setq gv (GetVert ent))
(IF (car gv)
 (If (and (setq ssf (ssget "f" gv '((0 . "INSERT")))) )
 (PROGN
	(if  (= (acet-dxf 0 (entget ent)) "LINE")
(progn (command "pedit" "m" ent "" "y" "") (setq ent (ENTLAST)))
   )
 (setq obj (vlax-ename->vla-object ent))

 (foreach y (mapcar
'(lambda(x)
(acet-dxf 10 (entget x))
   )
(acet-ss-to-list ssf)
  )
 (if (equal (vlax-curve-getClosestPointTo obj y nil) y 0.1)
(vlax-invoke Obj 'AddVertex (1+ (fix (vlax-curve-getparamatpoint obj
     (vlax-curve-getClosestPointTo obj y nil))))
(list (car y) (cadr y)))
 )
 )
 )
)
)
 )
))
 (vla-Zoomprevious (vlax-get-acad-object))
 (command "undo" "END")
)

 

@Ketxu: Lỗi chổ được chổ không ấy là do cái Block của bạn thanhlamct làm bằng Wipeout

Cũng tương tự như hàm (ssget "c" ...) mà cái PLINE được cấu tạo bằng đường (not continous) thì chổ được chổ không đấy.

=> Giải pháp triệt để là sử dụng (ssget "f" ...) và các ý mà Tue_NV đã trình bày

Đã sử xong việc "không cố tình thay đổi giới tính" của LINE mà trên đó không có Block nào.

  • 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

Cũng tương tự như hàm (ssget "c" ...) mà cái PLINE được cấu tạo bằng đường (not continous) thì chỗ được chỗ không đấy.

Tôi thích câu này, bởi thường không để ý tớ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

Hê hê, chạy ngon rồi, kết quả e k biết nó có hết không ^^ Đúng là e chưa lường được trường hợp nét không liền

- Hàm getvert với Line bị lạm phát nè ^^

- Không thay đổi giới tính của Line mà trên đó không có Block nào "thỏa mãn" thì chính xác hơn bác ạ, nên cái command phải đẩy xuống nữa thì hay hơn hè^^

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
Đăng nhập để thực hiện theo  

×