Newer
Older
import bpy
from bpy_extras import object_utils
from math import (
pi, sin,
cos,
)
from bpy.props import (
IntProperty,
BoolProperty,
BoolVectorProperty,
FloatProperty,
FloatVectorProperty,
)
class honeycomb_geometry():
def __init__(self, rows, cols, D, E):
self.rows = rows
self.cols = cols
self.D = D
self.E = E
CoDEmanX
committed
CoDEmanX
committed
CoDEmanX
committed
self.d = self.a * self.D
self.hd = 0.5 * self.d
self.e = self.hE / self.a
self.he = 0.5 * self.e
self.r = self.R - self.e
self.hr = 0.5 * self.r
CoDEmanX
committed
self.H = self.R * (1.5 * self.rows + 0.5) + self.e
if self.rows > 1:
self.W = self.d * (self.cols + 0.5) + self.E
else:
self.W = self.d * self.cols + self.E
CoDEmanX
committed
CoDEmanX
committed
self.sy = -self.hH + self.he + self.R
self.sx = -self.hW + self.hE + self.hd
CoDEmanX
committed
CoDEmanX
committed
CoDEmanX
committed
if row >= 0 and row < self.rows and col >= 0 and col < self.cols:
return [0, 1, 2, 3, 4, 5]
if row == -1 and col == self.cols - 1:
return [1, 2]
if row == 0 and self.rows > 1 and col == self.cols:
return [1, 2, 3]
if row == -1 and col == -1:
return [0, 1]
if row == self.rows and col == -1:
return [4, 5]
if row == self.rows and col == self.cols - 1:
return [3, 4]
if row == self.rows - 1 and self.rows > 1 and col == self.cols:
return [2, 3, 4]
if row == self.rows and col == 0:
return [4, 5]
if row == self.rows - 1 and self.rows > 1 and col == -1:
return [0, 4, 5]
if row == self.rows and col == self.cols:
return [3, 4]
# horizontal lines
if col >= 0 and col < self.cols:
if row == -1:
return [0, 1, 2]
if row == self.rows:
return [3, 4, 5]
# vertical lines
if row >= 0 and row < self.rows:
if col == -1:
if row % 2:
return [0, 1, 4, 5]
else:
return [0, 5]
if row % 2 or self.rows == 1:
return [2, 3]
else:
return [1, 2, 3, 4]
CoDEmanX
committed
cp = [self.sx + self.dx * col, self.sy + self.dy * row, 0] # central point
if row % 2:
cp[0] += self.gx
co = [] # vertices coords
CoDEmanX
committed
a = pi / 6 + i * pi / 3 # angle
ap[i] = idx + len(co)
co.append((cp[0] + cos(a) * self.r, cp[1] + sin(a) * self.r, cp[2]))
return co, ap
CoDEmanX
committed
def generate(self):
ar = 1
ac = 1
cells = []
verts = []
faces = []
CoDEmanX
committed
for row in range(-ar, self.rows + ar):
level = []
for col in range(-ac, self.cols + ac):
co, ap = self.cell(row, col, len(verts))
verts += co
level.append(ap)
cells.append(level)
CoDEmanX
committed
# bottom row
row = 0
for col in range(1, len(cells[row]) - 1):
s = cells[row][col]
l = cells[row][col - 1]
u = cells[row + 1][col]
CoDEmanX
committed
faces.append((s[1], u[5], u[4], s[2]))
faces.append((s[2], u[4], l[0]))
# top row
row = len(cells) - 1
cs = 0
for col in range(1 + cs, len(cells[row]) - 1):
s = cells[row][col]
l = cells[row][col - 1]
d = cells[row - 1][col - cs]
faces.append((s[3], l[5], d[1]))
faces.append([s[3], d[1], d[0], s[4]])
CoDEmanX
committed
# middle rows
for row in range(1, len(cells) - 1):
cs = 0
for col in range(1, len(cells[row]) - 1):
s = cells[row][col]
l = cells[row][col - 1]
u = cells[row + 1][col - cs]
d = cells[row - 1][col - cs]
CoDEmanX
committed
faces.append((s[1], u[5], u[4], s[2]))
faces.append((s[2], u[4], l[0]))
faces.append([s[2], l[0], l[5], s[3]])
faces.append((s[3], l[5], d[1]))
faces.append([s[3], d[1], d[0], s[4]])
CoDEmanX
committed
# right column
row = 0
col = len(cells[row]) - 1
for row in range(1, len(cells) - 1):
cs = 0
CoDEmanX
committed
s = cells[row][col]
l = cells[row][col - 1]
u = cells[row + 1][col - cs]
d = cells[row - 1][col - cs]
CoDEmanX
committed
if row % 2 and row < len(cells) - 2:
faces.append((s[1], u[5], u[4], s[2]))
faces.append((s[2], u[4], l[0]))
faces.append([s[2], l[0], l[5], s[3]])
faces.append((s[3], l[5], d[1]))
if row % 2 and row > 1:
faces.append([s[3], d[1], d[0], s[4]])
CoDEmanX
committed
# final fix
if not self.rows % 2:
row = len(cells) - 1
s = cells[row][col]
l = cells[row][col - 1]
d = cells[row - 1][col - 1]
faces.append((s[3], l[5], d[1]))
faces.append([s[3], d[1], d[0], s[4]])
CoDEmanX
committed
return verts, faces
def edge_max(diam):
return diam * sin(pi / 3)
bl_idname = "mesh.honeycomb_add"
bl_label = "Add HoneyComb"
bl_description = "Simple honeycomb mesh generator"
CoDEmanX
committed
def fix_edge(self, context):
m = edge_max(self.diam)
if self.edge > m:
self.edge = m
name="Num of rows",
default=2,
min=1, max=100,
description='Number of the rows'
)
name='Num of cols',
default=2,
min=1, max=100,
description='Number of the columns'
)
layers = BoolVectorProperty(
name="Layers",
size=20,
subtype='LAYER',
options={'HIDDEN', 'SKIP_SAVE'},
)
name='Cell Diameter',
default=1.0,
min=0.0, update=fix_edge,
description='Diameter of the cell'
)
name='Edge Width',
default=0.1,
min=0.0, update=fix_edge,
description='Width of the edge'
)
name="Align to View",
default=False
)
name="Location",
subtype='TRANSLATION'
)
name="Rotation",
subtype='EULER'
)
CoDEmanX
committed
@classmethod
def poll(cls, context):
return context.scene is not None
CoDEmanX
committed
def execute(self, context):
mesh = bpy.data.meshes.new(name='honeycomb')
CoDEmanX
committed
comb = honeycomb_geometry(self.rows, self.cols, self.diam, self.edge)
verts, faces = comb.generate()
CoDEmanX
committed
mesh.from_pydata(vertices=verts, edges=[], faces=faces)
CoDEmanX
committed
object_utils.object_data_add(context, mesh, operator=self)
CoDEmanX
committed