Troubles getting values from attributes

Troubles getting values from attributes

Homecad2007
Enthusiast Enthusiast
1,120 Views
16 Replies
Message 1 of 17

Troubles getting values from attributes

Homecad2007
Enthusiast
Enthusiast

Im having troubles with this lips routine,  I think it once worked but not sure its not working anymore.  I am trying to get values from 2 attributes and then get an average number between them by adding them and then dividing by 2.  ELEV always reports nil so I need help with this

 

(defun c:interp (/ txtheight txtht txtht1 tp1At TP1T tp2At TP2T newpt elev)
(SETVAR "ATTREQ" 1)
(SETVAR "ATTDIA" 0)
(setvar "cmdecho" 0)
(setvar "blipmode" 0)
(command "osmode" 😎
(setq txtheight(getvar "txtht"))
(setq txtht 0.05)
(setq txtht1 (* txtht 20))
(setq Currentla (getvar "clayer"))

(prompt "\nPick Elevation Marker : ")
(SETQ tbdata(entget (car (entsel))))
(setq tp1At (dxf 10 tbdata))
(setq tbdata (entget (entnext (dxf -1 tbdata))))
(setq TP1T (atof(dxf 1 tbdata)))

(prompt "\nPick Elevation Marker : ")
(SETQ tbdata(entget (car (entsel))))
(setq tp2At (dxf 10 tbdata))
(setq tbdata (entget (entnext (dxf -1 tbdata))))
(setq TP2T (atof(dxf 1 tbdata)))

(setvar "osmode" 0)
(setq newpt (getpoint "\npick point for new elevation: "))
(setq elev (rtos(/ (+ tp1t tp2t)2)2 2))
;;(atof (rtos elev 2 2));round to 2 decimal places
;;(rtos elev 2 2);round to 2 decimal places


(setq aa (/ (* (angle tp2At tp1At) 180.0) pi))
(command "-insert" "level" newpt "" "" aa elev )
;;(setq elev 0)

(setvar "osmode" 545)
(setvar "cmdecho" 1)
(setvar "blipmode" 1)
(SETVAR "ATTDIA" 1)
(setvar "clayer" Currentla)
(SETQ txtht TXTHEIGHT)

(princ)
)

0 Likes
Accepted solutions (1)
1,121 Views
16 Replies
Replies (16)
Message 2 of 17

ВeekeeCZ
Consultant
Consultant

Post a dwg example.

Also, which acad version you have?

0 Likes
Message 3 of 17

Homecad2007
Enthusiast
Enthusiast

I would like it to work on Autocad 2014 and up if possible

 

I have attached a sample file with the attributes that I am trying to extract the elevation levels from

 

Thanks

Tony

0 Likes
Message 4 of 17

pbejse
Mentor
Mentor
Accepted solution

@Homecad2007 wrote:

I have attached a sample file with the attributes that I am trying to extract the elevation levels from


The code you posted is missing dxf subfunction

(defun c:interp (/ dxf txtheight txtht txtht1 tp1At TP1T tp2At TP2T newpt elev)
(Defun dxf  (d ed) (cdr (assoc d ed)))
  (SETVAR "ATTREQ" 1)
  (SETVAR "ATTDIA" 0)
  (setvar "cmdecho" 0)
...

HTH

 

0 Likes
Message 5 of 17

Homecad2007
Enthusiast
Enthusiast

That seems to do the trick! Thanks!

0 Likes
Message 6 of 17

Homecad2007
Enthusiast
Enthusiast

Is it possible that this will work in 2016 and up but not in 2014?  Seems like this lisp routine works on my computer (2018) but not on a colleagues which is 2014

0 Likes
Message 7 of 17

dbroad
Mentor
Mentor

Your code is overly complicated and with some hidden bugs.  You shouldn't have to twiddle with attreq, osmode, attdia, cmdecho, and blipmode.  You shouldn't need to worry about text heights. This will always yield nil for example: (getvar "txtht") since there is no "txtht" variable.  The drawing you posted also has some units issues and thousands of errors when recover is used.  When I tried inserting level, it was 24.5 times larger than it should be.  You're also using anonymous blocks for the plus symbol inside the level block, which doesn't seem very user friendly.  I suggest paring things down and then put back the extra stuff if you really think you need it.

(defun dxf (key elist)(cdr(assoc key elist)))

(defun c:interp	(/ aa elev newpt tbdata tp1at tp1t tp2at tp2t)
  (prompt "\nPick Elevation Marker : ")
  (setq tbdata (entget (car (entsel))))
  (setq tp1at (dxf 10 tbdata))
  (setq tbdata (entget (entnext (dxf -1 tbdata))))
  (setq tp1t (atof (dxf 1 tbdata)))
  (prompt "\nPick Elevation Marker : ")
  (setq tbdata (entget (car (entsel))))
  (setq tp2at (dxf 10 tbdata))
  (setq tbdata (entget (entnext (dxf -1 tbdata))))
  (setq tp2t (atof (dxf 1 tbdata)))
  (setq newpt (getpoint "\npick point for new elevation: "))
  (setq elev (rtos (/ (+ tp1t tp2t) 2) 2 2))
  (setq aa (/ (* (angle tp2at tp1at) 180.0) pi))
  (command "-insert" "level" "_non" newpt "" "" aa elev)
  (princ)
  )

 

Architect, Registered NC, VA, SC, & GA.
0 Likes
Message 8 of 17

devitg
Advisor
Advisor

Hi , @dbroad , just trying to learn from  your post . 

 

Why the insert command ask me to type the elev value at the tag ?

devitg_0-1618262221805.png

Thanks in advance

 

 

0 Likes
Message 9 of 17

Kent1Cooper
Consultant
Consultant

@devitg wrote:

Hi , @dbroad , just trying to learn from  your post . 

....

Why the insert command ask me to type the elev value at the tag ?


Turn off ATTDIA?

Kent Cooper, AIA
0 Likes
Message 10 of 17

devitg
Advisor
Advisor

@Kent1Cooper , yes ATTDIA to 0 and solved . 

 

Thanks

 

0 Likes
Message 11 of 17

pbejse
Mentor
Mentor

@Homecad2007 wrote:

Is it possible that this will work in 2016 and up but not in 2014?  Seems like this lisp routine works on my computer (2018) but not on a colleagues which is 2014


In what way does it not work in 2014? Are there any error messages in the command prompt?  Did you use the same code on the same drawing file?

The only thing I found odd on your posted code is this

(getvar "txtht")

which should be

(getvar "TEXTSIZE")

 

0 Likes
Message 12 of 17

dbroad
Mentor
Mentor

And for what reason in that program might he need to know the text size?

Architect, Registered NC, VA, SC, & GA.
0 Likes
Message 13 of 17

pbejse
Mentor
Mentor

@dbroad wrote:

And for what reason in that program might he need to know the text size?


That is the question you need to ask the OP.

Just pointing out that the below is not a valid system variable

 

(getvar "txtht")

 

My guess, the intent was to be set it back to its original value after setting the value to another

 

(SETQ txtht TXTHEIGHT) 
as 
(setvar "txtht" txtheight)

 

 but somehow got lost in translation. 

 

The more pressing question is, in what way does it not work in 2014, I can't tell what is what  just by this statement

Is it possible that this will work in 2016 and up but not in 2014? 

 

0 Likes
Message 14 of 17

dbroad
Mentor
Mentor

The point I made in my first post, which must have been lost, was that a program shouldn't get lost in collecting,  setting and resetting variables that don't matter to the task.  It makes them harder to read and multiplies debugging tasks.  Examples were mentioned.  The most absurd being the need to know the text height and the current layer.  That particular error was hidden because the  txtheight local variable was not used for anything but setting another local variable txtht before closing.

 

For other aspiring programmers, start with the task at hand, using a minimum of setting changes. Test over time and manage only system variables that matter.  Then make sure to change them back.  The side effect of setting osmode to a particular state is also problematic.

 

For most of us, I would imaging that the questions regarding 2014 and 2016 are unanswerable but probably related to other problematic LISP's or other versions of the block content.

Architect, Registered NC, VA, SC, & GA.
0 Likes
Message 15 of 17

Anonymous
Not applicable

Why not

 

(prompt "\nPick Elevation Marker : ")
(setq tbdata (entget (car (entsel))))

(setq tbdata (entget (car (entsel"\nPick Elevation Marker : "))))
0 Likes
Message 16 of 17

dbroad
Mentor
Mentor

So what you learn by writing it basic is what you need to add.  In this case, attdia would be a necessary variable to adjust to make the program work.  But it should be changed back at the end of the program in case the user prefers to normally operate that way.  One correct way to do this is to add a locally defined user  *error* program that will automatically restore variable settings in case the function gets cancelled. To keep each program from getting too complicated, I created several programs that I use with a global variable but have rewritten here to serve as an example.  I'm sure you could find numerous threads about this.

 

 

 

;;;Example global function to save and set sysvars that use local variables
;;;A is the list of '(sysvar . value) pairs
;;;LST is the quoted local var to hold the settings
(defun MODESS  (A LST / I)
  (foreach I  A
    (set LST (cons (cons (car I) (getvar (car I))) (eval LST)))
    (setvar (car I) (cadr I))))

;;;Example global function to reset the system variable changes in the main function.
;;;lst is in the form (...(<sysvar> . <value>)...)
(defun moder  (lst / i result)
  (foreach i  lst
    (if	(vl-catch-all-error-p
	  (vl-catch-all-apply
	    '(lambda (i) (setvar (car i) (cdr i)))
	    (cons i nil)))
      (princ (strcat "ERROR IN MODER: Could not restore "
		     (vl-princ-to-string (car i))
		     " to "
		     (vl-princ-to-string (cdr i))
		     "."))))
  (princ))

 

 

 

That looks more complicated that the OP's but since they are global, it simplifies settings in programs that use them. For example, the main function would look like this:

(defun c:main ( / *error* sysvars ....)

(defun *error* (msg)

  (if msg (princ msg))
  (moder sysvars))

....main program stuff

;;;example sysvar change. Note double parentheses at the list start and end and the local var to store the sysvars.

(modess '((attdia . 0)(blipmode . 0)) 'sysvars )

....main program stuff

(*error* nil);;end of program will reset variables automatically

)

 

Alternatives would be to try to use ActiveX methods that wouldn't require system variable changes.

 

Unfortunately, there are more problems with the program in the OP and my revision other than just saving and setting variable issues. 

For example, the user is calling this interpolation but is asking the user to pick the point for the new elevation while using the average elevation between the two points.  That won't really be interpolation if the point picked for the new location isn't exactly between the two other points.

 

Architect, Registered NC, VA, SC, & GA.
0 Likes
Message 17 of 17

dbroad
Mentor
Mentor

@devitg 

I admit that setting ATTDIA is something I overlook because I always keep it set to 0 anyway, preferring to use the properties palette and command line entry. For those who keep it on, it's certainly necessary to turn it off when using the insert or -insert command while automatically filling in attributes.

Architect, Registered NC, VA, SC, & GA.
0 Likes