PDA

View Full Version : Extract the radius of a 3D cylinder using LISP?


oflm
2008-02-19, 03:16 PM
Howdy folks-

Our company designs piping systems in AutoCAD using 3D solids for pipe and fittings and am now working on a LISP routine to automate inserting u-bolts. I'd like to set the u-bolt size by picking the cylinder the u-bolt will straddle, but haven't been able to decipher the dxf data for 3D solid entities.

Would anyone have a piece of LISP code that can extract the radius or diameter of a 3D solid cylinder?

Thanks in advance,

Mike O'Flaherty
Hebeler Corporation

'gile'
2008-02-19, 04:45 PM
Hi,

You can get some informations through VisualLISP if the cylinder is a primitive 3d solid (created with the CYLINDER command) but this won't work if it's an extruded solid.

(vl-load-com)

(if (and
;; solid selection
(setq cyl (car (entsel "\nSelect a cylinder: ")))

;; changing ename to vla-object
(setq cyl (vlax-ename->vla-object cyl))

;; checking if it's a 3d solid
(= (vla-get-ObjectName cyl) "AcDb3dSolid")

;; checking if it's a cylinder (primitive)
(= (vl-catch-all-apply 'vla-get-SolidType (list cyl))
"Cylindre"
)
)

(setq
;; cylinder height
ht (* 2
(distance (vlax-get cyl 'Position) (vlax-get cyl 'centroid))
)

;; cylinder radius
rad (sqrt (/ (vla-get-Volume cyl) (* pi ht)))
)

(princ "\nUnvalid Entity.")
)

oflm
2008-02-19, 07:19 PM
That is perfect! I can see several uses for this: locating o-let fittings on pipe spools, gathering total lengths of pipe used in an assembly, one-click to get the cut-length of a pipe, etc. This code was exactly what I needed. Thank you very much for sharing it!

Mike

Mike O'Flaherty
Hebeler Corporation

irneb
2008-02-20, 05:44 AM
Just thought of a way of working around this. Maybe copy the 3dSolid to a temporary spot (to be deleted later). Then Explode the solid. Catch all exploded entities using (ssget "p"). Select all Regions from those entities. Explode them to check for Circle - then once you've obtained the Radius, erase the selection set of temporary exploded solid.
This should work for most 3dObjects, even extruded ones - except of course if none of it's surfaces has a circle.

irneb
2008-02-20, 06:16 AM
This seems to work:
(defun c:ShowRadius (/ Cyl SS1 SS2 SS3 en ed n Rad)
(setq Cyl (entsel "Select 3dSolid: "))
(if (and Cyl
(setq Cyl (car Cyl))
(= "3DSOLID" (cdr (assoc 0 (entget Cyl))))
) ;_ end of and
(progn
(command "_copy" Cyl "" "0,0,0" "0,0,0") ;Copy 3dSolid
(setq Cyl (entlast)) ;Get copied version's name
(command "_explode" "_last" "") ;Explode copied version
(setq SS1 (ssget "P")) ;Get selection set of exploded entities
(setq SS2 (ssget "P" '((0 . "REGION"))))
;Get sel-set of only Regions from Exploded

;; Remove all Regions from SS1
(setq n 0)
(while (< n (sslength SS2))
(setq SS1 (ssdel (ssname SS2 n) SS1))
(setq n (1+ n))
) ;_ end of while

(command "_explode" SS2 "") ;Explode Regions
(setq SS2 nil) ;Clear Selection Set
(gc) ;Force garbage collection
(setq SS2 (ssget "P")) ;Get selection set of exploded entities
(setq n 0
Rad nil
) ;_ end of setq
;;Step through SS2 search for Circle
(while (and (not Rad) (< n (sslength SS2)))
(setq en (ssname SS2 n))
(setq ed (entget en))
(if (= "CIRCLE" (cdr (assoc 0 ed)))
(setq Rad (cdr (assoc 40 ed)))
) ;_ end of if
(setq n (1+ n))
) ;_ end of while

(command "_erase" SS1 SS2 "") ;Delete all temporary objects
(setq SS1 nil
SS2 nil
) ;Clear select sets
(gc) ;Force garbage collection

;;Show radius
(if Rad
(princ (strcat "\nThe 3dSolid's radius is " (rtos Rad)))
(princ "\nThe 3dSolid does not seem to have a Circle")
) ;_ end of if
) ;_ end of progn
(princ
"\Function canceled, either no / incorrect object selected."
) ;_ end of princ
) ;_ end of if
(princ)
) ;_ end of defun

oflm
2008-02-20, 02:12 PM
Thanks for the post irneb, I'm going to do some experimenting with that code. I've got some ideas where it would be very handy.

I'm amazed at how quickly help has been offered here. It is greatly appreciated.

Thanks to you both,

Mike