Jump to content

LISP for measuring distances between all similar blocks from custom insertion point


toper

Recommended Posts

So new to LISP it's ridiculous, and I need help.

 

I'm doing some designs for lighting and sound, and I have sets of blocks at various points around a floorplan. I plan on making these blocks (dynamic blocks if necessary) and giving them similar nomenclature according to what they are (speakers, monitors, motors, trusses, etc.).

 

Now, rather than going through and measuring the distance by hand, so to speak, for every single item, I'd love to find a LISP routine where I can insert a custom (like 200, 0) insertion point to measure from, and measure each (or batch) block's distance from that point. If the results could be posted in a table, that would be even more awesome. Presumably I would use the names of the similar blocks, as in, any block with the word "motor" in its tag or name.

 

I sense I am asking for something rather big here...

Link to comment
Share on other sites

This should get you started:

 

(defun c:FOO (/ pt)
 (if (setq pt (getpoint "\nSpecify base point: "))
   (while (and (not (initget 32))
               (/= nil (setq pt2 (getpoint pt "\nSpecify point to measure: "))))
     (prompt (strcat "\n  >>  Distance  >>  " (rtos (distance pt pt2) 2 2))))
   (prompt "\n** Invalid point ** "))
 (princ))

 

There are plenty of things that can be done to improve this as well... Enjoy! :)

Link to comment
Share on other sites

Thanks RenderMan! This is an excellent starting point for me. Gives me a base to start with and I can click on as many objects as I want and it specifies a separate distance for each, not a total (which is good, I don't want a total). Now if I can figure out a a way to get the routine to automatically select all objects/blocks with a name starting with "###" and give me a list of all those measurements...I'd be even happier. The struggle goes on.

 

And oh yea, next thing: What I need to do ideally, which I just realized, is this: The measurement I need to create is an X,Y coordinate. So I'd need to measure from a basepoint (say, a midpoint on a back wall), then a distance along X to a point where I then up Y to the object, creating two separate distances. Does this make sense?

Link to comment
Share on other sites

Hope you do not mind dear Renderman . :)

 

Just an idea .

 

