Help with an interpolate lisp routine

Help with an interpolate lisp routine

Homecad2023
Participant Participant
1,006 Views
15 Replies
Message 1 of 16

Help with an interpolate lisp routine

Homecad2023
Participant
Participant

Need help with this lisp routine.  I am trying to interpolate a level between 2 existing levels.  The user picks one, then the other level and then picks a point in between the first 2 points.  The program should insert a block with the value shown.  I believe this once worked on older cad but doesnt seem to work anymore.  Any help would be great

 

(defun c:interp ()
(defun dxf (key elist)(cdr(assoc key elist)))
(SETVAR "ATTREQ" 1)
(SETVAR "ATTDIA" 0)
(setvar "cmdecho" 0)
(setvar "blipmode" 0)
(setq ostemp (getvar "osmode"))
(command "osnap" "node")
(setq cnt 0)

(prompt "\nPick first elevation : ")
(SETQ tbdata(entget (car (entsel))))
(setq INTPT1 (dxf 10 tbdata));GETS POINT
(setq INTPT1A (entget (entnext (dxf -1 tbdata))))
(setq INTP1X (atof(dxf 1 INTPT1A)));GETS STRING

(prompt "\nPick second elevation : ")
(SETQ tbdata(entget (car (entsel))))
(setq INTPT2 (dxf 10 tbdata));GETS POINT
(setq INTPT2A (entget (entnext (dxf -1 tbdata))))
(setq INTP2X (atof(dxf 1 INTPT2A)));GETS STRING

(SETVAR "OSMODE" 545)
(setq newpt (osnap(getpoint "\npick point for new elevation: ")"nea"))
(setvar "osmode" 0)
(setq dist (distance INTPT1 INTPT2))
(setq aa (angle INTPT1 INTPT2))
(setq dist1 (/(distance INTPT1 INTPT2)2))

(IF (< INTP1X INTP2X)(setq ang (ANGTOS(angle INTPT1 INTPT2))))
(IF (> INTP1X INTP2X)(setq ang (ANGTOS(angle INTPT1 INTPT2))))

(setq dist2 0)
(setq percent (/(abs(- INTP1X INTP2X))dist));slope percentage
(if(and(< INTP1X INTP2X)(/= dist2 nil))(setq dist2 (distance INTPT1 newpt))(setq newelev (* percent dist2)))
(if(and(< INTP2X INTP1X)(/= dist2 nil))(setq dist2 (distance INTPT2 newpt)))(setq newelev (* percent dist2))
(if(< INTP1X INTP2X)(setq elev (rtos(+ INTP1X newelev)2 2)))
(if(< INTP2X INTP1X)(setq elev (rtos(+ INTP2X newelev)2 2)))

(setq dim (getvar "dimscale"));;new
(Setq txtht (* dim 0.4));;new
(Setq txtht1 (* dim 0.16));;new

;;(command "insert" "level" newpt "" "" ang elev )
(command "insert" "level" newpt txtht "" ang elev )

(if (or (> (car INTPT1) (car INTPT2))
(= (rtd aa) 270))
(command "rotate" "last" "" newpt 180.0)
);if
(setvar "cmdecho" 1)
(SETVAR "ATTDIA" 1)
(setvar "osmode" ostemp)
(princ)
)

0 Likes
1,007 Views
15 Replies
Replies (15)
Message 2 of 16

devitg
Advisor
Advisor

@Homecad2023 Please upload the sample.dwg

0 Likes
Message 3 of 16

Kent1Cooper
Consultant
Consultant

What is the type of object you select for the "elevation"s?  A contour?  It looks at quick glance like maybe the code was designed for those to be "heavy" 2D Polylines, but I'm not sure without a deeper dive.  If that's true, and yours are "lightweight" Polylines, some things may need to be done differently.  Or maybe it was designed with the expectation that the next object following each selected contour is a Text or Mtext object, which may not be something that can be assumed.  A small sample drawing, with notes about what you would do in it, would answer some of the questions.

Kent Cooper, AIA
0 Likes
Message 4 of 16

Homecad2023
Participant
Participant

Hi there,

 

