Jump to content

Need help with inserting a block to a specific known vertex of a polyline (lwployline, 3d polyline)


Recommended Posts

Posted

Hi.

I need help with a lisp that will enable me to do the follow:

1. lisp prompt the user to select a ployline.

2. lisp prompt the user to enter the vertex number.

3. lisp inserting a block at the selected vertex.

 

the block is already inserted to the drawing.

 

I've attached a sample drawing with a polyline and a simple block.

 

Any help will be appreciated...

 

thanks,

aridzv.

plvertex_Example1.dwg

Posted

That's a fun one to write.

This should work.

 

Command IBTV, for Insert Block To Vertex (feel free to change the function name)

 

;; 1. lisp prompt the user to select a ployline.
;; 2. lisp prompt the user to enter the vertex number.
;; 3. lisp inserting a block at the selected vertex.

(defun drawInsert (pt Nme)
 (entmakex (list (cons 0 "INSERT")
                 (cons 2 Nme)
                 (cons 10 pt))))
				 
;; LW Vertices  -  Lee Mac
;; Returns a list of lists in which each sublist describes
;; the position, starting width, ending width and bulge of the
;; vertex of a supplied LWPolyline
(defun LM:LWVertices ( e )
    (if (setq e (member (assoc 10 e) e))
        (cons
            (list
                (assoc 10 e)
                (assoc 40 e)
                (assoc 41 e)
                (assoc 42 e)
            )
            (LM:LWVertices (cdr e))
        )
    )
)

;; Command IBTV, for Insert Block To Vertex (feel free to change the function name)
(defun c:ibtv ( / Nme pl vertices ind str_ pt)
	(setq Nme "3014")
	;; 1. lisp prompt the user to select a ployline.
	(setq pl 
		(ssname 
			(ssget "_+.:S" (list (cons 0 "*POLYLINE")))
		0) 	
	)
	;; 2. lisp prompt the user to enter the vertex number.
	(setq vertices (LM:LWVertices  (entget pl)))
	
	;;(princ vertices)
	(princ (length vertices))
	
	(setq str_ (strcat 
		"\nEnter vertex number (1 to "  
		(itoa (length vertices) )
		"): "
	))
	(if (and 
			(setq ind (getint str_))
			(> ind 0)
			(< ind (+ (length vertices) 1))
		)
		(progn
			
			;; 3. lisp inserting a block at the selected vertex.
			(setq pt (cdr (assoc 10 (nth (- ind 1) vertices))))
			(drawInsert pt Nme)
		)
	)
	(princ)
	
)

 

  • Like 1
  • Thanks 2
Posted

This looked liked it was wanting your nentsel LISP from the other day - Select the segment and the block is inserted, then I had a think and you'd need a rule to which end of the segment to place the block (perhaps closest coordinate to the mouse click)

  • Like 1
Posted (edited)

@Emmanuel Delay

First - MANY THANKS!!!!

 

I've added 2 features to the lisp (See attached IBTV2.lsp )

1. I've let the user to select the block and the lisp extract the block name for the insert command.

    there are 2 code segments for this task:

    A. for autocad & bricscad - probebly will not work with *U blocks.

    B. for bricscad only - should work with *U blocks using getpropertyvalue "EffectiveName~Native" method.

2. I've made a while loop for more vertex number to insert the block to them - exit with ESC.

 

again - many thanks for the help.

aridzv

IBTV2.lsp

Edited by aridzv
  • Like 1
Posted

Hi.

the lisp works for LWPOLYLINE but not for 3D POLYLINE.

dose anyone knows how to modify LM:LWVertices to work with 3D POLYLINE?...

 

Posted

I have a slightly different version of this same request. I'd like to insert a block on a line at a specific inputted elevation.

 

 

Posted
5 hours ago, Survey66 said:

I have a slightly different version of this same request. I'd like to insert a block on a line at a specific inputted elevation.

 

 

