Newer
Older
Spivak Vladimir (cwolf3d)
committed
from bpy_extras import object_utils
from math import (
pi, sin,
cos,
)
from bpy.props import (
IntProperty,
BoolProperty,
BoolVectorProperty,
FloatProperty,
FloatVectorProperty,
Spivak Vladimir (cwolf3d)
committed
StringProperty,
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)
Spivak Vladimir (cwolf3d)
committed
class add_mesh_honeycomb(bpy.types.Operator, object_utils.AddObjectHelper):
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
Spivak Vladimir (cwolf3d)
committed
HoneyComb : BoolProperty(name = "HoneyComb",
default = True,
description = "HoneyComb")
change : BoolProperty(name = "Change",
default = False,
description = "change HoneyComb")
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'
)
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'
)
CoDEmanX
committed
Spivak Vladimir (cwolf3d)
committed
def draw(self, context):
layout = self.layout
layout.prop(self, 'rows', expand=True)
layout.prop(self, 'cols', expand=True)
layout.prop(self, 'diam', expand=True)
layout.prop(self, 'edge', expand=True)
if self.change == False:
col = layout.column(align=True)
col.prop(self, 'align', expand=True)
col = layout.column(align=True)
col.prop(self, 'location', expand=True)
col = layout.column(align=True)
col.prop(self, 'rotation', expand=True)
@classmethod
def poll(cls, context):
return context.scene is not None
CoDEmanX
committed
# turn off 'Enter Edit Mode'
use_enter_edit_mode = bpy.context.preferences.edit.use_enter_edit_mode
bpy.context.preferences.edit.use_enter_edit_mode = False
Spivak Vladimir (cwolf3d)
committed
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
if bpy.context.mode == "OBJECT":
if context.selected_objects != [] and context.active_object and \
('HoneyComb' in context.active_object.data.keys()) and (self.change == True):
obj = context.active_object
oldmesh = obj.data
oldmeshname = obj.data.name
comb = honeycomb_geometry(self.rows, self.cols, self.diam, self.edge)
verts, faces = comb.generate()
mesh = bpy.data.meshes.new('HoneyComb')
mesh.from_pydata(verts, [], faces)
obj.data = mesh
for material in oldmesh.materials:
obj.data.materials.append(material)
bpy.data.meshes.remove(oldmesh)
obj.data.name = oldmeshname
else:
comb = honeycomb_geometry(self.rows, self.cols, self.diam, self.edge)
verts, faces = comb.generate()
mesh = bpy.data.meshes.new('HoneyComb')
mesh.from_pydata(verts, [], faces)
obj = object_utils.object_data_add(context, mesh, operator=self)
obj.data["HoneyComb"] = True
obj.data["change"] = False
for prm in HoneyCombParameters():
obj.data[prm] = getattr(self, prm)
Spivak Vladimir (cwolf3d)
committed
if bpy.context.mode == "EDIT_MESH":
active_object = context.active_object
name_active_object = active_object.name
bpy.ops.object.mode_set(mode='OBJECT')
comb = honeycomb_geometry(self.rows, self.cols, self.diam, self.edge)
verts, faces = comb.generate()
mesh = bpy.data.meshes.new('HoneyComb')
mesh.from_pydata(verts, [], faces)
obj = object_utils.object_data_add(context, mesh, operator=self)
Spivak Vladimir (cwolf3d)
committed
obj.select_set(True)
active_object.select_set(True)
bpy.ops.object.join()
context.active_object.name = name_active_object
bpy.ops.object.mode_set(mode='EDIT')
CoDEmanX
committed
if use_enter_edit_mode:
bpy.ops.object.mode_set(mode = 'EDIT')
# restore pre operator state
bpy.context.preferences.edit.use_enter_edit_mode = use_enter_edit_mode