Lisp that moves alot of blocks to the nearest vertex of a polyline at once (end of Polyline vertex or either closest vertex)

Lisp that moves alot of blocks to the nearest vertex of a polyline at once (end of Polyline vertex or either closest vertex)

t_pladet
Contributor Contributor
2,004 Views
32 Replies
Message 1 of 33

Lisp that moves alot of blocks to the nearest vertex of a polyline at once (end of Polyline vertex or either closest vertex)

t_pladet
Contributor
Contributor

Hello everyone,

 

Been moving alot of blocks manually for a couple of months now and it is really sucking alot of energy out of me haha.

is there a option to resolve this problem with a lisp? Images included for explanation!

Schermafbeelding 2023-11-03 095653.png

Schermafbeelding 2023-11-03 095712.png

Schermafbeelding 2023-11-03 095738.png

 

All the help would be really appreciated! thanks in advance!

0 Likes
Accepted solutions (3)
2,005 Views
32 Replies
Replies (32)
Message 2 of 33

pbejse
Mentor
Mentor

@t_pladet wrote:

 

Been moving alot of blocks manually...

All the help would be really appreciated! thanks in advance!


Can you post a small enough drawing sample to get a better idea of how your drawings are structured?

 

0 Likes
Message 3 of 33

t_pladet
Contributor
Contributor

Here it is

0 Likes
Message 4 of 33

pbejse
Mentor
Mentor

@t_pladet wrote:

Here it is


is that either StartPoint or EndPoint but never on a vertex between them?

0 Likes
Message 5 of 33

t_pladet
Contributor
Contributor

There are certain blocks that are in the middle of a line those also need to move to the closest vertex near them. so not necessarily to a endpoint perse. But most of them do have a endpoint where they need to be snapped on too!

0 Likes
Message 6 of 33

pbejse
Mentor
Mentor
Accepted solution

@t_pladet wrote:

There are certain blocks that are in the middle of a line those also need to move to the closest vertex near them. so not necessarily to a endpoint perse. But most of them do have a endpoint where they need to be snapped on too!



