Chuyển đến nội dung
Diễn đàn CADViet
  • Thông báo

    • Nguyen Hoanh

      CADViet đã hoàn tất nâng cấp   14/09/2017

      Chào các bạn, CADViet đã hoàn tất việc nâng cấp lên phiên bản mới. Tất cả các chức năng đã hoạt động theo kỳ vọng của ban quản trị. Nếu có vấn đề gì cần phản hồi, các bản post ở đây nhé: Trân trọng, Nguyễn Hoành.
Đăng nhập để thực hiện theo  
prute

[Nhờ viết lisp] offset tự động

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

Em có 1 bản vẽ gồm nhiều đối tượng kín (vd: hình tròn, elip, hình vuông ...), em muốn lisp tự động offset theo hướng vào bên trong đối tượng, khoảng cách offset là cố định trong lisp(không cần yêu cầu nhập khoảng cách) và xoá đối tượng cũ đi.

Tóm lại mình sẽ chỉ phải chọn đối tượng và lisp sẽ tự động offset, không hiện một yêu cầu nào cả.

Các anh giúp em vấn đề này nhé. Thanks trước.

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

Lisp offset tất cả các đối tượng kín được chọn vào phía bên trong đối tượng, với cùng 1 khoảng cách offset.

;Doan Van Ha - CADViet.com - Ngay 21/6/2012
;Muc dich: Offset tat ca doi tuong vao ben trong voi 1 khoang cach co dinh, va xoa tat ca doi tuong cu.
(defun C:HA ( / ss )
(vl-load-com) (command "undo" "be") (setq cmd (getvar "cmdecho") osm (getvar "osmode")) (setvar "cmdecho" 0) (setvar "osmode" 0)
(or *stp* (setq *stp* 10.0))
(setq stp (getint (strcat "\nKhoang cach Offset <" (rtos *stp* 2) ">: ")))
(if (not stp) (setq stp *stp*) (setq *stp* stp))
(princ "\nChon cac hinh kin can Offset...")
(setq ss (ssget '((0 . "CIRCLE,ELLIPSE,POLYLINE,LWPOLYLINE,SPLINE"))))
(foreach obj (HA:ss->vla ss)
 (command "offset" *stp* (vlax-vla-object->ename obj) (HA:CenCur obj) ""))
(command "erase" ss "")
(setvar "cmdecho" cmd) (setvar "osmode" osm) (command "undo" "end") (princ))
(defun HA:CenCur (obj / ttc)
(cond
 ((= (cdr (assoc 0 (entget (vlax-vla-object->ename obj)))) "REGION")
  (setq ttc (vlax-get obj 'Centroid)))
 ((wcmatch (cdr (assoc 0 (entget (vlax-vla-object->ename obj)))) "CIRCLE,ELLIPSE,POLYLINE,LWPOLYLINE,SPLINE")
  (setq ttc (vlax-get (car (vlax-invoke (vla-get-modelspace (vla-get-activedocument (vlax-get-acad-object))) 'addregion (list obj))) 'Centroid))
  (entdel (entlast))))
ttc)
(defun HA:ss->vla (ss / i l)
(if ss
 (repeat (setq i (sslength ss))
  (setq l (cons (vlax-ename->vla-object (ssname ss (setq i (1- i)))) 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

@OP : Title topic sai quy định

@ Bác Hạ :

- *dynOff của bác chưa có ^^ (typo)

- Tâm có thể nằm ngoài đối tượng

- Đối tượng kín OP yêu cầu thì có Area

=>

(defun c:test ()
(cond ((ssget '((0 . "CIRCLE,ELLIPSE,POLYLINE,LWPOLYLINE,SPLINE")))
 (or *dist (setq *dist 100))
 (setq *dist (cond ((getdist (strcat "\nDistance <" (rtos *dist 2 2) ">")))(*dist)))
 (vlax-for obj (vla-get-activeselectionset (vla-get-activedocument (vlax-get-acad-object)))
  (mapcar 'vla-delete
(cdr
	(vl-sort
 	(list (car(vlax-invoke obj 'Offset *dist)) obj  (car (vlax-invoke obj 'Offset (- *dist))))
 	'(lambda(x y)(< (vlax-get x 'Area)(vlax-get y 'Area)))
	)
)
  )
 )
 )(T (princ "\nNo thing to do"))
)(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

Hôm qua em làm chỉ có các hình kín, hôm nay em muốn phát triển thêm là trong hình của em có thêm các khác không kín.

--Do hôm qua em nghĩ là nhờ các anh viết cho phần offset còn phần chọn đối tượng kín hay không kin thì em làm được nhưng mà về đọc lisp của anh ketxu thì những lệnh đó em chưa dùng lần nào nên không sửa được.

--Em tính làm theo cách quét tất cả các đối tượng và lưu thông tin vào 1 list sau đó duyệt từng đối tượng 1 để kiểm tra kín và offset nhưng phần chọn đối tượng (ssget '((0 . "CIRCLE,ELLIPSE,POLYLINE,LWPOLYLINE,SPLINE")) bình thường em thấy hay lưu vào một biến nào đó nhưng mà ở đây em không biết mình chọn đối tượng xong lưu ở đâu.

--Hôm nay nhờ mấy anh giúp em thêm trường hợp đối với nhiều đối tượng trong đó có kín và không kín, ta quét chọn tất cả bản vẽ và lisp sẽ offset những đối tượng kín.

Cảm ơn các anh

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

Dòng gán tập chọn chính là dòng này

(vla-get-activeselectionset (vla-get-activedocument (vlax-get-acad-object)))

vlax-for obj: duyệt qua tập chọn (giống như foreach), mỗi đối tượng tạm đặt là Obj (đối tượng vla-object))

1. Circle : hiển nhiên kín

2. Ellipse : kín khi startAngle bằng 0

3. *Line : kiểm tra thuộc tính Closed hoặc kiểm tra đỉnh đầu trùng đỉnh cuối (tùy theo nhu cầu của bạn)

 

Nếu bạn biết chút ít về Vl thì có thể tự làm, nếu không thì bạn chờ các bác sửa hộ cho nhé ^^ Mình hơi bậ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

Các anh giúp em nhé!!

- Bản vẽ có nhiều đối tượng ( kín và không kín )

- Em muốn mình chỉ quét chọn tất cả các đối tượng đó 1 lần

- Nếu đối tượng nào kín thì offset hình đó theo hướng bên trong đối tượng một khoảng cố định trong lisp

- Lisp không yêu cầu nhập gì cả

- xoá đối tượng cũ

Chỉ quét chọn đối tượng và nếu kín thì offset 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

Quick code, bạn khử biến đi nhé. Đây chỉ là 1 ví dụ mình đưa ra thôi, vì khái niệm bên trong rất khó, nhất là trong các trường hợp đối tượng của bạn phức tạp, giao nhau, hoặc ngoằn nghèo

Ở đây mình chỉ lấy list 3 đối tượng gồm có : gốc, offset -dist, offset + dist, và xóa đi 2 thằng to hơn, giữ lại thằng nhỏ nhất (theo diện tích) - để phù hợp với nhu cầu offset vào "trong" của bạn. Trường hợp method offset sinh ra nhiều hơn 1 đối tượng thì không còn chuẩn nữa, nếu bạn là lispser thì hãy cố gắng xử lý vấn đề này xem sao :)

(defun c:test ()
(cond ((ssget '((0 . "CIRCLE,ELLIPSE,POLYLINE,LWPOLYLINE,SPLINE")))
 (or *dist (setq *dist 100))
 (setq *dist (cond ((getdist (strcat "\nDistance <" (rtos *dist 2 2) ">")))(*dist))
 isClosed (lambda(x)(cond  ((and  (= (vla-get-ObjectName x) "AcDbEllipse")(zerop (vla-get-StartAngle x))))
    	((and  (wcmatch (vla-get-ObjectName x) "AcDb*line")
      	(equal  (car (setq sth (acet-geom-vertex-list (vlax-vla-object->ename x))))
        	(last sth)
        	0.01
      	)
     	)
    	)
 	)
)
)
 (vlax-for obj (vla-get-activeselectionset (vla-get-activedocument (vlax-get-acad-object)))
(if (isclosed obj)
  (mapcar 'vla-delete
(cdr
 (vl-sort
  (list (car(vlax-invoke obj 'Offset *dist)) obj  (car (vlax-invoke obj 'Offset (- *dist))))
  '(lambda(x y)(< (vlax-get x 'Area)(vlax-get y 'Area)))
 )
)
  )
 )
 ))(T (princ "\nNo thing to do"))
)(princ)
)

  • 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

Ối giời ơi! Cái offset tưởng đơn giản, hoá ra lắm chuyện.

Test trên lisp trước của ket thì nó sinh ra 1 object hở từ 1 object kín?

Test trên lisp sau thì lỗi.

Thằng Spline mà offset rắc rối thậ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

- PLine và Spline khi Offset có thể sinh ra nhiều hơn 1 đối tượng

- 1 đối tượng kín vẫn có thể Offset ra 1 đối tượng hở ^^

- 1 đối tượng hở từ Spline, Pline vẫn có Area

=> lắm chuyện vui buồn lẫn lộn.

Vui như ở đây

Buồn như trong lisp đo đường bất kỳ hoặc lisp này bác ạ :D

  • 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

Quick code, bạn khử biến đi nhé. Đây chỉ là 1 ví dụ mình đưa ra thôi, vì khái niệm bên trong rất khó, nhất là trong các trường hợp đối tượng của bạn phức tạp, giao nhau, hoặc ngoằn nghèo

Ở đây mình chỉ lấy list 3 đối tượng gồm có : gốc, offset -dist, offset + dist, và xóa đi 2 thằng to hơn, giữ lại thằng nhỏ nhất (theo diện tích) - để phù hợp với nhu cầu offset vào "trong" của bạn. Trường hợp method offset sinh ra nhiều hơn 1 đối tượng thì không còn chuẩn nữa, nếu bạn là lispser thì hãy cố gắng xử lý vấn đề này xem sao :)

(defun c:test ()
(cond ((ssget '((0 . "CIRCLE,ELLIPSE,POLYLINE,LWPOLYLINE,SPLINE")))
 (or *dist (setq *dist 100))
 (setq *dist (cond ((getdist (strcat "\nDistance <" (rtos *dist 2 2) ">")))(*dist))
 isClosed (lambda(x)(cond  ((and  (= (vla-get-ObjectName x) "AcDbEllipse")(zerop (vla-get-StartAngle x))))
		((and  (wcmatch (vla-get-ObjectName x) "AcDb*line")
  		(equal  (car (setq sth (acet-geom-vertex-list (vlax-vla-object->ename x))))
    		(last sth)
    		0.01
  		)
     	)
		)
 	)
)
)
 (vlax-for obj (vla-get-activeselectionset (vla-get-activedocument (vlax-get-acad-object)))
(if (isclosed obj)
  (mapcar 'vla-delete
(cdr
 (vl-sort
  (list (car(vlax-invoke obj 'Offset *dist)) obj  (car (vlax-invoke obj 'Offset (- *dist))))
  '(lambda(x y)(< (vlax-get x 'Area)(vlax-get y 'Area)))
 )
)
  )
 )
 ))(T (princ "\nNo thing to do"))
)(princ)
)

lisp này em chạy thử thì thấy đường tròn không được

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

- PLine và Spline khi Offset có thể sinh ra nhiều hơn 1 đối tượng

- 1 đối tượng kín vẫn có thể Offset ra 1 đối tượng hở ^^

- 1 đối tượng hở từ Spline, Pline vẫn có Area

=> lắm chuyện vui buồn lẫn lộn.

Vui như ở đây

Buồn như trong lisp đo đường bất kỳ hoặc lisp này bác ạ :D

vừa xem xong cái mà anh ketxu bảo vui, xem xong không vui tí nào mà hoảng ^^, nghĩ lỡ như mà kết quả sau khi mình chạy cũng như vậy thì toi.

Đối với spline thì vẽ hình kin có lẽ đối với em là hiếm nên các anh có thể bỏ qua luôn cho thuận tiện.

Thanks 2 anh nhé, khuya quá mà vẫn còn giúp, 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

Thử cái này, dựa vào lisp của anh Ketxu. Có vài khiếm khuyết nhé (như đã phân tích ở trên).

(defun c:test ()
(cond
 ((ssget '((0 . "CIRCLE,ELLIPSE,POLYLINE,LWPOLYLINE,SPLINE")))
  (or *dist (setq *dist 100))
  (setq *dist
(cond
	((getdist (strcat "\nDistance <" (rtos *dist 2 2) ">: ")))
	(*dist)))
  (vlax-for obj (vla-get-activeselectionset (vla-get-activedocument (vlax-get-acad-object)))
(if (HA:Closed (vlax-vla-object->ename obj))
	(mapcar 'vla-delete
(cdr
	(vl-sort
 	(list (car (vlax-invoke obj 'Offset *dist)) obj  (car (vlax-invoke obj 'Offset (- *dist))))
 	'(lambda (x y) (< (vlax-get x 'Area) (vlax-get y 'Area)))))))))
 (T (princ "\nNo thing to do")))
(princ))
(defun HA:Closed (ent / data lstP lstS)
(setq data (entget ent)
      	lstP (mapcar 'cdr (vl-remove-if-not '(lambda (x) (= (car x) 10)) (entget ent)))
      	lstS (mapcar 'cdr (vl-remove-if-not '(lambda (x) (= (car x) 11)) (entget ent))))
(or
 (= "CIRCLE" (cdr (assoc 0 data)))
 (and (= "ELLIPSE" (cdr (assoc 0 data))) (= 0 (cdr (assoc 41 data))))
 (and
  (= (cdr (assoc 0 data)) "LWPOLYLINE")
  (or
(= 1 (logand 1 (cdr (assoc 70 data))))
(equal (car lstP) (last lstP) 1E-8)))
 (and
  (= (cdr (assoc 0 data)) "SPLINE")
  (or
(= 1 (logand 1 (cdr (assoc 70 data))))
(equal (car lstS) (last lstS) 1E-8)))))

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

@OP : Title topic sai quy định

@ Bác Hạ :

- *dynOff của bác chưa có ^^ (typo)

- Tâm có thể nằm ngoài đối tượng

- Đối tượng kín OP yêu cầu thì có Area

 

Em nhớ không nhầm thì có thể dùng hàm ExOffset trong menu Express để làm việc này với việc giữ phím Ctrl khi thực hiện việc nhấp chuột quy định phía offset đối tượng; khi đó nó sẽ del đối tượng cũ đi mà, hơn nữa cách dùng hoàn toàn như lệnh offset của Cad. cho phép lưu layer, thought của lần vẽ trước mà, không cần dùng list đâu ạ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

Anh cho em hỏi em dùng code gì để Cad nhận là người dùng gõ vào Shift hay chuột phải, hay Ctral gì gì đó ạ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

Thử cái này, dựa vào lisp của anh Ketxu. Có vài khiếm khuyết nhé (như đã phân tích ở trên).

(defun c:test ()
(cond
 ((ssget '((0 . "CIRCLE,ELLIPSE,POLYLINE,LWPOLYLINE,SPLINE")))
  (or *dist (setq *dist 100))
  (setq *dist
(cond
((getdist (strcat "\nDistance <" (rtos *dist 2 2) ">: ")))
(*dist)))
  (vlax-for obj (vla-get-activeselectionset (vla-get-activedocument (vlax-get-acad-object)))
(if (HA:Closed (vlax-vla-object->ename obj))
(mapcar 'vla-delete
(cdr
(vl-sort
 	(list (car (vlax-invoke obj 'Offset *dist)) obj  (car (vlax-invoke obj 'Offset (- *dist))))
 	'(lambda (x y) (< (vlax-get x 'Area) (vlax-get y 'Area)))))))))
 (T (princ "\nNo thing to do")))
(princ))
(defun HA:Closed (ent / data lstP lstS)
(setq data (entget ent)
  		lstP (mapcar 'cdr (vl-remove-if-not '(lambda (x) (= (car x) 10)) (entget ent)))
  		lstS (mapcar 'cdr (vl-remove-if-not '(lambda (x) (= (car x) 11)) (entget ent))))
(or
 (= "CIRCLE" (cdr (assoc 0 data)))
 (and (= "ELLIPSE" (cdr (assoc 0 data))) (= 0 (cdr (assoc 41 data))))
 (and
  (= (cdr (assoc 0 data)) "LWPOLYLINE")
  (or
(= 1 (logand 1 (cdr (assoc 70 data))))
(equal (car lstP) (last lstP) 1E-8)))
 (and
  (= (cdr (assoc 0 data)) "SPLINE")
  (or
(= 1 (logand 1 (cdr (assoc 70 data))))
(equal (car lstS) (last lstS) 1E-8)))))

được rồi anh ak. để em test thêm xem sao

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

lisp này em chạy thử thì thấy đường tròn không được

À ừ, mình bỏ quên nó, bạn thêm dòng (= (vla-get-objectname x) "AcDbCircle") vào cùng hàm cond của isclosed là được :)

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

hic, spline bị lỗi rồi 2 anh ak, em thử vẽ 1 trái tim kín, chạy lệnh thì báo lỗi

AutoCAD.Application: Invalid offset

trường hợp nữa là bị tách thành hình ko kín và offset không dúng phía.

Cái spline này rắc rối 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

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  

×