Simple LISP routine

Discussion in 'AutoCAD' started by Mike Cunningham, Jul 13, 2004.

  1. I would like to write a LISP routine that basically combines two functions.
    I would like to issue the MASSPROP command, then generate a SPHERE using the
    centroid found by the MASSPROP command, with a radius to be supplied by the
    user. I do alot of 3d modeling for crane picks, and use the centroid of the
    solids for rigging purposes. I would like the sphere to be generated simply
    for a visual.

    As of right now, I use MASSPROP, then use SPHERE, fit F2, then use "Paste to
    Command Line" for the X,Y, and Z values of the centroid!! It's pretty
    quick, but obviously could be much easier using a LISP routine. I am just
    too rusty - how do I extract the values for X, Y and Z given by the MASSPROP
    command?

    Any help is greatly appreciated. Thanks.

    Mike
     
    Mike Cunningham, Jul 13, 2004
    #1
  2. Mike Cunningham

    T.Willey Guest

    You can if you change it to an object instead of a entity.

    (vl-load-com)
    (setq ent1 (vlax-ename->(car entsel "\nSelect solid")))
    (setq cpt1 (vla-get-centroid ent1))

    The only problem is it gives it as a varient, and I don't know how to get it in point form. I'm pretty new at the ActiveX functions within lisp. Maybe one of the others will chime in and clear this up so I can learn also.

    Tim
    Sorry not too much help.
     
    T.Willey, Jul 13, 2004
    #2
  3. 'object' is a valid vla-object that has a centroid property

    (setq centroid (vla-get-centroid object))

    dealing with the variant
    (vlax-safearray->list (vlax-variant-value centroid))

    bypassing the variant
    (vlax-get object 'centroid)



    --
    Autodesk Discussion Group Facilitator


    it in point form. I'm pretty new at the ActiveX functions within lisp.
    Maybe one of the others will chime in and clear this up so I can learn also.
     
    Jason Piercey, Jul 13, 2004
    #3
  4. Mike Cunningham

    andywatson Guest

    (vlax-get ent1 "centroid") will return a list of points.
    I have found that with most vl-functions, using (vlax-get <obj> "<property>") will return lisp-readable values, and using (vlax-invoke <obj> arg1 ... ) will allow you to use lisp values as well.

    e.g.
    (setq p1 (0.0 0.0)
    p2 (10.0 10.0)
    coordList (apply 'append (list p1 p2))
    )
    (vlax-invoke *mspace* "addLightWeightPolyline" coordList)

    ....didn't have to convert coordList to a safearray.

    or...

    (vlax-invoke blockObj "GetAttributes") returns a list of attribute objects instead of a variant.
     
    andywatson, Jul 13, 2004
    #4
  5. Mike Cunningham

    T.Willey Guest

    Ooops.. mistyped

    (setq ent1 (vlax-ename->(car entsel "\nSelect solid")))
    Should be:
    (setq ent1 (vlax-ename->vla-object (car (entsel "\nSelect solid"))))

    Tim.
    Thanks Andy for clearing things up.
     
    T.Willey, Jul 13, 2004
    #5
  6. Thank you all very much for the input. Of course, the first thing I noticed
    is that I'm a lot rustier than I thought!! This gets me going though.

    Thanks again.
    Mike
     
    Mike Cunningham, Jul 14, 2004
    #6
  7. I have the basic routine down, but one of the features of the massprop
    command is that you can select multiple solids, and it returns the centroid
    of the entire volume of everything selected. How would I adjust the routine
    to do that also?

    I am also having another annoying issue, although it doesn't affect the
    routine. It asks me to select the solid, then asks me for the radius I want
    to draw the sphere with. Looking at the command line, when the prompt for
    Radius: comes up, the previous command line is still on the same line. To
    clarify, this is exactly what I see on the command line when it asks for the
    radius:

    Radius: olid

    The "olid" is from the prompt "Select solid". Please remind me...how do I
    get the lines to seperate? Not a big deal, just annoying to look at!!
    Thanks again for all your help. Time to relearn LISP I think.

    Mike
     
    Mike Cunningham, Jul 14, 2004
    #7
  8. I've got this noted in one of my routine where
    I noticed that first character being stripped out
    for whatever reason.

    (setq obj (entsel "select a solid: \n"));< extra \n required!
     
    Jason Piercey, Jul 14, 2004
    #8
  9. Mike Cunningham

    spencer1971 Guest

    Mike,

    I have this lisp that I wrote a while ago for the same reason.

    create a block called cen with the centre of the sphere as 0,0,0

    (defun c:Centroid ()
    (setq x (entsel))
    (command "massprop" x "" "y" "C:\\lisp\\centroid.mpr")
    (setq i (open "C:\\lisp\\centroid.mpr" "r"))
    (setq s (read-line i))

    (while (/= s nil)
    (setq s (read-line i))
    (if (= (substr s 1 1) "C") (progn
    (setq l (strlen s))
    (setq x (substr s 26 (- l 27)))
    (setq s (read-line i))
    (setq l (strlen s))
    (setq y (substr s 26 (- l 27)))
    (setq s (read-line i))
    (setq l (strlen s))
    (setq z (substr s 26 (- l 27)))
    (setq s nil)
    ))
    )
    (close i)
    (setq centr (strcat x "," y "," z))
    (command "insert" "C:\\lisp\\cen" centr "" "" "")
    )

    Basic but it works
     
    spencer1971, Jul 14, 2004
    #9
  10. Mike Cunningham

    T.Willey Guest

    (defun c:MassCent()

    (prompt "\nSelect solids for centroid location. ")
    (setq sset1 (ssget)
    slng1 (sslength sset1)
    cnt1 0
    cnt2 0
    clist nil
    )

    (repeat slng1
    (setq sent1 (vlax-ename->vla-object (ssname sset1 cnt2)))
    (if (vlax-property-available-p sent1 "Centroid")
    (progn
    (setq clist (append clist (list (vlax-get sent1 "Centroid"))))
    (setq cnt1 (1+ cnt1))
    )
    )
    (Setq cnt2 (1+ cnt2))
    )

    )

    Here is a start to getting the centroid of all the solids, but my experience with lists is close to nil. This will get all the centroid points and make a list of lists of those points. Where I'm stuck is, how do I process the master list (here it's clist) to find the centroid of all the point sets? I was trying to do it so that you could select as many as possible, but I'm stuck.

    Maybe someone with more list experience can chime in and help, for I would love to learn more also.

    Tim
     
    T.Willey, Jul 14, 2004
    #10
  11. Mike Cunningham

    T.Willey Guest

    (defun c:MassCent(/ sset1 slng1 cnt1 cnt2 clist sent1 xlist ylist zlist xpt ypt zpt cpt)

    (prompt "\nSelect solids for centroid location. ")
    (setq sset1 (ssget)
    slng1 (sslength sset1)
    cnt1 0
    cnt2 0
    clist nil
    )

    (repeat slng1
    (setq sent1 (vlax-ename->vla-object (ssname sset1 cnt2)))
    (if (vlax-property-available-p sent1 "Centroid")
    (progn
    (setq clist (append clist (list (vlax-get sent1 "Centroid"))))
    (setq cnt1 (1+ cnt1))
    )
    )
    (Setq cnt2 (1+ cnt2))
    )
    (setq xlist (mapcar 'car clist))
    (setq xpt (car xlist))
    (setq ylist (mapcar 'cadr clist))
    (setq ypt (car ylist))
    (setq zlist (mapcar 'caddr clist))
    (Setq zpt (car zlist))
    (repeat (fix (- (vl-list-length clist) 1))
    (setq xlist (cdr xlist))
    (setq xpt (+ xpt (car xlist)))
    (setq ylist (cdr ylist))
    (setq ypt (+ ypt (car ylist)))
    (setq zlist (cdr zlist))
    (setq zpt (+ zpt (car zlist)))
    )
    (setq cpt (list xpt ypt zpt))
    (setq cpt (mapcar '(lambda (x) (/ x cnt1)) cpt))
    (princ "\n")
    (princ cpt)
    (princ)
    )

    Here is the finished copy. It works for my test drawing and if you want to do more things variable "cpt" is the center centroid point of all the solids selected with this command. I don't know how elegante it is, because of my limited list knowledge, but it works.

    Have fun.

    Tim
     
    T.Willey, Jul 14, 2004
    #11
  12. Spencer,
    I finally got it!! I basically used your routine, but modified it slightly.
    I made it so that it allows multiple solid selection, and also it uses the
    sphere command to draw a sphere of user specified size. I also changed the
    output file to the D drive per the way I have my machine set up, but that's
    me. Here's the final routine:

    (defun c:Centroid()
    (command "ucs" "w");; I've had problems not being in World
    (setq x (ssget))
    (command "massprop" x "" "y" "D:\\lisp\\centroid.mpr")
    (setq i (open "D:\\lisp\\centroid.mpr" "r"))
    (setq s (read-line i))

    (while (/= s nil)
    (setq s (read-line i))
    (if (= (substr s 1 1) "C") (progn
    (setq l (strlen s))
    (setq x (substr s 26 (- l 27)))
    (setq s (read-line i))
    (setq l (strlen s))
    (setq y (substr s 26 (- l 27)))
    (setq s (read-line i))
    (setq l (strlen s))
    (setq z (substr s 26 (- l 27)))
    (setq s nil)
    ))
    )
    (close i)
    (setq centr (strcat x "," y "," z))
    (setq r1 (getint "\Radius: "))
    (command "sphere" centr r1)
    (command "ucs" "p")
    (princ)
    )


    The only thing additional I could see (am I never happy??) is that the
    center point it uses is only to one decimal place. It should be sufficient
    for what I am doing, but how would you get it to more decimal places?

    Thanks everyone for the help. This routine will make my life a lot simpler,
    not to mention getting calcs done much faster. I think Tim is on to
    something as well, but I like this method because it outputs the massprop
    file, which allows me to get volumes also, for additional calcs.

    This is awesome. Thanks again everyone.

    Mike
     
    Mike Cunningham, Jul 14, 2004
    #12
  13. Mike Cunningham

    T.Willey Guest

    (defun c:MassCent(/ sset1 slng1 cnt1 cnt2 clist sent1 xlist ylist zlist xpt ypt zpt cpt rad vol1 vlist ucp)

    (vl-cmdf "._undo" "_end")
    (vl-cmdf "._undo" "_group")
    (vl-cmdf "._ucs" "_w")
    (prompt "\nSelect solids for centroid location. ")
    (setq sset1 (ssget)
    slng1 (sslength sset1)
    cnt1 0
    cnt2 0
    clist nil
    )

    (repeat slng1
    (setq sent1 (vlax-ename->vla-object (ssname sset1 cnt2)))
    (if (vlax-property-available-p sent1 "Centroid")
    (progn
    (setq clist (append clist (list (vlax-get sent1 "Centroid"))))
    (setq vlist (append vlist (list (vlax-get sent1 "Volume"))))
    (setq cnt1 (1+ cnt1))
    )
    )
    (Setq cnt2 (1+ cnt2))
    )
    (setq xlist (mapcar 'car clist))
    (setq xpt (car xlist))
    (setq ylist (mapcar 'cadr clist))
    (setq ypt (car ylist))
    (setq zlist (mapcar 'caddr clist))
    (Setq zpt (car zlist))
    (setq vol1 (car vlist))
    (repeat (fix (- (vl-list-length clist) 1))
    (setq xlist (cdr xlist))
    (setq xpt (+ xpt (car xlist)))
    (setq ylist (cdr ylist))
    (setq ypt (+ ypt (car ylist)))
    (setq zlist (cdr zlist))
    (setq zpt (+ zpt (car zlist)))
    (setq vlist (cdr vlist))
    (Setq vol1 (+ vol1 (car vlist)))
    )
    (setq cpt (list xpt ypt zpt))
    (setq cpt (mapcar '(lambda (x) (/ x cnt1)) cpt))
    (setq vol1 (strcat (rtos vol1 2 5) " cu. in."))
    (setq rad (getreal "\nEnter radius: "))
    (vl-cmdf "._sphere" cpt rad)
    (vl-cmdf "._ucs" "_p")
    (vl-cmdf "._undo" "_end")
    (princ "\n")
    (princ "Centroid point: ")
    (princ cpt)
    (princ (strcat " - Volume: " vol1))
    (princ)
    )

    If you only need the volume also then try this one. You can get more things from solids if you like, but here are the ones you specified.

    Have fun, tell me what you think.
    Tim
     
    T.Willey, Jul 14, 2004
    #13
  14. Works like a charm. I like the way it lists the volume at the command
    prompt too, and it seems to take care of the decimal place issue as well.
    For me, this routine is a bit involved, LISP language -wise. I like that
    though, as it's easy to follow for those of us that need to update our LISP
    programming!! Thanks a bunch.

    Mike


    xpt ypt zpt cpt rad vol1 vlist ucp)
    things from solids if you like, but here are the ones you specified.
     
    Mike Cunningham, Jul 14, 2004
    #14
  15. Mike Cunningham

    T.Willey Guest

    Mike,

    The only thing I don't really like about it is that it assumes you are working in inches. There is a way to test and then change the prompt at the end. If you would like that I can write that also. I posted it before I realized that error.

    Other than that I'm glad it works for you.

    Tim
     
    T.Willey, Jul 14, 2004
    #15
  16. Mike Cunningham

    T.Willey Guest

    Here is the one that will make the right prompt per units user selects. Have fun.

    (defun c:MassCent(/ sset1 slng1 cnt1 cnt2 clist sent1 xlist ylist zlist xpt ypt zpt cpt rad vol1 vlist ucp ut2)

    (vl-cmdf "._undo" "_end")
    (vl-cmdf "._undo" "_group")
    (vl-cmdf "._ucs" "_w")
    (GetUnits)
    (prompt "\nSelect solids for centroid location. ")
    (setq sset1 (ssget)
    slng1 (sslength sset1)
    cnt1 0
    cnt2 0
    clist nil
    )

    (repeat slng1
    (setq sent1 (vlax-ename->vla-object (ssname sset1 cnt2)))
    (if (vlax-property-available-p sent1 "Centroid")
    (progn
    (setq clist (append clist (list (vlax-get sent1 "Centroid"))))
    (setq vlist (append vlist (list (vlax-get sent1 "Volume"))))
    (setq cnt1 (1+ cnt1))
    )
    )
    (Setq cnt2 (1+ cnt2))
    )
    (setq xlist (mapcar 'car clist))
    (setq xpt (car xlist))
    (setq ylist (mapcar 'cadr clist))
    (setq ypt (car ylist))
    (setq zlist (mapcar 'caddr clist))
    (Setq zpt (car zlist))
    (setq vol1 (car vlist))
    (repeat (fix (- (vl-list-length clist) 1))
    (setq xlist (cdr xlist))
    (setq xpt (+ xpt (car xlist)))
    (setq ylist (cdr ylist))
    (setq ypt (+ ypt (car ylist)))
    (setq zlist (cdr zlist))
    (setq zpt (+ zpt (car zlist)))
    (setq vlist (cdr vlist))
    (Setq vol1 (+ vol1 (car vlist)))
    )
    (setq cpt (list xpt ypt zpt))
    (setq cpt (mapcar '(lambda (x) (/ x cnt1)) cpt))
    (setq vol1 (strcat (rtos vol1 2 5) " Cubic " ut2))
    (setq rad (getreal "\nEnter radius: "))
    (vl-cmdf "._sphere" cpt rad)
    (vl-cmdf "._ucs" "_p")
    (vl-cmdf "._undo" "_end")
    (princ "\n")
    (princ "Centroid point: ")
    (princ cpt)
    (princ (strcat " - Volume: " vol1))
    (princ)
    )

    (defun GetUnits (/ ut1)

    (setq ut1 (getvar "insunits"))
    (cond
    ((= ut1 0)
    (alert "No units specified.
    Calculating as if in inches." )
    (setq ut2 "Inche(s)")
    )
    ((= ut1 1)
    (setq ut2 "Inche(s)")
    )
    ((= ut1 2)
    (setq ut2 "Feet")
    )
    ((= ut1 3)
    (setq ut2 "Mile(s)")
    )
    ((= ut1 4)
    (setq ut2 "Millimeter(s)")
    )
    ((= ut1 5)
    (setq ut2 "Centimeter(s)")
    )
    ((= ut1 6)
    (setq ut2 "Meter(s)")
    )
    ((= ut1 7)
    (setq ut2 "Kilometer(s)")
    )
    ((= ut1 8)
    (setq ut2 "Microinche(s)")
    )
    ((= ut1 9)
    (setq ut2 "Mil(s)")
    )
    ((= ut1 10)
    (setq ut2 "Yard(s)")
    )
    ((= ut1 11)
    (setq ut2 "Angstrom(s)")
    )
    ((= ut1 12)
    (setq ut2 "Nanometer(s)")
    )
    ((= ut1 13)
    (setq ut2 "Micron(s)")
    )
    ((= ut1 14)
    (setq ut2 "Decimeter(s)")
    )
    ((= ut1 15)
    (setq ut2 "Decameter(s)")
    )
    ((= ut1 16)
    (setq ut2 "Hectometer(s)")
    )
    ((= ut1 17)
    (setq ut2 "Gigameter(s)")
    )
    ((= ut1 18)
    (setq ut2 "Astronomical Unit(s)")
    )
    ((= ut1 19)
    (setq ut2 "Light Year(s)")
    )
    ((= ut1 20)
    (setq ut2 "Parsec(s)")
    )
    )

    )

    Tim
     
    T.Willey, Jul 14, 2004
    #16
Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments (here). After that, you can post your question and our members will help you out.