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

[Hỏi] Cách vẽ đường LwPolyline theo mặt phẳng bất kỳ ?

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

Chào mọi người,

Anh em cho hỏi cách vẽ đường LwPolyline theo 1 mặt phẳng bất kỳ sử dụng lệnh của Cad và dùng AutoLisp ?

 

Cụ thể trong file đính kèm, có ba điểm thuộc đỉnh của đường polyline3d màu trắng,

 - làm cách nào vẽ được đường LwPolyline màu cyan ?

image.thumb.png.95746c7e3f9caefa6e172483f3f9016d.png

Cám ơn mọi người đã đọc tin.

LwPolyline in 3d.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
28 phút trước, gia_bach đã nói:

Chào mọi người,

Anh em cho hỏi cách vẽ đường LwPolyline theo 1 mặt phẳng bất kỳ sử dụng lệnh của Cad và dùng AutoLisp ?

 

Cụ thể trong file đính kèm, có ba điểm thuộc đỉnh của đường polyline3d màu trắng,

 - làm cách nào vẽ được đường LwPolyline màu cyan ?

image.thumb.png.95746c7e3f9caefa6e172483f3f9016d.png

Cám ơn mọi người đã đọc tin.

LwPolyline in 3d.dwg

Bạn chuyển mặt phẳng vẽ về 3 đỉnh của Poly3D thử xem được k? Lệnh UCS enter xong 3 và enter.

  • Like 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
11 phút trước, DuongTrungHuy đã nói:

Bạn chuyển mặt phẳng vẽ về 3 đỉnh của Poly3D thử xem được k? Lệnh UCS enter xong 3 và enter.

Cám ơn bác, dùng lệnh UCS với 3 point để tạo 1 hệ trục tọa độ mới đã giải quyết được vấn đề (sau đó dùng lệnh Pline để vẽ như bình thường).

 

Bác có thể giới thiệu cách vẽ đường LwPolyline dùng AutoLisp  ?

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 command cho 2d


(command ".pline";start "pline" command
     (repeat (length pt-list);repeat for each point
       (command (nth cnt pt-list));enter current point
       (setq cnt (1+ cnt));counter to next point
       "";return value to close "pline" command
     );end point repeat
);end command

nếu 3d point phải đổi về ucs mới

Dùng entmake (2D)


(entmakex    (append    '((0 . "LWPOLYLINE")    (100 . "AcDbEntity")    (100 . "AcDbPolyline"))
        (list (cons 90 (length pt-list)) (cons 70 isclose))     (mapcar ''((x) (cons 10 x)) pt-list))    )

  • Like 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 giờ} trướ}c, gia_bach đã nói:

Cám ơn bác, dùng lệnh UCS với 3 point để tạo 1 hệ trục tọa độ mới đã giải quyết được vấn đề (sau đó dùng lệnh Pline để vẽ như bình thường).

 

Bác có thể giới thiệu cách vẽ đường LwPolyline dùng AutoLisp  ?

Hì Bạn gia_bach là siêu LISP mà chắc viết đơn giản thôi.

Mình gửi Bạn nhóm chương trình mình viết phục vụ cho vẽ 3D mà mình thường làm trong công việc.

Có lẽ nó sẽ không tối ưu lắm trong giải thuật cũng như ngữ pháp, nhưng được kết quả là được Bạn nhé.

Trên cơ sở đó Bạn có thể phát triển cái mà Bạn cần.

=== oOo ===

 

(defun c:3D(/ ss0 ss1 xx yy loai0 i tt)
  (setvar "cmdecho" 0)
  (princ "\nBan chon loai nao")
  (setq loai0 nil
        xx (List "Duong thang vuong goc mat phang"
                 "Xac dinh diem co k/c tren mat bang"
                 "Giao Duong thang voi Mat phang"
                 "Chieu doan thang xuong mat phang"
           )
        yy '(0 0 0 0 0 0) loai0 (dos_popupmenu xx yy) ss0 nil lop nil
  )
  (print loai0)
  (Cond
   ((= 0 loai0)(cDT_VG_MP))
   ((= 1 loai0) (cdiem3D))
   ((= 2 loai0) (cGiaoDT_MP))
   ((= 3 loai0) (cChieuDT_MP))
  ) 
)

