Monday, May 8, 2017

A dynamic block that reads tree trunk and drip diameters from Civil 3D COGO Points


A dynamic block that reads tree trunk and drip diameters from Civil 3D COGO Points



This blog is being written while I develop a workflow that allows a land surveyor to import points, having different values for trunk and drip diameters, and have AutoCAD insert a dynamic block whose trunk and drip lines can be scaled independently of one another. This workflow will rely on AutoLISP programming to automate the insertion and scaling of the blocks, based on the values obtained from the points.

Create the dynamic block

I will start by creating the dynamic block. My block has simple objects, a circle and a hexagon,but you can dress yours up. The diameter is 1. This is important. Also, notice the center of the circle is at 0,0, the block's insertion and scale point.




I created a Linear Parameter for Drip and another for Trunk. I used quadrants of the circle as the snapped control points for both Parameters.

Then I added a Scale Action to each Parameter. I changed the properties of the Actions, changing the base type to Independent and being sure Base X and Base Y are both set to 0.





The point description 

For this workflow, I am going to use point raw description in the same way as Description Keys. The LISP routine is going to expect "TREE 12 36" in the description field to represent a tree with 12 inch trunk and 36 foot drip.

If you prefer to use User Defined Properties for Points (UDP), that is certainly a legitimate way of doing this.Your LISP will be different than mine.

The trunks have been input in inches, and my LISP routine will account for this. Here's what my descriptions look like:


Let's import the points and then we can get to programming, the fun part of all this.





Using LISP to marry the dynamic blocks to the COGO Points


So we have the points, and the descriptions are correct. Now we write the program that will marry the dynamic blocks to the points. 



(vl-load-com)

(defun c:go ( / pts len ctr pt obnam desc)
  (prompt "Select Points: ")
  (setq pts (ssget)
len (sslength pts)
ctr 0
  )

  (while (< ctr len)
    (setq pt (vlax-ename->vla-object (ssname pts ctr))
 obnam (vlax-get pt 'ObjectName)
    )
    (if (= obnam "AeccDbCogoPoint")
      (progn
(setq desc (vlax-get pt 'RawDescription))
(if (= (strcase (substr desc 1 4)) "TREE")
 (progn
(GetTrunk desc)
(InsBlock trunk drip)
))
      )
    )
    (setq ctr (1+ ctr))
  )

) ;end defun c:go



(defun GetTrunk (str / len txstr len stpt space1 space2)  
    (setq space1 (vl-string-position (ascii " ") str 0))
    (setq trunk (substr str (+ 2 space1) 2))
    (setq drip (substr str (+ space1 5) 2))
   (princ)
);end defun



;function to insert the block

(defun InsBlock (trunk drip / trunk drip)
  (setq pt-ins (list (vlax-get pt 'Easting)
    (vlax-get pt 'Northing)
    )
)
  (vl-cmdf "insert" "tree" pt-ins "1" "1" "0")
  (setq ob (entlast))
  (TreeSizer ob trunk drip)
  )
;next step is to modify the two parameters using the trunk and drip.


;--------------------function to modify block parameters to scale for trunk and drip
  
(defun TreeSizer (blk trunk drip / blkv dynprops trunksize dripsize)
  (setq blkv (vlax-ename->vla-object blk))
  (setq DynProps (vlax-invoke blkv 'GetDynamicBlockProperties))
  (setq Trunksize (nth 2 dynprops))

  (setq Dripsize (nth 0 dynprops))
  
  
  (vlax-put-property
    Trunksize
    'Value
    (vlax-make-variant (* (atof trunk) 0.08333333) vlax-vbDouble) ;this applies ft to inch scale factor
    )
  (vlax-put-property
    Dripsize
    'Value
    (vlax-make-variant drip vlax-vbDouble)
    )
) ;end defun

I use c:go so I can start the program by typing Go at the command line. Replace the word Go with what you want to type to make it run.

The main routine calls a couple of functions: GetTrunk takes the point description and separates the trunk diameter from the drip diameter TreeSizer accepts block name, trunk size and drip size and then modifies the dynamic block properties accordingly. InsBlock is used to insert and then modify the block.

Run it and you get this:


This is a proof of concept. The LISP can be modified to accommodate other tree types, so if you separate out by Oak, Pine, etc., it would be easy to make this work for you. If you need help, call me in California: 530.221.2994