@Survey66, please upload your sample.dwg  with before and after

Posted (edited)

Hi.

EDIT - Solved.

I found this Lee Mac code here in the forum that create a list of vertices from a 3D polyline ( @Survey66 - see if this help):

 (if (setq e (car (entsel "\nSelect 3D polyline: ")))
        (if (and (= "POLYLINE" (cdr (assoc 0 (setq x (entget e)))))
                 (= 8 (logand 8 (cdr (assoc 70 x))))
            )
            (progn
                (setq v (entnext e)
                      x (entget  v)
                )
                (while (= "VERTEX" (cdr (assoc 0 x)))
                    (setq l (cons (cdr (assoc 10 x)) l)
                          v (entnext v)
                          x (entget  v)
                    )
                )
                (print (reverse l))
            )
            (princ "\nThe selected object is not a 3D polyline.")
        )
    )

 

I'm using it in the lisp this way:

;; 1. lisp prompt the user to select a ployline.
;; 2. lisp prompt the user to enter the vertex number.
;; 3. lisp inserting a block at the selected vertex.

(defun drawInsert (pt Nme)
 (entmakex (list (cons 0 "INSERT")
                 (cons 2 Nme)
                 (cons 10 pt))))
				 

;; Command IBTV3, for Insert Block To Vertex (feel free to change the function name)
(defun c:ibtv3 ( / Nme pl vertices ind str_ pt en e1 e2)
	;;(setq Nme "3014")


;; set block name to Nme Var for insert (FOR AUTOCAD);;
;;select block
;(setq en(cadr(entsel"\nSelect Block:")))
;(setq e1(ssget en))
;(setq e2 (entget (ssname e1 0)))
;(setq Nme (cdr(assoc 2 e2)))

;; set block name to Nme Var for insert (FOR Bricscad - all blocks including *U name blocks);;
;;select block
(setq en(car(entsel"\nSelect Block:")))
(setq Nme (getpropertyvalue en "EffectiveName~Native"))

;;Select The 3D POLYLINE and make a vertices List
 (if (setq e (car (entsel "\nSelect 3D polyline: ")))
        (if (and (= "POLYLINE" (cdr (assoc 0 (setq x (entget e)))))
                 (= 8 (logand 8 (cdr (assoc 70 x))))
            )
            (progn
                (setq v (entnext e)
                      x (entget  v)
                )
                (while (= "VERTEX" (cdr (assoc 0 x)))
                    (setq l (cons (cdr (assoc 10 x)) l)
                          v (entnext v)
                          x (entget  v)
                    )
                )
                ;;(print (reverse l))
            )
            (princ "\nThe selected object is not a 3D polyline.")
        )
    )

(princ (length l))

   (while	
	(setq str_ (strcat 
		"\nEnter vertex number (1 to "  
		(itoa (length l) )
		"): "
	))
	(if (and 
			(setq ind (getint str_))
			(> ind 0)
			(< ind (+ (length l) 1))
		)
		(progn
			
			;; 3. lisp inserting a block at the selected vertex.
			(setq pt (nth (- ind 1) (reverse l)))
			(drawInsert pt Nme)
		)
	)
   );end while
	(princ)
	
)
 

 

 

 

 

plvertex_Example3.dwg

IBTV3.lsp

Edited by aridzv
Posted
(defun c:11 (/ *error* actdoc obj ent blk name vert pt)
 (defun *error* (msg)
  (vla-regen adoc acactiveviewport)
  (vla-endundomark adoc)
  (princ msg)
  (princ)
 )
 (vl-load-com)
 (setvar "DYNMODE" 1)
 (setq actdoc (vla-get-ActiveDocument (vlax-get-acad-object))
       obj    (vla-get-ModelSpace actdoc)
 )
 (setq ent  (car (entsel "Select Polyline >"))
       blk  (vlax-ename->vla-object (car (entsel "Select Block >")))
       name (vla-get-EffectiveName blk)
       vert (1- (getint "Vertex number?"))
       pt   (vlax-curve-getPointAtParam ent vert)
 )
 (vla-InsertBlock obj (vlax-3D-point pt) name 1 1 1 0)
)

 

  • Thanks 1
