Visual LISP, AutoLISP and General Customization
cancel
Showing results for 
Show  only  | Search instead for 
Did you mean: 

Insert block at intersection

27 REPLIES 27
SOLVED
Reply
Message 1 of 28
jbear0000
8100 Views, 27 Replies

Insert block at intersection

Does anyone know of a lisp that will insert a block at the intersection points of multiple lines or polylines? Basically it would ask you to select polylines or lines, then check to see where their intersections are with each other and insert a block at those points. See the attached image for what I am looking for.

27 REPLIES 27
Message 2 of 28
stevor
in reply to: jbear0000

Two ways, starting with ssget "c" or "f":

 

1. Close the pline, by pedit if the ends are close enough, or add a pline to do so, and use it to ssget the crossing 'yellow' lines, and find the on-seg intersections of them with the pline; or

 

2. process each segment of the pline with a narrow ssget to find the crossing lines in that segment, so on.

S
Message 3 of 28
diagodose2009
in reply to: jbear0000

Please , you attach here drawing file
one demonstration...
I use this file ( who attached) for make you program requested LISP/ARX..
Thanks...........
Message 4 of 28
scottbolton
in reply to: jbear0000

How's about this? Pick the main line (red), pick the crossing lines (yellow) and Bob's your aunty.

 

S

 

