Visual LISP, AutoLISP and General Customization
cancel
Showing results for 
Show  only  | Search instead for 
Did you mean: 

Macro to find out the lowest point of selected objects and align it to z=0

13 REPLIES 13
SOLVED
Reply
Message 1 of 14
Anonymous
1521 Views, 13 Replies

Macro to find out the lowest point of selected objects and align it to z=0

Hello, I have a file to start from which has objects who are put randomly in the 3D space.

I need the lowest point of all the objects to be on z=0. The objects need to stay like they are, and on the same distance of eachother. I want the macro to find out what is the lowest point and move everything to z=0. No x or y movements need to be made.

No flattening has to be done either.

13 REPLIES 13
Message 2 of 14
Kent1Cooper
in reply to: Anonymous

Try this:

(defun C:LZ0 (/ ss n zobj zmin); = move objects so Lowest Z coordinate is at 0
  (command "_.ucs" ""); force to World Coordinate System
  (setq ss (ssget "_X" (list (cons 410 (getvar 'ctab))))); everything in current space
  (repeat (setq n (sslength ss))
    (vla-getBoundingBox
      (vlax-ename->vla-object (ssname ss (setq n (1- n))))
      'minpt 'maxpt
    ); ...getBoundingBox
    (setq
      zobj (caddr (vlax-safearray->list minpt))
      zmin (if zmin (min zmin zobj) zobj); lowest Z coordinate of anything so far
    ); setq
  ); repeat
  (command "_.move" ss "" (list 0 0 (- zmin)) "")
  (princ)
); defun

 

If the lowest initial point on anything is above Z=0, it Moves them all down; if it's below, it Moves them all up.

 

It can be changed to have the User select things instead of doing everything in the current space, to reset the UCS if it wasn't already in World Coordinates [or to do it differently and not change the UCS at all], and the usual other enhancements.

 

If anything is on a locked Layer, it won't be Moved, but the code could include unlocking all Layers if that's appropriate.

Kent Cooper, AIA
Message 3 of 14
Anonymous
in reply to: Kent1Cooper

Hello,

 

Thanks for your reply, but I can't use LISP, because of OEM restrictions. I use 2013 Autocad.

Very annoying! Could this be done solely with macro commands?

 

I have a macro to flatten all points, but that is not what I want.

 

Message 4 of 14
Kent1Cooper
in reply to: Anonymous


@Anonymous wrote:

.... Could this be done solely with macro commands?....


 

I don't know of a way to do that solely with macro-command [or Script] operations.  The Moving part is easy enough, but I can't picture a way of the finding of the lowest point on anything  that doesn't require either:

A.  stepping though a selection set and looking at each object, and AutoLisp functions are the only way I know to do that; or

B.  if you want everything  in the drawing [not a limited selection], the Z coordinate of the EXTMIN System Variable will give you that lowest elevation, but that also requires AutoLisp to extract, with (caddr (getvar 'extmin)).  I realize you can't use the following either, but for any who can  use AutoLisp and who are looking for such a routine, what my earlier routine does could actually be done with just this:

(defun C:LZ0 (); = move objects so Lowest Z coordinate is at 0
  (command
    "_.ucs" "" ; force to World Coordinate System
    "_.zoom" "_extents" ; to update EXTMIN System Variable, just in case
    "_.move" "_all" "" (list 0 0 (- (caddr (getvar 'extmin)))) ""
    "_.zoom" "_previous"
"_.ucs" "_previous" ); command (princ) ); defun

 

[The Zoom Extents is in there because the EXTMIN & EXTMAX System Variables are reset farther outboard whenever something beyond  their former values is added/Moved/Copied/etc., but when something is Erased/Moved/Trimmed etc. to make the Extents smaller, the System Variables do not reflect that pulling in until a Zoom All or Zoom Extents happens.  The routine also sets the UCS back, in case it wasn't already in the WCS, which should be added into the previous version, too.]

 

But something like the earlier routine with modification on the selection set  would still be needed if a User selection is desired, rather than everything in the current space.

Kent Cooper, AIA
Message 5 of 14
Anonymous
in reply to: Kent1Cooper

Those EXTMIN and EXTMAX are very good return values, but read only.

That's a pitty for Macro use.

 

I read you can compile lisp programs and that you can run every compiled lisp program on any version.

How can I do that exactly?

Message 6 of 14
Kent1Cooper
in reply to: Anonymous


@Anonymous wrote:

Those EXTMIN and EXTMAX are very good return values, but read only.  That's a pitty for Macro use.

 

I read you can compile lisp programs and that you can run every compiled lisp program on any version.

How can I do that exactly?


 

The pity isn't that EXTMIN/EXTMAX are read-only, but that there doesn't seem to be a way to read them in a command macro  [or in a Script] without the use of the AutoLisp (getvar) function.

 

I haven't done compiling [I just use things in their .lsp file formats], but I had the impression it was a way of protecting distributed routines from alteration or extraction of their code content by the unauthorized, rather than a way to get AutoLisp routines to work in OEM or LT versions that can't otherwise use AutoLisp.  Others with more experience in such things may chime in....

Kent Cooper, AIA
Message 7 of 14
Paul_Gander
in reply to: Anonymous

This macro is equivalent to @Kent1Cooper's second lisp routine (post 4) and uses a diesel expression to extract the z-value from the EXTMIN system variable:

 

^c^c_.ucs;_world;_.zoom;_extents;_.move;_all;;_none;0,0,$m=$(index,2,$(getvar,extmin));_none;0,0,0;_.zoom;_previous;_.ucs;_previous

 

This variation allows the user to select which objects get tested and moved:

 

^c^c_.select;$m=$(if,$(getvar,cmdactive),\)_.ucs;_world;_.isolateobjects;_previous;;_.zoom;_extents;_.move;_previous;;_none;0,0,"$m=$(index,2,$(getvar,extmin));_none;0,0,0;_.unisolateobjects;_.zoom;_previous;_.ucs;_previous"

Be aware however that the EXTMIN and EXTMAX values are not always accurate and can be a few hundredths of a unit different to the objects' actual outermost co-ordinates. I do not know of a better way of obtaining that information though.

Message 8 of 14
Anonymous
in reply to: Paul_Gander

Woow! I'm gonna try this one!

I was getting into Diesel expressions myself.

Hope I can use them 'cause of the OEM restrictions.

Thank you very much!!!

Message 9 of 14
Anonymous
in reply to: Anonymous

Hello, I did some fast testing on my file!

It works perfectly! Woow. Though not completely accurate for some reason like you mentioned, but that is not so important. It is z+ instead of z- and that is ok.

I'm very happy with it! Thank you very much!

Message 10 of 14
Anonymous
in reply to: Paul_Gander

The 2 in index. Does it mean 2 digits after the comma?

Can somebody point me out to a good site were I can learn to use DIESEL expressions?

Thank you!

 

Message 11 of 14
Kent1Cooper
in reply to: Anonymous


@Anonymous wrote:

The 2 in index. Does it mean 2 digits after the comma?

Can somebody point me out to a good site were I can learn to use DIESEL expressions?

Thank you!

 


 

I assume it's like AutoLisp's (nth) function, in which the first item in a list is item 0, and item 2 in an XYZ point list is the third item, i.e. the Z coordinate.

 

>Here< is the Diesel Functions Reference.  In addition to the links at the bottom to related topics, in the broader Customization Guide Reference, there are additional Diesel entries about halfway down.

Kent Cooper, AIA
Message 12 of 14
Anonymous
in reply to: Paul_Gander

Hello,

 

In addition to this macro, I want to do the same to the X and Y coordinates.

I made this one:

 

^c^c_.ucs;_world;_.zoom;_extents;_.move;_all;;_none;$m=$(index,0,$(getvar,extmin),$m=$(index,1,$(getvar,extmin),$m=$(index,2,$(getvar,extmin));_none;0,0,0;-view;top;_zoom;extents;

 

But only the Z axis works. What am I doing wrong here?

Message 13 of 14
Sea-Haven
in reply to: Anonymous

What do you mean OEM restrictions is it just that you can not do Appload. What does drag and drop do dragging a lisp from explorer.

 

A test copy and paste this to command line (alert "mylisp is working") alert box should appear I copy and paste from notepad every day when writing code.

Message 14 of 14
cadffm
in reply to: Anonymous


@Anonymous  schrieb:

$m=$(index,0,$(getvar,extmin),$m=$(index,1,$(getvar,extmin),$m=$(index,2,$(getvar,extmin))


extmin is x,y,z

you trie to seprate each

 

x y z

 

and put a comma between x-y and Y-z

 

x,y,z

 

hmm, the last line looks like the first line: x,y,z => x,y,z

Crazy! ?

Use $M=$(getvar,EXTMIN)

instead of

$m=$(index,0,$(getvar,extmin),$m=$(index,1,$(getvar,extmin),$m=$(index,2,$(getvar,extmin))

 

like this:

 

^C^C^C_.UCS;_world;_TREEDEPTH;$M=$(getvar,TREEDEPTH);_.MOVE;_all;;_none;$m=$(getvar,EXTMIN);_none;0,0,0;_.-VIEW;_top;_.ZOOM;_extents

 

One hint more: You should UNLOCK ALL LAYERS before,objects on locked layers can't be modify by commands like move.

Sebastian

EESignature

Can't find what you're looking for? Ask the community or share your knowledge.

Post to forums  

Forma Design Contest


Autodesk Design & Make Report