Insert Elbow Lisp

Insert Elbow Lisp

smallƑish
Advocate Advocate
1,846 Views
31 Replies
Message 1 of 32

Insert Elbow Lisp

smallƑish
Advocate
Advocate

smallish_0-1740992406668.png

Select two pipe blocks
Find their intersection point and calculates the rotation.
It inserts an "ELBOW" block at the intersection point with the correct rotation

 

If it can be automated with lisp please help me 

 

Thank you 

 

0 Likes
Accepted solutions (4)
1,847 Views
31 Replies
Replies (31)
Message 2 of 32

smallƑish
Advocate
Advocate

It's not easy to do this by lisp.

0 Likes
Message 3 of 32

ec-cad
Collaborator
Collaborator

Seems like you post the same stuff several times.

 

Are your pipes Dynamic Blocks, or just Plines ?

How about a small sample drawing ?

ECCAD

0 Likes
Message 4 of 32

Moshe-A
Mentor
Mentor

@smallƑish  hi,

 

check this ELBOW command.

 

You can selected multiple pipes together. the program than goes to match pairs and if 2 pipes insertion point is joined

(in your sample they are not) the elbow is inserted in place 😀 pipes that have no pair or their  insertion points are not joined 

are ignored.

 

enjoy

Moshe

 

(vl-load-com)