(defun c:Test (/ p ss i pt e)
 (if (and (setq p (getpoint "\n Specify Starting point :"))
          (setq ss (ssget "_:L" '((0 . "INSERT"))))
     )
   (repeat (setq i (sslength ss))
     (setq sset (ssname ss (setq i (1- i))))
     (setq pt (cdr (assoc 10 (setq e (entget sset)))))
     (print
       (strcat ">> * Distance between Sarting point to Block :"
               (cdr (assoc 2 e))
               "is :"
               (rtos (distance p pt) 2)
       )
     )
   )
   (princ)
 )
 (princ)
)

Tharwat

Link to comment
Share on other sites

Thanks RenderMan! This is an excellent starting point for me.

 

You're welcome. :)

 

Now if I can figure out a a way to get the routine to automatically select all objects/blocks with a name starting with "###" and give me a list of all those measurements...I'd be even happier. The struggle goes on.

 

Welcome to the world of selection sets!

 

This exampe assumes you're measuring from the base point to the insertion point of each block selected:

 

(defun c:FOO (/ pt ss oBlock)
 (vl-load-com)
 (if (and (setq pt (getpoint "\nSpecify base point: "))
          (setq ss (ssget '((0 . "INSERT") ;|(2 . "###*")|)))
   ((lambda (i / e)
      (while (setq e (ssname ss (setq i (1+ i))))
        (prompt
          (strcat
            "\n  >>  Distance  >>  "
            (rtos (distance pt
                            (vlax-get
                              (setq oBlock
                                     (vlax-ename->vla-object e))
                                    'insertionpoint))
                  2
                  2)
            ", to "
            (vla-get-effectivename oBlock)))))
     -1)
   (cond (pt (prompt "\n** Nothing selected ** "))
         ((prompt "\n** Invalid point ** "))))
 (princ))

 

... Not sure if I have enough information for you to correlate the distance to a specific entity yet, though.

 

[edit] BTW - It is unclear if you meant "###" is the actual prefix to your block names, or if that was a generic annotation for number-number-number (i.e., 123*, or 456*, etc.). [/edit]

 

And oh yea, next thing: What I need to do ideally, which I just realized, is this: The measurement I need to create is an X,Y coordinate. So I'd need to measure from a basepoint (say, a midpoint on a back wall), then a distance along X to a point where I then up Y to the object, creating two separate distances. Does this make sense?

 

No, not at all... Perhaps a screen shot would help?

Edited by BlackBox
Corrected else statement
Link to comment
Share on other sites

I love this forum. Intelligent people actually respond.

 

This takes the LISP to the next step, I can select multiple objects and then get a set of distances as a result, rather than doing one at a time. Next steps are:

 

* Determine the coordinates along the X and Y axes from the base point to each object.

 

* Then, if possible, have the ability to enter a name prefix and the LISP function would determine those X & Y coordinates for all objects (or blocks w/ attributes?) that contain that name prefix.

 

I appreciate so much any help being offered. Trying to work through the code on my own, but I fear little progress will get made. But I try, nonetheless! :)

Link to comment
Share on other sites

I love this forum. Intelligent people actually respond.

 

That's very kind of you to say.

 

 

This takes the LISP to the next step, I can select multiple objects and then get a set of distances as a result, rather than doing one at a time.

 

That's the point - programming allows us to take repaeted tasks, or sequences of, and automate them to increase efficiency.

 

Next steps are:

 

Whoa, whoa, whoa, there buddy... you're going to have to crack open the Developer Documentation and start reading for yourself here, real soon. :)

 

* Determine the coordinates along the X and Y axes from the base point to each object.

 

This is a bit confusing to me. Are you interested in the X,Y of the blocks insertion point, or the angle from the base point to same?

 

* Then, if possible, have the ability to enter a name prefix and the LISP function would determine those X & Y coordinates for all objects (or blocks w/ attributes?) that contain that name prefix.

 

Yes, simply store a user input string to a variable/symbol, then supply that value to the appropriate DXF code for your ssget filter, walla.

 

I appreciate so much any help being offered. Trying to work through the code on my own, but I fear little progress will get made. But I try, nonetheless! :)

 

Shortly here, you'll have the opportunity (responsability) of writing & posting your own code, so that we see you're doing some of your own work (or at least making genuiine effort), and we'll help from there.

 

Just remember, everyone here is a volunteer... as long as you're polite, and respectful, we're happy to help. :)

Link to comment
Share on other sites

Yea my babbling was a little confusing, this is the way I need to measure distance, so my riggers can walk the floor precisely to the spot where (above them) the lights will be hung, speaker boxes hung, etc.

 

Thanks again.

 

xy_problem.jpg

 

I'm working myself, too, but at this point my coding skills are worthy of, well, nothing. I will definitely pitch in when I start getting at least a little proficient.

 

The "next step" was just me thinking out loud, not to worry.

Link to comment
Share on other sites

Is there a block located at the final destination (you only show the midpoint of what I beleive to be a wall)?

 

Otherwise, the distance and coordinate extraction is not a problem.

Link to comment
Share on other sites

The block on the left (long thin rectangle) is my 2-second scribble representation of a wall. So the measuring is going from the wall point on the left up to the square.

 

I'm combing through AutoCAD's documentation on this too. So far I'm finding mostly general, broad-strokes sort of information, but that's probably because I don't know what to look for as well yet.

Link to comment
Share on other sites

The block on the left (long thin rectangle) is my 2-second scribble representation of a wall. So the measuring is going from the wall point on the left up to the square.

 

This is the part I need for you to be more specific.

 

At the destination point you show, will there be (is there) a block representing the device (i.e., monitor, speaker, etc.), or is the square-like shape the block itself, and the destination point shown is that blocks insertion point?

 

Also, what is your block naming conventions (i.e., "Monitor_001", "001-speaker", etc.)? Try to be as specific as possible, for each of the blocks you 'd like to use this routine on.

Link to comment
Share on other sites

Gotcha. Sorry, the LISP language is literally new to me as of Wednesday. I plan on spending the rest of the next few weeks in my spare time trying to get my head around programming for LISP.

 

The naming will be keyword first, so, Box_001 or GoBo_001, etc. So in this drawing I'll call the square "Box_001". The basepoint is against the middle of that rectangle on the left, which represents a wall. So when the script runs and asks me to Specify Base point, that's where I'm starting in this example. The point on the blocks can be anywhere, but I think I'll make it the midpoint on the bottom edge.

 

The weird-looking shape in the bottom of the drawing can be ignored.

Link to comment
Share on other sites

Gotcha. Sorry, the LISP language is literally new to me as of Wednesday. I plan on spending the rest of the next few weeks in my spare time trying to get my head around programming for LISP.

 

The naming will be keyword first, so, Box_001 or GoBo_001, etc. So in this drawing I'll call the square "Box_001". The basepoint is against the middle of that rectangle on the left, which represents a wall. So when the script runs and asks me to Specify Base point, that's where I'm starting in this example. The point on the blocks can be anywhere, but I think I'll make it the midpoint on the bottom edge.

 

The weird-looking shape in the bottom of the drawing can be ignored.

 

No worries.

 

This weekend, read up on the Developer Documentation, and pay special attention to the cond funtion. Also, if you can, read up on the quadrants (i.e., half pi, pi, one and a half pi, and two pi, or zero pi), as you're going to use this to determine the orientation of the destination point, in relation to the base point.

 

If you're really feeling ambitious, write some code, experiment... for example in the scenario you posted, pick your base point, and your destination point, and try to work out how to find that point of intersection if you will. Here's some hints -> look into the car, cadr, and last functions.

 

Good luck!

Link to comment
Share on other sites

I'll do some reading, and thanks for your help. I'll let you know if/when I figure it out. :)

 

I'll be happy to continue helping... see what you can do over the weekend, and post the code you can come up with. We'll go from there... the point is to get started, put forth your best effort, then get some input on how better to do the same thiing (

 

[edit] I'll be the first to tell you that I'm still learning, in many respects [/edit]

 

Have a good weekend!

Link to comment
Share on other sites

Maybe this will get you started:

 

(defun c:test ( / _pt->str en fn fo i p1 p2 ss )

 (defun _pt->str ( pt )
   (apply 'strcat (mapcar 'strcat (mapcar 'rtos pt) '(","",""")))
 )

 (if
   (and
     (setq p1 (getpoint "\nSpecify Base Point: "))
     (setq ss (ssget '((0 . "INSERT"))))
     (setq fn (getfiled "Output File" "" "txt" 1))
     (setq fo (open fn "w")) 
   )
   (progn
     (setq i -1 p1 (trans p1 1 0))
     (write-line (strcat "From Base: " (_pt->str p1)) fo)
     (write-line "Block\tInsertion\tDx,Dy" fo)
     
     (while (setq en (ssname ss (setq i (1+ i))))
       (setq p2 (cdr (assoc 10 (entget en))))
       (write-line (strcat (cdr (assoc 2 (entget en))) "\t" (_pt->str p2) "\t" (_pt->str (mapcar '- p2 p1))) fo)
     )
     (close fo) (startapp "notepad" fn)
   )
 )
 (princ)
)

 

Will write the values to a file of your choosing :)

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