Please see attached sample drawing.  There are 2 level blocks that a user needs to pick and a point where to place the new level thats interperated

 

Hope this clarifies it better

0 Likes
Message 5 of 16

Kent1Cooper
Consultant
Consultant

Ah -- a Block with an Attribute.  That makes more sense.  I'll look again later, if someone else doesn't jump in.

Kent Cooper, AIA
0 Likes
Message 6 of 16

devitg
Advisor
Advisor

@Homecad2023  please test it 

0 Likes
Message 7 of 16

Homecad2023
Participant
Participant

Thanks, the program seems to work great but one thing that I would like to do is pick the point between the first 2 points and then have the program interpolate for that new point.  The new point does not have to be in the middle of the first 2 points selected

0 Likes
Message 8 of 16

calderg1000
Mentor
Mentor

Regards @Homecad2023 

The code was working fine, just set the height of the text, the rotation is aligned with the insertion points. There were also some other lines.

(defun c:interp ()
(defun dxf (key elist)(cdr(assoc key elist)))
(SETVAR "ATTREQ" 1)
(SETVAR "ATTDIA" 0)
(setvar "cmdecho" 0)
(setvar "blipmode" 0)
(setq ostemp (getvar "osmode"))
(command "osnap" "node")
(setq cnt 0)
(prompt "\nPick first elevation : ")
(SETQ tbdata(entget (car (entsel))))
(setq INTPT1 (dxf 10 tbdata));GETS POINT
(setq INTPT1A (entget (entnext (dxf -1 tbdata))))
(setq INTP1X (atof(dxf 1 INTPT1A)));GETS STRING
(prompt "\nPick second elevation : ")
(SETQ tbdata(entget (car (entsel))))
(setq INTPT2 (dxf 10 tbdata));GETS POINT
(setq INTPT2A (entget (entnext (dxf -1 tbdata))))
(setq INTP2X (atof(dxf 1 INTPT2A)));GETS STRING
(SETVAR "OSMODE" 545)
(setq newpt (osnap(getpoint "\npick point for new elevation: ")"nea"))
(setvar "osmode" 0)
(setq dist (distance INTPT1 INTPT2))
(setq aa (angle INTPT1 INTPT2))
(setq dist1 (/(distance INTPT1 INTPT2)2))
(IF (< INTP1X INTP2X)(setq ang (ANGTOS(angle INTPT1 INTPT2))))
(IF (> INTP1X INTP2X)(setq ang (ANGTOS(angle INTPT1 INTPT2))))
(setq dist2 0)
(setq percent (/(abs(- INTP1X INTP2X))dist));slope percentage
(if(and(< INTP1X INTP2X)(/= dist2 nil))(setq dist2 (distance INTPT1 newpt))(setq newelev (* percent dist2)))
(if(and(< INTP2X INTP1X)(/= dist2 nil))(setq dist2 (distance INTPT2 newpt)))(setq newelev (* percent dist2))
(if(< INTP1X INTP2X)(setq elev (rtos(+ INTP1X newelev)2 2)))
(if(< INTP2X INTP1X)(setq elev (rtos(+ INTP2X newelev)2 2)))
;;;(setq dim (getvar "dimscale"));;new
;;;(Setq txtht (* dim 0.4));;new
 (Setq txtht 1.) 
;;;(Setq txtht1 (* dim 0.16));;new
;;(command "insert" "level" newpt "" "" ang elev )
(command "insert" "level" newpt txtht "" ang elev )
;;;(if (or (> (car INTPT1) (car INTPT2))
;;;(= (rtd aa) 270))
;;;(command "rotate" "last" "" newpt 180.0)
;;;);if
(setvar "cmdecho" 1)
(SETVAR "ATTDIA" 1)
(setvar "osmode" ostemp)
(princ)
)

 


Carlos Calderon G
EESignature
>Did you find this post helpful? Feel free to Like this post.
Did your question get successfully answered? Then click on the ACCEPT SOLUTION button.

0 Likes
Message 9 of 16

Kent1Cooper
Consultant
Consultant

@Homecad2023 wrote:

....  I believe this once worked on older cad but doesnt seem to work anymore.  ....