Posted (edited)

@1958

Nice...👏

I made small modifications to the code (see below):

1. I entered the vertices input and block insert to a while loop to enable the user inserting blocks to multiple vertices.

2. I saved the current DYNMODE value to a var at the biggining of the lisp and restored it before exiting.

(defun c:blk2vrtx (/ *error* actdoc obj ent blk name vert pt dynmd)
 (defun *error* (msg)
  (vla-regen adoc acactiveviewport)
  (vla-endundomark adoc)
  (princ msg)
  (setvar "DYNMODE" dynmd)
  (princ)
 )
 (vl-load-com)

 (setq dynmd (getvar "DYNMODE"))
 (setvar "DYNMODE" 1)

 (setq actdoc (vla-get-ActiveDocument (vlax-get-acad-object))
       obj    (vla-get-ModelSpace actdoc)
 )

 (setq ent  (car (entsel "Select Polyline >"))
       blk  (vlax-ename->vla-object (car (entsel "Select Block >")))
       name (vla-get-EffectiveName blk)

       ;; code for Bricscad
       ;;blk  (car(entsel"\nSelect Block:"))
       ;;name (getpropertyvalue blk "EffectiveName~Native")
 )

 (while
    (setq vert (1- (getint "Vertex number?"))
          pt   (vlax-curve-getPointAtParam ent vert)
    )

    (vla-InsertBlock obj (vlax-3D-point pt) name 1 1 1 0)
 );end while

 (setvar "DYNMODE" dynmd)
)

 

Edited by aridzv
Posted (edited)

2 comments using vl-get-coordinates will get the co-ordinates of either a 2d or 3d poly it is a single list of all values you can then convert to a 2d or 3d list based on object type.

 

The other is if you say "put at vertice 2" it may put block at opposite end than what you thought was vertice 2 as the direction of the pline has not been considered, a solution is to select pline near an end for open plines you can then work out a pline direction. 

Edited by BIGAL
  • Like 1
Posted
On 1/12/2024 at 4:19 PM, Survey66 said:

I have a slightly different version of this same request. I'd like to insert a block on a line at a specific inputted elevation.

 

 

Can you explain exactly what you want?

It's quite easy to solve, I jusrt need the details.

Posted

This one also works for 3D polylines

 


;; https://www.cadtutor.net/forum/topic/79133-need-help-with-inserting-a-block-to-a-specific-known-vertex-of-a-polyline-lwployline-3d-polyline/
;; 1. lisp prompt the user to select a ployline.
;; 2. lisp prompt the user to enter the vertex number.
;; 3. lisp inserting a block at the selected vertex.

(defun drawInsert (pt Nme)
 (entmakex (list (cons 0 "INSERT")
                 (cons 2 Nme)
                 (cons 10 pt))))
				 