(defun c:elbow (/ _swapVar _pairs _insert_block ; local functions
		  adoc ss ename AcDbBlkRef p0 rot data^ pair item0 item1 a0 a1 a3)

 (defun _swapVar (Qa0 Qa1 / tmp)
  (setq tmp (vl-symbol-value Qa0))
  (set  Qa0 (vl-symbol-value Qa1))
  (set  Qa1 tmp)
 ); _swapVar
  
  
 ; return pairs of blocks
 (defun _pairs (data^ / i j item0 item1 lst0 lst1)
  (setq i 0)
  (while (setq item0 (nth i data^))
   (setq j (1+ i) lst1 nil lst1 (cons item0 lst1))
   (while (setq item1 (nth j data^))
    (if (equal (distance (cadr item0) (cadr item1)) 0.0 1e-3)
     (cond
      ((= (car item0) (car item1))
       (setq data^ (vl-remove item1 data^))
      ); case
      ((< (vl-list-length lst1) 2)
       (setq lst1 (cons item1 lst1))
       (setq data^ (vl-remove item1 data^)) 
      ); case
      ( t
       (setq data^ (vl-remove item1 data^))
      ); case
     ); cond
    ); if
     
    (setq j (1+ j))
   ); while

   (if (= (vl-list-length lst1) 2)
    (setq lst0 (cons lst1 lst0))
   )
    
   (setq i (1+ i))
  ); while

  lst0
 ); _pairs


 (defun _insert_block (bn pt x y z r)
  (entmake
   (list
    '(0 . "insert")
     (cons 2 bn)
     (cons 10 pt)
     (cons 41 x)
     (cons 42 y)
     (cons 43 z)
     (cons 50 r)
    )
  ); entmake
 ); _insert_block

  
 ; here start c:elbow
 (setq adoc (vla-get-activedocument (vlax-get-acad-object)))
 (vla-startUndoMark adoc)
   
 (if (setq ss (ssget '((0 . "insert") (2 . "PIPE,`*U*"))))
  (progn
   (foreach ename (vl-remove-if 'listp (mapcar 'cadr (ssnamex ss)))
    (setq AcDbBlkRef (vlax-ename->vla-object ename))

    (if (eq (vla-get-effectiveName AcDbBlkRef) "PIPE")
     (progn
      (setq p0 (vlax-safearray->list (vlax-variant-value (vla-get-insertionPoint AcDbBlkRef))))
      (setq rot (vla-get-rotation AcDbBlkRef))
      (setq sx (vla-get-XEffectiveScaleFactor AcDbBlkRef))
      (setq sy (vla-get-YEffectiveScaleFactor AcDbBlkRef))
      (setq data^ (cons (list rot p0 sx sy) data^))  
     ); progn
    ); if
   
    (vlax-release-object AcDbBlkRef)
   ); foreach

   (foreach pair (setq l (_pairs data^))
    (setq item0 (car pair))
    (setq a0 (car item0))
    (setq item1 (cadr pair))
    (setq a1 (car item1))
    
    (if (> a0 a1)
     (_swapVar 'a0 'a1)
    )

    (setq a2 (- a1 a0))
    (if (equal a2 (* pi 1.5) 1e-4)
     (progn
      (setq a0 (+ a0 (* pi 2)))
      (setq a2 (- a0 a1))
     ); progn
    ); if

    (if (equal a2 (/ pi 2) 1e-4) ; only 90 degrees
     (progn
      (if (and (> a1 (* pi 0.5)) (< a1 (* pi 1.5)))
       (setq a3 a1)
       (setq a3 a0)
      ); if
      (_insert_block "elbow" (cadr item0) (caddr item0) (cadddr item0) (caddr item0) a3)
     ); progn
    ); if
   ); foreach 
   
  ); progn
 ); if

 (vla-endUndoMark adoc)
 (vlax-release-object adoc)
		     
 (princ)
); c:elbow

 

 

 

Message 5 of 32

smallƑish
Advocate
Advocate

Project file sample attached as instructed, 

  1. My working plan is beak all the plines to line. referring the start mid and end point using lisp replace to pipe block (dynamic)
  2. then using elbow cmd select each pair of pipe block at intersection insert elbow block (referring non intersected ends) pick main pipe , pick elbow pipe hence find the rotation orientation
  3. using TEE cmd insert tee block referring the second pipe block orientation rotation. pick main pipe , pick branch pipe hence find the rotation orientation

That's all others anyhow I have to do manually 

 

IF INSERTION OF FITTINGS EASY WITH LINES, THE PIPE BLOCK REPLACEMENT CAN BE DO AT THE END TOO. 

0 Likes
Message 6 of 32

smallƑish
Advocate
Advocate

Thank you for the code, but in this workflow its I request to reconsidered. 

0 Likes
Message 7 of 32

Moshe-A
Mentor
Mentor

 


@smallƑish wrote:

Thank you for the code, but in this workflow its I request to reconsidered. 


explain that

 

Message 8 of 32

smallƑish
Advocate
Advocate

please have a look to reply no 4 above 

0 Likes
Message 9 of 32

Moshe-A
Mentor
Mentor

how about using MLINE?

Message 10 of 32

smallƑish
Advocate
Advocate

MLINE is perfect and easy too.

0 Likes
Message 11 of 32

smallƑish
Advocate
Advocate

I have  modified this with MLINE. file attached 

0 Likes
Message 12 of 32

Moshe-A
Mentor
Mentor
Accepted solution

@smallƑish ,

 

Check this new version to support mlines.

 

a few things to be aware of:

 

1. the mline (pipe) must be of one segment only (not multi segments) and the start + end must be cut straight 90 degree.

    make sure two mlines (corner / L shape) are joined exactly 100% 😀

 

2. always draw the mline at justify = Zero.

 

3. at select object(s) you can pick as many mlines, than program goes to find match pairs. un match mline is ignored.

   

4. an mline can be connect at it's both end. if you select odd objects (like 3) there is times the pairs will not be recognized

    hance result missing elbow. in this cases, run the command on these two again (yes, it's a bug 😱)

 

5. in your elbow block, i found the distance from the insertion point to it's edge is 30.7142. do not know how you got this

    and if it's not important and you want to make it more pro, change it to 30 fix (or any other fix number).

    why i am dealing with that? this is the length the mlines should be trimed after inserting elbow block - yes?!

    if you do modify the block, update the new value in the code on line# 107

(setq RETREAT 30.7142) ; const

 

 

enjoy

Moshe

 

 

(vl-load-com)

(defun c:elbow (/ _geometric _swapVar _pairs _insert_block ; local functions
		  RETREAT adoc ss data^ pair item0 item1 p0 p1 p2 p3 a0 a1 a2 itm pair elist m0 m1)
  
 (defun _geometric (p / ename)
  (mapcar
    (function
      (lambda (ename)
       (append (vl-remove-if-not (function (lambda (e) (= (car e) 11))) (entget ename)) (list ename))
      ); lambda
    ); function
    (vl-remove-if 'listp (mapcar 'cadr (ssnamex p)))
  ); mapcar
 ); _geometric 

  
 (defun _swapVar (Qa0 Qa1 / tmp)
  (setq tmp (vl-symbol-value Qa0))
  (set  Qa0 (vl-symbol-value Qa1))
  (set  Qa1 tmp)
 ); _swapVar

  
 ; return pairs of blocks
 (defun _pairs (data^ / dat0 dat1 lst0 lst1 t0 t1 t2 t3 t4)

  (foreach dat0 (reverse (cdr (reverse data^)))
   (setq lst1 nil)
   (setq t0 (cdr (car  dat0)))
   (setq t1 (cdr (cadr dat0)))

   (setq lst1 (vl-some
    		(function
     		 (lambda (dat1)
      		  (setq t2 (cdr (car  dat1)))
      		  (setq t3 (cdr (cadr dat1)))

      		  (if (< (vl-list-length lst1) 2)
       		   (if (setq t4 (inters t0 t1 t2 t3))
        	    (cond
         	     ((and
           	       (equal (distance t4 t0) 0.0 1e-3)
           	       (equal (distance t4 t3) 0.0 1e-3)
          	      ); and
          	      (_swapVar 't2 't3)
	  	      (if (/= (angle t0 t1) (angle t2 t3))
           	       (list dat0 (list (cadr dat1) (car dat1) (caddr dat1)))
	              )
                     ); case
                     ((and
                       (equal (distance t4 t1) 0.0 1e-3)
                       (equal (distance t4 t2) 0.0 1e-3)
                      ); and
                      (_swapVar 't0 't1)
	              (if (/= (angle t0 t1) (angle t2 t3))
                       (list (list (cadr dat0) (car dat0) (caddr dat0)) dat1)
	              )
                     ); case
                     ((and
                       (equal (distance t4 t1) 0.0 1e-3)
                       (equal (distance t4 t3) 0.0 1e-3)
                      ); and
                      (_swapVar 't0 't1)
		      (_swapVar 't2 't3)
	              (if (/= (angle t0 t1) (angle t2 t3))
                       (list (list (cadr dat0) (car dat0) (caddr dat0)) (list (cadr dat1) (car dat1) (caddr dat1)))
	              )
                     ); case
                    ); cond
                   ); if
                  ); if
                 ); lambda
                ); function
		(cdr (member dat0 data^))
               ); vl-some
   ); setq

   (if lst1
    (setq lst0 (cons lst1 lst0))
   )
  ); foreach

  lst0
 ); _pairs

  
 (defun _insert_block (bn pt x y z r)
  (entmake
   (list
    '(0 . "insert")
     (cons 2 bn)
     (cons 10 pt)
     (cons 41 x)
     (cons 42 y)
     (cons 43 z)
     (cons 50 r)
    )
  ); entmake
 ); _insert_block

 
 ; here start c:elbow
 (setq adoc (vla-get-activedocument (vlax-get-acad-object)))
 (vla-startUndoMark adoc)

 (setq RETREAT 30.7142) ; const

 (cond
  ((not
     (or
       (tblsearch "block" "elbow")
       (findfile "elbow.dwg")
     )
   )
   (vlr-beep-reaction)
   (prompt "\nBlock elbow is not found.")
  ); case
  ;| filter mlines of segment, justify = zero |;
  ((setq ss (ssget '((0 . "mline") (70 . 1) (72 . 2))))
   (setq data^ (_geometric ss))

   (foreach pair (_pairs data^)
    (setq item0 (car pair))
    (setq p0 (cdr (car item0)))
    (setq p1 (cdr (cadr item0)))
     
    (setq item1 (cadr pair))
    (setq p2 (cdr (car item1)))
    (setq p3 (cdr (cadr item1)))
     
    (setq a0 (angle p0 p1))
    (setq a1 (angle p2 p3))

    (if (> a0 a1)
     (_swapVar 'a0 'a1)
    )

    (setq a2 (- a1 a0))
     
    (if (equal a2 (* pi 1.5) 1e-4)
     (progn
      (setq a0 (+ a0 (* pi 2)))
      (setq a2 (- a0 a1))
      (_swapVar 'a0 'a1)
     ); progn
    ); if
     
    (if (equal a2 (/ pi 2) 1e-4) ; only 90 degrees
     (progn
      (foreach itm pair
       (setq elist (entget (last itm)))
       (setq m0 (cdr (assoc '11 elist)))
       (setq m1 (cdr (assoc '11 (reverse elist))))

       (if (equal (distance p0 m0) 0.0 1e-3)
        (entmod (subst (cons '11 (polar m1 (angle m1 m0) (- (distance m1 m0) RETREAT))) (assoc '11 elist) elist))
        (entmod (subst (cons '11 (polar m0 (angle m0 m1) (- (distance m0 m1) RETREAT))) (assoc '11 (reverse elist)) elist))
       ); if
      ); foreach
       
      (_insert_block "elbow" p0 1 1 1 a1)
     ); progn
    ); if
   ); foreach
   
  ); case
 ); cond

 (vla-endUndoMark adoc)
 (vlax-release-object adoc)
  
 (princ)
); c:elbow

Message 13 of 32

Moshe-A
Mentor
Mentor
Accepted solution

@smallƑish ,

 

bug fixed.

 

enjoy

 

Message 14 of 32

smallƑish
Advocate
Advocate

Thank you so much for the updated code. It's working nicely. I m sure its helpful not only for me. A lot of people who is working in plumbing drawings. Thank you so much. 

Message 15 of 32

smallƑish
Advocate
Advocate

A request, is that possible to convert a line to MLine by using lisp, I found few of them from Google. But most of them are not working properly. If you can share one. It could be easier to work.

 

Again thank you so much. 

0 Likes
Message 16 of 32

Moshe-A
Mentor
Mentor
Accepted solution

@smallƑish hi,

 

Made fine tunning and add efficiency, use this update 😀

 

A new command L2M (lines to mlines) is added.  it let you select lines and plines. pline polyarcs are ignored.

if "DR" mlstyle is not exist, it won't work (need to be loaded first)

 

enjoy

Moshe

 

 

Message 17 of 32

smallƑish
Advocate
Advocate

Ooooohhhh!!! Seriously, you took this to another level!

You turned the hardest part of drafting into the most interesting one. It’s beyond amazing! I just have to say—you made this absolutely great. Thank you so much! So many thanks! No words to express how much I loved it!

0 Likes
Message 18 of 32

Moshe-A
Mentor
Mentor

@smallƑish ,

 

Your respond is more like a B I G  F I S H 😀

this of course made me happy, glade i could help

thank you

 

Message 19 of 32

smallƑish
Advocate
Advocate

Since you've already developed a very helpful tool that benefits all draftsmen working on piping, truly appreciate your efforts.

I have one last request that I believe could be useful:

Would it be possible to automatically insert a tee block when two Mlines intersect perpendicularly selected ? I've attached a video file for better understanding.

smallish_0-1741346800663.gif

I made this video using oops command by recovering last deleted item. not with lisp lol.

I hope you can take a look at it.

Thank you again for your support!

0 Likes
Message 20 of 32

Moshe-A
Mentor
Mentor

@smallƑish  hi,

 

i am working on it so be patience it will take more time cause i will be very busy this week.

saw your request on my private mail box, what's on your mind?

 

Moshe