Author Topic: Here's a challange; plotting tables  (Read 2529 times)

0 Members and 1 Guest are viewing this topic.

Rabbit

  • Guest
Here's a challange; plotting tables
« on: February 10, 2011, 02:02:40 PM »
Well, at least for me it is.  I need to plot out several tables in AutoCAD.  These are Electrical panelboards tables which I have custom created.  Now, these tables are straight forward, but the problem is in plotting them.  I usually plot them out on 8.5X11 sheets to make it easier for going back and reviewing sheets before they are sent out final.  I have to go in to plot> window>picks points of the window and then plot.  This can be time consuming if there are a bunch of these.  Being the type which hates doing redundant stuff, I want to create a routine in which I get the geoextents of the table and put that into a plotting routine which will go through all these tables using ssget and plot them out. Being that I have never used plot in conjunction with lisp I don't have the faintest idea where to start.  Any pointers or ideas?

Sincerely,
Rabbit

PS, if you need more info, please let me know and I'll try to post the answers.

Lee Mac

  • Seagull
  • Posts: 12922
  • London, England
Re: Here's a challange; plotting tables
« Reply #1 on: February 10, 2011, 02:07:26 PM »
Hi Rabbit,

If the Tables are a single object (i.e. an ACAD_TABLE), you could use the BoundingBox VL method to retrieve the corner points, and use these in the plot command (or alternatively use the SetWindowtoPlot method in conjunction with the PlottoDevice method).

Example of BoundingBox method to return a list of (<LowerLeft> <UpperRight>):

Code: [Select]
(mapcar 'vlax-safearray->list
  (progn
    (vla-getBoundingBox <VLA-Object> 'll 'ur) (list ll ur)
  )
)

[ Where <VLA-Object> is the Object to query ] - this might also be of interest.

If the Tables aren't single objects, but rather composed of many objects, you could look to calculate the BoundingBox of a SelectionSet of these objects - for this task, perhaps see here.

The overall selection of the Tables would depend upon whether they are a single object or not - if they are a single object, the plotting process could be completely automated using a SelectionSet of all such Tables in the Drawing, otherwise the user would have to select each set of objects making up each Table.

Lee
« Last Edit: February 10, 2011, 02:12:20 PM by Lee Mac »

cmwade77

  • Swamp Rat
  • Posts: 1443
Re: Here's a challange; plotting tables
« Reply #2 on: February 10, 2011, 02:51:35 PM »
Our solution is a little different, what we do is each panel schedule is it's own file and gets xrefed into the drawing. We can the batch plot the files, if needed. Of course the reason for this is we have a lisp routine that has been used to run all of the calculations, I have tried turning it into a table with formulas, but with very little success.

Rabbit

  • Guest
Re: Here's a challange; plotting tables
« Reply #3 on: February 10, 2011, 03:21:02 PM »
@ cmwade77:  I haven't had time to fully digest what you suggested, but, I think you have me on the right track.  The SETWINDOWTOPLOT method I'm not familliar with.  Of course, I would look it up, but, since AutoDesk decided to put their help files online, I haven't got a very good acces to vlisp/VBA references.  in other words, would the syntax be something like (vla-setwindowtoplot <VLA-OBJECT a.k.a. the table> <bounding box>)

@Lee:  I have a very intricate, and very ugly, set of lisp routines which I can insert the tables in and then use another lisp to put in the load, description and breaker amperage.  The rest of the calcs are done using fields within the table.  If you want, I can post the block for you to look at.

Thanks again,
Rabbit

Lee Mac

  • Seagull
  • Posts: 12922
  • London, England
Re: Here's a challange; plotting tables
« Reply #4 on: February 10, 2011, 04:06:39 PM »
As a quick example, this will window plot the tables using the current plot settings for the Layout:

Code: [Select]
(defun c:PlotTables ( / acdoc aclay acplt ss ll ur ) (vl-load-com)
  ;; Lee Mac 2011  -  www.lee-mac.com

  (setq acdoc (vla-get-ActiveDocument (vlax-get-acad-object))
        aclay (vla-get-ActiveLayout acdoc)
        acplt (vla-get-Plot acdoc)
  )

  (if (ssget "_X" (list (cons 0 "ACAD_TABLE") (cons 410 (getvar 'CTAB))))
    (progn     
      (vlax-for obj (setq ss (vla-get-ActiveSelectionSet acdoc))
        (apply 'vlax-invoke
          (cons aclay
            (cons 'SetWindowtoPlot
              (mapcar
                (function
                  (lambda ( x ) (list (car x) (cadr x)))
                )
                (mapcar 'vlax-safearray->list
                  (progn
                    (vla-getBoundingBox obj 'll 'ur) (list ll ur)
                  )
                )
              )
            )
          )
        )
        (vla-put-PlotType aclay acWindow)
        (vla-PlottoDevice acplt nil)
      )
      (vla-delete ss)
    )
    (princ "\n--> No Tables Found <--")
  )

  (princ)
)

Rabbit

  • Guest
Re: Here's a challange; plotting tables
« Reply #5 on: February 11, 2011, 09:47:55 AM »
Okay, you went over my head there.  MAPCAR, LAMBDA and VLAX-INVOKE are the three worst areas for me.  For the life of me I can seem to figure those out, and I have tried many times.  With that said, I think I get the gest of your code.  It looks for tables using SSGET and then the VLAX-FOR OBJ allows for getting the plot window of each one, then plots that with the current plot settings.  I'm taking for granted that it uses the plot settings of the current space/tab that the table is in.

How close am I?

Sincerely,
Rabbit

<revision>
HOLY CRAP!!  With only a change to the SSGET to get the proper layer, this does exactly what I was talking about.  Dude, you didn't have to do it for me, but it's appreciated.  I would have never figured this out.  Hopefully I can reverse engineer it some to figure out what's going on.  Double thanks, once for helping me out and again for the code.  Very much appreciated!

Lee Mac

  • Seagull
  • Posts: 12922
  • London, England
Re: Here's a challange; plotting tables
« Reply #6 on: February 11, 2011, 11:27:43 AM »
Okay, you went over my head there.  MAPCAR, LAMBDA and VLAX-INVOKE are the three worst areas for me.  For the life of me I can seem to figure those out, and I have tried many times.  With that said, I think I get the gest of your code.  It looks for tables using SSGET and then the VLAX-FOR OBJ allows for getting the plot window of each one, then plots that with the current plot settings.  I'm taking for granted that it uses the plot settings of the current space/tab that the table is in.

Not bad  :-)

I'll admit, my code is slightly more obfuscated than it could be for the sake of not repeating expressions. I'll annotate the code so that you can see whats going on:

Code: [Select]
([color=BLUE]defun[/color] c:PlotTables

   [color=GREEN];; Define Function[/color]

  ( [color=BLUE]/[/color] acdoc aclay acplt ss ll ur )

  [color=GREEN];; Localise Variables[/color]
  [color=GREEN];; To understand why this is so important, read my tutorial at:[/color]
  [color=GREEN];; [/color]
  [color=GREEN];; www.lee-mac.com/localising.html[/color]
  [color=GREEN];; [/color]
  [color=GREEN];; ---------------------------------------------------------------------;;[/color]
  [color=GREEN];; Example courtesy of Lee Mac 2011  -  www.lee-mac.com                 ;;[/color]
  [color=GREEN];; ---------------------------------------------------------------------;;[/color]

  ([color=BLUE]vl-load-com[/color]) [color=GREEN];; Load the Visual LISP ActiveX Functionality[/color]

  ([color=BLUE]setq[/color] acdoc ([color=BLUE]vla-get-ActiveDocument[/color] ([color=BLUE]vlax-get-acad-object[/color]))  [color=GREEN];; Active Document Object[/color]
        aclay ([color=BLUE]vla-get-ActiveLayout[/color] acdoc)                     [color=GREEN];; Active Layout Object[/color]
        acplt ([color=BLUE]vla-get-Plot[/color] acdoc)                             [color=GREEN];; Plot Object[/color]
  )

  ([color=BLUE]if[/color] ([color=BLUE]ssget[/color] [color=MAROON]"_X"[/color] ([color=BLUE]list[/color] ([color=BLUE]cons[/color] 0 [color=MAROON]"ACAD_TABLE"[/color]) ([color=BLUE]cons[/color] 410 ([color=BLUE]getvar[/color] 'CTAB))))

    [color=GREEN];; If we can get a SelectionSet of all Tables in the current Layout[/color]
    [color=GREEN];; then do the following:[/color]
   
    ([color=BLUE]progn[/color]

      [color=GREEN];; Use the progn function to wrap the following statements into a single[/color]
      [color=GREEN];; expression that we can pass to the IF function to constitute the 'Then' argument.[/color]
     
      ([color=BLUE]vlax-for[/color] obj ([color=BLUE]setq[/color] ss ([color=BLUE]vla-get-ActiveSelectionSet[/color] acdoc))

        [color=GREEN];; Iterate through all objects in the Active SelectionSet[/color]
        [color=GREEN];; (i.e. the SelectionSet that we have just retrieved).[/color]

        [color=GREEN];; I approach it this way so that I don't have to convert Entity Names[/color]
        [color=GREEN];; into VLA-Objects but rather deal directly with the VLA-Objects.[/color]
       
        ([color=BLUE]apply[/color] '[color=BLUE]vlax-invoke[/color]
          ([color=BLUE]cons[/color] aclay
            ([color=BLUE]cons[/color] 'SetWindowtoPlot
              ([color=BLUE]mapcar[/color]
                ([color=BLUE]function[/color]
                  ([color=BLUE]lambda[/color] ( x ) ([color=BLUE]list[/color] ([color=BLUE]car[/color] x) ([color=BLUE]cadr[/color] x)))
                )
                ([color=BLUE]mapcar[/color] '[color=BLUE]vlax-safearray->list[/color]
                  ([color=BLUE]progn[/color]
                    ([color=BLUE]vla-getBoundingBox[/color] obj 'll 'ur) ([color=BLUE]list[/color] ll ur)
                  )
                )
              )
            )
          )
        )

        [color=GREEN];; OK, so this is a little more complicated than it needs to be.[/color]

        [color=GREEN];; Here's a step by step of the above:[/color]
        [color=GREEN];|

           (vla-getBoundingBox obj 'll 'ur) ;; Points are stored in variables 'll' and 'ur'

           ;; Then we are effectively doing this:

           (mapcar 'vlax-safearray->list (list ll ur))

           ;; Which is the same as:

           (list
             (vlax-safearray->list ll)
             (vlax-safearray->list ur)
           )

           ;; Which will return something like:

           ((1.23 4.56 0.0) (2.52 62.6 0.0))

           ;; We then convert these to 2D points as required by the
           ;; SetWindowtoPlot method:

           (mapcar
             (function
               (lambda ( x ) (list (car x) (cadr x)))
             )
             (list <LowerLeft> <UpperRight>)
           )

           ;; Which is equivalent to:

           (list
             (list (car  <LowerLeft>) (cadr  <LowerLeft>))
             (list (car <UpperRight>) (cadr <UpperRight>))
           )

           ;; Finally, I use vlax-invoke so that I don't have to
           ;; convert these points into Variants.

           ;; I use 'apply' since my arguments are in a list, but
           ;; I could have alternatively used:

           (vlax-invoke aclay 'SetWindowtoPlot
             (list (car  <LowerLeft>) (cadr  <LowerLeft>))
             (list (car <UpperRight>) (cadr <UpperRight>))
           )

           ;; Without the use of the 'apply' statement.
           |;[/color]
       
        ([color=BLUE]vla-put-PlotType[/color] aclay [color=BLUE]acWindow[/color])

        [color=GREEN];; Set the Plot Type of the Layout to a Window Plot[/color]
       
        ([color=BLUE]vla-PlottoDevice[/color] acplt [color=BLUE]nil[/color])

        [color=GREEN];; Perform the Plot using the current Plot Settings of the Layout[/color]
        [color=GREEN];; For specific plot settings we could replace 'nil' with the[/color]
        [color=GREEN];; name of a PC3 file.[/color]
       
      ) [color=GREEN];; End VLAX-FOR[/color]
     
      ([color=BLUE]vla-delete[/color] ss)

      [color=GREEN];; Delete the SelectionSet from the SelectionSets Collection[/color]
      [color=GREEN];; since we are finished with it.[/color]
     
    ) [color=GREEN];; End PROGN[/color]
   
    ([color=BLUE]princ[/color] [color=MAROON]"\n--> No Tables Found <--"[/color])

    [color=GREEN];; Else no Tables were found.[/color]
   
  ) [color=GREEN];; End IF[/color]

  ([color=BLUE]princ[/color])

  [color=GREEN];; Exit Cleanly.[/color]
 
) [color=GREEN];; End DEFUN[/color]


<revision>
HOLY CRAP!!  With only a change to the SSGET to get the proper layer, this does exactly what I was talking about.  Dude, you didn't have to do it for me, but it's appreciated.  I would have never figured this out.  Hopefully I can reverse engineer it some to figure out what's going on.  Double thanks, once for helping me out and again for the code.  Very much appreciated!

You're very welcome :-)

I enjoyed writing this one actually - I don't write too much code to plot things, so this was good practice for me too.

Rabbit

  • Guest
Re: Here's a challange; plotting tables
« Reply #7 on: February 11, 2011, 11:53:15 AM »
Seems I have some homework.  Time to take what you've taught me and start using it some more.  I do like the way that you handle the selection set.  I've always had to do it by stepping through the set with SSNAME and REPEAT and then having to convert enames to vla-objects.

Once again, THANKS!!
And thanks for the wisdom,
Rabbit

Lee Mac

  • Seagull
  • Posts: 12922
  • London, England
Re: Here's a challange; plotting tables
« Reply #8 on: February 11, 2011, 04:25:28 PM »
You're welcome Rabbit, have a good weekend!  :-)