AutoLISP: Break 3D line through User defined Plane

This routine was made by Chen Qing Jun, qjchen and is found at http://www.theswamp.org/index.php?topic=40494.msg457913#msg457913

It is quite handy if you happen to need to break a line that passes through a “plane.” I am using the term “plane” loosely because it doesn’t have to be a 3d object like a face or a solid. You define the “plane” by picking 3 points without having to use a different UCS…

Here’s how:

  • PBL
  • Pick 3 points to define the plane
  • Select the Line(s) to be broken – (Note: they must pass through the defined plane)
  • Thank you Chen!!

    Break 3d Line through Plane

     

    
    ;;;Break 3d lines by a 3d Plane
    ;;;Author: Chen Qing Jun, qjchen
    ;;;Programed by: South China University of Technology
    ;;;date: 2011.12.19
    ;;;Note: the intersection function of Line and Plane, has the parameter of nil and T
    ;;;      For T, the line segment should pass through the plane
    ;;;      but it is not necessary for the nil parameter.
    ;;;      The plane defined by 3p is infinite.
    ;;; 
    ;;; http://www.theswamp.org/index.php?topic=40494.msg457913#msg457913
    ;;;
    ;;;_Some vector function, some get from gile's great function________________
    ;;;
    (defun q:geo:is-3p-plane(p1 p2 p3)
     (> (q:vec:Len (q:vec:Norm (q:vec:cross* (q:vec:- p2 p1) (q:vec:- p3 p1)))) 1e-6)
    )
    (defun q:geo:is-samepoint(p1 p2) (< (distance p1 p2) 1e-5) )
    (defun q:vec:+(v1 v2) (mapcar '+ v1 v2) )
    (defun q:vec:-(v1 v2) (mapcar '- v1 v2) )
    (defun q:vec:*c(v a) (mapcar '(lambda(x) (* x a)) v) )
    (defun q:vec:dot*(v1 v2) (apply '+ (mapcar '* v1 v2)) )
    (defun q:vec:cross*(v1 v2)
      (list (q:det:2 (cadr v1) (caddr v1) (cadr v2) (caddr v2))
            (q:det:2 (caddr v1) (car v1) (caddr v2) (car v2))
            (q:det:2 (car v1) (cadr v1) (car v2) (cadr v2))) 
    )
    ;;;;cal determinant
    ;;;;|a1 a2|
    ;;;;|b1 b2|
    (defun q:det:2(a1 a2 b1 b2)  (- (* a1 b2) (* a2 b1)))
    ;;;;Normalize a vector
    (defun q:vec:Norm(v / l)
      (if (not (zerop (setq l (distance '(0 0 0) v))))
      (mapcar '(lambda(x) (/ x l)) v))
    )
    ;;;;Vector Length
    (defun q:vec:Len(v / l)  (distance '(0 0 0) v))
    ;;;;a normal to a plane, 
    (defun q:geo:normal.to.3p(p1 p2 p3)
      (if (q:geo:is-3p-plane p1 p2 p3)(q:vec:cross* (q:vec:- p2 p1) (q:vec:- p3 p1)))
    )
    ;;p1 p2 are two points,V is the normal of the plane, VP is one point on the plane
    ;;ref:   http://en.wikipedia.org/wiki/Line-plane_intersection
    ;;       http://softsurfer.com/Archive/algorithm_0104/algorithm_0104B.htm
    (defun q:geo:line-intersect-plane-1(P1 P2 V VP F / d l n)
     (setq n (q:vec:Norm V) l (q:vec:Norm (q:vec:- P2 P1)))
     (if (not (zerop (q:vec:dot* l n)))
       (progn
         (setq d (/ (q:vec:dot* (q:vec:- VP P1) n) (q:vec:dot* l n)))
         (setq res (q:vec:+ P1 (q:vec:*c l d)))
         (setq temp (q:vec:Len (q:vec:- P2 P1)))
         (if (and F (or (< d 0) (> d (q:vec:Len (q:vec:- P2 P1))))) (setq res nil)) 
       )
     )
     res
    )
    ;;;;;;______end of Vector function__________________________________;;;
    (defun q:entmake:point(pt layer)
      (entmake (list (cons 0 "POINT")(cons 8 layer)(cons 10 pt)))
    )
    (defun q:mulentmod (ent numlst contentlst / i x)
      (setq i 0)
      (foreach x numlst
        (if (/= (assoc x ent) nil)
          (setq ent (subst (cons x (nth i contentlst)) (assoc x ent) ent ) )
          (setq ent (append ent (list (cons x (nth i contentlst))) ) )
        )
        (setq i (1+ i))
      )
      (entmod ent)  ;(entupd ent)
    )
    ;;;;;stdlib from Reini Urban
    (defun std-sslist (ss / n lst)
      (if (eq 'pickset (type ss))
        (repeat (setq n (fix (sslength ss))) ; fixed
          (setq lst (cons (ssname ss (setq n (1- n))) lst))
        )
      )
    )
    ;;;???______by qjchen____________________________;;;
    (defun c:PBL()
      (setq p1 (getpoint "\nThe first point:") p2 (getpoint "\nThe second point:") p3 (getpoint "\nThe third point:"))
      (if (q:geo:is-3p-plane p1 p2 p3)
        (progn 
          (setq c (std-sslist(ssget '((0 . "LINE")))))
          (setq pn (q:geo:normal.to.3p p1 p2 p3))
          (foreach x c
           (setq pa (cdr (assoc 10 (entget x))) pb (cdr (assoc 11 (entget x))))
           (setq int (q:geo:line-intersect-plane-1 pa pb pn p1 T))
           
           (if (and int (not (q:geo:is-samepoint int pa))(not (q:geo:is-samepoint int pb)))
    	  (progn
    	    (q:mulentmod (entget (entmakex (entget x))) (list 62 11) (list 1 int))
    	    (q:mulentmod (entget (entmakex (entget x))) (list 62 10) (list 2 int))
    	    (entdel x)
    	    (q:entmake:point int "0")
    	 )
    	 )
          )
        )
        (princ "\n These three points can not form a plane.")
      )
    )
    
    (princ)
    (princ "\n Break 3d lines by a 3d Plane,by qjchen,the command is :test")
    (princ)
    
    Advertisements

    About AutoCAD Tips

    This blog serves as a knowledge base for myself (and anyone else) so that I can reference tips & tricks that I have learned and also refer others to it as well. I hope that this blog helps you learn at least one tip to make your drafting/design experience better.
    This entry was posted in AutoLISP, AutoLISP: 3D, AutoLISP: Modify, Modifying. Bookmark the permalink.

    2 Responses to AutoLISP: Break 3D line through User defined Plane

    1. Ken Krupa says:

      Excellent – thank you!

    Leave a Reply

    Fill in your details below or click an icon to log in:

    WordPress.com Logo

    You are commenting using your WordPress.com account. Log Out / Change )

    Twitter picture

    You are commenting using your Twitter account. Log Out / Change )

    Facebook photo

    You are commenting using your Facebook account. Log Out / Change )

    Google+ photo

    You are commenting using your Google+ account. Log Out / Change )

    Connecting to %s