;; LW Vertices  -  Lee Mac
;; Returns a list of lists in which each sublist describes
;; the position, starting width, ending width and bulge of the
;; vertex of a supplied LWPolyline
(defun LM:LWVertices ( e )
    (if (setq e (member (assoc 10 e) e))
        (cons
            (list
                (assoc 10 e)
                (assoc 40 e)
                (assoc 41 e)
                (assoc 42 e)
            )
            (LM:LWVertices (cdr e))
        )
    )
)
;; just returns a list of vertex points.  Uses the result of LM:LWVertices  as input
(defun vertexlist ( vertices / pts pt)
	(setq pts (list))
	(foreach a vertices
		(setq pt (cdr (assoc 10 a)))  ;; (nth i vertices)
		(setq pts (append pts (list pt)))
	)
	pts
)

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; based on
;; https://www.cadtutor.net/forum/topic/71165-vertexes-of-3dpoly/?do=findComment&comment=571205
;;;  Create List Of 3DPOLY Vertices
;; param enc: encase it in a extra list, to make it consistent to LM:LWVertices
(defun threeD_pv ( ss / en vl  vn vd)
	(while (not en)
        (and 	
			ss
			(= (sslength ss) 1)
			(setq en (ssname ss 0))
		)
	)
	(setq vn (entnext en)
        vd (entget vn))
	(while (= "VERTEX" (cdr (assoc 0 vd)))
		(setq 	vl (cons (cdr (assoc 10 vd) )vl) 
				vn (entnext vn)
				vd (entget vn)
		)
	)
	
   (setq vl (reverse vl))
)
;; test function for threeD_pv
(defun c:3dpv ( / ss vertices)
	(setq ss (ssget (list (cons 0 "POLYLINE")
                                    (cons -4 "&")
                                     (cons 70 8)))
	)
	(if ss  (progn
		(setq vertices (threeD_pv ss))
		(princ vertices)
	))
	(princ )
)


;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

;; Command IBTV, for Insert Block To Vertex (feel free to change the function name)
(defun c:ibtv ( / Nme pl vertices ind str_ pt)
	(setq Nme "3014")
	;; 1. lisp prompt the user to select a ployline.
	(setq pl 
		(ssname 
			(setq pl_ (ssget "_+.:S" (list (cons 0 "*POLYLINE"))))
		0) 	
	)
	
	;; 2. lisp prompt the user to enter the vertex number.
		;; First see if it's a 2D poly or 3D poly
	(if
		(= 8 (cdr (assoc 70 (entget pl))))			;; 3D polyline has (70 8)
		;; 3D polyline
		(setq vertices (threeD_pv pl_))  ;; pl
		;; 2D polyline
		(setq vertices (vertexlist (LM:LWVertices (entget pl))))
	)
	
	;;(princ vertices)
	;;(princ (length vertices))
	
	(setq str_ (strcat 
		"\nEnter vertex number (1 to "  
		(itoa (length vertices) )
		"): "
	))
	(if (and 
			(setq ind (getint str_))
			(> ind 0)
			(< ind (+ (length vertices) 1))
		)
		(progn
			
			;; 3. lisp inserting a block at the selected vertex.
			;; (setq pt (cdr (assoc 10 (nth (- ind 1) vertices))))
			(setq pt (nth (- ind 1) vertices))
			(drawInsert pt Nme)
		)
	)
	(princ)
	
)

 

Posted (edited)

Another, no error checking for correct object selected. Possibly needs a pline direction check.

 

; insert block on vertice
; By AlanH Jan 2024

