Highest Distance Value

Highest Distance Value

Anonymous
Not applicable
2,285 Views
24 Replies
Message 1 of 25

Highest Distance Value

Anonymous
Not applicable
Hello,

First time posting here. I am trying to setup a field or something similar that will display the longest distance of 6 different lines within a block. Then I want to extract the longest distance use it to calculate the slope. The part im struggling with is getting the max value from the variable lines within the block.

Something like =(MAX (Distance1 Distance2 ... Distance 6))*.125

I cant get this code to work in the formula portion of the field and I have no experience with LISP. I am still trying to wrap my head around the coding for LISP . I tried to find an answer before posting, any help would be appreciated.
0 Likes
Accepted solutions (1)
2,286 Views
24 Replies
Replies (24)
Message 2 of 25

Ajilal.Vijayan
Advisor
Advisor

Hi,

Welcome to Autodesk discussion forum .

To use the MAX function, no need to provide the numbers inside the brackets

Try like this.

(max Distance1 Distance2 ... Distance 6)

and if you want to multiply the max value use this

( * 0.125 (max Distance1 Distance2 ... Distance 6))
0 Likes
Message 3 of 25

Anonymous
Not applicable

I assume this has to be inserted into a LISP routine? I am not very familiar with how they work. Any time I tried to code one I can't seem to get it to function. Maybe I am going about it the wrong way. I attached an image of what I am attempting. Is there a good resource for setting up a LISP like this. When I add this MAX function line of code into a .LSP it gives me a "error: bad argument type: numberp: nil" I have no idea what I am doing, I've been using CAD for years, but have never had this much trouble figuring something out. Thanks for the help.

 

Drain Formula.JPG

0 Likes
Message 4 of 25

Kent1Cooper
Consultant
Consultant

@Anonymous wrote:

.... When I add this MAX function line of code into a .LSP it gives me a "error: bad argument type: numberp: nil".....


I would want to see the code you have so far, and how you're getting the length values in it.  It's not clear to me whether everything in the image is part of the Block -- you mention 6 lines, but there are 8 if the perimeter is included, and from your description, I would think you need to consider only the 4 of them that meet at the drain in the middle.

 

It may be easier to collect the length values into a list, and after they're all in it, find the longest one not by putting them into a (max) function directly, but this way:

 