(defun c:sbx ( / )
  (progn
    (setq ent (car (entsel "\nSelect main line: ")))
    (if ent
      (progn
 (princ "\nSelect crossing line(s): ")
 (if (setq ss (ssget))
   (progn
     (setq count 0
    obj (vlax-ename->vla-object ent)
    pointlist nil
    )
     (repeat (sslength ss)
       (setq xent (ssname ss count)
      xobj (vlax-ename->vla-object xent)
      )
       (if (setq int (vla-IntersectWith obj xobj acExtendNone))
  (progn
    (setq int (vlax-safearray->list (vlax-variant-value int))
   pointlist (append pointlist (list int))
   )
    )
  )
       (setq count (1+ count))
       )
     (if (null (tblobjname "BLOCK" "SBblock"))
       (progn
  (entmake (list (cons 0 "BLOCK") (cons 2 "SBblock") (cons 70 0) (list 10 0.0 0.0 0.0)))
  (entmake '((0 . "LWPOLYLINE") (100 . "AcDbEntity") (8 . "0") (100 . "AcDbPolyline") (90 . 2) (70 . 1) (43 . 1.0) (38 . 0.0) (39 . 0.0)
      (10 2.5 0.0) (40 . 1.0) (41 . 1.0) (42 . 1.0) (91 . 0)
      (10 -2.5 0.0) (40 . 1.0) (41 . 1.0) (42 . 1.0) (91 . 0)
      (210 0.0 0.0 1.0)
      )
    )
  (setq blockname (entmake '((0 . "ENDBLK"))))
  )
       )
     (foreach pt_nth pointlist
       (entmake (append
    '((0 . "INSERT") (100 . "AcDbEntity") (8 . "0") (100 . "AcDbBlockReference") (2 . "SBblock"))
    (list (cons 10 pt_nth))
    '((41 . 1.0) (42 . 1.0) (43 . 1.0) (50 . 0.0) (70 . 0) (71 . 0) (44 . 0.0) (45 . 0.0) (210 0.0 0.0 1.0))
    )
         )
       )
     )
   )
 )
      )
    )
  (princ)
  )

Message 5 of 28
Hallex
in reply to: scottbolton

Good work,

Just forgot to add

(vl-load-com) at the start of code,

do edition, please,

 

Regards

🙂

_____________________________________
C6309D9E0751D165D0934D0621DFF27919
Message 6 of 28
jbear0000
in reply to: scottbolton

Thanks scottbolton, that works great. I simiply changed the block name in the lisp and added (vl-load-com) to the beginning as Hallex pointed out and it worked. Thanks for the help.

Message 7 of 28
scottbolton
in reply to: jbear0000

You're welcome.

 

I use many vl-commands in many routines and so I have (vl-load-com) in my acaddoc.lsp.

 

S

Message 8 of 28
saurabhshp05
in reply to: scottbolton

sir i am a newbee in autolisp.. can u plz brief me how to use all the vla commands... & what is the use of vlax-safearray-... command. thanks
Message 9 of 28
paullimapa
in reply to: saurabhshp05

You can read up on vla- & vlax- functions by doing a search on-line or in acad help.

So in acad, you can type .HELP and do a search for vlax-safearray


Paul Li
IT Specialist
@The Office
Apps & Publications | Video Demos
Message 10 of 28
MrBlack911
in reply to: jbear0000

Hi Jason,

 

May I ask exactly where you inserted the name of the block to be used i.e which line/s of code did you alter?

I'm very new to AutoLisp and not sure which line/s to change as there's more than one that contain/mention some variant of "Block Name".

Feel like I've tried replacing avery instance but still having no joy here.

Thanks for your time.

Message 11 of 28
MrBlack911
in reply to: scottbolton

Hey guys,

 

Very new to AutoLisp so please forgive my ignorance

 

I guess to add my own block to be used I change the line:

(setq blockname (entmake '((0 . "ENDBLK")))) and replace "ENDBLK" with my desired block?

 

Have done that and replaced it with a block name thats present in the current drawing.  I can run the program successfully... well, it seems to anyway (it lets me select the main line and then the crossing line but once I've done that nothing happens - no block inserted.  Have pasted the output of the command line below:

 

Command: SBX
Select main line:
Select crossing line(s):
Select objects: 1 found
Select objects:
; error: bad DXF group: (10 -369648.0 90767.2 0.0 -369648.0 91067.2 0.0 -369348.0 90767.2 0.0 -369348.0 91067.2 0.0)

 

Anyone know what might be happening here?  Would love to be able to use this program.

 

Many thanks.

Message 12 of 28
Sea-Haven
in reply to: MrBlack911

No, No if your going to use lisp with entmakes then you need to be aware of the dxf codes, its the rule book. 

 

This is the simplest I can get for you just type on command line (entget (car (entsel))) it will ask for you to select an object you will see all the entity codes so pick a block the one for this code that you want is (2 . "SBblock")

Look at the values and you will see matching items 8 layer, 10 is a co-ords point.

 

Command: (entget (car (entsel)))
selected a block
Select object: ((-1 . <Entity name: 295d85d6c00>) (0 . "INSERT") (330 . <Entity name: 295d7e465a0>) (5 . "D998") (100 . "AcDbEntity") (67 . 1) (410 . "D01") (8 . "DRGTEXT") (100 . "AcDbBlockReference") (66 . 1) (2 . "DA1DRTXT") (10 0.0 0.0 0.0) (41 . 1.0) (42 . 1.0) (43 . 1.0) (50 . 0.0) (70 . 0) (71 . 0) (44 . 0.0) (45 . 0.0) (210 0.0 0.0 1.0))
Message 13 of 28
MrBlack911
in reply to: Sea-Haven

Mate thanks for the reply but I still can't get anything working.  Could you possibly just show me what the full code should look like after I run the "(entget (car (entsel)))" command as you've suggested?  The results of running that are below:

 

Command: (entget (car (entsel)))
Select object: ((-1 . <Entity name: 1e4e3e199b0>) (0 . "INSERT") (330 . <Entity name: 1e4e3e72820>) (5 . "A68FB") (100 . "AcDbEntity") (67 . 0) (410 . "Model") (8 . "BORED-PIER-NEW") (100 . "AcDbBlockReference") (2 . "BORED PIER-PLAN-450dia") (10 -456881.0 38594.6 0.0) (41 . -1.0) (42 . 1.0) (43 . 1.0) (50 . 0.0) (70 . 0) (71 . 0) (44 . 0.0) (45 . 0.0) (210 0.0 0.0 1.0))

 

Appreciate the help here.

Message 14 of 28
Sea-Haven
in reply to: MrBlack911

I have not checked code but (cons 2 "SBblock") replace all with (cons 2 "yourblockname")

 

Look at your entget see the (2 . "BORED PIER-PLAN-450dia") has returned the block name.

 

Note that blocks are known as "Insert" not block.

 

 

 

Message 15 of 28
MrBlack911
in reply to: Sea-Haven

Really wanted to be able to use this one but I just cant get it to happen.  There's so many different variations of "BLOCK", "SBLOCK", "ENDBLK" and "BLOCKNAME" etc scattered throughout the code...I'm also confused by your last comment that BLOCKS are also known as "INSERT."  Feel like I've tried every combination of exchanging details but I'm completely out of my depth.  Every change I make still ends with :

error: bad DXF group: (10 -370612.0 85675.4 0.0 -370912.0 85675.4 0.0 -370612.0 85375.4 0.0 -370912.0 85375.4 0.0)

I know the name of the my block I want to use (BORED PIER-PLAN-450dia) and the layer it goes (BORED-PIER-NEW) but unless some kind soul has the time to slot those details in and return the code in its entirety, I'm going to have to let this one go.  I don't know enough about LISP to fix this. 

 

Thanks for trying to help me anyway mate.  Appreciate the effort.

Message 16 of 28
ВeekeeCZ
in reply to: MrBlack911

This should make your life easier. One place to specify block and layer name.

Credits to the author.

 

; https://forums.autodesk.com/t5/visual-lisp-autolisp-and-general/insert-block-at-intersection/m-p/9321877#M396005
; Author: scottbolton
; Mods BeekeeCZ

(vl-load-com)

(defun c:sbx ( / blockname layername count ent int obj pointlist ss xent xobj)
  
  (setq blockname "SBlock"  	; <- here put name of your block. Insert the block into drawing BEFORE you run this routine.
	layername "0")		; <- block name. Will be created autmatically if not exists.
  
  (if (and (setq ent (car (entsel "\nSelect main line: ")))
	   (princ "\nSelect crossing line(s): ")
	   (setq ss (ssget))
	   )
    (progn
      (setq count 0
	    obj (vlax-ename->vla-object ent)
	    pointlist nil)
      
      (repeat (sslength ss)
	(setq xent (ssname ss count)
	      xobj (vlax-ename->vla-object xent))
	(if (setq int (vla-IntersectWith obj xobj acExtendNone))
	  (progn
	    (setq int (vlax-safearray->list (vlax-variant-value int))
		  pointlist (append pointlist (list int)))))
	(setq count (1+ count)))

      (if (null (tblobjname "BLOCK" blockname))
	(progn
	  (entmake (list (cons 0 "BLOCK") (cons 2 blockname) (cons 70 0) (list 10 0.0 0.0 0.0)))
	  (entmake '((0 . "LWPOLYLINE") (100 . "AcDbEntity") (8 . "0") (100 . "AcDbPolyline") (90 . 2) (70 . 1) (43 . 1.0) (38 . 0.0) (39 . 0.0)
		     (10 2.5 0.0) (40 . 1.0) (41 . 1.0) (42 . 1.0) (91 . 0)
		     (10 -2.5 0.0) (40 . 1.0) (41 . 1.0) (42 . 1.0) (91 . 0)
		     (210 0.0 0.0 1.0)))
	  (entmake '((0 . "ENDBLK")))))

      (foreach pt_nth pointlist
	(entmake (append
		   (list '(0 . "INSERT") '(100 . "AcDbEntity") (cons 8 layername) '(100 . "AcDbBlockReference") (cons 2 blockname))
		   (list (cons 10 pt_nth))
		   '((41 . 1.0) (42 . 1.0) (43 . 1.0) (50 . 0.0) (70 . 0) (71 . 0) (44 . 0.0) (45 . 0.0) (210 0.0 0.0 1.0)))))))
  (princ)
  )

 

Message 17 of 28
MrBlack911
in reply to: ВeekeeCZ

Bugger; Have just called it quits for the day so won't get to play with/test your modified version BeeKeeCZ. You've never steered me wrong previously though so I feel pretty confident in expressing my most sincere thanks & appreciation to you regardless. Am trying to squeeze in as much LISP study as I can between work and home life but progress has been slow. Thank you so very much for breaking this down for a lowly beginner such as myself. It's a genius little command & I'm so pleased I can add it to my kit.

The beers are on me next time! The amount of time & resources you provide in this forum does not go unnoticed. Much gratitude to you mate.

 

Message 18 of 28
MrBlack911
in reply to: ВeekeeCZ

Very sorry but Ii've spoken too soon.  Tested your modified version and I get the same error "bad DXF group etc....".

 

It works fine if I run it on regular lines but no joy on multilines.

Message 19 of 28
ВeekeeCZ
in reply to: MrBlack911

Hmm, then the block insertion worked fine. The issue is that the routine does not handle MULTILINEs correctly.

The following routine should cover that.

 

(vl-load-com)

(defun c:BlockInsertX ( / sel blockname layername)
  
  (setq blockname "SBlock"  	; <- here put name of your block. Insert the block into drawing BEFORE you run this routine.
	layername "0")		; <- block name. Will be created autmatically if not exists.
  
  (if (and (or (tblsearch "BLOCK" blockname)
	       (prompt (strcat "\nError: There is no '" blockname "' in the drawing!"))
	       (alert (strcat "\nError: There is no '" blockname "' in the drawing!"))
	       )
	   (setq sel (ssget))
	   )
    (foreach pnt (LM:intersectionsinset sel)
      (entmake (append
		 (list '(0 . "INSERT") '(100 . "AcDbEntity") (cons 8 layername) '(100 . "AcDbBlockReference") (cons 2 blockname))
		 (list (cons 10 pnt))
		 '((41 . 1.0) (42 . 1.0) (43 . 1.0) (50 . 0.0) (70 . 0) (71 . 0) (44 . 0.0) (45 . 0.0) (210 0.0 0.0 1.0))))))
  (princ)
  )


;; Intersections in Set  -  Lee Mac
;; Returns a list of all points of intersection between all objects in a supplied selection set.
;; sel - [sel] Selection Set

(defun LM:intersectionsinset ( sel / id1 id2 ob1 ob2 rtn )
  (repeat (setq id1 (sslength sel))
    (setq ob1 (vlax-ename->vla-object (ssname sel (setq id1 (1- id1)))))
    (repeat (setq id2 id1)
      (setq ob2 (vlax-ename->vla-object (ssname sel (setq id2 (1- id2))))
	    rtn (cons (LM:intersections ob1 ob2 acextendnone) rtn)
	    )
      )
    )
  (apply 'append (reverse rtn))
  )

;; Intersections  -  Lee Mac
;; Returns a list of all points of intersection between two objects
;; for the given intersection mode.
;; ob1,ob2 - [vla] VLA-Objects
;;     mod - [int] acextendoption enum of intersectwith method

(defun LM:intersections ( ob1 ob2 mod / lst rtn )
  (if (and (vlax-method-applicable-p ob1 'intersectwith)
	   (vlax-method-applicable-p ob2 'intersectwith)
	   (setq lst (vlax-invoke ob1 'intersectwith ob2 mod))
	   )
    (repeat (/ (length lst) 3)
      (setq rtn (cons (list (car lst) (cadr lst) (caddr lst)) rtn)
	    lst (cdddr lst)
	    )
      )
    )
  (reverse rtn)
  )

 

 
Message 20 of 28
MrBlack911
in reply to: ВeekeeCZ

Really appreciate your time in trying to fix this for me.  This version does indeed work...but rather than inserting a single block at a multiline intersection, its like it treats them all as individual lines and so inserts 4x blocks at each intersection.

 

We might just have to let this one go BeeKeeper.

Can't find what you're looking for? Ask the community or share your knowledge.

Post to forums  

Autodesk Design & Make Report

”Boost