Author Topic: dynamic block grid  (Read 1714 times)

0 Members and 1 Guest are viewing this topic.

ifncdylan

  • Guest
dynamic block grid
« on: October 17, 2016, 10:36:19 PM »
Hey all, long time!  :mrgreen:

I've written a routine that inserts a tonne of blocks in a grid format, based on some input. Basically the grid is a X,Y grid with position 1,1 being labelled AA up to position 26,26 which would be ZZ, along with a 'type' attribute for each block. Basically the grid represents a bank of underground conduits in real life - e.g. a bank of 16 100mm copper conduits labeled AA to DD.

Essentially I'm just calculating a base point and then adding up the width/height required to get the block inserted at the right location. It works, but it can insert hundreds blocks in one large grid which then becomes pretty difficult to select/move around, especially when it gets large and it's on top of linework.

I was wondering if there was a way to make a dynamic block that could display information dynamically from a set of attributes (even if its 1000 attributes) in a single block object rather than what is possibly over 700 blocks in a grid layout - it would make it way easier to work with after it's inserted! :)

Essentially it would just be drawing a grid of circles from one list of 'position references' (AA-ZZ) and inserting a text inside that circle if that 'position reference' is in another list. Is that possible with dynamic blocks, or is it too fancy? :)

ChrisCarlson

  • Guest
Re: dynamic block grid
« Reply #1 on: October 18, 2016, 08:06:35 AM »
An XY array is perfect for dynamic blocks.

dgorsman

  • Water Moccasin
  • Posts: 2437
Re: dynamic block grid
« Reply #2 on: October 18, 2016, 10:09:45 AM »
Only up to a certain point - I've had problems with using it for grid lines with a dotted linetype.
If you are going to fly by the seat of your pants, expect friction burns.

try {GreatPower;}
   catch (notResponsible)
      {NextTime(PlanAhead);}
   finally
      {MasterBasics;}

ronjonp

  • Needs a day job
  • Posts: 7529
Re: dynamic block grid
« Reply #3 on: October 18, 2016, 10:23:19 AM »
Maybe posting an example drawing would help explain exactly what you're looking for.

Windows 11 x64 - AutoCAD /C3D 2023

Custom Build PC

ifncdylan

  • Guest
Re: dynamic block grid
« Reply #4 on: October 18, 2016, 10:13:37 PM »
I should learn to post drawings with this kind of stuff  :uglystupid2:

Here's two basic grids that show the inputs and outputs required. Essentially the direction determines which side of the grid AA is on and the ducts/empty lists are the information used to make the grid of blocks up.

In the right box you can see a simple grid setup, it is just a bunch of P100 types with some "vacant" ducts in the mix. The type P100 goes in the center-bottom of the 'box' that makes up the P100 types (in this case the 'box' is position AA to DD, so the attribute goes in the middle there).

As you see in the left box, there is two different types, so the A100 types would be inserted and one of the attributes is then moved to the middle of that 'array' of ducts, then the C100 types have their own attribute centered on their 'base point' as well. I'm pretty sure I can't do this with my current approach.

The inputs are generated from a larger array of information, so if the way the information in those lists is organized stops it from being efficiently processed, then it can be changed in format easily. :)

This is the code I currently use to make the ducts, however it won't do stuff like what's in the left box, that was a manual one and something I'm hoping I could automate :)

