1 # SPDX-License-Identifier: GPL-2.0-or-later
6 from bpy_extras
import object_utils
11 from bpy
.props
import (
21 class honeycomb_geometry():
22 def __init__(self
, rows
, cols
, D
, E
):
28 self
.hE
= 0.5 * self
.E
33 self
.d
= self
.a
* self
.D
34 self
.hd
= 0.5 * self
.d
35 self
.e
= self
.hE
/ self
.a
36 self
.he
= 0.5 * self
.e
37 self
.r
= self
.R
- self
.e
38 self
.hr
= 0.5 * self
.r
40 self
.H
= self
.R
* (1.5 * self
.rows
+ 0.5) + self
.e
42 self
.W
= self
.d
* (self
.cols
+ 0.5) + self
.E
44 self
.W
= self
.d
* self
.cols
+ self
.E
46 self
.hH
= 0.5 * self
.H
47 self
.hW
= 0.5 * self
.W
49 self
.sy
= -self
.hH
+ self
.he
+ self
.R
50 self
.sx
= -self
.hW
+ self
.hE
+ self
.hd
54 self
.dy
= 1.5 * self
.R
57 def vert(self
, row
, col
):
59 if row
>= 0 and row
< self
.rows
and col
>= 0 and col
< self
.cols
:
60 return [0, 1, 2, 3, 4, 5]
62 if row
== -1 and col
== self
.cols
- 1:
64 if row
== 0 and self
.rows
> 1 and col
== self
.cols
:
67 if row
== -1 and col
== -1:
71 if row
== self
.rows
and col
== -1:
74 if row
== self
.rows
and col
== self
.cols
- 1:
76 if row
== self
.rows
- 1 and self
.rows
> 1 and col
== self
.cols
:
80 if row
== self
.rows
and col
== 0:
82 if row
== self
.rows
- 1 and self
.rows
> 1 and col
== -1:
85 if row
== self
.rows
and col
== self
.cols
:
88 if col
>= 0 and col
< self
.cols
:
94 if row
>= 0 and row
< self
.rows
:
101 if row
% 2 or self
.rows
== 1:
107 def cell(self
, row
, col
, idx
):
108 cp
= [self
.sx
+ self
.dx
* col
, self
.sy
+ self
.dy
* row
, 0] # central point
111 co
= [] # vertices coords
112 vi
= self
.vert(row
, col
)
116 a
= pi
/ 6 + i
* pi
/ 3 # angle
117 ap
[i
] = idx
+ len(co
)
118 co
.append((cp
[0] + cos(a
) * self
.r
, cp
[1] + sin(a
) * self
.r
, cp
[2]))
129 for row
in range(-ar
, self
.rows
+ ar
):
131 for col
in range(-ac
, self
.cols
+ ac
):
132 co
, ap
= self
.cell(row
, col
, len(verts
))
139 for col
in range(1, len(cells
[row
]) - 1):
141 l
= cells
[row
][col
- 1]
142 u
= cells
[row
+ 1][col
]
144 faces
.append((s
[1], u
[5], u
[4], s
[2]))
145 faces
.append((s
[2], u
[4], l
[0]))
152 for col
in range(1 + cs
, len(cells
[row
]) - 1):
154 l
= cells
[row
][col
- 1]
155 d
= cells
[row
- 1][col
- cs
]
156 faces
.append((s
[3], l
[5], d
[1]))
157 faces
.append([s
[3], d
[1], d
[0], s
[4]])
160 for row
in range(1, len(cells
) - 1):
164 for col
in range(1, len(cells
[row
]) - 1):
166 l
= cells
[row
][col
- 1]
167 u
= cells
[row
+ 1][col
- cs
]
168 d
= cells
[row
- 1][col
- cs
]
170 faces
.append((s
[1], u
[5], u
[4], s
[2]))
171 faces
.append((s
[2], u
[4], l
[0]))
172 faces
.append([s
[2], l
[0], l
[5], s
[3]])
173 faces
.append((s
[3], l
[5], d
[1]))
174 faces
.append([s
[3], d
[1], d
[0], s
[4]])
178 col
= len(cells
[row
]) - 1
179 for row
in range(1, len(cells
) - 1):
185 l
= cells
[row
][col
- 1]
186 u
= cells
[row
+ 1][col
- cs
]
187 d
= cells
[row
- 1][col
- cs
]
189 if row
% 2 and row
< len(cells
) - 2:
190 faces
.append((s
[1], u
[5], u
[4], s
[2]))
191 faces
.append((s
[2], u
[4], l
[0]))
192 faces
.append([s
[2], l
[0], l
[5], s
[3]])
193 faces
.append((s
[3], l
[5], d
[1]))
194 if row
% 2 and row
> 1:
195 faces
.append([s
[3], d
[1], d
[0], s
[4]])
198 if not self
.rows
% 2:
201 l
= cells
[row
][col
- 1]
202 d
= cells
[row
- 1][col
- 1]
203 faces
.append((s
[3], l
[5], d
[1]))
204 faces
.append([s
[3], d
[1], d
[0], s
[4]])
210 return diam
* sin(pi
/ 3)
213 class add_mesh_honeycomb(bpy
.types
.Operator
, object_utils
.AddObjectHelper
):
214 bl_idname
= "mesh.honeycomb_add"
215 bl_label
= "Add HoneyComb"
216 bl_description
= "Simple honeycomb mesh generator"
217 bl_options
= {'REGISTER', 'UNDO'}
219 def fix_edge(self
, context
):
220 m
= edge_max(self
.diam
)
224 HoneyComb
: BoolProperty(name
= "HoneyComb",
226 description
= "HoneyComb")
227 change
: BoolProperty(name
= "Change",
229 description
= "change HoneyComb")
235 description
='Number of the rows'
241 description
='Number of the columns'
244 name
='Cell Diameter',
246 min=0.0, update
=fix_edge
,
247 description
='Diameter of the cell'
252 min=0.0, update
=fix_edge
,
253 description
='Width of the edge'
256 def draw(self
, context
):
259 layout
.prop(self
, 'rows', expand
=True)
260 layout
.prop(self
, 'cols', expand
=True)
261 layout
.prop(self
, 'diam', expand
=True)
262 layout
.prop(self
, 'edge', expand
=True)
264 if self
.change
== False:
265 col
= layout
.column(align
=True)
266 col
.prop(self
, 'align', expand
=True)
267 col
= layout
.column(align
=True)
268 col
.prop(self
, 'location', expand
=True)
269 col
= layout
.column(align
=True)
270 col
.prop(self
, 'rotation', expand
=True)
273 def poll(cls
, context
):
274 return context
.scene
is not None
276 def execute(self
, context
):
277 # turn off 'Enter Edit Mode'
278 use_enter_edit_mode
= bpy
.context
.preferences
.edit
.use_enter_edit_mode
279 bpy
.context
.preferences
.edit
.use_enter_edit_mode
= False
281 if bpy
.context
.mode
== "OBJECT":
282 if context
.selected_objects
!= [] and context
.active_object
and \
283 (context
.active_object
.data
is not None) and ('HoneyComb' in context
.active_object
.data
.keys()) and \
284 (self
.change
== True):
285 obj
= context
.active_object
287 oldmeshname
= obj
.data
.name
288 comb
= honeycomb_geometry(self
.rows
, self
.cols
, self
.diam
, self
.edge
)
289 verts
, faces
= comb
.generate()
290 mesh
= bpy
.data
.meshes
.new('HoneyComb')
291 mesh
.from_pydata(verts
, [], faces
)
293 for material
in oldmesh
.materials
:
294 obj
.data
.materials
.append(material
)
295 bpy
.data
.meshes
.remove(oldmesh
)
296 obj
.data
.name
= oldmeshname
298 comb
= honeycomb_geometry(self
.rows
, self
.cols
, self
.diam
, self
.edge
)
299 verts
, faces
= comb
.generate()
300 mesh
= bpy
.data
.meshes
.new('HoneyComb')
301 mesh
.from_pydata(verts
, [], faces
)
302 obj
= object_utils
.object_data_add(context
, mesh
, operator
=self
)
304 obj
.data
["HoneyComb"] = True
305 obj
.data
["change"] = False
306 for prm
in HoneyCombParameters():
307 obj
.data
[prm
] = getattr(self
, prm
)
309 if bpy
.context
.mode
== "EDIT_MESH":
310 active_object
= context
.active_object
311 name_active_object
= active_object
.name
312 bpy
.ops
.object.mode_set(mode
='OBJECT')
313 comb
= honeycomb_geometry(self
.rows
, self
.cols
, self
.diam
, self
.edge
)
314 verts
, faces
= comb
.generate()
315 mesh
= bpy
.data
.meshes
.new('HoneyComb')
316 mesh
.from_pydata(verts
, [], faces
)
317 obj
= object_utils
.object_data_add(context
, mesh
, operator
=self
)
319 active_object
.select_set(True)
320 bpy
.context
.view_layer
.objects
.active
= active_object
321 bpy
.ops
.object.join()
322 context
.active_object
.name
= name_active_object
323 bpy
.ops
.object.mode_set(mode
='EDIT')
325 if use_enter_edit_mode
:
326 bpy
.ops
.object.mode_set(mode
= 'EDIT')
328 # restore pre operator state
329 bpy
.context
.preferences
.edit
.use_enter_edit_mode
= use_enter_edit_mode
333 def HoneyCombParameters():
334 HoneyCombParameters
= [
340 return HoneyCombParameters