(Defun c:MoveMe ( / _Points _DistanceFrom ss i e ent ANCollection CableIDCollection)
(defun _Points (e / l )
(repeat (setq p (1+ (fix (vlax-curve-getEndParam e))))
        (setq l (cons (vlax-curve-getPointAtParam e (setq p (1- p))) l))
      )
  )

(defun _DistanceFrom (pt pts)
  (Car (vl-sort pts '(lambda (a b)(< (distance pt a)(distance pt b)))))
  )
(setq ss (ssget  '((-4 . "<OR")
			   (-4 . "<AND")(0 . "LWPOLYLINE")(8 . "AccessNet")(-4 . "AND>")
			   (-4 . "<AND")(0 . "INSERT")(66 . 1)(2 . "KabelID")(-4 . "AND>")
			   (-4 . "OR>")
			   )
		     )
      )
(progn
	(repeat (setq i (sslength ss))
	  (setq e (ssname ss (setq i (1- i))))
	  (if (eq (cdr (assoc 0 (Setq ent (entget e)))) "LWPOLYLINE")
	    (setq ANCollection (cons (list (_Points e) e ) ANCollection )
		  )
	    (setq CableIDCollection (cons (list (cdr (assoc 10 ent)) e) CableIDCollection))
	    )
	  )
  (and ANCollection
	  (Foreach this CableIDCollection
	    (setq thisPoint (Car this) ent (entget (Cadr this))
		  theNearestLWPolyline  
		(vl-sort  (mapcar '(lambda (en)
			       (cons  (distance thisPoint
					(vlax-curve-getClosestPointTo (Cadr en) thisPoint)) en)) ANCollection)
		   	'(lambda (a b)(< (Car a)(Car b))))
	    	_thePoint (_DistanceFrom thisPoint (Cadr (Car theNearestLWPolyline)))
		  )    
	    	(entmod (subst (Cons 10 _thePoint) (assoc 10 ent) ent))	    
;;		(setq ANCollection (vl-remove (cdr (Car theNearestLWPolyline))  ANCollection))
	    )
	  )
  )(princ)
)

 

This section will remove the Polyline closest to the Block from the collection reducing the number of Polylines for evaluation. 

(setq ANCollection (vl-remove (cdr (Car theNearestLWPolyline))  ANCollection))	

 I opted to comment this out and would suggest the user to select by areas instead of the entire drawing at one time.

 

You can take out the ";" on the comment block, but it will have an adverse effect if the "AccessNet" cables are one continuous polyline, but the program will be slower as the number of selection increase.

 

HTH

 

 

 

Message 7 of 33

Kent1Cooper
Consultant
Consultant

I was thinking a routine could simply apply Osnap ENDpoint to the insertion points of Blocks to find the Polyline vertex nearby, if they're all within Osnap distance of where they should end up.  But the Donut "dots" that are part of the Block are themselves Polylines, and have ENDpoints of their arc segments that I assume might sometimes be closer to the insertion point than the intended Polyline vertex point, so ENDpoint Osnap wouldn't be reliable.  So an approach could be to search for a Polyline in the vicinity of a Block's insertion point, using a crossing-window box built around it at some distance that you think will always be enough, and find its nearest vertex.

 

BUT could you redefine the Block to use CIRCLEs instead of Donut Polylines for those dots?  Then there wouldn't be any ENDpoint to Osnap to except for the desired Polyline vertex, which would greatly simplify a routine to do what you want.

Kent Cooper, AIA
0 Likes
Message 8 of 33

t_pladet
Contributor
Contributor

@pbejse Thank you so much it works perfect! You are a saint. This is going to save me hours upon hours of work :D!

 

 

 

 

0 Likes
Message 9 of 33

Kent1Cooper
Consultant
Consultant

@Kent1Cooper wrote:

....

BUT could you redefine the Block to use CIRCLEs instead of Donut Polylines for those dots?  Then there wouldn't be any ENDpoint to Osnap to except for the desired Polyline vertex, which would greatly simplify a routine to do what you want.


If the Block is edited that way, for example like this:

Kent1Cooper_0-1699015956810.png

then Zoomed out to where I can see all of them, this is all it takes to do it in your sample drawing:

 

(defun C:B2V (/ ss n blk); = Blocks {to} Vertices
  (if (setq ss (ssget "_X" '((2 . "KabelID"))))
    (repeat (setq n (sslength ss))
      (setq blk (ssname ss (setq n (1- n))))
      (setpropertyvalue blk "Position" (osnap (getpropertyvalue blk "Position") "_end"))
    ); repeat
  ); if
  (prin1)
)

 

It assumes there aren't other things around that could have closer endpoints than the Polyline vertices to the Block insertion points.  The selection filter can be adjusted for other Block names, limited to certain Layers, ask for User selection [such as windowing an area] instead of just finding all such Blocks, etc.

Kent Cooper, AIA
Message 10 of 33

komondormrex
Mentor
Mentor

hey there,

another one thou.

 

;*****************************************************************************************************************************

(defun remove_duplicates (_list / duplicateless_list)
	(while _list
		(if (not (member (setq list_element (car _list)) (setq _list (cdr _list))))
			(setq duplicateless_list (cons list_element duplicateless_list))
		)
	)
	duplicateless_list
)

;*****************************************************************************************************************************

(defun c:move_me_too (/ vertices_list insertion_point)
	(setvar 'pickfirst 1)
	(prompt "\nSelect plines and blocks...")
	(sssetfirst nil (ssget '((0 . "insert,lwpolyline"))))
	(setq vertices_list 
		  (remove_duplicates 
		  		(vl-sort 
					(apply 'append (mapcar '(lambda (ename) (mapcar 'cdr (vl-remove-if-not '(lambda (group) (= 10 (car group))) (entget ename)))) 
					 	  		   			(vl-remove-if 'listp (mapcar 'cadr (ssnamex (ssget "_i" '((0 . "lwpolyline"))))))
				 		  		   )
					)
			 	   '(lambda (vertex_1 vertex_2) (< (car vertex_1) (car vertex_2)))
				)
		  )
	)
	(foreach insert (vl-remove-if 'listp (mapcar 'cadr (ssnamex (ssget "_i" '((0 . "insert") (2 . "kabelid"))))))
		(setq insertion_point (cdr (assoc 10 (entget insert))))
		(setq closest_vertex (car (vl-sort vertices_list
										   '(lambda (vertex_1 vertex_2) (< (distance insertion_point vertex_1)
																		   (distance insertion_point vertex_2)
																		)
											)
								  )
							 )
			  vertices_list (vl-remove closest_vertex vertices_list) 
		)
		(vla-put-insertionpoint (vlax-ename->vla-object insert) (vlax-3d-point closest_vertex))
	)
	(sssetfirst)
	(princ)
)

;*****************************************************************************************************************************

updated

 

Message 11 of 33

t_pladet
Contributor
Contributor

How could I change the block though to look like that? could you help me with that?

 

I want to give your LISP also a go!

0 Likes
Message 12 of 33

t_pladet
Contributor
Contributor

Hi I came across a problem with the LISP, maybe you know how to fix it? So the drawing I am now making has the adresses way further then the one I send you before. As I see now the lisp only moves the circle itself but the text is not moving with it! Is there a possibility so that the text moves with the circle they belong to aswell?

0 Likes
Message 13 of 33

komondormrex
Mentor
Mentor

think you've mistaken to address Kent. in that case you may change block name in the line 28 (2 . "kabelid") where "kabelid" is the block name.

maybe not.

0 Likes
Message 14 of 33

t_pladet
Contributor
Contributor

Sorry but what do you mean exactly? I should change that text to something else? the 'Kabelid'?

 

Then the text will move with it aswell? 

0 Likes
Message 15 of 33

komondormrex
Mentor
Mentor

i thought you want to change a block name, sorry. but yes the attributed text moves as well. tested on your previous example. if the block is still 'kabelid' do nothing, just run the program.  and regarding view of the block. the pline-circle  in it has global width. clear it and its view will be changed.

0 Likes
Message 16 of 33

t_pladet
Contributor
Contributor

can i send you the file that I changed. can u try to use the lisp and see what happens? the circle moves but the text does not. 

0 Likes
Message 17 of 33

t_pladet
Contributor
Contributor

So all the text needs to move with the circle. And when I run the lisp it is not working

0 Likes
Message 18 of 33

Kent1Cooper
Consultant
Consultant

@t_pladet wrote:

How could I change the block though to look like that? could you help me with that? ....


REFEDIT the Block definition.  ERASE the Donut Polyline, and draw a CIRCLE [or more than one] in its place, or OFFSET the little one in the middle to some appropriate size(s).  You just need to have no ENDpoints in the Block that Osnap can jump to, forcing it to jump to the closest ENDpoint of the path Polyline.

Kent Cooper, AIA
0 Likes
Message 19 of 33

t_pladet
Contributor
Contributor

I just changed the blocks to look just like yours, I deleted the donut Polyline and put 3 circles. But still it is not working? the B2V command is not working and Osnap aswell.

0 Likes
Message 20 of 33

Kent1Cooper
Consultant
Consultant

@t_pladet wrote:

.... it is not working? ....


That is never enough information.

Kent Cooper, AIA
0 Likes