Autocad Autolisp variable Start Z / End Z - autocad

What variable will we extract the START Z value from the line.
e.g.
getvar "perimeter" - get the length of the selected polyline

You will need to obtain the list of coordinates associated with DXF group 10 from the DXF data for the line.
You can obtain the DXF data for the line entity using the entget function:
(defun c:test ( / ent enx )
(if (setq ent (car (entsel)))
(setq enx (entget ent))
)
)
You can then obtain DXF group 10 using the assoc function:
(defun c:test ( / ent enx )
(if (setq ent (car (entsel)))
(progn
(setq enx (entget ent))
(assoc 10 enx)
)
)
)

Related

How to read Layer in AutoLisp

How to read layer from poline?
e.g with this i can get (8. "LAYER_NAME") but i wanna see onyl LAYER_NAME because I want to later check by name something
(defun c:test ( / ent enx )
(if (setq ent (car (entsel)))
(progn
(setq enx (entget ent))
(assoc 8 enx)
)
)
)
Change the line
(assoc 8 enx)
to
(cdr (assoc 8 enx))

How can I amend the below code to add additional materials to the LISP

I am new to coding but very eager to learn. I am attempting to edit this existing LISP to add additional materials to the list. Currently when I run the LISP it only has Aluminium as an option to select. I would like to add additional materials and weights to suit. I also would like to know how to change the weight settings from LBS/FT to Kilograms & Meters.
Any help would be hugely appreciated.
;;; Lisp function for calculating weight with choice to assign material for selected:
;;; 2d shape - expressed in pounds per foot lenght - lbs/ft.
;;; or
;;; 3d solid - expressed in Pounds - lbs
(defun C:Wt (/ area volume en ent obj ospace prefix pt remd resp suffix suffix1)
;;local defun
(defun density (mat)
(cond ((eq "Aluminium" mat) 0.0972) ;<--lb/inĀ³
;; add other materials density similarly
(T nil)
)
)
(defun matname (mat)
(cond ((eq "Aluminium" mat) " mat: Aluminium")
;; add other materials names similarly
(T nil)
)
)
;;main part
(setvar "dynmode" 3)
(setvar "dynprompt" 1)
(setq ospace (vla-get-block
(vla-get-activelayout
(vla-get-activedocument
(vlax-get-acad-object)
)
)
)
)
(setq prefix "Weight="
suffix "lbs/ft."
suffix1 "lbs"
)
(setq ent (entsel "\nSelect a object:"))
(setq en (car ent))
(if (wcmatch (cdr (assoc 0 (entget en)))
"REGION,*POLYLINE,CIRCLE,ELLIPSE"
)
(progn
(setq obj (vlax-ename->vla-object en))
(initget
"Aluminium"
) ;<-- add other materials here
(setq resp
(getkword
"\Choose material [ALuminium] <AL>: "
)
)
(setq area (strcat prefix
(rtos (* (vla-get-area obj)
(density resp)
)
3 ;<-- inches
4 ;<-- precision
)
suffix
(matname resp)
)
)
(setq pt (getpoint "\nPick text point: "))
(vla-addtext
ospace
area
(vlax-3d-point (trans pt 1 0))
(getvar 'Textsize)
)
)
)
(princ)
(if (wcmatch (cdr (assoc 0 (entget en))) "3DSOLID")
(progn
(setq obj (vlax-ename->vla-object en))
(initget
"Aluminium Steel SS316 Glass Rubber Silicone Plastic Granit Marble"
) ;<-- add other materials here
(setq resp
(getkword
"\Choose material
[ALuminium/STeel/SS316/GLass/RUbber/SIlicone/PLastic/GRanit/MArble] <AL>: "
)
)
(setq volume (strcat prefix
(rtos (* (vla-get-volume obj)
(* (density resp) 0.001)
)
2 ;<-- metric
5 ;<-- precision
)
suffix1
(matname resp)
)
)
(setq pt (getpoint "\nPick text point: "))
(vla-addtext
ospace
volume
(vlax-3d-point (trans pt 1 0))
(getvar 'Textsize)
)
)
)
(princ)
)

My code works, although only on my machine

I'm creating some AutoLisp commands for my team, and now that I'm finished, the code breaks apart in their computer and I can't figure out why. Works fine in mine.
The idea of the code is to stretch a polyline and update the block attributes that is grouped with.
The code asks to select the block, the actual width of the polyline and the fraction that is is supposed to take (ex: 0.75 to reduce to 75%).
Then, and here is were the problem starts, select the sides to stretch. On their computers, he does not allow to select, it simply jumps ahead.
(defun c:MRV (/ a b c d e)
;ungroup
(command "pickstyle" 0)
;variables
(setq blk (entsel "\nSelect block to modify: "))
(initget (+ 1 2 4))
(setq a (getreal "\nWidth?"))
(initget (+ 1 2 4))
(setq b (getreal "\nNew module fraction? (>0;1<)"))
;distance to reduce
(setq c (- 1 b))
(setq d (* a c -0.5))
(setq e (* -1 d))
;stretch
(command "stretch" pause pause "" "0,0" (polar '(0 0) (/ pi 2) d))
(command "stretch" pause pause "" "0,0" (polar '(0 0) (/ pi 2) e))
;open layer
(setq LayerTable (vla-get-layers (vla-get-activedocument (vlax-get-acad-object))))
(if (and (tblsearch "LAYER" "MC_BLOCO_INFO_AREAS")
(setq layname (vla-item layertable "MC_BLOCO_INFO_AREAS"))
(= (vlax-get-property layname 'lock) :vlax-true)
)
(vla-put-lock layname :vlax-false))
;change attribute
(setq l (cons "CAMPO_6" (rtos b 2 2)))
(LM:SetAttributeValues (car blk) (list l))
;close layer
(setq LayerTable (vla-get-layers (vla-get-activedocument (vlax-get-acad-object))))
(if (and (tblsearch "LAYER" "MC_BLOCO_INFO_AREAS")
(setq layname (vla-item layertable "MC_BLOCO_INFO_AREAS"))
(= (vlax-get-property layname 'lock) :vlax-false)
)
(vla-put-lock layname :vlax-true))
;update block width
(command "regenall")
;regroup
(command "pickstyle" 1)
(print "Modulo modificado.")
(princ)
)
(defun LM:SetAttributeValues ( blk lst / enx itm )
(if (= "ATTRIB" (cdr (assoc 0 (setq enx (entget (setq blk (entnext blk)))))))
(if (setq itm (assoc (strcase (cdr (assoc 2 enx))) lst))
(progn
(if (entmod (subst (cons 1 (cdr itm)) (assoc 1 enx) enx))
(entupd blk)
)
(LM:SetAttributeValues blk lst)
)
(LM:SetAttributeValues blk lst)
)
)
)
What should be happening:
When the AutoCAD STRETCH command issues the prompt for a selection of objects selected using a crossing window (crossing the segments that are to be stretched), the prompt is a standard selection prompt and the STRETCH command will subsequently obtain information about how the selection was acquired in the same way as you might using the AutoLISP ssnamex function.
As such, I would suggest supplying the STRETCH command with a selection set which has already been acquired using a crossing window selection method.
For example, you might define a function such as:
(defun mystretch ( dis / pt1 pt2 sel )
(while
(and
(setq pt1 (getpoint "\nSpecify first point of crossing window: "))
(setq pt2 (getcorner pt1 "\nSpecify opposite point of crossing window: "))
(not (setq sel (ssget "_C" pt1 pt2)))
)
(princ "\nNo objects were found within the crossing window.")
)
(if sel
(progn
(command "_.stretch" sel "" "_non" '(0 0) "_non" (list 0 dis))
t
)
)
)
You can then evaluate the above function with the distance that you wish to stretch the objects in the Y-direction, e.g.:
(mystretch 10.0)
Or, using the variables in your code:
(mystretch d)
(mystretch e)
The function will then return t (True) if the user has supplied two valid points and the STRETCH command has been issued - you can test for this in your program before proceeding.
Using this approach you can ensure that the user has supplied two points defining a crossing window which intersects one or more objects prior to issuing the AutoCAD STRETCH command.
The use of the ssget crossing mode string (C) also ensures that you are always supplying the STRETCH command which has been obtained using a crossing selection method.
You may also wish to refer to this answer regarding the use of the _non object snap modifier and also the _. command prefix in the above example code.

how to change attribute of block using ObjectDBX

I need to change an attribute of drawing with the ObjectDBX method using AutoLISP. this routine run properly but not change the attribute,can you suggest any change in code or any other method to achieve this task?
Thank you.
;;;;;;;;;;;;;;;;;;;
(defun DBX_ATT_CHANGE (f)
(vl-load-com)
(setq cadver (substr (getvar "acadver") 1 2))
(setq id (strcat "objectdbx.AxDbDocument." cadver))
(setq dbx (vlax-create-object id))
(vla-open dbx f)
(vlax-for n_object (vla-get-modelspace dbx)
(setq dbx_en (vlax-vla-object->ename n_object))
(setq upc_blkobj (vlax-ename->vla-object dbx_en))
(if (vlax-method-applicable-p upc_blkobj 'GetAttributes)
(progn
(setq upc_attlist
(vlax-invoke upc_blkobj 'GetAttributes)
)
(foreach upc_att upc_attlist
(progn
(if (= (vla-get-tagstring upc_att) (strcase "P_TAG1"))
(vlax-put-property
upc_att
'TextString
"555"
)
)
)
)
)
)
(vlax-release-object upc_blkobj)
)
(vla-saveas dbx dwgfile)
(vlax-release-object dbx)
(prin1)
)
(defun c:test ()
(DBX_ATT_CHANGE
"D:/6. R&D/Delet Group LispDBXapi/7-EU-FE-48-AC-CIOC-SA - Copy.dwg"
)
)
;;;;;;;;;;;;;;;
There are a couple of oddities present in your current code:
(setq dbx_en (vlax-vla-object->ename n_object))
(setq upc_blkobj (vlax-ename->vla-object dbx_en))
You are converting the vla-object n_object into an entity name dbx_en, and then converting this entity name back into a vla-object upc_blkobj. These two lines are redundant, as you can work with the n_object variable directly.
(= (vla-get-tagstring upc_att) (strcase "P_TAG1"))
You are using strcase to convert a literal uppercase string P_TAG1 to uppercase, and then comparing this uppercase string to a string which may or may not be uppercase - I believe this line should be:
(= (strcase (vla-get-tagstring upc_att)) "P_TAG1")
To offer you an alternative for this task, you could make use of my ObjectDBX Wrapper function, which provides a way to evaluate a given function on another drawing or set of drawings, without opening such drawings in the AutoCAD Editor.
I would personally write your code in the following way:
(defun c:test ( )
(LM:DBXAttChange
"D:\\6. R&D\\Delet Group LispDBXapi\\7-EU-FE-48-AC-CIOC-SA - Copy.dwg"
'(("P_TAG1" . "555"))
)
(princ)
)
(defun LM:DBXAttChange ( dwg lst / doc flg val )
(if (setq doc (LM:GetDocumentObject dwg))
(progn
(vlax-for lyt (vla-get-layouts doc)
(vlax-for obj (vla-get-block lyt)
(if (and (= "AcDbBlockReference" (vla-get-objectname obj))
(= :vlax-true (vla-get-hasattributes obj))
)
(foreach att (vlax-invoke obj 'getattributes)
(if (and (setq val (cdr (assoc (strcase (vla-get-tagstring att)) lst)))
(vlax-write-enabled-p att)
)
(progn
(vla-put-textstring att val)
(setq flg t)
)
)
)
)
)
)
(if flg (vla-saveas doc dwg))
(vlax-release-object doc)
flg
)
(prompt (strcat "\nThe drawing \"" dwg "\" was not found or could not be accessed."))
)
)
;; Get Document Object - Lee Mac
;; Retrieves the VLA Document Object for the supplied filename.
;; The Document Object may be present in the Documents collection, or obtained through ObjectDBX.
;; It is the callers responsibility to release such object.
(defun LM:GetDocumentObject ( dwg / app dbx dwl err vrs )
(cond
( (not (setq dwg (findfile dwg))) nil)
( (cdr
(assoc (strcase dwg)
(vlax-for doc (vla-get-documents (setq app (vlax-get-acad-object)))
(setq dwl (cons (cons (strcase (vla-get-fullname doc)) doc) dwl))
)
)
)
)
( (progn
(setq dbx
(vl-catch-all-apply 'vla-getinterfaceobject
(list app
(if (< (setq vrs (atoi (getvar 'acadver))) 16)
"objectdbx.axdbdocument" (strcat "objectdbx.axdbdocument." (itoa vrs))
)
)
)
)
(or (null dbx) (vl-catch-all-error-p dbx))
)
(prompt "\nUnable to interface with ObjectDBX.")
)
( (vl-catch-all-error-p (setq err (vl-catch-all-apply 'vla-open (list dbx dwg))))
(prompt (strcat "\n" (vl-catch-all-error-message err)))
)
( dbx )
)
)
(vl-load-com) (princ)

Add element to all open files

I've been using AutoLISP/CAD for a while and now I want to add a label with my name to all the open files. I've managed to iterate over all the open files, but the text command only runs in the first file. I thought it was too quick for CAD to work properly, so I added delays but it didn't work. I've checked in all the open files and the variables are shared and synced. By the way, the text is added once per open file, but only in the first one.
Here is my code:
(defun c:labeling()
(vl-load-com)
(setq docs (vla-get-documents (vlax-get-acad-object)))
(setq top (vla-get-count docs))
(setq p1 (list 10 -10))
(setq p2 (list 95 -15))
(setq p3 (list 12 -14))
(setq c 0)
(vl-propagate 'docs)
(vl-propagate 'top)
(vl-propagate 'p1)
(vl-propagate 'p2)
(vl-propagate 'p3)
(vl-propagate 'c)
(while (< c top)
(vla-activate (vla-item docs c))
(command "_rectang" p1 p2)
(command "delay" 500)
(command "_text" p3 "3" 0 "My name - year" "" nil)
;(print c)
(setq c (+ c 1))
(vl-propagate 'c)
(command "delay" 1000)
)
)
It's a bit complicated to explain in such short time I have but:
Each drawig has his own "namespace" probably it's wrong word, but nevermind.
When You run command it runs only in active drawing, but when You change active drawing You lost active lisp routine.
So it's not enought to activate drawing.
Better way is to draw by manipulate model object. for example like this:
(defun c:labeling()
(vl-load-com)
(setq docs (vla-get-documents (vlax-get-acad-object)))
(setq top (vla-get-count docs))
(setq p1 (list 10 -10))
(setq p2 (list 95 -15))
(setq p3 (list 12 -14))
(setq c 0)
(vlax-for ThisDoc docs
(setq Space (vlax-get-property ThisDoc 'ModelSpace ) )
(Rectangle Space p1 p2 )
(setq txt (vlax-invoke-method Space 'AddText "My name - year" (vlax-3d-point p3 ) 3 ))
(setq c (+ c 1))
)
)
(defun Rectangle ( Space P1 P2 / lpts pts poly )
(setq lpts (append p1 (list 0 ) (list (car p1 ) (cadr p2 ) 0 ) p2 (list 0 ) (list (car P2) (cadr p1) 0 ) ) )
(setq pts (L2v lpts vlax-vbDouble ) )
(setq poly(vlax-invoke-method Space 'AddPolyline pts ) )
(vlax-put-property poly 'Closed :vlax-true )
poly
)
(defun L2v(lista typ / NObj SelObjArray iCount iList SelObjArrayVar)
;|
vlax-vbInteger (2) Integer
vlax-vbLong (3) Long integer
vlax-vbSingle (4) Single-precision floating-point number
vlax-vbDouble (5) Double-precision floating-point number
vlax-vbString (8) String
vlax-vbBoolean (11) Boolean
vlax-vbVariant (12) Variant
|;
(setq NObj (length lista)
SelObjArray (vlax-make-safearray typ (cons 0 (1- NObj) ))
iCount 0)
(repeat NObj
(vlax-safearray-put-element SelObjArray iCount (nth iCount lista))
(setq iCount (1+ iCount))
)
(setq SelObjArrayVar (vlax-make-variant SelObjArray))
)

Resources