(apply 'max YourLengthListVariable)

Kent Cooper, AIA
0 Likes
Message 5 of 25

jdiala
Advocate
Advocate
(defun C:test (/ p ss e lst d1 d2 p1)
  (if
    (and
      (setq p (cdr (assoc 10 (entget (car (entsel "\nSelect a block: "))))))
      (princ "\nSelect lines:")
      (setq ss (ssget ":L" '((0 . "LINE"))))
    )
    (repeat 
      (setq i (sslength ss))
      (foreach x 
        (setq lst 
          (cons  
            (cdr 
              (assoc 11 
                (entget 
                  (setq e 
                    (ssname ss 
                      (setq i (1- i))
                    )
                  )
                )
              )
            ) 
            (setq lst 
              (cons 
                (cdr 
                  (assoc 10 
                    (entget e)
                  )
                ) lst
              )
            )
          )
        )
        (setq d1 (distance p x))
        (if 
          (>= d1 d2 ) 
          (setq d2 d1 p1 x)
        )
      )
    )
  )
  (entmake
    (list
      '(0 . "LINE")
       (cons 10 p)
       (cons 11 p1)
      '(62 . 1) 
    )
  )
  (princ (strcat "Farthest distance is " (rtos d2)))
  (princ)
)
  

You can try something like this.

0 Likes
Message 6 of 25

Anonymous
Not applicable

Thank you everyone for the input. I've been at work, so I haven't had time to reply. The image from my 2nd post was a quick block I made on the spot to try to help demonstrate what I was trying to do. I have attached more closely the block demonstrating what I am trying to accomplish.

 

What it comes down to is that I started the idea for this dynamic block and I can everthing to work the way I expect, with the exception of extracting the longest distance of the 6 lines. I thought there might be something within the FIELD dialog that would work like this, but I wasn't able to find anything.

 

I figured a LISP was the only. The problem with that is I have minimal experience with LISP routines.I've been trying to read since I ran into this, but even with the suggestions given, I can't get it to function. I am still trying to learn how to tell the code to grab the appropriate data.

 

jeri32,

When I load the .LSP and attempt to selec the block, it acts like the block isn't selectable. If I hit enter it says " ; error: bad DXF group: (11)

 

Thanks again,

 

rifflemj

 

0 Likes
Message 7 of 25

jdiala
Advocate
Advocate
Just follow the command line.

1. Pick a block.
2. Select the lines.
3. Press enter.
0 Likes
Message 8 of 25

Anonymous
Not applicable

Obviously.

 

It's not working.

I'll figure out how to do what I am trying to accomplish eventually. I'll just list all possible outcomes for the time being. Thanks all for the help.

0 Likes
Message 9 of 25

jdiala
Advocate
Advocate

My bad. I didn't check the drawing yesterday when I replied. 

 

When I coded yesterday, I assumed that the fd is a block and some line. Instead Everything is a block including the line. It's gonna be tough coding that on, instead try this 2 below.

 

Watch screencast. Can't zoom in while screen is recording, don't know why...

 

 

(defun C:test (/ p ss e i lst d1 d2 p1)
  (if
    (and
      (setq p (cdr (assoc 10 (entget (car (entsel "\nSelect a block: "))))))
      (princ "\nSelect lines:")
      (setq ss (ssget ":L" '((0 . "LINE"))))
    )
    (repeat 
      (setq i (sslength ss))
      (foreach x 
        (setq lst 
          (cons  
            (cdr 
              (assoc 11 
                (entget 
                  (setq e 
                    (ssname ss 
                      (setq i (1- i))
                    )
                  )
                )
              )
            ) 
            (setq lst 
              (cons 
                (cdr 
                  (assoc 10 
                    (entget e)
                  )
                ) lst
              )
            )
          )
        )
        (setq d1 (distance p x))
        (if 
          (>= d1 d2 ) 
          (setq d2 d1 p1 x)
        )
      )
    )
  )
  (entmake
    (list
      '(0 . "LINE")
       (cons 10 p)
       (cons 11 p1)
      '(62 . 1) 
    )
  )
  (princ (strcat "Farthest distance is " (rtos d2)))
  (princ)
)
  
(defun C:test2 (/ p ss e i lst d1 d2 p1 p2)
  (if
    (and
      (setq p (cdr (assoc 10 (entget (car (entsel "\nSelect a block: "))))))
      (princ "\nSelect lines:")
      (setq ss (ssget ":L" '((0 . "LINE"))))
    )
    (progn
      (repeat 
        (setq i (sslength ss))
          (if 
            (> 
              (distance 
                (setq p1 
                  (cdr 
                    (assoc 10 
                      (entget 
                        (setq e 
                          (ssname ss 
                            (setq i (1- i))
                          )
                        )
                      )
                    )
                  )
                ) p
              )
              (distance 
                (setq p2 
                  (cdr 
                    (assoc 11 
                      (entget e)
                    )
                  )
                ) p
              )
            )
            (setq lst (cons p1 lst))
            (setq lst (cons p2 lst))           
          )           
      )
      (foreach x lst
        (setq d1 (distance p x))
        (if 
          (>= d1 d2 ) 
          (setq d2 d1 p1 x)
        )
      )
    )
  )
  (entmake
    (list
      '(0 . "LINE")
       (cons 10 p)
       (cons 11 p1)
      '(62 . 1) 
    )
  )
(princ (strcat "\nFarthest distance is " (rtos d2)))
(princ)
)
0 Likes
Message 10 of 25

Kent1Cooper
Consultant
Consultant

I'm not at my location with a new-enough version of AutoCAD to work with Dynamic Blocks, so certain things I can't try at the moment, but....

 

If you don't mind selecting the Lines in the Block, rather than the Block as a whole, here's something that works whether they're top-level Lines or nested in Blocks of any kind:

 

(defun C:LongestLine (/ lin lenlist)
  (while (setq lin (car (nentsel "\nSelect Line: ")))
    (setq lenlist (cons (vla-get-Length (vlax-ename->vla-object lin)) lenlist))
  ); while
  (prompt (strcat "\nLongest Line length: " (rtos (car (vl-sort lenlist '>))) "."))
); defun

 

Very basic, and without all sorts of possible controls and enhancements, but see whether it works as a starting point.  Presumably selection of a Block containing Lines could be made to feed the Lines in, but what I can't check on is whether it can extract their lengths in the particular insertion, or only their "native" lengths in the Block definition.  I don't think the above cares, at least it doesn't in converting your sample drawing to an earlier version where they're anonymous but not dynamic Blocks.

Kent Cooper, AIA
0 Likes
Message 11 of 25

Anonymous
Not applicable

I should have made my first post more clear. It just frustrates me, because I have a lot of experience with CAD but am having a hard time grasping this coding. You guys are like a bunch of wizards. 

 

I just ran your code and it works, just not quite in the application I am hoping for. My intent is to have a bunch of these drains with varying slope distances for the concrete. The end result being a number inside the block which displays how deep the drain needs to be placed. (Farthest Distance / 96). 

 

If this information can be placed in a field within the block such that it updates when the distances change that would be ideal.

 

Thanks again for all the help. I'll keep studying the AutoLisp code, so I can try to figure some of this out on my own.

0 Likes
Message 12 of 25

Anonymous
Not applicable

Kent, that piece of code allowed me to get the longest distance.

 

I keep getting the feeling that I won't be able to just execute this once and keep it as an updateable field within a block.

0 Likes
Message 13 of 25

Kent1Cooper
Consultant
Consultant

@Anonymous wrote:

Kent, that piece of code allowed me to get the longest distance.

 

I keep getting the feeling that I won't be able to just execute this once and keep it as an updateable field within a block.


It could set the longest-length value into a variable, instead of just reporting it.  Someone else would need to work out whether it can be applied to a field; the Block could certainly be "found" from any of the pickpoints on the Lines, assuming you don't pick Lines in more than one Block, or that aren't part of one of those Blocks.

 

And to be consistent with my earlier Reply [and to be a hair shorter], that reporting would be:

(prompt (strcat "\nLongest Line length: " (rtos (apply 'max lenlist)) "."))

 

Saving that for further use:

(prompt (strcat "\nLongest Line length: " (rtos (setq longest (apply 'max lenlist))) "."))

Kent Cooper, AIA
0 Likes
Message 14 of 25

dbroad
Mentor
Mentor

I hesitate to mention this because a real application should reload itself with the drawing and should also work when you send your drawings out to others.  

 

That said, you could construct your blocks as you have and add object reactors to track modifed events.  The modified event would pass the objects changed to a command reactor.  The command reactor could scan the block to find the maximum parameter length and change the attribute.  The problem with object reactors is that they are not persistent and lose their owners when the drawing is saved.  You could code an application to scan your drawing looking for these blocks and add them back as object owners and update the lengths.  It would still require automatically loading the application for functionality.

Architect, Registered NC, VA, SC, & GA.
0 Likes
Message 15 of 25

doni49
Mentor
Mentor

@Anonymous wrote:

I assume this has to be inserted into a LISP routine? I am not very familiar with how they work. Any time I tried to code one I can't seem to get it to function. Maybe I am going about it the wrong way. I attached an image of what I am attempting. Is there a good resource for setting up a LISP like this. When I add this MAX function line of code into a .LSP it gives me a "error: bad argument type: numberp: nil" I have no idea what I am doing, I've been using CAD for years, but have never had this much trouble figuring something out. Thanks for the help.

 

Drain Formula.JPG


Based on this image, it appears that you want to put this lisp function in a formula for a Field.  The fields won't accept lisp -- there've been many times I wished it would.  But fields WILL accept Diesel functions.  Diesel doesn't include a max function but you can do it using IF.  But instead of telling it "Formula", you'll need to choose "Diesel".

 

Assuming four possible values:

$(*, 0.125, $(if,value1>$(if,value2>$(if, (>, value3,value4),value3,value4),value2,$(if, (>, value3,value4),value3,value4)),value1,$(if,value2>$(if, (>, value3,value4),value3,value4),value2,$(if, (>, value3,value4),value3,value4))))

 

Of course, you'll need to replace value1 through value4 with the appropriate values.

 

All it says to compare 3 &4 then compare the highest value to 2.  Then compare the highest of those to 1.  Then display the highest of those two.

 

The simplest way to make this change would be to copy/paste the code into notepad, use the Find/Replace tool to change value1 to the appropriate value.  Then value2 etc.......  This way you won't miss any.

 

EDIT:  it appears that I hadn't read far enough through the thread -- my mistake.



Don Ireland
Engineering Design Technician




If a reply solves your issue, please remember to click on "Accept as Solution". This will help other users looking to solve a similar issue. Thank you.


Please do not send a PM asking for assistance. That's what the forums are for. This allows everyone to benefit from the question asked and the answers given.

0 Likes
Message 16 of 25

dbroad
Mentor
Mentor

You could do this in fields alone if the max function was supported.  It is not.  LISP expressions are not supported. Only lisp variables are accessible.  Diesel does not have the capabilities either.

Architect, Registered NC, VA, SC, & GA.
0 Likes
Message 17 of 25

doni49
Mentor
Mentor

@Anonymous wrote:

You could do this in fields alone if the max function was supported.  It is not.  LISP expressions are not supported. Only lisp variables are accessible.  Diesel does not have the capabilities either.


I tested it in 2014 before posting.  It worked fine for me.  Not nearly as good as having a MAX function.  But it gets the job done.



Don Ireland
Engineering Design Technician




If a reply solves your issue, please remember to click on "Accept as Solution". This will help other users looking to solve a similar issue. Thank you.


Please do not send a PM asking for assistance. That's what the forums are for. This allows everyone to benefit from the question asked and the answers given.

0 Likes
Message 18 of 25

dbroad
Mentor
Mentor

Doni,

If you can make the diesel method work for a field inside a dynamic block as posted where the person drags a line and the field automatically recalculates the maximum length, I would be interested.  Each of those values you posted would need to get information one or more times from the 6 lines in the block parameters of the dynamic block.  I just don't see that as a practical solution, especially wrt maintenance, but am willing to eat those words.  Please post an attached drawing with a dynamic block that works.

Architect, Registered NC, VA, SC, & GA.
0 Likes
Message 19 of 25

Anonymous
Not applicable

Thank you everyone for all the suggestions. I might have a solution with reporting from a table with inserted fields. But 12 am here, I'll test it tomorrow and report back with why it failed Smiley Tongue

 

 

0 Likes
Message 20 of 25

ВeekeeCZ
Consultant
Consultant

@Anonymous wrote:
Hello,

First time posting here. I am trying to setup a field or something similar that will display the longest distance of 6 different lines within a block. ...

Hey,

it is complitated but possible - see attached your example for 4 distances. Sorry for using a metrical units. See hint.

0 Likes