aridzv Posted January 12 Posted January 12 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 Quote
Emmanuel Delay Posted January 12 Posted January 12 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) ) 1 2 Quote
Steven P Posted January 12 Posted January 12 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) 1 Quote
aridzv Posted January 12 Author Posted January 12 (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 January 12 by aridzv 1 Quote
aridzv Posted January 12 Author Posted January 12 Hi. the lisp works for LWPOLYLINE but not for 3D POLYLINE. dose anyone knows how to modify LM:LWVertices to work with 3D POLYLINE?... Quote
Survey66 Posted January 12 Posted January 12 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. Quote
devitg Posted January 12 Posted January 12 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 Quote
aridzv Posted January 12 Author Posted January 12 (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 January 12 by aridzv Quote
1958 Posted January 13 Posted January 13 (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) ) 1 Quote
aridzv Posted January 13 Author Posted January 13 (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 January 13 by aridzv Quote
BIGAL Posted January 13 Posted January 13 (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 January 13 by BIGAL 1 Quote
Emmanuel Delay Posted January 13 Posted January 13 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. Quote
Emmanuel Delay Posted January 15 Posted January 15 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) ) Quote
BIGAL Posted January 15 Posted January 15 (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 January 15 by BIGAL Quote
Survey66 Posted January 17 Posted January 17 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 Quote
Survey66 Posted January 19 Posted January 19 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 Quote
Survey66 Posted January 19 Posted January 19 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 Quote
BIGAL Posted January 20 Posted January 20 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. ;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) ) Quote
Recommended Posts
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.