(Defun cDT_VG_MP()
 (command "ucs" "w")(setvar "cmdecho" 0)
  (Setvar "Osmode" 1) (Setvar "orthomode" 0)
  (setq d1 (getpoint "\nCho dinh duong cao: "))
 (Setvar "Osmode" 512)
  (setq p1 (getpoint d1 "\nCho diem 1 tren mat phang")
        p2 (getpoint d1 "\nCho diem 2 tren mat phang")
        p3 (getpoint d1 "\nCho diem 3 tren mat phang")
  )    
  (Setvar "Osmode" 0)(command "3DPoly" p1 p2 p3 "c")
  (command "UCS" 3 p1 p2 p3)
  (Setvar "Osmode" 0)(setq d1 (Cal "w2u(d1)") dO (list (car d1) (cadr d1) 0))
  (If (< (abs (caddr d1)) 0.00000001)
    (Alert "Diem nam trong mat phang!")
  (Progn
    (command "line" d1 dO "") 
    (Princ (strcat "\nKhoang cach la: " (rtos (distance d1 dO) 2 8) "m ."))
    (setq dO (Cal "u2w(dO)"))
    
  )
  )
  (command "ucs" "w")
  (Setvar "Osmode" 1) 

(defun cdiem3D()
  (setvar "cmdecho" 0)
  (Setvar "Osmode" 33)(setq d1 (getpoint "\nCho diem goc <End>: "))
  (Setvar "Osmode" 512)(setq d2 (getpoint d1 "\nCho diem dong <Nearest>: ") kc1 (distance d1 d2))
  (Princ (strcat "\nKhoang cach 2 diem nay la: " (rtos kc1 2 3) " Cho khoang cach: "))
  (setq kc 1.0 dk (grread))
  (If (= (car dk) 2)
    (setq chu1 (strcat (chr (cadr dk)) (getstring (strcat "\nCho khoang cach (" (rtos kc1 2 3) "): " (chr (cadr dk)))))
          kc (atof chu1)
    )
  )
  (If (or (= (car dk) 11)(= (car dk) 3))
    (setq dkc1 (getpoint "\nCho goc KC1:") dkc2 (getpoint dkc1 "\nCho goc KC2:" )
          kc (distance dkc1 dkc2)
    )      
  )
  (setq 
        d1a (list (car d1) (cadr d1) 0.0) d2a (list (car d2) (cadr d2) 0.0)
        dxa (cal "pld(d1a,d2a,kc)")    dxb (list (car dxa) (cadr dxa) 1000.0)
        d00 (inters d1 d2 dxa dxb nil)
  )
  (print kc)
  (Setvar "Osmode" 0)(command "line" d1a dxa d00 "")(Setvar "Osmode" 33)

(Defun cGiaoDT_MP()
  (Princ "\nBan chay chuong trinh Geomcal")
  (command "ucs" "w")(setvar "cmdecho" 0)
  (Setvar "Osmode" 512) (Setvar "orthomode" 0)
  (setq p1 (getpoint "\nCho diem tren mat phang <Neareast>: ")
        p2 (getpoint p1 "\nCho diem tren mat phang <Neareast>: ")
        p3 (getpoint p2 "\nCho diem tren mat phang <Neareast>: ")
  )    
  (command "UCS" 3 p1 p2 p3) ; (Setvar "Osmode" 1) 
  (setq d1 (getpoint "\nCho diem 1: ") 
        d2 (getpoint d1 "\nCho diem 2: ")
        Beta (- (caddr d1) (caddr d2)) 
  )
  (Setvar "Osmode" 0)
  (If (< (abs beta) 0.0000001)
    (Alert "Duong thang song song voi mat phang!")
  (Progn
    (setq d11 (list (car d1) (cadr d1) 0) d22 (list (car d2) (cadr d2) 0)
          dO (inters d1 d2 d11 d22 nil)
    )
    (command "Pline" (Cal "w2u(p1)") (Cal "w2u(p2)") (Cal "w2u(p3)") (Cal "w2u(p1)") dO "") 
  )
  )
  (setq dO (Cal "u2w(dO)"))
  (command "ucs" "w")
  (Setvar "Osmode" 33) 

(Defun cChieuDT_MP()
 (command "ucs" "w")(setvar "cmdecho" 0)
  (Setvar "Osmode" 512) (Setvar "orthomode" 0)
  (setq da (getpoint "\nCho diem 1: ") db (getpoint da "\nCho diem 2: ")
        p1 (getpoint "\nCho diem 1 tren mat phang")
        p2 (getpoint p1 "\nCho diem 2 tren mat phang")
        p3 (getpoint p2 "\nCho diem 3 tren mat phang")        
  )    
  (Setvar "Osmode" 0)(command "3DPoly" p1 p2 p3 "c")
  (command "UCS" 3 p1 p2 p3)
  (Setvar "Osmode" 0)
  (setq d1 (Cal "w2u(da)") da1 (list (car d1) (cadr d1) 0)
        d2 (Cal "w2u(db)") db1 (list (car d2) (cadr d2) 0)
  )
  (If (< (abs (caddr d1)) 0.00000001)
    (Alert "Diem nam trong mat phang!")
  (Progn
    (command "Pline" da1 db1 db da "c")
    (Princ (strcat "\nKhoang cach la: " (rtos (distance d1 dO) 2 8) "m ."))
    (setq dO (Cal "u2w(dO)"))
  )
  )
  (command "ucs" "w")    
  (command "color" 2) (command "line" da db "") (command "color" "Bylayer")
  (Setvar "Osmode" 1) 

 

 

PS. Cái lệnh 3D là mình nhở Popup của DOS_LIB có thể nó ko chạy trên máy Bạn nhưng chắc Bạn sẽ nhờ cái đó để hiểu tác dụng của các hàm bên dưới. Có gì thắc mắc trao đổi nhé.

  • Like 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 bác Huy, bác Tiềm và mọi người nhiều. 

Trước giờ tôi chỉ làm CAD 2D nên phần 3D không rành lắm, xem như mới tập tành nhập môn, nhờ mọi người giúp đỡ.

 

@DuongTrungHuy: bác vui lòng post thêm hàm CAL.

 

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
51 phút trước, gia_bach đã nói:

Cám ơn bác Huy, bác Tiềm và mọi người nhiều. 

Trước giờ tôi chỉ làm CAD 2D nên phần 3D không rành lắm, xem như mới tập tành nhập môn, nhờ mọi người giúp đỡ.

 

@DuongTrungHuy: bác vui lòng post thêm hàm CAL.

 

À cái hàm này tên là geomcal.crx   cũng có khi đuôi arx tuỳ đời Cad.

Nó là hàm của Cad. Bạn có thể load nó thường trực luôn khi khởi động cũng được. Nó ở trong thư mục cài đặt của Cad, Bạn có thể search để tìm vị trí.

 

Chào nhé!

  • Like 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

@gia_bach: Thông thường mở Cad thì hàm CAL chưa hiệu lực nên lỗi. Nếu có dòng (load "geomcal.*") để load trước thì CAL sẽ hiệu lực.

Tuy nhiên do đời Cad mà CAL nằm trong file ".*" chưa xác định. Để khỏi lo đời cũ/mới thì chơi 1 dòng này vào đầu lisp là chắc ăn (khỏi load gì cả):

(if (not cal) (command "CAL" "0"))

  • Like 1
  • 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

Test thử lệnh cal thây có Hàm nor cũng vui nên thử viết lisp chuyển 3dpolyline thành lwpoline.

(defun c:test(/ en lp a210 a70 p1 p2 p3)
  (setq en (car(entsel "select 3d polyline"))
	lp (acet-geom-vertex-list en))
  (mapcar 'set '(p1 p2 p3) lp)
  (setq a210 (cal "nor(p1,p2,p3)"))
  (if (eq (car lp) (last lp))
    (setq a70 1
	  lp (reverse (cdr (reverse lp))))
    (setq a70 0))
  (setq lp (mapcar '(lambda(x) (trans x 0 a210)) lp))
	
  (entmakex (append
	      (list '(0 . "LWPOLYLINE") '(100 . "AcDbEntity") '(100 . "AcDbPolyline")
		    (cons 38 (caddar lp)) (cons 90 (length lp)) (cons 70 a70))
	      (mapcar '(lambda(x) (list 10 (car x) (cadr x))) lp)
	      (list (cons 210 a210))))
  (princ))

Viết sơ đơn giản nên không kiễm tra đấu vào và yêu cầu 3 điểm đấu tiên của 3dpolyline phải không thăng hàng.

Chưa kiểm tra đồng phẳng của 3d polyline (Kiềm tra lại z của các đinh sau khi trans.)

Lệnh cal nor sẽ tính pháp vector làm assoc 210. Bình thường nếu không dùng lệnh cal nor này thì có thể dùng lisp của leemac để tính.

https://www.cadtutor.net/forum/topic/24823-3-3d-point-to-ucs-extrusion-direction/

  • Like 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 giờ} trướ}c, ngokiet đã nói:

Có bác nào biết help chi tiết lệnh cal có thể tìm ở đâu không vậy ?

Mình chỉ tìm được

w2u u2w thì mình thường dùng trans

pld thì mình dùng polar

vec thì dùng mapcar '-

các hàm toán học cơ bản như abs, sqrt thì có sẵn trong lisp rồi.

Ngoài ra còn có gì thì mình ko biết muốn tìm hiểu thêm. Không biết sử dụng có nhanh hơn bên lisp không? Dù sao đây là lệnh cad chứ không phải lisp.

Có phải bác hỏi cái này không: https://knowledge.autodesk.com/support/autocad/learn-explore/caas/CloudHelp/cloudhelp/2021/ENU/AutoCAD-Core/files/GUID-B93BD7BF-B69D-40D4-968E-1EB60F90D93E-htm.html

  • Like 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
3 phút trước, NTHAHT đã nói:

Thanks. Mình cũng mới tìm ra nên viết thử lisp trê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
1 giờ} trướ}c, ngokiet đã nói:

Có bác nào biết help chi tiết lệnh cal có thể tìm ở đâu không vậy ?

Mình chỉ tìm được

w2u u2w thì mình thường dùng trans

pld thì mình dùng polar

vec thì dùng mapcar '-

các hàm toán học cơ bản như abs, sqrt thì có sẵn trong lisp rồi.

Ngoài ra còn có gì thì mình ko biết muốn tìm hiểu thêm. Không biết sử dụng có nhanh hơn bên lisp không? Dù sao đây là lệnh cad chứ không phải lisp.

Gửi Bạn:

 

Định copy ra đây mấy thứ thì đã có người kiếm được trang web. Cái này mình viết lâu quá nên cũng không nhớ hết cũng copy lại các Bạn xem sao

 

          (setq tamO2 (cal "plt(dOO3,dOO4,0.5)+kctron2*dau42*nor(dOO3,dOO4)"))
          (setq kcO2 (cal "dpl(tamO2,dOO1,dOO2)") dcO2 (distance dOO1 tamO2))
         (setq da1 (cal "diemO1+huong*1.5*lanve*nor(diemO1,diemO2)") da2 (cal "diemO2+huong*1.5*lanve*nor(diemO1,diemO2)"))
         (setq da1 (cal "rot(diemO1,tamquay,huong*2.0*lanve)") da2 (cal "rot(diemO2,tamquay,huong*2.0*lanve)"))
         (cal "2+3*5^2 + sin(2.3)") 

  • Like 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
12 phút trước, DuongTrungHuy đã nói:

Gửi Bạn:

 

Định copy ra đây mấy thứ thì đã có người kiếm được trang web. Cái này mình viết lâu quá nên cũng không nhớ hết cũng copy lại các Bạn xem sao

 

          (setq tamO2 (cal "plt(dOO3,dOO4,0.5)+kctron2*dau42*nor(dOO3,dOO4)"))
          (setq kcO2 (cal "dpl(tamO2,dOO1,dOO2)") dcO2 (distance dOO1 tamO2))
         (setq da1 (cal "diemO1+huong*1.5*lanve*nor(diemO1,diemO2)") da2 (cal "diemO2+huong*1.5*lanve*nor(diemO1,diemO2)"))
         (setq da1 (cal "rot(diemO1,tamquay,huong*2.0*lanve)") da2 (cal "rot(diemO2,tamquay,huong*2.0*lanve)"))
         (cal "2+3*5^2 + sin(2.3)") 

Thanks bác. Có điều lệnh cal này hơi khó chịu 1 chút là nếu sai thì dễ gây treo khi lập trình lisp khi chạy thử. Nhiều hàm cũng hay và có hàm lisp tương ứng. Nếu rảnh thì viết lại bằng lisp thì mình nghĩ hay hơn.

  • Like 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
2 giờ trước, ngokiet đã nói:

Thanks bác. Có điều lệnh cal này hơi khó chịu 1 chút là nếu sai thì dễ gây treo khi lập trình lisp khi chạy thử. Nhiều hàm cũng hay và có hàm lisp tương ứng. Nếu rảnh thì viết lại bằng lisp thì mình nghĩ hay hơn.

Đúng như bạn Ngô Kiệt nói, Nếu rảnh thì viết lại bằng lisp thì mình nghĩ hay hơn.

Ví dụ: nếu biết 3 điểm trong không gian, thì tìm vetơ pháp tuyến của mặt phẳng đi qua 3 điểm, cũng không khó, nếu hiểu về hình học giải tích:

defun normal (p1 p2 p3 / v1 v2)
    (setq v1 (mapcar '- p1 p2)
          v2 (mapcar '- p2 p3)
    )
    (setq n (list (- (* (cadr v1) (caddr v2)) (* (cadr v2) (caddr v1)))
                  (- (* (caddr v1) (car v2)) (* (caddr v2) (car v1)))
                  (- (* (car v1) (cadr v2)) (* (car v2) (cadr v1)))
            )
    )
    n
)

 

  • Like 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

Xin cám ơn tất cả mọi người đã đọc và đóng góp ý kiến cho chủ đề này, nói chung là các code-Lisp đều chạy tốt trên AutoCAD.

Tuy nhiên do cá nhân tôi, từ khi viết tool cho nhiều nền tảng khác AutoCAD (vd: ZwCAD, BricsCad, IntelliCAD...) tôi thường có thói quen chỉ sử dụng các hàm thuần AutoLISP, hạn chế sử dụng các hàm built-in của AutoCAD như Express-tool (acet-*) hay VisualLISP (vla-*) khi có thể. Dĩ nhiên nếu không có cách khác thì phải sử dụng các hàm built-in thôi.

Nếu chỉ dùng AutoCAD thì việc sử dụng các hàm này sẽ tiết kiệm rất nhiều thời gian và công sức, đạt hiệu suất cao vì đã được tối ưu cho AutoCAD. Và mục đích chính là làm cho AutoCAD phục vụ mình nhanh hơn, diệu kỳ hơn ... đã đạt được.

Nhưng trong trường hợp phài sử dụng các phần mềm CAD khác (vì lý do bản quyền, chi phí đầu tư ...)  thì sẽ gặp khá nhiều khó khăn khi chuyển đổi, tính tương thích không cao (các CAD khác không hỗ trợ hoặc hỗ trợ rất kém các hàm này). Nếu muốn viết lại hàm thì không có công thức/thuật toán để chuyển đổi.

Trên cơ sở các lisp của mọi người, xin cập nhật và hiệu chỉnh để có thể chạy với các CAD khác.

 

;; CrossProduct (Gile)
;; Returns the cross product (vector) of two vectors
;;
;; Arguments: two vectors
(defun CrossProduct (v1 v2)
 (list    (- (* (cadr v1) (caddr v2)) (* (caddr v1) (cadr v2)))
   (- (* (caddr v1) (car v2)) (* (car v1) (caddr v2)))
   (- (* (car v1) (cadr v2)) (* (cadr v1) (car v2)))
 )
)

;; Normalize (Gile)
;; Returns the single unit vector of a vector
;;
;; Argument : a vector
(defun Normalize (v)
 ((lambda (l)
    (if (/= 0 l)
      (mapcar (function (lambda (x) (/ x l))) v)
    )
  )
   (distance '(0 0 0) v)
 )
)

;; Norm_3Points (Gile)
;; Returns the single unit normal vector of a plane definedby 3 points
;;
;; Arguments: three points
(defun norm_3pts (p0 p1 p2)
 (Normalize (CrossProduct (mapcar '- p1 p0) (mapcar '- p2 p0)))
)

;; Collinearity check (Lee Mac)
(defun isCollinear ( p1 p2 p3 fz )
 (equal (rem (angle p1 p2) pi) (rem (angle p2 p3) pi) fz)
)

(defun c:test(/ lp p1 p2 p3 a210)
  (if
    (and
       (setq p1 (getpoint "\nChon diem 1"))
       (setq p2 (getpoint p1 "\nChon diem 2"))
       (setq p3 (getpoint p2 "\nChon diem 3"))       )
    (progn
      (setq p1 (trans p1 1 0)
	    p2 (trans p2 1 0)
	    p3 (trans p3 1 0))
      (if (isCollinear p1 p2 p3 1e-6)
	(setq a210 '(0 0 1))
	(setq a210 (norm_3pts p1 p2 p3)))
      (setq lp (list p1 p2 p3))
      (setq lp (mapcar '(lambda(x) (trans x 0 a210)) lp))
      (entmakex (append
		  (list '(0 . "LWPOLYLINE") '(100 . "AcDbEntity") '(100 . "AcDbPolyline")
			(cons 38 (caddar lp))(cons 90 (length lp)) )
		  (mapcar '(lambda(x) (list 10 (car x) (cadr x))) lp)
		  (list (cons 210 a210))))      )    )
  (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
19 phút trước, gia_bach đã nói:

Tuy nhiên do cá nhân tôi, từ khi viết tool cho nhiều nền tảng khác AutoCAD (vd: ZwCAD, BricsCad, IntelliCAD...) tôi thường có thói quen chỉ sử dụng các hàm thuần AutoLISP, hạn chế sử dụng các hàm built-in của AutoCAD như Express-tool (acet-*) hay VisualLISP (vla-*) khi có thể. Dĩ nhiên nếu không có cách khác thì phải sử dụng các hàm built-in thôi.


;; CrossProduct (Gile)
; Returns the cross product (vector) of two vectors
;
; Arguments: two vectors
(defun CrossProduct (v1 v2)
 (list    (- (* (cadr v1) (caddr v2)) (* (caddr v1) (cadr v2)))
   (- (* (caddr v1) (car v2)) (* (car v1) (caddr v2)))
   (- (* (car v1) (cadr v2)) (* (cadr v1) (car v2)))
 )
)

;; Normalize (Gile)
; Returns the single unit vector of a vector
;
; Argument : a vector
(defun Normalize (v)
 ((lambda (l)
    (if (/= 0 l)
      (mapcar (function (lambda (x) (/ x l))) v)
    )
  )
   (distance '(0 0 0) v)
 )
)

;; Norm_3Points (Gile)
; Returns the single unit normal vector of a plane definedby 3 points
;
; Arguments: three points
(defun norm_3pts (p0 p1 p2)
 (Normalize (CrossProduct (mapcar '- p1 p0) (mapcar '- p2 p0)))
)

;; Collinearity check (Lee Mac)
(defun isCollinear ( p1 p2 p3 fz )
 (equal (rem (angle p1 p2) pi) (rem (angle p2 p3) pi) fz)
)

(defun c:test(/ lp p1 p2 p3 a210)
  (if
    (and
       (setq p1 (getpoint "\nChon diem 1"))
       (setq p2 (getpoint p1 "\nChon diem 2"))
       (setq p3 (getpoint p2 "\nChon diem 3"))       )
    (progn
      (setq p1 (trans p1 1 0)
	    p2 (trans p2 1 0)
	    p3 (trans p3 1 0))
      (if (isCollinear p1 p2 p3 1e-6)
	(setq a210 '(0 0 1))
	(setq a210 (norm_3pts p1 p2 p3)))
      (setq lp (list p1 p2 p3))
      (setq lp (mapcar '(lambda(x) (trans x 0 a210)) lp))
      (entmakex (append
		  (list '(0 . "LWPOLYLINE") '(100 . "AcDbEntity") '(100 . "AcDbPolyline")
			(cons 38 (caddar lp))(cons 90 (length lp)) )
		  (mapcar '(lambda(x) (list 10 (car x) (cadr x))) lp)
		  (list (cons 210 a210))))      )    )
  (princ))    

Anh Gia_bach viết lisp dùng cho nhiều nền tảng Cad khác đã bao giờ dính những lỗi đau đớn chưa?

Tôi vừa viết cho AutoCad vừa cho ZWCad đã dính nhiều đòn chí tử rồi đó: cùng tên hàm nhưng Cad cho kq là A còn ZWCad cho kq là B đó.

  • Like 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
29 phút trước, gia_bach đã nói:

Xin cám ơn tất cả mọi người đã đọc và đóng góp ý kiến cho chủ đề này, nói chung là các code-Lisp đều chạy tốt trên AutoCAD.

Tuy nhiên do cá nhân tôi, từ khi viết tool cho nhiều nền tảng khác AutoCAD (vd: ZwCAD, BricsCad, IntelliCAD...) tôi thường có thói quen chỉ sử dụng các hàm thuần AutoLISP, hạn chế sử dụng các hàm built-in của AutoCAD như Express-tool (acet-*) hay VisualLISP (vla-*) khi có thể. Dĩ nhiên nếu không có cách khác thì phải sử dụng các hàm built-in thôi.

Nếu chỉ dùng AutoCAD thì việc sử dụng các hàm này sẽ tiết kiệm rất nhiều thời gian và công sức, đạt hiệu suất cao vì đã được tối ưu cho AutoCAD. Và mục đích chính là làm cho AutoCAD phục vụ mình nhanh hơn, diệu kỳ hơn ... đã đạt được.

Nhưng trong trường hợp phài sử dụng các phần mềm CAD khác (vì lý do bản quyền, chi phí đầu tư ...)  thì sẽ gặp khá nhiều khó khăn khi chuyển đổi, tính tương thích không cao (các CAD khác không hỗ trợ hoặc hỗ trợ rất kém các hàm này). Nếu muốn viết lại hàm thì không có công thức/thuật toán để chuyển đổi.

Trên cơ sở các lisp của mọi người, xin cập nhật và hiệu chỉnh để có thể chạy với các CAD khác.

 


;; CrossProduct (Gile)
; Returns the cross product (vector) of two vectors
;
; Arguments: two vectors
(defun CrossProduct (v1 v2)
 (list    (- (* (cadr v1) (caddr v2)) (* (caddr v1) (cadr v2)))
   (- (* (caddr v1) (car v2)) (* (car v1) (caddr v2)))
   (- (* (car v1) (cadr v2)) (* (cadr v1) (car v2)))
 )
)

;; Normalize (Gile)
; Returns the single unit vector of a vector
;
; Argument : a vector
(defun Normalize (v)
 ((lambda (l)
    (if (/= 0 l)
      (mapcar (function (lambda (x) (/ x l))) v)
    )
  )
   (distance '(0 0 0) v)
 )
)

;; Norm_3Points (Gile)
; Returns the single unit normal vector of a plane definedby 3 points
;
; Arguments: three points
(defun norm_3pts (p0 p1 p2)
 (Normalize (CrossProduct (mapcar '- p1 p0) (mapcar '- p2 p0)))
)

;; Collinearity check (Lee Mac)
(defun isCollinear ( p1 p2 p3 fz )
 (equal (rem (angle p1 p2) pi) (rem (angle p2 p3) pi) fz)
)

(defun c:test(/ lp p1 p2 p3 a210)
  (if
    (and
       (setq p1 (getpoint "\nChon diem 1"))
       (setq p2 (getpoint p1 "\nChon diem 2"))
       (setq p3 (getpoint p2 "\nChon diem 3"))       )
    (progn
      (setq p1 (trans p1 1 0)
	    p2 (trans p2 1 0)
	    p3 (trans p3 1 0))
      (if (isCollinear p1 p2 p3 1e-6)
	(setq a210 '(0 0 1))
	(setq a210 (norm_3pts p1 p2 p3)))
      (setq lp (list p1 p2 p3))
      (setq lp (mapcar '(lambda(x) (trans x 0 a210)) lp))
      (entmakex (append
		  (list '(0 . "LWPOLYLINE") '(100 . "AcDbEntity") '(100 . "AcDbPolyline")
			(cons 38 (caddar lp))(cons 90 (length lp)) )
		  (mapcar '(lambda(x) (list 10 (car x) (cadr x))) lp)
		  (list (cons 210 a210))))      )    )
  (princ))    

 

- Cái a210 không cần tính về Normalize mà chỉ cần tính CrossProduct thôi là được rồi. Tính về CrossProduct thì khi entmake nó cũng tính lại hay sao đó. 

- Còn kiểm tra 3 điểm thẳng hàng thì đơn giản hơn là CrossProduct là <> '(0 0 0) . (not (vl-every 'zerop a210)) 

   Trong trường hợp này bạn phải tính 1 vecto bất kỳ nào đó vuông góc với phương đó làm a210 chứ ko lấy '(0 0 1) vì nếu z khác nhau.

(còn kiểm tra p1 p2 p3 không trùng nhau nữa)

 

 

  • Like 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
5 phút trước, ngokiet đã nói:

- Cái a210 không cần tính về Normalize mà chỉ cần tính CrossProduct thôi là được rồi. Tính về CrossProduct thì khi entmake nó cũng tính lại hay sao đó. 

- Còn kiểm tra 3 điểm thẳng hàng thì đơn giản hơn là CrossProduct là <> '(0 0 0) . (not (vl-every 'zerop a210)) 

   Trong trường hợp này bạn phải tính 1 vecto bất kỳ nào đó vuông góc với phương đó làm a210 chứ ko lấy '(0 0 1) vì nếu z khác nhau.

(còn kiểm tra p1 p2 p3 không trùng nhau nữa)

 

 

@ngokiet

- A210 phải tính vecto đon vị, đã kiểm tra.

- ok tr/hợp thẳng hàng đưa về (0 0 1) là chưa chính xá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
4 phút trước, gia_bach đã nói:

@ngokiet

- A210 phải tính vecto đon vị, đã kiểm tra.

- ok tr/hợp thẳng hàng đưa về (0 0 1) là chưa chính xác.

(defun c:test(/ en lp a210 a70 p1 p2 p3)
  (defun nor(a b c)
    (setq b (mapcar '- b a)
	  c (mapcar '- c a))
    (list (- (* (cadr b) (caddr c)) (* (caddr b)(cadr c)))
	  (- (* (caddr b) (car c)) (* (car b)(caddr c)))
	  (- (* (car b) (cadr c)) (* (cadr b)(car c)))))
	  
  (setq en (car(entsel "select 3d polyline"))
	lp (acet-geom-vertex-list en))
  (mapcar 'set '(p1 p2 p3) lp)
  (setq a210 (nor p1 p2 p3)) ;(cal "nor(p1,p2,p3)"))
  (if (eq (car lp) (last lp))
    (setq a70 1
	  lp (reverse (cdr (reverse lp))))
    (setq a70 0))
  (setq lp (mapcar '(lambda(x) (trans x 0 a210)) lp))
	
  (entmakex (append
	      (list '(0 . "LWPOLYLINE") '(100 . "AcDbEntity") '(100 . "AcDbPolyline")
		    (cons 38 (caddar lp)) (cons 90 (length lp)) (cons 70 a70))
	      (mapcar '(lambda(x) (list 10 (car x) (cadr x))) lp)
	      (list (cons 210 a210))))
  (princ))

Mình thử thấy vẫn ok mà . 

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
2 phút trước, Doan Van Ha đã nói:

@gia_bach: hỏi ké ở đây tí: với zwcad có thể tạo dialog với các label của title bằng tiếng Việt không? Thanks!

Tôi thường sử dụng .NET để làm giao diện, nên không rành về dialog lắm.

 

@ngokiet ừ, để  CrossProduct  chạy cũng đc, chắc có gì nhầm lẫn giửa các CAD.

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 nghĩ AutoCAD có tính toán lại. Vì 1 mặt phẳng có 2 pháp vector ngược nhau. Nên khi entmake nó phải tính lại hướng. Ví dụ như ‘(0 0 1) và ‘(0 0 -1) thì nó tính như nhau. Nên tính đúng assoc 210 phải kiểm tra thêm. Nên cho Cad tính luôn. Mình ko biết Cad khác có vậy ko. Nếu có xem có lỗi gì khi pháp vector ngược nhau.

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 giờ} trướ}c, ngokiet đã nói:

Mình nghĩ AutoCAD có tính toán lại. Vì 1 mặt phẳng có 2 pháp vector ngược nhau. Nên khi entmake nó phải tính lại hướng. Ví dụ như ‘(0 0 1) và ‘(0 0 -1) thì nó tính như nhau. Nên tính đúng assoc 210 phải kiểm tra thêm. Nên cho Cad tính luôn. Mình ko biết Cad khác có vậy ko. Nếu có xem có lỗi gì khi pháp vector ngược nhau.

Mọi mặt phẳng trong không gian có phương trình tổng quát có dạng :  Ax + By + Cz +D = 0  Khi đó vectơ  '(A  B  C) là vectơ pháp tuyến của mặt phẳng.

Vì vậy với 1 mặt phẳng, theo quy ước chỉ có 1 vecto pháp tuyến mà thôi.

Điều này hình như có liên quan đến quy tắc bàn tay phải, nghĩa là: nếu ta bẹt 3 ngón tay của bàn tay phải sao cho vuông góc nhau như 3 trục hệ toạ độ vuông góc: ngón tay trỏ là hướng dương trục Ox, ngón tay giữa là trục Oy thì ngón tay cái là vecto pháp tuyến của trục Oz.

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 giờ trước, thiep đã nói:

Mọi mặt phẳng trong không gian có phương trình tổng quát có dạng :  Ax + By + Cz +D = 0  Khi đó vectơ  '(A  B  C) là vectơ pháp tuyến của mặt phẳng.

Vì vậy với 1 mặt phẳng, theo quy ước chỉ có 1 vecto pháp tuyến mà thôi.

Điều này hình như có liên quan đến quy tắc bàn tay phải, nghĩa là: nếu ta bẹt 3 ngón tay của bàn tay phải sao cho vuông góc nhau như 3 trục hệ toạ độ vuông góc: ngón tay trỏ là hướng dương trục Ox, ngón tay giữa là trục Oy thì ngón tay cái là vecto pháp tuyến của trục Oz.

Vậy có điều kiện ABCD như thế nào không? Ví dụ như 0x+0y+1z -5=0 với 0x+0y-1z+5=0 là 1 mặt phẳng. Nhưng khi lấy ABC là 0 0 1 và 0 0 -1 là 2 vecto đối nhau.

vì vây khi tính tích có hướng thì làm sao xác định nó là pháp vecto hay là Vectơ đối?

Lập trình mình quên quy tắc toán nhiều nên đôi khi tự định quy tắc ko giống ai.

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  

×