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.
Now it will start asking for distances between Vertical Grids. Once finished entering the vertical grid offsets, enter 0.
Recommended by LinkedIn
The program will show a summary of the values you have entered.
... and it draws all the grids with the bubbles and numbers
Let us check if the measurements are correct
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)
Konstantinos Kyrtsonis