Code - Auto/Visual Lisp: [Select]
  1. (defun dgrid ( tx ducts empty / width left up fleft fup tx vx lx)
  2.                  ((and (= tdir "e"))
  3.                   (vla-put-AttachmentPoint (vlax-ename->vla-object tx) 3)
  4.                   )
  5.                  ((and (= tdir "w"))
  6.                   (vla-put-AttachmentPoint (vlax-ename->vla-object tx) 1)
  7.                   )
  8.  
  9.   )
  10.   (setq width 2.7268
  11.         ductBlocks (list)
  12.         vx (vlax-ename->vla-object tx)
  13.         itemsInserted (list vx)
  14.         lx (vla-get-TextString vx)
  15.         inspt (vlax-safearray->list (vlax-variant-value (vla-get-InsertionPoint vx)))
  16.         attpt (vla-get-AttachmentPoint vx)
  17.         lastDuctRef (last ducts) ;(lastDuct ducts empty)
  18.         ducts (vl-remove-if '(lambda (a) (member a empty)) ducts) ; remove emptys
  19.         ;ducts (if (= "SINGLE-CONDUIT" (dxf "ROUTE_CONST" routeDetails))
  20.         ;       (list "AA")
  21.         ;       ducts) 
  22.        
  23.         maxw (- (ascii (substr lastDuctRef 1)) 64)
  24.         maxh (- (ascii (substr lastDuctRef 2)) 64)
  25.         base (shiftdown
  26.                (cond
  27.                  ((and (= dir "e") (= tdir "e")) ;; if the direction of the duct grid and which way we want the text justified dont match, we need to move the base point either way
  28.                   inspt
  29.                   )
  30.                  ((and (= dir "w") (= tdir "w"))
  31.                   inspt
  32.                   )
  33.                  ((and (= dir "e") (= tdir "w"))
  34.                   (shiftleft inspt (+ width (* width maxw)))
  35.                   )
  36.                  ((and (= dir "w") (= tdir "e")) ;; test.. 'east east'
  37.                   (shiftright inspt (+ width (* width maxw)))
  38.                   )
  39.                  
  40.  
  41.                 )
  42.  
  43.                
  44.                 (+ (* maxh width) (/ width 2))
  45.                )
  46.         )
  47.   (foreach i empty (if (not (member i ducts)) (makeDuct i " " base dir)))
  48.   (foreach i ducts (makeDuct i i base dir))
  49.   (makeLeader lastDuctRef base dir)
  50.   (entmod (append (vl-remove-if '(lambda ( x ) (member (car x) '(45 63 90 421 431 441))) (entget (vlax-vla-object->ename vx)))
  51.                            '((90 . 3) (63 . 256))
  52.                         (list (cons 45 1) '(441 . 0))
  53.                     )
  54.                 )
  55.  
  56. )
  57. (defun makeDuct (pos ref base dir / ip b ductRef ductType width)
  58.   (setq width 2.7268
  59.         y (- (ascii (substr pos 1)) 64)
  60.         x (- (ascii (substr pos 2)) 64)
  61.         ip (if (= dir "w")
  62.              (shiftup (shiftleft base (* width y)) (* width x))
  63.              (shiftup (shiftright base (* width y)) (* width x))
  64.             )
  65.         disp (if (= dir "w")
  66.                                          (* -1 (/ (- maxw 1) 2.0))
  67.                                          (/ (- maxw 1) 2.0)
  68.                                          )
  69.         b (if (and (< y 26) (> y -1) (< x 26) (> x -1)) (insertDuct ref ip))
  70.         ductBlocks (cons b ductBlocks)
  71.         )
  72.   (if (= "AA" pos) (progn
  73.     (vla-move
  74.       (setq att (nth 0
  75.                      (vlax-safearray->list
  76.                        (variant-value (vla-getattributes b))
  77.                      )
  78.                 )
  79.       )
  80.       (vlax-3d-point '(0.0 0.0 0.0))
  81.       (vlax-3d-point (list (* width disp) 0.0 0.0))
  82.     )
  83.     (vla-put-textString att dType)
  84.     )
  85.     )
  86. )
  87.  
  88. (defun makeLeader (pos base dir / ip)
  89.   (setq y (- (ascii (substr pos 1)) 64)
  90.         x (- (ascii (substr pos 2)) 64)
  91.         ip
  92.             (if (= dir "w")
  93.              (shiftup (shiftleft base (* maxw (/ width 2))) (+ (* width x) (/ width 2)))
  94.              (shiftup (shiftright base (/ width 2)) (+ (* width x) (/ width 2)))
  95.             )
  96.         )
  97. (setq pt1 (shiftup ip 1.6)
  98.       pt2 (shiftup (shiftdown ip (/ width 2)) 0.3)
  99.       pt3 (shiftleft (shiftdown ip (/ width 2)) 0.09)
  100.       ptlist (apply 'append (list pt1 pt2 pt3))
  101.       txtobj (vla-addmtext space (vlax-3d-point pt3) 0 "")
  102.       ldrobj (vlax-invoke space 'addleader ptlist txtobj acLineWithArrow)
  103.  )
  104.   (if (/= 1 gddScale) (vla-put-ScaleFactor ldrobj gddScale))
  105. (vla-delete txtobj)  
  106. (setq itemsInserted (append itemsInserted (list ldrobj)))
  107.  
  108. )
  109. (defun insertDuct (ref ip)
  110.         (setq thisdrawing (vla-get-activedocument
  111.                               (vlax-get-acad-object)))
  112.         (setq mspace (vla-get-modelspace thisdrawing))
  113.         (setq theblock (vla-InsertBlock mspace (vlax-3d-point ip)
  114.                               "DUCT" 1 1 1 0))
  115.         (LM:vl-setattributevalue theblock "DUCTREF" ref)
  116.         (setq itemsInserted (append itemsInserted (list theblock)))
  117.         theblock
  118. )
  119. (defun shiftleft ( pt dist / p1 p2 p3 ) (list (- (car pt) dist) (cadr pt) 0.0))
  120. (defun shiftright ( pt dist / p1 p2 p3 ) (list (+ (car pt) dist) (cadr pt) 0.0))
  121. (defun shiftup ( pt dist / p1 p2 p3 ) (list (car pt) (+ (cadr pt) dist) 0.0))
  122. (defun shiftdown ( pt dist / p1 p2 p3 ) (list (car pt) (- (cadr pt) dist) 0.0))
  123.  

ronjonp

  • Needs a day job
  • Posts: 7529
Re: dynamic block grid
« Reply #5 on: October 20, 2016, 01:02:04 PM »
Give the code below a try. This is how I'd structure the data & apply offset values using the text info.
Code - Auto/Visual Lisp: [Select]
  1. (defun c:ducts (/ att b bp dir ducts off ref spc)
  2.   ;; RJP 10.20.2016
  3.   ;; Example to place 'duct' blocks based off of offset values derived from ascii codes of text
  4.   ;; Block offset distance ( from example drawing )
  5.   (setq off 5.453578)
  6.   (or *ductdirection* (setq *ductdirection* "1-RightUp"))
  7.   (initget 0 "1-RightUp 2-RightDown 3-LeftUp 4-LeftDown")
  8.   (setq   *ductdirection*
  9.     (cond
  10.       ((getkword
  11.          (strcat "\nDuct Direction [1-RightUp/2-RightDown/3-LeftUp/4-LeftDown] <"
  12.             *ductdirection*
  13.             ">: "
  14.          )
  15.        )
  16.       )
  17.       (*ductdirection*)
  18.     )
  19.   )
  20.   (setq
  21.     dir   (cdr (assoc (atof *ductdirection*)
  22.           (list (list 1.0 '(+ +)) (list 2.0 '(+ -)) (list 3.0 '(- +)) (list 4.0 '(- -)))
  23.         )
  24.    )
  25.   )
  26.   (if (and ;; Get start point
  27.       (or (setq bp (getpoint "\nPick a base point: ")) (setq bp '(0. 0. 0.)))
  28.       ;; Data structure
  29.       (setq ducts '(("P100" ("AA" "AB" "AC" "AD" "AB" "BB" "CA" "CD" "DB" "DC" "DD"))
  30.           ("EMPTY" ("BC" "BD" "CB" "CC" "CD"))
  31.          )
  32.       )
  33.       ;; Get the smallest string value
  34.       (setq ref (vl-string->list (car (vl-sort (apply 'append (mapcar 'cadr ducts)) '<))))
  35.       ;; Make a list of strings & offset numbers that will be multiplied by 'off' variable above
  36.       ;; These numbers can be modified with + - to get the desired offset direction
  37.       (setq ducts (mapcar '(lambda (x) (cons x (mapcar '- (vl-string->list x) ref)))
  38.                 (apply 'append (mapcar 'cadr ducts))
  39.              )
  40.       )
  41.       ;; Current space to insert attributed block below
  42.                 (if (= (getvar 'cvport) 1)
  43.              'paperspace
  44.              'modelspace
  45.                 )
  46.            )
  47.       )
  48.       )
  49.     (foreach duct ducts
  50.       ;;Try to insert block if it's defined
  51.       (if (and (tblobjname "block" "duct")
  52.           (setq b (vla-insertblock
  53.           spc
  54.           (vlax-3d-point
  55.             (list ((eval (caar dir)) (car bp) (* off (cadr duct)))
  56.              ((eval (cadar dir)) (cadr bp) (* off (caddr duct)))
  57.              (caddr bp)
  58.             )
  59.           )
  60.           "duct"
  61.           2.
  62.           2.
  63.           2.
  64.           0.
  65.              )
  66.           )
  67.           ;; Get the attribute to add the text to
  68.           (setq att (car (vl-remove-if-not
  69.             '(lambda (x) (= "DUCTREF" (vla-get-tagstring x)))
  70.             (vlax-invoke b 'getattributes)
  71.                )
  72.           )
  73.           )
  74.      )
  75.    ;; Fill in the value
  76.      att
  77.      (if (member (car duct) (cadr (assoc "EMPTY" ducts)))
  78.        ""
  79.        (car duct)
  80.      )
  81.    )
  82.       )
  83.     )
  84.   )
  85.   (princ)
  86. )
« Last Edit: October 21, 2016, 02:35:21 PM by ronjonp »

Windows 11 x64 - AutoCAD /C3D 2023

Custom Build PC

ifncdylan

  • Guest
Re: dynamic block grid
« Reply #6 on: October 21, 2016, 10:30:11 PM »
Thanks Ron! That's a much better way to deal with the offsetting and it performs a whole lot quicker too.

My next challenge is to deal with the groupings on the left example. I'm thinking of perhaps drawing a bounding box around all P100 type blocks and then putting the P100 text at the bottom center of that box.

That will probably be a lot easier to achieve with Ron's code :)

ronjonp

  • Needs a day job
  • Posts: 7529
Re: dynamic block grid
« Reply #7 on: October 21, 2016, 11:32:08 PM »
Thanks Ron! That's a much better way to deal with the offsetting and it performs a whole lot quicker too.

My next challenge is to deal with the groupings on the left example. I'm thinking of perhaps drawing a bounding box around all P100 type blocks and then putting the P100 text at the bottom center of that box.

That will probably be a lot easier to achieve with Ron's code :)
Glad to help :) .. perhaps you could find the 'base' of each scenario & fill that in. Seems like that would get the point across.


Windows 11 x64 - AutoCAD /C3D 2023

Custom Build PC

ifncdylan

  • Guest
Re: dynamic block grid
« Reply #8 on: October 26, 2016, 09:11:28 AM »
I'm trying to set that up this week, we've had some new work come in so I've been preparing for that. I think the main thing would be ability to set an attribute on the center block of a set, how to figure out which one that is is what's eluding me so far.