Jump to content

Lookup table in LISP?


Nickvnlr

Recommended Posts

I have this lisp that calculates friction loss in a pipe based on the length of line(s) selected and size/flow input by user.  My issue: the trade size of pipe is not the actual ID.  I would like to incorporate a lookup table somehow.  I tried a hash table but ACAD didn't recognize "make-hash-table"  ??

Here's the working LISP without table:

(defun C:Hazen ()
  (setq ss (ssget))
  (if ss
    (progn
      (setq pipeDiameter (getreal "\nEnter pipe diameter (in inches): "))
      (setq flowRateGPM (getreal "\nEnter flow rate (GPM): "))
      (setq roughnessFactor 140)
      (setq pipeLength 0.0)
      (setq n (1- (sslength ss)))

      (while (>= n 0)
        (setq ent (entget (ssname ss n))
              obj (cdr (assoc 0 ent)))

        (cond
          ((= obj "LINE")
            (setq pipeLength (+ pipeLength (distance (cdr (assoc 10 ent)) (cdr (assoc 11 ent))))))
          ((= obj "ARC")
            (setq l (cdr (assoc 40 ent)))
            (if (minusp (setq l (- (cdr (assoc 51 ent)) (cdr (assoc 50 ent)))))
              (setq l (+ pi pi l)))
            (setq pipeLength (+ pipeLength l)))
          ((or (= obj "CIRCLE") (= obj "SPLINE") (= obj "POLYLINE")
               (= obj "LWPOLYLINE") (= obj "ELLIPSE"))
            (setq pipeLength (+ pipeLength (getvar "perimeter"))))
          (T nil))
        (setq n (1- n)))

      ; Calculate pressure loss using Hazen-Williams equation
      (setq pressureLoss (/ (* (* 4.55 (expt (/ flowRateGPM 140) 1.852)) (/ pipeLength 12))
      									(expt pipeDiameter 4.87))                
      )

      (alert (strcat "Pressure loss (psi): " (rtos pressureLoss 2 2)))
    )
    (alert "No valid pipe selected.")
  )
  (princ)
)

 

