Python + AutoCAD : Grid Lines Automation

Python + AutoCAD : Grid Lines Automation

Python is a wonderful programming language, infact one which is the closest to the human's English lanuage. Learning Python and doing stuff using Python is real fun. The simplicity of the syntax itself is what makes it more attractive. For example check out this statement;

buy_milk() if cash_in_hand > 20 else buy_chocolate()        

Except for those brackets, and if you know the '>' stands for 'greater than', you can easily understand the meaning of the above statement. But what if I say, this is a valid line of code in Python? However, it is as easy as that to learn Python. Today Python is the most popular programming language used in AI and Machine Learning. Simple yet Extrmely Powerful...! There is a very huge community of Python users that you will a library or package for almost anything under the sun..!!

Well, comming to today's topic. Many of my friends who work on AutoCAD and who have tried atleast some automation in AutoCAD with Python, should have heard about the Python library called 'pyautocad'. If not, I would stringly recommend you to have a look at the documentation given below;

I wrote a small function in Python to generate an alpabetical sequence from a given number. For example, if 1 passed as argument to the function, it returns the alphabet 'A'. if 26 is passed into it, it returns 'Z'. Simillarly, 27 gives you 'AA' and 52 gives 'AZ', 53 gives 'BA'...... 703 gives 'ZZ' and so on ... So I thought of sharing it with you all. I am sure there is scope for improvement in this function, but let me leave that to you to try...! Here is the function;

def get_grid_number(n, result = '')
    if 1 <= n <= 26:
        result += chr(n + 64)
        return result
    if n // 26 > 26:
        result += 'Z'
        n -= 677
        return get_grid_number(n, result)
    else:
        result += chr(((n - 1) //  26) + 64)
        if n % 26 == 0: 
            result += 'Z'
        else:
            result += chr((n % 26) + 64)
        return result:        

After writing this, I thought of automating the task of drawing grids in AutoCAD and changed the function name to get_grid_number. I used pyautocad for this.

The program would keep asking you for offset of next grid line from the last one, for horizontal and vertical grids seperately. Starting grid value is set to 0 for both directions. It will first ask you to enter the distances between Horizontal Grids. Keep entering the distance to the next horizontal grid. The program keeps showing you the list of values you have entered. Once done, enter 0 (zero) to stop entering the horizontal grid offsets.

No alt text provided for this image

Now it will start asking for distances between Vertical Grids. Once finished entering the vertical grid offsets, enter 0.

No alt text provided for this image

The program will show a summary of the values you have entered.

No alt text provided for this image

... and it draws all the grids with the bubbles and numbers

No alt text provided for this image

Let us check if the measurements are correct

No alt text provided for this image

Done...!!!

I know there are several improvements possible for this, for example, by using a grid bubble block with attribute instead of just circle and text, placing the bubbles and line in a their layers , create the layers if not exist, etc... I just wanted to inpire you all to learn Python and start exploring the endless possibilities. All the best...!!!

IMPORTANT : The program will first erase everything in the file unless you comment the line doc.SendCommand('erase all  '). So I would recommend try it on a fresh blank new file.

Here is the complete code;

import os
os.system('cls')


from pyautocad import Autocad, APoint, ACAD
acad = Autocad(True)
model = acad.model
doc = acad.ActiveDocument


doc.SendCommand('erase all  ')


def get_grid_number(n, result = ''):
    if 1 <= n <= 26:
        result += chr(n + 64)
        return result
    if n // 26 > 26:
        result += 'Z'
        n -= 677
        return get_grid_number(n, result)
    else:
        result += chr(((n - 1) //  26) + 64)
        if n % 26 == 0: 
            result += 'Z'
        else:
            result += chr((n % 26) + 64)
        return result


rowOffsets = [0.0]
columnOffsets = [0.0]


os.system('cls')
while True:
    print('Distance between Horizontal Grids')
    print(f'{", ".join([str(d) for d in  rowOffsets])}')
    try:
        r = float(input('Enter distance to next horizontal grid : (0 to finish rows)'))
        if r == 0:
            break
        else:
            rowOffsets.append(r)
    except ValueError:
        print('please enter a decimal value, or 0 to finish entering rows')



os.system('cls')
while True:
    print('Distance between Vertical Grids')
    print(f'{", ".join([str(d) for d in  columnOffsets])}')
    try:
        c = float(input('Enter distance to next vertical grid : (0 to finish columns)'))
        if c == 0:
            break
        else:
            columnOffsets.append(c)
    except ValueError:
        print('please enter a decimal value, or 0 to finish entering columns')


os.system('cls')


print('Horizontal grids offset values')
print(f'{", ".join([str(d) for d in  rowOffsets])}')
    
print('Vertical grids offset values')
print(f'{", ".join([str(d) for d in  columnOffsets])}')


c_sum = sum(columnOffsets)
r_sum = sum(rowOffsets)


all_vals = list(set(rowOffsets + columnOffsets))
min_val = all_vals[1] / 2


hlinelength = c_sum + min_val * 4
vlinelength = r_sum + min_val * 4
textHeight = min_val * 0.5
bubbleRadius = min_val
sx = 0
sy = 0 - min_val * 2
ex = sx
ey = sy + vlinelength
for i, c in  enumerate(columnOffsets):
    sx += c
    ex = sx
    sp = APoint(sx, sy)
    ep = APoint(ex, ey)
    line = model.AddLine(sp, ep)
    center = APoint(ex, ey + bubbleRadius)
    bubble = model.AddCircle(center, bubbleRadius)
    text = model.AddText(str(i + 1), center, textHeight)
    text.Alignment = ACAD.acAlignmentCenter
    text.HorizontalAlignment = 1
    text.VerticalAlignment = 2
    text.TextAlignmentPoint = center
doc.Regen(0)


sx = 0 - min_val * 2
sy = 0
ex = sx + hlinelength
ey = sy
for i, r in enumerate(rowOffsets):
    sy += r
    ey = sy 
    sp = APoint(sx, sy)
    ep = APoint(ex, ey)
    line = model.AddLine(sp, ep)
    center = APoint(sx - bubbleRadius, sy)
    bubble = model.AddCircle(center, bubbleRadius)
    text = model.AddText(get_grid_number(i + 1), center, textHeight)
    text.Alignment = ACAD.acAlignmentCenter
    text.HorizontalAlignment = 1
    text.VerticalAlignment = 2
    text.TextAlignmentPoint = center


doc.Regen(0)
        

To view or add a comment, sign in

More articles by Harilal MN

  • Revit API : A study on Oriented Bounding Boxes

    As we all know, the BoundingBoxXYZ in Revit API gives Axis Aligned Bounding Boxes. This is an effort to create an…

    18 Comments
  • Revit API : Extension Methods to Visualize Point, Line and CurveLoop

    While working on Revit API, many times it becomes a strong requirement to visualize a Point (XYZ), a Curve or a…

    6 Comments
  • Revolutions

    The Original Post is here..

  • The Revit Tree

    Let me try to explain the code behind. I created this in the Macro environment.

    1 Comment
  • The Newyear Countdown

    Here I convert the timespan between Newyear and current time and draw lines for each digit, sweep cylinders along the…

    1 Comment

Others also viewed

Explore content categories