More information, please.  What doesn't work about it?  Does it fail to load?  If it loads, does it not recognize the command name?  Are there any messages?  If it runs, but doesn't finish the process, how far does it get?  Does it finish but get the numerical value wrong for the intermediate location?  Could it be only that you are missing some sub-function definition such as (rtd)?  Etc., etc.

Kent Cooper, AIA
0 Likes
Message 10 of 16

Kent1Cooper
Consultant
Consultant

Here's something I notice -- the difference in what's inside the (if) function and what's outside it:

(if (and (< INTP1X INTP2X) (/= dist2 nil)) (setq dist2 (distance INTPT1 newpt)) (setq newelev (* percent dist2)))
(if (and (< INTP2X INTP1X) (/= dist2 nil)) (setq dist2 (distance INTPT2 newpt))) (setq newelev (* percent dist2))

 

Should those have the same closing-parenthesis arrangements?  I think the whole thing could be constructed in a much more concise way, but first figure out what it's really supposed to be doing.

Kent Cooper, AIA
0 Likes
Message 11 of 16

Homecad2023
Participant
Participant

Thanks, looks like its working better.

How do I get the height of the text and the layer of the text in my first selection.  I would like to set the text height and layer when I select the first level

Also should I note this as solution accepted?

0 Likes
Message 12 of 16

Homecad2023
Participant
Participant

what wasnt working is that it would not even insert the text with the interpolated amount.  I would just get an error

0 Likes
Message 13 of 16

Kent1Cooper
Consultant
Consultant

@Homecad2023 wrote:

what wasnt working is that it would not even insert the text with the interpolated amount.  I would just get an error


... and that error would be...?

Kent Cooper, AIA
0 Likes
Message 14 of 16

Homecad2023
Participant
Participant

What it was doing was giving me the level of the last selection and not giving me the interpolated value

0 Likes
Message 15 of 16

Kent1Cooper
Consultant
Consultant

@Homecad2023 wrote:

What it was doing was giving me the level of the last selection and not giving me the interpolated value


That suggests that the 'newelev' variable is 0, which could be because the 'percent' variable is 0.  Since it doesn't localize variables, after running it they will still exist, so find out what they were set to, by typing their names following exclamation points:

!percent

!newelev

What do they report?

Kent Cooper, AIA
0 Likes
Message 16 of 16

john.uhden
Mentor
Mentor

@Homecad2023 

It seems clear to me that your selected points are actually blocks with an attribute for elevation.

The blocks are all inserted at elev. 0 so you have to dig in to get the elev. from the attribute.  This is just like the days of DCA -> Softdesk.

I don't like your naming convention so I'm using my style and hope you can see what's doin'.

(defun dxf (# ent)(cdr (assoc # ent)))
;; GET 1ST POINT
(SETQ b1 (car (entsel "\nSelect 1st block insertion: ")))
(setq p1 (dxf 10 (entget b1)))
(setq z1 (atof (dxf 1 (entget (entnext b1)))))
;; GET 2ND POINT
(SETQ b2 (car (entsel "\nSelect 2nd block insertion: ")))
(setq p2 (dxf 10 (entget b2)))
(setq z2 (atof (dxf 1 (entget (entnext b2)))))
;; Now we will ask for the interpolation point,
;; BUT it might not be located on the straight line between b1 and b2,
;; So we will proportionate the location of the point on the line,
;; OR, probably better is to find its perpendicular location to the line
(setq p3 (getpoint p1 "\nPick interpolation point: "))
(setq ang (angle p1 p2)
      p (inters p1 p2 p3 (polar p3 (+ ang (* 0.5 pi)) 100) nil)
      z (+ z1 (* (/ (distance p1 p)(distance p1 p2))(- z2 z1)))
      p3 (list (car p3)(cadr p3) z)
)
;; Now maybe you want to insert your block at p3 with an attribute for z
;; but I'm just gonna put an AutoCAD POINT there for this exercise.
(setvar "pdmode" 34)
(setvar "pdsize" 1.0)
(entmakex (list '(0 . "POINT")(cons 10 p3)'(8 . "TEST")))

;; BTW, this has not been tested at all, but GOOD LUCK!

 

John F. Uhden

0 Likes