I was hoping to add something like this and lookup the values to use for the calculation:

 (setq pipe-hash (make-hash-table :test 'equal))
  (setf (gethash '1 pipe-hash) "1.189")
  (setf (gethash '1.5 pipe-hash) "1.72")
  (setf (gethash '2 pipe-hash) "2.22")
  (setf (gethash '3 pipe-hash) "3.23")
  (setf (gethash '4 pipe-hash) "4.267")
  (setf (gethash '5 pipe-hash) "5.27")
  (setf (gethash '6 pipe-hash) "6.282")
  (setf (gethash '8 pipe-hash) "7.82")
  (setf (gethash '10 pipe-hash) "9.78")
  (setf (gethash '12 pipe-hash) "11.73")
  (setf (gethash '15 pipe-hash) "14.66")
  (setf (gethash '18 pipe-hash) "17.92")
  (setf (gethash '21 pipe-hash) "21.13")
  (setf (gethash '24 pipe-hash) "23.77")
  (setf (gethash '27 pipe-hash) "26.79")

 

Is there a better way or something that works?

 

Thanks in advance!

Link to comment
Share on other sites

Don't know what your quite asking for. maybe a cond testing the value.

 

(cond 
  ((if (= test 1))
    (setq  pipe-hash 1.189) ;double
  )
  ((if (= test 1.5))
    (setq  pipe-hash "1.720") ;string
  )
)

 

Link to comment
Share on other sites

You could use a list of dotted pairs.  Make a list such as (setq pipelst '((1 . 1.189)(1.5 . 1.72)(2 . 2.22) .......)

I am not on my computer so I can't properly write code.  You then ask user for nominal size and using autolisp assoc command get the actual diameter with the cdr command.

I know this is not very specific but look up dotted pairs , assoc and cdr commands.

  • Thanks 1
Link to comment
Share on other sites

14 hours ago, JerryFiedler said:

You could use a list of dotted pairs.  Make a list such as (setq pipelst '((1 . 1.189)(1.5 . 1.72)(2 . 2.22) .......)

I am not on my computer so I can't properly write code.  You then ask user for nominal size and using autolisp assoc command get the actual diameter with the cdr command.

I know this is not very specific but look up dotted pairs , assoc and cdr commands.

 

I will look into that.  Thank you.

Link to comment
Share on other sites

14 hours ago, mhupp said:

Don't know what your quite asking for. maybe a cond testing the value.

 

(cond 
  ((if (= test 1))
    (setq  pipe-hash 1.189) ;double
  )
  ((if (= test 1.5))
    (setq  pipe-hash "1.720") ;string
  )
)

 

 

So you would do an IF statement for each condition?

 

I am looking for a way to do this, except with a large data set.  Something like an array or lookup table stored in the LISP.

Link to comment
Share on other sites

You could do 'if' or better 'cond'. I'd be like Jerry and go for dotted pairs:

 

 (setq pipe-hash (list
  (cons 1 "1.189")
  (cons 1.5 "1.72")
  (cons 2 "2.22")
  (cons 3 "3.23")
  (cons 4 "4.267")
  (cons 5 "5.27")
  (cons 6 "6.282")
  (cons 8 "7.82")
  (cons 10 "9.78")
  (cons 12 "11.73")
  (cons 15 "14.66")
  (cons 18 "17.92")
  (cons 21 "21.13")
  (cons 24 "23.77")
  (cons 27 "26.79")
)) ; end setq, end list

 

Note the use of cons allows for some calculation within each dotted pair, if these are static could use '(1 "1.189") for example, similarly the (lidt could be replaced with a '( if all the (cons .... ) are static

 

and to interrogate this to get the value use (assoc ....)

 

(setq Size (cdr (assoc 1.5 Pipe-Hash)))

 

where 1.5 is the value you want, cdr above selects the 2nd item in the list, without it it returns the whole dotted pair

Edited by Steven P
Link to comment
Share on other sites

Dotted pairs worked great.  Thank you!

Here is the completed LISP.

;Created by Nick Van Laar for use @ STREAMLINE IRRIGATION
;Calculates the friction loss and velocity of water through common sizes of PVC for the distance of user selected lines/polylines/arcs/etc.
(defun C:Hazen ()
  (setq ss (ssget))
  (if ss
    (progn
      (setq pipeDiameter (getreal "\nEnter pipe diameter (in inches): "))
      (setq flowRateGPM (getreal "\nEnter flow rate (GPM): "))
      (setq pipeLength 0.0)
      (setq pipelist '((1 . 1.189)
                       (1.5 . 1.72)
                       (2 . 2.22)
                       (3 . 3.23)
                       (4 . 4.267)
                       (5 . 5.27)
                       (6 . 6.282)
                       (8 . 7.82)
                       (10 . 9.78)
                       (12 . 11.73)
                       (15 . 14.66)
                       (18 . 17.92)
                       (21 . 21.13)
                       (24 . 23.8)
                       (27 . 26.8)))
      (setq n (1- (sslength ss)))
      
	  ;Adapted TLEN.LSP - (C) Tee Square Graphics
      (while (>= n 0)
    (setq ent (entget (setq itm (ssname ss n)))
          obj (cdr (assoc 0 ent))
          l (cond
              ((= obj "LINE")
                (distance (cdr (assoc 10 ent))(cdr (assoc 11 ent))))
              ((= obj "ARC")
                (* (cdr (assoc 40 ent))
                   (if (minusp (setq l (- (cdr (assoc 51 ent))
                                          (cdr (assoc 50 ent)))))
                     (+ pi pi l) l)))
              ((or (= obj "CIRCLE")(= obj "SPLINE")(= obj "POLYLINE")
                   (= obj "LWPOLYLINE")(= obj "ELLIPSE"))
                (command "_.area" "_o" itm)
                (getvar "perimeter"))
              (T 0))
          pipeLength (+ pipeLength l)
          n (1- n)))
	  ;Get pipe ID
	  (defun get-value (key 1st)
      (cdr (assoc key 1st)))
      (setq pipeID (get-value pipeDiameter pipelist))
      ;Get roughnessFactor
      (setq rCoef nil)
      (IF (>= pipeDiameter 8)
		  (setq rCoef 150)
		  (setq rCoef 140)
      )
      ; Calculate pressure loss using Hazen-Williams equation
      (setq pressureLoss (/ (* (* 4.55 (expt (/ flowRateGPM rCoef) 1.852)) (/ pipeLength 12))
      									(expt pipeID 4.87))                
      )
	  ; Calculate Velocity
      (setq velocity (/ (* 0.408 flowRateGPM) (expt pipeID 2))
      )
      (alert (strcat "Pressure loss (psi): " (rtos pressureLoss 2 3) "
      Velocity (fps): " (rtos velocity 2 2)))
    )
    (alert "No valid pipe selected.")
  )

 

  • Like 1
Link to comment
Share on other sites

Quick question, I know it's in the TLEN section, but is there a way to get rid of the perimeter/area/length display?

 

Thank you.

 

 

ACAD display.jpg

Link to comment
Share on other sites

Just me I dont use dotted pairs in list ((1.0 0.875)(1.25 1.034) the (car (nth x lst)) and (cadr (nth x lst)) are values from a list, as I say just my preference.

Edited by BIGAL
Link to comment
Share on other sites

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...