(defun c:insvert ( / drawinsert get_vertices coords co-ordsxy bname pt num obj 23d)

; Drawinsert By Emmanuel Delay

(defun drawInsert (pt Nme)
 (entmakex (list 
 (cons 0 "INSERT")
 (cons 2 Nme)
 (cons 10 pt)
 (cons 41 1.0) ; scale x
 (cons 42 1.0) ; scale y
 (cons 43 1.0) ; scale z
 ))
)

(defun co-ords2xy (xyz co-ords / I XY )
(setq co-ordsxy '())
(if (= xyz 2)
  (progn
    (setq I 0)
    (repeat (/ (length co-ords) 2)
    (setq xy (list (nth i co-ords)(nth (+ I 1) co-ords) ))
    (setq co-ordsxy (cons xy co-ordsxy))
    (setq I (+ I 2))
    )
  )
)
(if (= xyz 3)
  (progn
    (setq I 0)
    (repeat (/ (length co-ords) 3)
    (setq xy (list (nth i co-ords)(nth (+ I 1) co-ords)(nth (+ I 2) co-ords) ))
    (setq co-ordsxy (cons xy co-ordsxy))
    (setq I (+ I 3))
    )
  )
)
(princ)
)

(setq obj (vlax-ename->vla-object (car (entsel "\nPlease choose 2d or 3d pline "))))
(setq entname (vlax-get obj 'objectname))

(if (= entname "AcDb3dPolyline")
  (setq 23d 3)
  (setq 23d 2)
)

(setq coords (vlax-get obj 'coordinates))
(co-ords2xy 23d coords)
(setq co-ordsxy (reverse co-ordsxy))
(setq bname "Northn") ; change to input name

(setq num (- (getint (strcat "\nEnter vertice number 1-" (rtos (length co-ordsxy) 2 0) " ")) 1))

(setq pt (nth num co-ordsxy))
(drawInsert pt bname)

(princ)
)

 

Edited by BIGAL
Posted
On 12/01/2024 at 15:29, devitg said:

@Survey66, please upload your sample.dwg  with before and after

its all explained inside the attached. I found "change line.lsp" by Tom Beauford which is great for trimming a line at a elevation. I included that also, could be the starting point?

test.dwg change line.lsp

Posted
On 17/01/2024 at 08:06, Survey66 said:

its all explained inside the attached. I found "change line.lsp" by Tom Beauford which is great for trimming a line at a elevation. I included that also, could be the starting point?

test.dwg 944.02 kB · 1 download change line.lsp 3.17 kB · 2 downloads

managed to convince IT security to let me have AutoLISP extension and Microsoft Visual Studio Code so I am digging in

Posted
On 13/01/2024 at 18:06, Emmanuel Delay said:

Can you explain exactly what you want?

It's quite easy to solve, I jusrt need the details.

I explained what is in my mind inside this file, but I am working in Civil3D, a nearing 60 yo surveyor and not a CAD professional.

We have to do this task thousands of times, so looking for a way to remove some of the repetitive clicking

 

Front end calc's done, layout in field done, piles being installed and asbuilts ongoing.

 

tower foundations are pipe piles on a batter. - hundreds of towers, each tower has 12 to 28 piles depending on design.

Each pile cluster has one vertical, the rest are battered, various diameters and batter angles.

 

reporting the "pre-cutoff" projected location of the battered piles is the task. QC hold point before allowing the pile to be cut.

 

So far I found and used "change line.LSP by Tom Beauford which is very helpful but only gets us part way.

 

imagine this:

2 survey points, PNEZD

Connect the 2 points with a simple line

Using Tom Beaufords "change line.lsp" , we trim the line at the cut off elevation.

The end of the line becomes the insertion point for an ellipse block at design batter, ignoring asbuilt batter.

Rotate the block on the 2pt line

add cad pt to center of ellipse

 

maybe we can skip the block and do a dynamic ellipse, minor axis=pipe diameter, major axis=pipe diameter cut flat on asbuilt batter, determined from the initial 2pt line, and add a point at center of the ellipse to export into the spreadsheet ....

 

 

test.dwg

Posted

Sin Cos comes to mind for the slope length, you have dia of pipe and angle, just need to look at manually how an ellipse is made. 2 points then a 3rd point which is based on a distance from the center of the ellipse. Need to think about it. Draw some ellipse's with actual sizes.

 

300 dia, offset from centre is 1/2 dia so p1 -> p2 length away, then midpoint p1-p2, then 1/2 dia away is 3rd point. Did this manually to test, used 45 deg as simple length. Have a go at a lisp, dont forget sin cos uses radians so need DTR function.

 

image.png.10e622a490c22d39f1909609d913f512.png

;The dtr function converts degrees to radians
;The rtd function converts radians to degrees
(defun dtr (a)
(* pi (/ a 180.0))
)
;
(defun rtd (a)
(/ (* a 180.0) pi)
)

 

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.
Note: Your post will require moderator approval before it will be visible.

Guest
Unfortunately, your content contains terms that we do not allow. Please edit your content to remove the highlighted words below.
Reply to this topic...

×   Pasted as rich text.   Restore formatting

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

×
×
  • Create New...